diff options
author | Megan Wachs <megan@sifive.com> | 2018-08-29 15:45:11 -0700 |
---|---|---|
committer | Megan Wachs <megan@sifive.com> | 2018-08-29 15:47:54 -0700 |
commit | 34ee883aef314f45b563b28b630a2b0b81086aea (patch) | |
tree | afddabad461e5299c2084788a6a32766a24715ae | |
parent | bdc43554934b12a340c82ceb6ce3eb0d1e61681b (diff) | |
parent | b4b2ec7d2d143146226e7b2f06e1399ee560148d (diff) | |
download | riscv-openocd-34ee883aef314f45b563b28b630a2b0b81086aea.zip riscv-openocd-34ee883aef314f45b563b28b630a2b0b81086aea.tar.gz riscv-openocd-34ee883aef314f45b563b28b630a2b0b81086aea.tar.bz2 |
Merge remote-tracking branch 'origin/riscv' into riscv-compliance-rebase
189 files changed, 22858 insertions, 1706 deletions
@@ -125,8 +125,8 @@ Flash drivers ADUC702x, AT91SAM, ATH79, AVR, CFI, DSP5680xx, EFM32, EM357, FM3, FM4, Kinetis, LPC8xx/LPC1xxx/LPC2xxx/LPC541xx, LPC2900, LPCSPIFI, Marvell QSPI, -Milandr, NIIET, NuMicro, PIC32mx, PSoC4, SiM3x, Stellaris, STM32, STMSMI, -STR7x, STR9x, nRF51; NAND controllers of AT91SAM9, LPC3180, LPC32xx, +Milandr, NIIET, NuMicro, PIC32mx, PSoC4, PSoC5LP, SiM3x, Stellaris, STM32, +STMSMI, STR7x, STR9x, nRF51; NAND controllers of AT91SAM9, LPC3180, LPC32xx, i.MX31, MXC, NUC910, Orion/Kirkwood, S3C24xx, S3C6400, XMC1xxx, XMC4xxx. diff --git a/configure.ac b/configure.ac index 312fda8..d4338df 100644 --- a/configure.ac +++ b/configure.ac @@ -115,7 +115,8 @@ m4_define([USB1_ADAPTERS], [[ulink], [Keil ULINK JTAG Programmer], [ULINK]], [[usb_blaster_2], [Altera USB-Blaster II Compatible], [USB_BLASTER_2]], [[ft232r], [Bitbang mode of FT232R based devices], [FT232R]], - [[vsllink], [Versaloon-Link JTAG Programmer], [VSLLINK]]]) + [[vsllink], [Versaloon-Link JTAG Programmer], [VSLLINK]], + [[xds110], [TI XDS110 Debug Probe], [XDS110]]]) m4_define([USB_ADAPTERS], [[[osbdm], [OSBDM (JTAG only) Programmer], [OSBDM]], @@ -659,7 +660,7 @@ PROCESS_ADAPTERS([USB0_ADAPTERS], ["x$use_libusb0" = "xyes"], [libusb-0.1]) PROCESS_ADAPTERS([HIDAPI_ADAPTERS], ["x$use_hidapi" = "xyes"], [hidapi]) PROCESS_ADAPTERS([HIDAPI_USB1_ADAPTERS], ["x$use_hidapi" = "xyes" -a "x$use_libusb1" = "xyes"], [hidapi and libusb-1.x]) PROCESS_ADAPTERS([LIBFTDI_ADAPTERS], ["x$use_libftdi" = "xyes"], [libftdi]) -PROCESS_ADAPTERS([LIBJAYLINK_ADAPTERS], ["x$use_internal_libjaylink" = "xyes" -o "x$use_libjaylink" = "xyes"], [libjaylink-0.1]) +PROCESS_ADAPTERS([LIBJAYLINK_ADAPTERS], ["x$use_internal_libjaylink" = "xyes" -o "x$use_libjaylink" = "xyes"], [libjaylink-0.2]) AS_IF([test "x$build_openjtag" = "xyes"], [ AS_IF([test "x$use_libusb1" != "xyes" -a "x$use_libusb0" != "xyes"], [ diff --git a/contrib/60-openocd.rules b/contrib/60-openocd.rules index da760f8..af092c1 100644 --- a/contrib/60-openocd.rules +++ b/contrib/60-openocd.rules @@ -128,6 +128,12 @@ ATTRS{idVendor}=="1781", ATTRS{idProduct}=="0c63", MODE="660", GROUP="plugdev", # TI/Luminary Stellaris In-Circuit Debug Interface (ICDI) Board ATTRS{idVendor}=="1cbe", ATTRS{idProduct}=="00fd", MODE="660", GROUP="plugdev", TAG+="uaccess" +# TI XDS110 Debug Probe (Launchpads and Standalone) +ATTRS{idVendor}=="0451", ATTRS{idProduct}=="bef3", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# TI Tiva-based ICDI and XDS110 probes in DFU mode +ATTRS{idVendor}=="1cbe", ATTRS{idProduct}=="00ff", MODE="660", GROUP="plugdev", TAG+="uaccess" + # Ambiq Micro EVK and Debug boards. ATTRS{idVendor}=="2aec", ATTRS{idProduct}=="6010", MODE="664", GROUP="plugdev", TAG+="uaccess" ATTRS{idVendor}=="2aec", ATTRS{idProduct}=="6011", MODE="664", GROUP="plugdev", TAG+="uaccess" diff --git a/contrib/libdcc/dcc_stdio.c b/contrib/libdcc/dcc_stdio.c index 5a457e7..7da78c6 100644 --- a/contrib/libdcc/dcc_stdio.c +++ b/contrib/libdcc/dcc_stdio.c @@ -17,9 +17,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * ***************************************************************************/ #include "dcc_stdio.h" diff --git a/contrib/libdcc/dcc_stdio.h b/contrib/libdcc/dcc_stdio.h index cb87ab3..f4a5d7e 100644 --- a/contrib/libdcc/dcc_stdio.h +++ b/contrib/libdcc/dcc_stdio.h @@ -15,9 +15,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * ***************************************************************************/ #ifndef DCC_STDIO_H diff --git a/contrib/libdcc/example.c b/contrib/libdcc/example.c index 2cbef20..99b7bf6 100644 --- a/contrib/libdcc/example.c +++ b/contrib/libdcc/example.c @@ -15,9 +15,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * ***************************************************************************/ #include "dcc_stdio.h" diff --git a/contrib/loaders/flash/at91sam7x/dcc.c b/contrib/loaders/flash/at91sam7x/dcc.c index 6ab2417..04a7f7a 100644 --- a/contrib/loaders/flash/at91sam7x/dcc.c +++ b/contrib/loaders/flash/at91sam7x/dcc.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * ***************************************************************************/ #include "dcc.h" diff --git a/contrib/loaders/flash/at91sam7x/dcc.h b/contrib/loaders/flash/at91sam7x/dcc.h index a3c1393..428bf49 100644 --- a/contrib/loaders/flash/at91sam7x/dcc.h +++ b/contrib/loaders/flash/at91sam7x/dcc.h @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * ***************************************************************************/ #ifndef dccH #define dccH diff --git a/contrib/loaders/flash/at91sam7x/main.c b/contrib/loaders/flash/at91sam7x/main.c index c4b4dcf..831e03f 100644 --- a/contrib/loaders/flash/at91sam7x/main.c +++ b/contrib/loaders/flash/at91sam7x/main.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * ***************************************************************************/ #include "platform.h" diff --git a/contrib/loaders/flash/at91sam7x/ocl.h b/contrib/loaders/flash/at91sam7x/ocl.h index 1fe4596..ef30c33 100644 --- a/contrib/loaders/flash/at91sam7x/ocl.h +++ b/contrib/loaders/flash/at91sam7x/ocl.h @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * ***************************************************************************/ #ifndef OCL_H #define OCL_H diff --git a/contrib/loaders/flash/at91sam7x/platform.h b/contrib/loaders/flash/at91sam7x/platform.h index 2b26e4b..3dfa4dc 100644 --- a/contrib/loaders/flash/at91sam7x/platform.h +++ b/contrib/loaders/flash/at91sam7x/platform.h @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * ***************************************************************************/ #ifndef platformH #define platformH diff --git a/contrib/loaders/flash/at91sam7x/samflash.c b/contrib/loaders/flash/at91sam7x/samflash.c index 49c84c8..3095394 100644 --- a/contrib/loaders/flash/at91sam7x/samflash.c +++ b/contrib/loaders/flash/at91sam7x/samflash.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * ***************************************************************************/ #include "samflash.h" diff --git a/contrib/loaders/flash/at91sam7x/samflash.h b/contrib/loaders/flash/at91sam7x/samflash.h index 1de02ae..18973a7 100644 --- a/contrib/loaders/flash/at91sam7x/samflash.h +++ b/contrib/loaders/flash/at91sam7x/samflash.h @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * ***************************************************************************/ #ifndef samflashH #define samflashH diff --git a/contrib/loaders/flash/cc26xx/Makefile b/contrib/loaders/flash/cc26xx/Makefile new file mode 100644 index 0000000..7cc1fb3 --- /dev/null +++ b/contrib/loaders/flash/cc26xx/Makefile @@ -0,0 +1,83 @@ +BIN2C = ../../../../src/helper/bin2char.sh + +CROSS_COMPILE ?= arm-none-eabi- +GCC = $(CROSS_COMPILE)gcc +OBJCOPY = $(CROSS_COMPILE)objcopy + +FLAGS = -mthumb -Os -ffunction-sections -fdata-sections -g -gdwarf-3 +FLAGS += -gstrict-dwarf -Wall -fno-strict-aliasing --asm + +CFLAGS = -c -I. + +CC26X0_CFLAGS = -mcpu=cortex-m3 -DDEVICE_CC26X0 + +CC26X2_CFLAGS = -mcpu=cortex-m4 -DDEVICE_CC26X2 + +CC26X0_OBJS := \ +cc26x0/flashloader.o \ +cc26x0/main.o \ +cc26x0/startup.o \ +cc26x0/flash.o + +CC26X2_OBJS := \ +cc26x2/flashloader.o \ +cc26x2/main.o \ +cc26x2/startup.o \ +cc26x2/flash.o + +all: cc26x0_algo.inc cc26x2_algo.inc + +cc26x0/%.o: %.c + @echo 'Building file: $<' + @echo 'Invoking: GNU Compiler' + $(GCC) $(FLAGS) $(CFLAGS) $(CC26X0_CFLAGS) -o"$@" "$(shell echo $<)" + @echo 'Finished building: $<' + @echo ' ' + +cc26x2/%.o: %.c + @echo 'Building file: $<' + @echo 'Invoking: GNU Compiler' + $(GCC) $(FLAGS) $(CFLAGS) $(CC26X2_CFLAGS) -o"$@" "$(shell echo $<)" + @echo 'Finished building: $<' + @echo ' ' + +cc26x0_algo.out: $(CC26X0_OBJS) + @echo 'Building target: $@' + @echo 'Invoking: GNU Linker' + $(GCC) $(FLAGS) -o$@ $(CC26X0_OBJS) -Wl,-T"cc26x0/cc26x0r2f.lds" + @echo 'Finished building target: $@' + @echo ' ' + +cc26x2_algo.out: $(CC26X2_OBJS) + @echo 'Building target: $@' + @echo 'Invoking: GNU Linker' + $(GCC) $(FLAGS) -o$@ $(CC26X2_OBJS) -Wl,-T"cc26x2/cc26x2r1f.lds" + @echo 'Finished building target: $@' + @echo ' ' + +%.bin: %.out + @echo 'Building target: $@' + @echo 'Invoking: GNU Objcopy Utility' + $(OBJCOPY) -Obinary $< $@ + @echo 'Finished building target: $@' + @echo ' ' + +%.inc: %.bin + @echo 'Building target: $@' + @echo 'Invoking Bin2Char Script' + $(BIN2C) < $< > $@ + rm $< $*.out + @echo 'Finished building target: $@' + @echo ' ' + +clean: + @echo 'Cleaning Targets and Build Artifacts' + rm -rf *.inc *.bin *.out *.map + rm -rf cc26x0/*.o cc26x0/*.d + rm -rf cc26x2/*.o cc26x2/*.d + @echo 'Finished clean' + @echo ' ' + +.PRECIOUS: %.bin + +.PHONY: all clean diff --git a/contrib/loaders/flash/cc26xx/cc26x0/cc26x0r2f.lds b/contrib/loaders/flash/cc26xx/cc26x0/cc26x0r2f.lds new file mode 100644 index 0000000..9a126fc --- /dev/null +++ b/contrib/loaders/flash/cc26xx/cc26x0/cc26x0r2f.lds @@ -0,0 +1,90 @@ +/****************************************************************************** +* +* Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/ +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the +* distribution. +* +* Neither the name of Texas Instruments Incorporated nor the names of +* its contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +******************************************************************************/ + +/* Entry Point */ +ENTRY( entry ) + +/* System memory map */ +MEMORY +{ + /* Application is stored in and executes from SRAM */ + PROGRAM (RWX) : ORIGIN = 0x20000000, LENGTH = 0x1BD8 + BUFFERS (RWX) : ORIGIN = 0x20001BD8, LENGTH = 0x3028 +} + +/* Section allocation in memory */ +SECTIONS +{ + .text : + { + _text = .; + *(.entry*) + *(.text*) + _etext = .; + } > PROGRAM + + .data : + { _data = .; + *(.rodata*) + *(.data*) + _edata = .; + } + + .bss : + { + __bss_start__ = .; + _bss = .; + *(.bss*) + *(COMMON) + _ebss = .; + __bss_end__ = .; + } > PROGRAM + + .stack : + { + _stack = .; + *(.stack*) + _estack = .; + } > PROGRAM + + .buffers : + { + _buffers = .; + *(.buffers.g_cfg) + *(.buffers.g_buf1) + *(.buffers.g_buf2) + *(.buffers*) + _ebuffers = .; + } > BUFFERS +} diff --git a/contrib/loaders/flash/cc26xx/cc26x0_algo.inc b/contrib/loaders/flash/cc26xx/cc26x0_algo.inc new file mode 100644 index 0000000..2246a36 --- /dev/null +++ b/contrib/loaders/flash/cc26xx/cc26x0_algo.inc @@ -0,0 +1,1217 @@ +/* Autogenerated with ../../../../src/helper/bin2char.sh */ +0x08,0xb5,0x00,0xbf,0x00,0xbf,0x00,0xbf,0x00,0xbf,0xdf,0xf8,0x1c,0xd0,0x07,0x48, +0x07,0x49,0x4f,0xf0,0x00,0x02,0x88,0x42,0xb8,0xbf,0x40,0xf8,0x04,0x2b,0xfa,0xdb, +0x00,0xf0,0xa8,0xf9,0xfe,0xe7,0x00,0x00,0xf0,0x0e,0x00,0x20,0x54,0x13,0x00,0x20, +0x98,0x13,0x00,0x20,0x08,0xb5,0x07,0x4b,0x07,0x48,0x03,0x33,0x1b,0x1a,0x06,0x2b, +0x04,0xd9,0x06,0x4b,0x00,0x2b,0x01,0xd0,0x00,0xf0,0x5c,0xf8,0x08,0xbc,0x01,0xbc, +0x00,0x47,0xc0,0x46,0x50,0x13,0x00,0x20,0x50,0x13,0x00,0x20,0x00,0x00,0x00,0x00, +0x08,0x48,0x09,0x49,0x09,0x1a,0x89,0x10,0x08,0xb5,0xcb,0x0f,0x59,0x18,0x49,0x10, +0x04,0xd0,0x06,0x4b,0x00,0x2b,0x01,0xd0,0x00,0xf0,0x44,0xf8,0x08,0xbc,0x01,0xbc, +0x00,0x47,0xc0,0x46,0x50,0x13,0x00,0x20,0x50,0x13,0x00,0x20,0x00,0x00,0x00,0x00, +0x10,0xb5,0x08,0x4c,0x23,0x78,0x00,0x2b,0x09,0xd1,0xff,0xf7,0xcb,0xff,0x06,0x4b, +0x00,0x2b,0x02,0xd0,0x05,0x48,0xaf,0xf3,0x00,0x80,0x01,0x23,0x23,0x70,0x10,0xbc, +0x01,0xbc,0x00,0x47,0x54,0x13,0x00,0x20,0x00,0x00,0x00,0x00,0xe0,0x0e,0x00,0x20, +0x08,0xb5,0x0b,0x4b,0x00,0x2b,0x03,0xd0,0x0a,0x48,0x0b,0x49,0xaf,0xf3,0x00,0x80, +0x0a,0x48,0x03,0x68,0x00,0x2b,0x04,0xd1,0xff,0xf7,0xc2,0xff,0x08,0xbc,0x01,0xbc, +0x00,0x47,0x07,0x4b,0x00,0x2b,0xf7,0xd0,0x00,0xf0,0x0c,0xf8,0xf4,0xe7,0xc0,0x46, +0x00,0x00,0x00,0x00,0xe0,0x0e,0x00,0x20,0x58,0x13,0x00,0x20,0x4c,0x13,0x00,0x20, +0x00,0x00,0x00,0x00,0x18,0x47,0xc0,0x46,0xd4,0x30,0x9f,0xe5,0x00,0x00,0x53,0xe3, +0xc8,0x30,0x9f,0x05,0x03,0xd0,0xa0,0xe1,0x00,0x20,0x0f,0xe1,0x0f,0x00,0x12,0xe3, +0x15,0x00,0x00,0x0a,0xd1,0xf0,0x21,0xe3,0x03,0xd0,0xa0,0xe1,0x01,0xaa,0x4d,0xe2, +0x0a,0x30,0xa0,0xe1,0xd7,0xf0,0x21,0xe3,0x03,0xd0,0xa0,0xe1,0x01,0x3a,0x43,0xe2, +0xdb,0xf0,0x21,0xe3,0x03,0xd0,0xa0,0xe1,0x01,0x3a,0x43,0xe2,0xd2,0xf0,0x21,0xe3, +0x03,0xd0,0xa0,0xe1,0x02,0x3a,0x43,0xe2,0xd3,0xf0,0x21,0xe3,0x03,0xd0,0xa0,0xe1, +0x02,0x39,0x43,0xe2,0xff,0x30,0xc3,0xe3,0xff,0x3c,0xc3,0xe3,0x04,0x30,0x03,0xe5, +0x00,0x20,0x53,0xe9,0xc0,0x20,0x82,0xe3,0x02,0xf0,0x21,0xe1,0x01,0xa8,0x43,0xe2, +0x00,0x10,0xb0,0xe3,0x01,0xb0,0xa0,0xe1,0x01,0x70,0xa0,0xe1,0x5c,0x00,0x9f,0xe5, +0x5c,0x20,0x9f,0xe5,0x00,0x20,0x52,0xe0,0x01,0x30,0x8f,0xe2,0x13,0xff,0x2f,0xe1, +0x00,0xf0,0x42,0xfd,0x10,0x4b,0x00,0x2b,0x01,0xd0,0xfe,0x46,0x9f,0x46,0x0f,0x4b, +0x00,0x2b,0x01,0xd0,0xfe,0x46,0x9f,0x46,0x00,0x20,0x00,0x21,0x04,0x00,0x0d,0x00, +0x0d,0x48,0x00,0xf0,0x89,0xfc,0x00,0xf0,0xc3,0xfc,0x20,0x00,0x29,0x00,0x00,0xf0, +0xd1,0xf8,0x00,0xf0,0x8b,0xfc,0x7b,0x46,0x18,0x47,0x00,0x00,0x11,0x00,0x00,0xef, +0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x54,0x13,0x00,0x20,0x98,0x13,0x00,0x20,0x15,0x0b,0x00,0x20,0x70,0xb5,0x04,0x46, +0x0e,0x46,0x15,0x46,0x00,0x21,0x28,0x22,0x00,0xf0,0x0e,0xfd,0x26,0x61,0x65,0x62, +0x00,0x21,0x20,0x22,0x02,0x48,0x00,0xf0,0x07,0xfd,0x00,0x20,0x70,0xbd,0x00,0xbf, +0x70,0x13,0x00,0x20,0x10,0xb5,0x01,0x20,0x00,0xf0,0xac,0xf9,0x04,0x46,0x28,0xb9, +0x01,0x21,0x20,0x22,0x03,0x48,0x00,0xf0,0xf7,0xfc,0x01,0xe0,0x40,0xf2,0x01,0x14, +0x20,0x46,0x10,0xbd,0x70,0x13,0x00,0x20,0x01,0x39,0xf8,0xb5,0x04,0x0b,0x08,0x44, +0x05,0x0b,0x26,0x03,0xac,0x42,0x14,0xd8,0x0b,0x4f,0xe3,0x5d,0x6b,0xb9,0x30,0x46, +0x00,0xf0,0xfc,0xf8,0x38,0xb1,0x00,0x04,0x00,0xf4,0x7f,0x00,0x40,0xea,0x04,0x60, +0x40,0xf4,0x81,0x70,0xf8,0xbd,0x01,0x23,0xe3,0x55,0x01,0x34,0x06,0xf5,0x80,0x56, +0xe8,0xe7,0x00,0x20,0xf8,0xbd,0x00,0xbf,0x70,0x13,0x00,0x20,0x2d,0xe9,0xf0,0x4f, +0x0d,0x46,0x53,0x1e,0x85,0xb0,0x0b,0x44,0x02,0x90,0x4f,0xea,0x11,0x38,0x1b,0x0b, +0x16,0x46,0x23,0x48,0x00,0x21,0x20,0x22,0x01,0x93,0x4f,0xea,0x08,0x37,0x00,0xf0, +0xbb,0xfc,0x4f,0xf0,0x00,0x09,0xc5,0xf3,0x0b,0x0c,0x01,0x9b,0x98,0x45,0x33,0xd8, +0x74,0x19,0x07,0xf5,0x80,0x5a,0x54,0x45,0x98,0xbf,0x34,0x46,0xdf,0xf8,0x64,0xb0, +0x88,0xbf,0xc4,0xf3,0x0b,0x04,0x39,0x46,0x4f,0xf4,0x80,0x52,0x58,0x46,0x88,0xbf, +0x34,0x1b,0xcd,0xf8,0x0c,0xc0,0x00,0xf0,0x5f,0xfc,0xdd,0xf8,0x0c,0xc0,0x02,0x9b, +0x0b,0xeb,0x0c,0x00,0x03,0xeb,0x09,0x01,0x22,0x46,0x00,0xf0,0x55,0xfc,0x38,0x46, +0x4f,0xf4,0x80,0x51,0x08,0xf1,0x01,0x08,0xff,0xf7,0x9e,0xff,0x68,0xb9,0x39,0x46, +0x58,0x46,0x4f,0xf4,0x80,0x52,0x25,0x44,0x00,0xf0,0xae,0xf8,0x36,0x1b,0xc5,0xf3, +0x0b,0x0c,0xa1,0x44,0x57,0x46,0xc8,0xe7,0x00,0x20,0x05,0xb0,0xbd,0xe8,0xf0,0x8f, +0x70,0x13,0x00,0x20,0x00,0x3c,0x00,0x20,0xb2,0xf5,0x80,0x5f,0xf8,0xb5,0x07,0x46, +0x0e,0x46,0x15,0x46,0x0b,0xd8,0x08,0x46,0x11,0x46,0xff,0xf7,0x7d,0xff,0x04,0x46, +0x40,0xb9,0x38,0x46,0x31,0x46,0x2a,0x46,0x00,0xf0,0x8e,0xf8,0x02,0xe0,0x4f,0xf4, +0x82,0x70,0xf8,0xbd,0x20,0x46,0xf8,0xbd,0x08,0xb5,0x00,0xf0,0x85,0xf8,0x00,0x20, +0x08,0xbd,0x00,0x00,0xf8,0xb5,0x31,0x48,0x31,0x49,0x32,0x4a,0x32,0x4c,0xff,0xf7, +0x3d,0xff,0x00,0x23,0x23,0x60,0x22,0x68,0x2c,0x4f,0x14,0x23,0x03,0xfb,0x02,0x73, +0x08,0x33,0x5b,0x68,0x00,0x2b,0xf7,0xd0,0x2c,0x4b,0x1a,0x68,0x11,0x07,0xfb,0xd4, +0x2b,0x4d,0x2c,0x4e,0x2a,0x68,0x32,0x60,0x42,0xf0,0x33,0x02,0x2a,0x60,0x1a,0x68, +0x12,0x07,0xfc,0xd4,0x21,0x68,0x14,0x22,0x02,0xfb,0x01,0x73,0x98,0x68,0x13,0x46, +0x01,0x38,0x04,0x28,0x26,0xd8,0xdf,0xe8,0x00,0xf0,0x03,0x06,0x0e,0x16,0x1e,0x00, +0xff,0xf7,0x28,0xff,0x20,0xe0,0x4b,0x43,0xfa,0x18,0x10,0x69,0xf9,0x58,0x52,0x68, +0xff,0xf7,0xc2,0xff,0x18,0xe0,0x4b,0x43,0xfa,0x18,0x10,0x69,0xf9,0x58,0x52,0x68, +0xff,0xf7,0xa2,0xff,0x10,0xe0,0x4b,0x43,0xfa,0x18,0x10,0x69,0xf9,0x58,0x52,0x68, +0xff,0xf7,0x44,0xff,0x08,0xe0,0x4b,0x43,0xfa,0x18,0xf8,0x58,0x51,0x68,0xff,0xf7, +0x1b,0xff,0x01,0xe0,0x40,0xf2,0x05,0x10,0x33,0x68,0x2b,0x60,0x0b,0x4b,0x1b,0x68, +0x1b,0x07,0xfb,0xd4,0x22,0x68,0x14,0x23,0x03,0xfb,0x02,0x77,0xfb,0x68,0xf8,0x60, +0x00,0xb1,0xfe,0xe7,0x82,0xf0,0x01,0x02,0x22,0x60,0xa4,0xe7,0xd8,0x1b,0x00,0x20, +0x00,0x1c,0x00,0x20,0x00,0x2c,0x00,0x20,0x90,0x13,0x00,0x20,0x00,0x40,0x03,0x40, +0x04,0x40,0x03,0x40,0x94,0x13,0x00,0x20,0xfe,0xe7,0x00,0x00,0x08,0xb5,0x04,0x4b, +0x1b,0x68,0x5b,0x69,0x98,0x47,0x03,0x4b,0x00,0x22,0x1a,0x60,0x08,0xbd,0x00,0xbf, +0xa8,0x01,0x00,0x10,0x84,0x04,0x60,0x42,0x08,0xb5,0x04,0x4b,0x1b,0x68,0x9b,0x69, +0x98,0x47,0x03,0x4b,0x00,0x22,0x1a,0x60,0x08,0xbd,0x00,0xbf,0xa8,0x01,0x00,0x10, +0x84,0x04,0x60,0x42,0x10,0xb5,0x33,0x4b,0x33,0x48,0x1b,0x68,0x33,0x4a,0x13,0xf0, +0x02,0x0f,0x03,0x68,0x43,0xf0,0x02,0x03,0x03,0x60,0x13,0x68,0x01,0x68,0x19,0xd0, +0x21,0xf4,0xe1,0x72,0xc3,0xf3,0xc1,0x04,0x22,0xf0,0x01,0x02,0x22,0x43,0xc3,0xf3, +0xc0,0x11,0x42,0xea,0x01,0x22,0xc3,0xf3,0x41,0x11,0x42,0xea,0x81,0x12,0x02,0x60, +0x02,0x68,0xd4,0x07,0x03,0xd5,0x26,0x4a,0x12,0x68,0x50,0x07,0xfb,0xd5,0x03,0xf0, +0x07,0x03,0x18,0xe0,0x21,0xf4,0xe1,0x72,0xc3,0xf3,0xc1,0x24,0x22,0xf0,0x01,0x02, +0xc3,0xf3,0xc0,0x31,0x22,0x43,0x42,0xea,0x01,0x22,0xc3,0xf3,0x41,0x31,0x42,0xea, +0x81,0x12,0x02,0x60,0x02,0x68,0xd1,0x07,0x03,0xd5,0x19,0x4a,0x12,0x68,0x52,0x07, +0xfb,0xd5,0xc3,0xf3,0x02,0x23,0x4a,0xf6,0xaa,0x22,0x16,0x49,0x16,0x48,0x0a,0x60, +0x02,0x68,0x1b,0x03,0xb3,0xf5,0xe0,0x4f,0x22,0xf4,0xe2,0x42,0x18,0xbf,0x43,0xf4, +0x80,0x73,0x13,0x43,0x03,0x60,0x45,0xf2,0xaa,0x53,0x0b,0x60,0x0f,0x4b,0x10,0x49, +0x01,0x22,0x1a,0x60,0x00,0x22,0x0a,0x60,0x1a,0x60,0x05,0x22,0xc3,0xf8,0x58,0x22, +0x4f,0xf0,0xff,0x32,0xc1,0xf8,0x8c,0x22,0xc1,0xf8,0x90,0x22,0x02,0x22,0xc3,0xf8, +0x58,0x22,0x10,0xbd,0x00,0x00,0x09,0x40,0x24,0x00,0x03,0x40,0x08,0x13,0x00,0x50, +0x1c,0x00,0x03,0x40,0x64,0x20,0x03,0x40,0xa8,0x20,0x03,0x40,0x30,0x20,0x03,0x40, +0x34,0x20,0x03,0x40,0x2d,0xe9,0xf8,0x4f,0xd4,0x4d,0x29,0x68,0x11,0xf0,0x01,0x01, +0x40,0xf0,0x95,0x81,0xdf,0xf8,0x90,0xe3,0x05,0x27,0xd1,0x4b,0xce,0xf8,0x00,0x70, +0x1b,0x68,0x4f,0xf4,0x40,0x72,0xc3,0xf3,0x03,0x23,0x01,0x33,0xb2,0xfb,0xf3,0xf3, +0xdf,0xf8,0x78,0xc3,0xdf,0xf8,0x78,0x83,0xdc,0xf8,0x00,0x20,0xd8,0xf8,0x00,0x40, +0x92,0xb2,0x5a,0x43,0xc2,0xf3,0x8f,0x16,0x22,0x0c,0x12,0x04,0x32,0x43,0xc8,0xf8, +0x00,0x20,0xc4,0x4a,0xc4,0x4c,0x12,0x68,0x26,0x68,0x5a,0x43,0xc3,0x4e,0x92,0x09, +0x22,0x60,0x32,0x68,0x54,0xf8,0x24,0x8c,0xc2,0xf3,0x07,0x42,0x5a,0x43,0x28,0xf0, +0xff,0x08,0xc2,0xf3,0x87,0x12,0xdf,0xf8,0x3c,0x93,0x42,0xea,0x08,0x02,0xdf,0xf8, +0x38,0x83,0x44,0xf8,0x24,0x2c,0xd9,0xf8,0x00,0xa0,0xd8,0xf8,0x00,0x20,0xca,0xf3, +0x07,0x4a,0x22,0xf0,0xff,0x02,0x4a,0xea,0x02,0x02,0xc8,0xf8,0x00,0x20,0xd9,0xf8, +0x00,0x20,0xdf,0xf8,0x18,0xa3,0x12,0x0e,0x5a,0x43,0xda,0xf8,0x00,0x80,0x92,0x00, +0x28,0xf4,0x7f,0x48,0x02,0xf4,0x7f,0x42,0x42,0xea,0x08,0x02,0xdf,0xf8,0x00,0x83, +0xca,0xf8,0x00,0x20,0xd8,0xf8,0x00,0x20,0xae,0xf5,0x09,0x7e,0x4f,0xea,0x12,0x6b, +0x0b,0xfb,0x03,0xfb,0xda,0xf8,0x04,0x20,0xcb,0xf3,0x8f,0x1b,0x12,0x0c,0x12,0x04, +0x4b,0xea,0x02,0x02,0xca,0xf8,0x04,0x20,0xd9,0xf8,0x00,0x20,0xc2,0xf3,0x07,0x22, +0x53,0x43,0x9f,0x4a,0x9b,0x00,0xd2,0xf8,0x00,0x90,0x03,0xf4,0x7f,0x43,0x29,0xf4, +0x7f,0x49,0x43,0xea,0x09,0x03,0xdf,0xf8,0xbc,0x92,0x13,0x60,0xd9,0xf8,0x00,0xa0, +0x52,0xf8,0x24,0x3c,0x4f,0xea,0x1a,0x6a,0x23,0xf4,0x7f,0x43,0x43,0xea,0x0a,0x23, +0x42,0xf8,0x24,0x3c,0xd9,0xf8,0x00,0xa0,0x52,0xf8,0x24,0x3c,0xca,0xf3,0x07,0x4a, +0x23,0xf0,0xff,0x03,0x4a,0xea,0x03,0x03,0x42,0xf8,0x24,0x3c,0xd9,0xf8,0x00,0xa0, +0x52,0xf8,0x1c,0x3c,0x0a,0xf4,0x7f,0x4a,0x23,0xf4,0x7f,0x43,0x4a,0xea,0x03,0x03, +0x42,0xf8,0x1c,0x3c,0xd9,0xf8,0x00,0x90,0x52,0xf8,0x1c,0x3c,0x5f,0xfa,0x89,0xf9, +0x23,0xf0,0xff,0x03,0x49,0xea,0x03,0x03,0xdf,0xf8,0x5c,0x92,0x42,0xf8,0x1c,0x3c, +0x32,0x68,0xd9,0xf8,0x00,0x30,0x02,0xf4,0x70,0x42,0x23,0xf4,0x70,0x43,0x13,0x43, +0xc9,0xf8,0x00,0x30,0xd8,0xf8,0x00,0x20,0xdf,0xf8,0x40,0x82,0x02,0xf4,0x70,0x42, +0xd8,0xf8,0x00,0x30,0x23,0xf4,0x70,0x43,0x13,0x43,0xc8,0xf8,0x00,0x30,0x32,0x68, +0x54,0xf8,0x24,0x3c,0x12,0x0e,0x23,0xf4,0x7f,0x43,0x43,0xea,0x02,0x23,0x44,0xf8, +0x24,0x3c,0x70,0x4b,0x1b,0x68,0x62,0x6a,0xc3,0xf3,0x0b,0x06,0x22,0xf4,0x7f,0x63, +0x23,0xf0,0x0f,0x03,0x33,0x43,0x6c,0x4e,0x63,0x62,0x32,0x68,0x63,0x6a,0x02,0xf4, +0x70,0x22,0x23,0xf4,0x70,0x23,0x13,0x43,0x63,0x62,0x68,0x4c,0x22,0x68,0xd8,0xf8, +0x58,0x30,0xc2,0xf3,0x83,0x42,0x23,0xf4,0x70,0x23,0x43,0xea,0x02,0x43,0xc8,0xf8, +0x58,0x30,0xdc,0xf8,0x00,0x30,0xd8,0xf8,0x58,0x20,0xc3,0xf3,0x0b,0x4c,0x22,0xf4, +0x7f,0x63,0x23,0xf0,0x0f,0x03,0x4c,0xea,0x03,0x03,0xc8,0xf8,0x58,0x30,0x23,0x68, +0xd8,0xf8,0x5c,0x20,0x4f,0xea,0xd3,0x5c,0x22,0xf0,0xff,0x73,0x23,0xf4,0x80,0x33, +0x43,0xea,0x0c,0x43,0xc8,0xf8,0x5c,0x30,0x33,0x68,0x55,0x4a,0x0f,0x33,0x03,0xf0, +0x0f,0x03,0x13,0x60,0x26,0x68,0x53,0x68,0xc6,0xf3,0x80,0x56,0x23,0xf4,0x00,0x03, +0x43,0xea,0xc6,0x53,0x53,0x60,0x53,0x68,0x4e,0x4e,0x43,0xf4,0x80,0x43,0x53,0x60, +0x02,0x23,0xce,0xf8,0x24,0x32,0x4a,0xf6,0xaa,0x23,0xdf,0xf8,0x74,0xc1,0xce,0xf8, +0x00,0x30,0xdc,0xf8,0x00,0x30,0x32,0x68,0x03,0xf0,0x0f,0x08,0x22,0xf4,0x7f,0x02, +0x42,0xea,0x08,0x42,0xc3,0xf3,0x03,0x23,0x42,0xea,0x03,0x53,0xdf,0xf8,0x54,0x81, +0x33,0x60,0xd8,0xf8,0x00,0x30,0x32,0x68,0xc3,0xf3,0x03,0x49,0x22,0xf0,0xff,0x02, +0x49,0xea,0x02,0x02,0xc3,0xf3,0x03,0x63,0x42,0xea,0x03,0x13,0x33,0x60,0xdc,0xf8, +0x00,0x60,0xdf,0xf8,0x34,0xc1,0x06,0xf4,0x70,0x22,0xdc,0xf8,0x00,0x30,0x23,0xf4, +0x7f,0x03,0x1a,0x43,0xc6,0xf3,0x03,0x63,0x42,0xea,0x03,0x53,0x32,0x4e,0xcc,0xf8, +0x00,0x30,0x32,0x68,0x5c,0xf8,0x08,0x3c,0xc2,0xf3,0x03,0x22,0x23,0xf0,0x0f,0x03, +0x13,0x43,0x4c,0xf8,0x08,0x3c,0xd8,0xf8,0x00,0x20,0xdc,0xf8,0x08,0x30,0x02,0xf4, +0xf8,0x52,0x23,0xf4,0xf8,0x53,0x13,0x43,0xcc,0xf8,0x08,0x30,0x32,0x68,0xdc,0xf8, +0x0c,0x30,0x12,0x0b,0x02,0xf4,0x70,0x42,0x23,0xf4,0x70,0x43,0x13,0x43,0xcc,0xf8, +0x0c,0x30,0x32,0x68,0x21,0x4e,0xc2,0xf3,0x04,0x42,0x33,0x68,0x23,0xf0,0x1f,0x03, +0x13,0x43,0x33,0x60,0x22,0x68,0x1e,0x4c,0xc2,0xf3,0x01,0x42,0x23,0x68,0x23,0xf4, +0x40,0x13,0x43,0xea,0x02,0x53,0x23,0x60,0x45,0xf2,0xaa,0x53,0x19,0x4a,0xce,0xf8, +0x00,0x30,0x17,0x60,0x2b,0x68,0x43,0xf0,0x01,0x03,0x2b,0x60,0x11,0x60,0x16,0x4b, +0x16,0x4c,0x1b,0x68,0x16,0x4a,0x13,0xf0,0x02,0x0f,0x23,0x68,0x15,0x4d,0x43,0xf0, +0x02,0x03,0x23,0x60,0x13,0x68,0x21,0x68,0x59,0xd0,0x3f,0xe0,0x40,0x00,0x03,0x40, +0x00,0x20,0x03,0x40,0x8c,0x11,0x00,0x50,0x44,0x22,0x03,0x40,0x74,0x11,0x00,0x50, +0x34,0x22,0x03,0x40,0x84,0x11,0x00,0x50,0x80,0x11,0x00,0x50,0xb0,0x12,0x00,0x50, +0x78,0x22,0x03,0x40,0x84,0x20,0x03,0x40,0x98,0x11,0x00,0x50,0x98,0x20,0x03,0x40, +0xa8,0x20,0x03,0x40,0x3c,0x00,0x03,0x40,0x00,0x00,0x09,0x40,0x24,0x00,0x03,0x40, +0x08,0x13,0x00,0x50,0x1c,0x00,0x03,0x40,0x88,0x22,0x03,0x40,0x88,0x11,0x00,0x50, +0x40,0x22,0x03,0x40,0x78,0x11,0x00,0x50,0x24,0x22,0x03,0x40,0x28,0x22,0x03,0x40, +0x7c,0x11,0x00,0x50,0x70,0x11,0x00,0x50,0x1c,0x22,0x03,0x40,0x14,0x22,0x03,0x40, +0x90,0x11,0x00,0x50,0x94,0x11,0x00,0x50,0x88,0x20,0x03,0x40,0x21,0xf4,0xe1,0x72, +0xc3,0xf3,0xc1,0x46,0x22,0xf0,0x01,0x02,0xc3,0xf3,0xc0,0x51,0x32,0x43,0x42,0xea, +0x01,0x22,0xc3,0xf3,0x41,0x51,0x42,0xea,0x81,0x12,0x22,0x60,0x22,0x68,0xd7,0x07, +0x02,0xd5,0x2a,0x68,0x56,0x07,0xfc,0xd5,0xc3,0xf3,0x02,0x43,0x16,0xe0,0xc3,0xf3, +0xc1,0x62,0xde,0x0f,0x42,0xea,0x06,0x26,0x21,0xf4,0xe1,0x72,0x22,0xf0,0x01,0x02, +0x32,0x43,0xc3,0xf3,0x41,0x71,0x42,0xea,0x81,0x12,0x22,0x60,0x22,0x68,0xd4,0x07, +0x02,0xd5,0x2a,0x68,0x51,0x07,0xfc,0xd5,0xc3,0xf3,0x02,0x63,0x4a,0xf6,0xaa,0x22, +0x3a,0x49,0x3b,0x4c,0x0a,0x60,0x22,0x68,0x1b,0x03,0xb3,0xf5,0xe0,0x4f,0x22,0xf4, +0xe2,0x42,0x18,0xbf,0x43,0xf4,0x80,0x73,0x13,0x43,0x23,0x60,0x45,0xf2,0xaa,0x53, +0x4f,0xf6,0xff,0x74,0x0b,0x60,0x33,0x4b,0x00,0x21,0x01,0x22,0x19,0x60,0x43,0xf8, +0x20,0x2c,0x31,0x4a,0x4f,0xf0,0x05,0x0e,0x14,0x60,0x30,0x4c,0x43,0xf8,0x20,0x1c, +0x02,0xf5,0xec,0x72,0x10,0x23,0xc4,0xf8,0x00,0xe0,0x13,0x60,0x2c,0x4b,0x15,0x26, +0x1e,0x60,0x02,0x26,0x26,0x60,0x2b,0x4e,0x37,0x68,0xc4,0xf8,0x00,0xe0,0xdf,0xf8, +0xb4,0xe0,0xce,0xf8,0x00,0x10,0xce,0xf8,0x04,0x10,0x18,0xb1,0x31,0x68,0x41,0xf4, +0x00,0x01,0x31,0x60,0x02,0x21,0x05,0x20,0x21,0x60,0x20,0x60,0x08,0x20,0x10,0x60, +0x15,0x22,0x1a,0x60,0x21,0x60,0x2b,0x68,0x9a,0x07,0xfc,0xd4,0x1e,0x4b,0x1b,0x68, +0x13,0xf0,0x10,0x0f,0x14,0xbf,0x04,0x25,0x00,0x25,0xff,0xf7,0x1b,0xfd,0x3b,0x02, +0x07,0xd4,0x05,0x23,0x23,0x60,0x33,0x68,0x23,0xf4,0x00,0x03,0x33,0x60,0x02,0x23, +0x23,0x60,0xbd,0xb9,0x15,0x4b,0x16,0x48,0x19,0x68,0x03,0xf5,0x10,0x53,0x04,0x33, +0x1a,0x68,0xc9,0xb2,0x02,0xf0,0x0f,0x02,0x51,0x43,0x1b,0x68,0x14,0x22,0x03,0xf0, +0x0f,0x03,0x9b,0x02,0xc3,0xeb,0x81,0x21,0x01,0xf6,0xd8,0x71,0xbd,0xe8,0xf8,0x4f, +0xff,0xf7,0xea,0xbc,0x28,0x46,0xbd,0xe8,0xf8,0x8f,0x00,0xbf,0x64,0x20,0x03,0x40, +0xa8,0x20,0x03,0x40,0x50,0x20,0x03,0x40,0x34,0x20,0x03,0x40,0x88,0x22,0x03,0x40, +0xb4,0x22,0x03,0x40,0x7c,0x22,0x03,0x40,0x54,0x20,0x03,0x40,0x2c,0x00,0x03,0x40, +0xf4,0x0e,0x00,0x20,0xc0,0x22,0x03,0x40,0x08,0xb5,0x01,0x1c,0x00,0x22,0x00,0x20, +0x00,0x23,0x00,0xf0,0xeb,0xf8,0x08,0xbc,0x02,0xbc,0x08,0x47,0x10,0xb5,0x00,0x21, +0x04,0x1c,0x00,0xf0,0x5d,0xf9,0x05,0x4b,0x18,0x68,0xc3,0x6b,0x00,0x2b,0x01,0xd0, +0x00,0xf0,0x06,0xf8,0x20,0x1c,0xff,0xf7,0xa7,0xfc,0xc0,0x46,0x0c,0x0f,0x00,0x20, +0x18,0x47,0xc0,0x46,0x38,0xb5,0x0a,0x4b,0x0a,0x4c,0xe4,0x1a,0xa4,0x10,0x0a,0xd0, +0x09,0x4a,0xa5,0x18,0xad,0x00,0xed,0x18,0x2b,0x68,0x01,0x3c,0x00,0xf0,0x0e,0xf8, +0x04,0x3d,0x00,0x2c,0xf8,0xd1,0x00,0xf0,0xcd,0xf9,0x38,0xbc,0x01,0xbc,0x00,0x47, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0x3f,0x18,0x47,0xc0,0x46, +0x70,0xb5,0x10,0x4e,0x10,0x4d,0xad,0x1b,0xad,0x10,0x00,0x24,0x00,0x2d,0x06,0xd0, +0xa3,0x00,0xf3,0x58,0x01,0x34,0x00,0xf0,0x1d,0xf8,0xa5,0x42,0xf8,0xd1,0x00,0xf0, +0xab,0xf9,0x0a,0x4e,0x0a,0x4d,0xad,0x1b,0xad,0x10,0x00,0x24,0x00,0x2d,0x06,0xd0, +0xa3,0x00,0xf3,0x58,0x01,0x34,0x00,0xf0,0x0d,0xf8,0xa5,0x42,0xf8,0xd1,0x70,0xbc, +0x01,0xbc,0x00,0x47,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x18,0x47,0xc0,0x46,0x70,0xb5,0x0f,0x2a,0x34,0xd9,0x04,0x1c, +0x0c,0x43,0x0b,0x1c,0xa4,0x07,0x33,0xd1,0x15,0x1c,0x04,0x1c,0x10,0x3d,0x2d,0x09, +0x01,0x35,0x2d,0x01,0x49,0x19,0x1e,0x68,0x26,0x60,0x5e,0x68,0x66,0x60,0x9e,0x68, +0xa6,0x60,0xde,0x68,0x10,0x33,0xe6,0x60,0x10,0x34,0x99,0x42,0xf3,0xd1,0x0f,0x23, +0x45,0x19,0x13,0x40,0x03,0x2b,0x1d,0xd9,0x1c,0x1f,0x00,0x23,0xa4,0x08,0x01,0x34, +0xa4,0x00,0xce,0x58,0xee,0x50,0x04,0x33,0xa3,0x42,0xfa,0xd1,0xed,0x18,0xc9,0x18, +0x03,0x23,0x1a,0x40,0x05,0xd0,0x00,0x23,0xcc,0x5c,0xec,0x54,0x01,0x33,0x93,0x42, +0xfa,0xd1,0x70,0xbc,0x02,0xbc,0x08,0x47,0x05,0x1c,0x00,0x2a,0xf3,0xd1,0xf8,0xe7, +0x05,0x1c,0xf0,0xe7,0x1a,0x1c,0xf8,0xe7,0x70,0xb5,0x83,0x07,0x43,0xd0,0x54,0x1e, +0x00,0x2a,0x3d,0xd0,0x0d,0x06,0x2d,0x0e,0x03,0x1c,0x03,0x26,0x03,0xe0,0x62,0x1e, +0x00,0x2c,0x35,0xd0,0x14,0x1c,0x01,0x33,0x5a,0x1e,0x15,0x70,0x33,0x42,0xf6,0xd1, +0x03,0x2c,0x24,0xd9,0xff,0x25,0x0d,0x40,0x2a,0x02,0x15,0x43,0x2a,0x04,0x15,0x43, +0x0f,0x2c,0x11,0xd9,0x26,0x1c,0x10,0x3e,0x36,0x09,0x01,0x36,0x36,0x01,0x1a,0x1c, +0x9b,0x19,0x15,0x60,0x55,0x60,0x95,0x60,0xd5,0x60,0x10,0x32,0x93,0x42,0xf8,0xd1, +0x0f,0x22,0x14,0x40,0x03,0x2c,0x0a,0xd9,0x26,0x1f,0xb6,0x08,0x01,0x36,0xb6,0x00, +0x1a,0x1c,0x9b,0x19,0x20,0xc2,0x93,0x42,0xfc,0xd1,0x03,0x22,0x14,0x40,0x00,0x2c, +0x06,0xd0,0x09,0x06,0x1c,0x19,0x09,0x0e,0x19,0x70,0x01,0x33,0xa3,0x42,0xfb,0xd1, +0x70,0xbc,0x02,0xbc,0x08,0x47,0x14,0x1c,0x03,0x1c,0xc9,0xe7,0xf8,0xb5,0x44,0x46, +0x5f,0x46,0x56,0x46,0x4d,0x46,0x9b,0x46,0x30,0x4b,0xf0,0xb4,0x1c,0x68,0xa4,0x23, +0x5b,0x00,0x05,0x1c,0xe0,0x58,0x0e,0x1c,0x90,0x46,0x00,0x28,0x4d,0xd0,0x43,0x68, +0x1f,0x2b,0x0f,0xdc,0x5c,0x1c,0x00,0x2d,0x23,0xd1,0x02,0x33,0x9b,0x00,0x44,0x60, +0x1e,0x50,0x00,0x20,0x3c,0xbc,0x90,0x46,0x99,0x46,0xa2,0x46,0xab,0x46,0xf8,0xbc, +0x02,0xbc,0x08,0x47,0x22,0x4b,0x00,0x2b,0x3c,0xd0,0xc8,0x20,0x40,0x00,0xaf,0xf3, +0x00,0x80,0x00,0x28,0x36,0xd0,0xa4,0x22,0x00,0x23,0x52,0x00,0xa1,0x58,0x43,0x60, +0x01,0x60,0xa0,0x50,0x40,0x32,0x83,0x50,0x04,0x32,0x83,0x50,0x01,0x24,0x00,0x2d, +0xdb,0xd0,0x9a,0x00,0x91,0x46,0x81,0x44,0x42,0x46,0x88,0x21,0x4f,0x46,0x7a,0x50, +0xc4,0x22,0x52,0x00,0x90,0x46,0x80,0x44,0x42,0x46,0x87,0x39,0x99,0x40,0x12,0x68, +0x0a,0x43,0x94,0x46,0x8a,0x46,0x42,0x46,0x61,0x46,0x11,0x60,0x84,0x22,0x49,0x46, +0x5f,0x46,0x52,0x00,0x8f,0x50,0x02,0x2d,0xbf,0xd1,0x02,0x1c,0x55,0x46,0x8d,0x32, +0xff,0x32,0x11,0x68,0x0d,0x43,0x15,0x60,0xb7,0xe7,0x20,0x1c,0x4d,0x30,0xff,0x30, +0xe0,0x50,0xac,0xe7,0x01,0x20,0x40,0x42,0xb4,0xe7,0xc0,0x46,0x0c,0x0f,0x00,0x20, +0x00,0x00,0x00,0x00,0x08,0xb5,0x04,0x4b,0x00,0x2b,0x02,0xd0,0x03,0x48,0xff,0xf7, +0x9b,0xfe,0x08,0xbc,0x01,0xbc,0x00,0x47,0x00,0x00,0x00,0x00,0x15,0x0b,0x00,0x20, +0xf0,0xb5,0x56,0x46,0x5f,0x46,0x4d,0x46,0x44,0x46,0xf0,0xb4,0x0e,0x1c,0x3f,0x4b, +0x1b,0x68,0x87,0xb0,0x03,0x93,0x49,0x33,0xff,0x33,0x01,0x90,0x04,0x93,0xa4,0x22, +0x03,0x9b,0x52,0x00,0x9f,0x58,0x00,0x2f,0x4d,0xd0,0x04,0x9b,0x98,0x46,0x00,0x23, +0x9b,0x46,0xc4,0x23,0x5b,0x00,0x9c,0x46,0xbc,0x44,0x63,0x46,0x02,0x93,0xc6,0x23, +0x5b,0x00,0x9a,0x46,0x7c,0x68,0xa5,0x00,0x7d,0x19,0xba,0x44,0x01,0x3c,0x08,0xd5, +0x27,0xe0,0x6b,0x1d,0xff,0x33,0x1b,0x68,0xb3,0x42,0x04,0xd0,0x04,0x3d,0x01,0x3c, +0x1f,0xd3,0x00,0x2e,0xf5,0xd1,0x7b,0x68,0x01,0x3b,0x6a,0x68,0xa3,0x42,0x3e,0xd0, +0x5b,0x46,0x6b,0x60,0x00,0x2a,0xf1,0xd0,0x7b,0x68,0x99,0x46,0x01,0x23,0xa3,0x40, +0x02,0x99,0x09,0x68,0x05,0x91,0x19,0x42,0x26,0xd1,0x00,0xf0,0x43,0xf8,0x7b,0x68, +0x4b,0x45,0xc4,0xd1,0x43,0x46,0x1b,0x68,0xbb,0x42,0xc0,0xd1,0x04,0x3d,0x01,0x3c, +0xdf,0xd2,0x1b,0x4b,0x00,0x2b,0x0e,0xd0,0x7b,0x68,0x00,0x2b,0x27,0xd1,0x3b,0x68, +0x00,0x2b,0x28,0xd0,0x42,0x46,0x38,0x1c,0x13,0x60,0xaf,0xf3,0x00,0x80,0x43,0x46, +0x1f,0x68,0x00,0x2f,0xb5,0xd1,0x07,0xb0,0x3c,0xbc,0x90,0x46,0x99,0x46,0xa2,0x46, +0xab,0x46,0xf0,0xbc,0x01,0xbc,0x00,0x47,0x51,0x46,0x09,0x68,0x19,0x42,0x08,0xd1, +0x2b,0x1c,0x84,0x33,0x19,0x68,0x01,0x98,0x00,0xf0,0x14,0xf8,0xcf,0xe7,0x7c,0x60, +0xc0,0xe7,0x2b,0x1c,0x84,0x33,0x18,0x68,0x00,0xf0,0x0c,0xf8,0xc7,0xe7,0x3b,0x68, +0xb8,0x46,0x1f,0x1c,0xdd,0xe7,0x00,0x23,0xfa,0xe7,0xc0,0x46,0x0c,0x0f,0x00,0x20, +0x00,0x00,0x00,0x00,0x10,0x47,0xc0,0x46,0xf8,0xb5,0xc0,0x46,0xf8,0xbc,0x08,0xbc, +0x9e,0x46,0x70,0x47,0xf8,0xb5,0xc0,0x46,0xf8,0xbc,0x08,0xbc,0x9e,0x46,0x70,0x47, +0x00,0x00,0x00,0x00,0x24,0xf2,0xff,0x7f,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x28,0x15,0x00,0x20,0xff,0xff,0xff,0xc5,0xff,0xff,0xff,0xff,0xc5,0xff,0xff,0xff, +0xc5,0xc5,0xc5,0xff,0xc5,0xc5,0xc5,0xff,0x43,0x00,0x00,0x00,0x18,0x0f,0x00,0x20, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x12,0x00,0x20, +0x6c,0x12,0x00,0x20,0xd4,0x12,0x00,0x20,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,0x08,0x0f,0x00,0x20, +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,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, +0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0x33,0xcd,0xab,0x34,0x12,0x6d,0xe6, +0xec,0xde,0x05,0x00,0x0b,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,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,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, +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,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,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,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,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,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,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,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,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,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,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,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,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x18,0x0f,0x00,0x20,0xc1,0x00,0x00,0x20,0x91,0x00,0x00,0x20,0x00,0x00,0x00,0x00, +0x95,0x0d,0x00,0x20,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,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,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,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,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,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,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,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,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,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,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,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, +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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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, +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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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, +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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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, +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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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, +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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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, +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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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, +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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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, +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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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, +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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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, +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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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, +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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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, +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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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, +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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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, +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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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, +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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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, +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,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,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, diff --git a/contrib/loaders/flash/cc26xx/cc26x2/cc26x2r1f.lds b/contrib/loaders/flash/cc26xx/cc26x2/cc26x2r1f.lds new file mode 100644 index 0000000..fb7cc56 --- /dev/null +++ b/contrib/loaders/flash/cc26xx/cc26x2/cc26x2r1f.lds @@ -0,0 +1,90 @@ +/****************************************************************************** +* +* Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/ +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the +* distribution. +* +* Neither the name of Texas Instruments Incorporated nor the names of +* its contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +******************************************************************************/ + +/* Entry Point */ +ENTRY( entry ) + +/* System memory map */ +MEMORY +{ + /* Application is stored in and executes from SRAM */ + PROGRAM (RWX) : ORIGIN = 0x20000000, LENGTH = 0x1FD8 + BUFFERS (RWX) : ORIGIN = 0x20001FD8, LENGTH = 0x6028 +} + +/* Section allocation in memory */ +SECTIONS +{ + .text : + { + _text = .; + *(.entry*) + *(.text*) + _etext = .; + } > PROGRAM + + .data : + { _data = .; + *(.rodata*) + *(.data*) + _edata = .; + } + + .bss : + { + __bss_start__ = .; + _bss = .; + *(.bss*) + *(COMMON) + _ebss = .; + __bss_end__ = .; + } > PROGRAM + + .stack : + { + _stack = .; + *(.stack*) + _estack = .; + } > PROGRAM + + .buffers : + { + _buffers = .; + *(.buffers.g_cfg) + *(.buffers.g_buf1) + *(.buffers.g_buf2) + *(.buffers*) + _ebuffers = .; + } > BUFFERS +} diff --git a/contrib/loaders/flash/cc26xx/cc26x2_algo.inc b/contrib/loaders/flash/cc26xx/cc26x2_algo.inc new file mode 100644 index 0000000..9adb919 --- /dev/null +++ b/contrib/loaders/flash/cc26xx/cc26x2_algo.inc @@ -0,0 +1,2049 @@ +/* Autogenerated with ../../../../src/helper/bin2char.sh */ +0x08,0xb5,0x00,0xbf,0x00,0xbf,0x00,0xbf,0x00,0xbf,0xdf,0xf8,0x1c,0xd0,0x07,0x48, +0x07,0x49,0x4f,0xf0,0x00,0x02,0x88,0x42,0xb8,0xbf,0x40,0xf8,0x04,0x2b,0xfa,0xdb, +0x00,0xf0,0xa8,0xf9,0xfe,0xe7,0x00,0x00,0xf0,0x0e,0x00,0x20,0x54,0x13,0x00,0x20, +0xfc,0x13,0x00,0x20,0x08,0xb5,0x07,0x4b,0x07,0x48,0x03,0x33,0x1b,0x1a,0x06,0x2b, +0x04,0xd9,0x06,0x4b,0x00,0x2b,0x01,0xd0,0x00,0xf0,0x5c,0xf8,0x08,0xbc,0x01,0xbc, +0x00,0x47,0xc0,0x46,0x50,0x13,0x00,0x20,0x50,0x13,0x00,0x20,0x00,0x00,0x00,0x00, +0x08,0x48,0x09,0x49,0x09,0x1a,0x89,0x10,0x08,0xb5,0xcb,0x0f,0x59,0x18,0x49,0x10, +0x04,0xd0,0x06,0x4b,0x00,0x2b,0x01,0xd0,0x00,0xf0,0x44,0xf8,0x08,0xbc,0x01,0xbc, +0x00,0x47,0xc0,0x46,0x50,0x13,0x00,0x20,0x50,0x13,0x00,0x20,0x00,0x00,0x00,0x00, +0x10,0xb5,0x08,0x4c,0x23,0x78,0x00,0x2b,0x09,0xd1,0xff,0xf7,0xcb,0xff,0x06,0x4b, +0x00,0x2b,0x02,0xd0,0x05,0x48,0xaf,0xf3,0x00,0x80,0x01,0x23,0x23,0x70,0x10,0xbc, +0x01,0xbc,0x00,0x47,0x54,0x13,0x00,0x20,0x00,0x00,0x00,0x00,0xe0,0x0e,0x00,0x20, +0x08,0xb5,0x0b,0x4b,0x00,0x2b,0x03,0xd0,0x0a,0x48,0x0b,0x49,0xaf,0xf3,0x00,0x80, +0x0a,0x48,0x03,0x68,0x00,0x2b,0x04,0xd1,0xff,0xf7,0xc2,0xff,0x08,0xbc,0x01,0xbc, +0x00,0x47,0x07,0x4b,0x00,0x2b,0xf7,0xd0,0x00,0xf0,0x0c,0xf8,0xf4,0xe7,0xc0,0x46, +0x00,0x00,0x00,0x00,0xe0,0x0e,0x00,0x20,0x58,0x13,0x00,0x20,0x4c,0x13,0x00,0x20, +0x00,0x00,0x00,0x00,0x18,0x47,0xc0,0x46,0xd4,0x30,0x9f,0xe5,0x00,0x00,0x53,0xe3, +0xc8,0x30,0x9f,0x05,0x03,0xd0,0xa0,0xe1,0x00,0x20,0x0f,0xe1,0x0f,0x00,0x12,0xe3, +0x15,0x00,0x00,0x0a,0xd1,0xf0,0x21,0xe3,0x03,0xd0,0xa0,0xe1,0x01,0xaa,0x4d,0xe2, +0x0a,0x30,0xa0,0xe1,0xd7,0xf0,0x21,0xe3,0x03,0xd0,0xa0,0xe1,0x01,0x3a,0x43,0xe2, +0xdb,0xf0,0x21,0xe3,0x03,0xd0,0xa0,0xe1,0x01,0x3a,0x43,0xe2,0xd2,0xf0,0x21,0xe3, +0x03,0xd0,0xa0,0xe1,0x02,0x3a,0x43,0xe2,0xd3,0xf0,0x21,0xe3,0x03,0xd0,0xa0,0xe1, +0x02,0x39,0x43,0xe2,0xff,0x30,0xc3,0xe3,0xff,0x3c,0xc3,0xe3,0x04,0x30,0x03,0xe5, +0x00,0x20,0x53,0xe9,0xc0,0x20,0x82,0xe3,0x02,0xf0,0x21,0xe1,0x01,0xa8,0x43,0xe2, +0x00,0x10,0xb0,0xe3,0x01,0xb0,0xa0,0xe1,0x01,0x70,0xa0,0xe1,0x5c,0x00,0x9f,0xe5, +0x5c,0x20,0x9f,0xe5,0x00,0x20,0x52,0xe0,0x01,0x30,0x8f,0xe2,0x13,0xff,0x2f,0xe1, +0x00,0xf0,0x42,0xfd,0x10,0x4b,0x00,0x2b,0x01,0xd0,0xfe,0x46,0x9f,0x46,0x0f,0x4b, +0x00,0x2b,0x01,0xd0,0xfe,0x46,0x9f,0x46,0x00,0x20,0x00,0x21,0x04,0x00,0x0d,0x00, +0x0d,0x48,0x00,0xf0,0x89,0xfc,0x00,0xf0,0xc3,0xfc,0x20,0x00,0x29,0x00,0x00,0xf0, +0xd1,0xf8,0x00,0xf0,0x8b,0xfc,0x7b,0x46,0x18,0x47,0x00,0x00,0x11,0x00,0x00,0xef, +0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x54,0x13,0x00,0x20,0xfc,0x13,0x00,0x20,0x15,0x0b,0x00,0x20,0x70,0xb5,0x04,0x46, +0x0e,0x46,0x15,0x46,0x00,0x21,0x28,0x22,0x00,0xf0,0x0e,0xfd,0x26,0x61,0x65,0x62, +0x00,0x21,0x84,0x22,0x02,0x48,0x00,0xf0,0x07,0xfd,0x00,0x20,0x70,0xbd,0x00,0xbf, +0x70,0x13,0x00,0x20,0x10,0xb5,0x01,0x20,0x00,0xf0,0xac,0xf9,0x04,0x46,0x28,0xb9, +0x01,0x21,0x84,0x22,0x03,0x48,0x00,0xf0,0xf7,0xfc,0x01,0xe0,0x40,0xf2,0x01,0x14, +0x20,0x46,0x10,0xbd,0x70,0x13,0x00,0x20,0x01,0x39,0xf8,0xb5,0x44,0x0b,0x08,0x44, +0x45,0x0b,0x66,0x03,0xac,0x42,0x14,0xd8,0x0b,0x4f,0xe3,0x5d,0x6b,0xb9,0x30,0x46, +0x00,0xf0,0xfc,0xf8,0x38,0xb1,0x00,0x04,0x00,0xf4,0x7f,0x00,0x40,0xea,0x04,0x60, +0x40,0xf4,0x81,0x70,0xf8,0xbd,0x01,0x23,0xe3,0x55,0x01,0x34,0x06,0xf5,0x00,0x56, +0xe8,0xe7,0x00,0x20,0xf8,0xbd,0x00,0xbf,0x70,0x13,0x00,0x20,0x2d,0xe9,0xf0,0x4f, +0x53,0x1e,0x85,0xb0,0x0b,0x44,0x02,0x90,0x0d,0x46,0x4f,0xea,0x51,0x38,0x5b,0x0b, +0x16,0x46,0x23,0x48,0x01,0x93,0x00,0x21,0x84,0x22,0x00,0xf0,0xbd,0xfc,0x4f,0xea, +0x48,0x37,0xc5,0xf3,0x0c,0x0c,0x4f,0xf0,0x00,0x09,0x01,0x9b,0x98,0x45,0x32,0xd8, +0x74,0x19,0xdf,0xf8,0x70,0xb0,0xcd,0xf8,0x0c,0xc0,0x07,0xf5,0x00,0x5a,0x54,0x45, +0x88,0xbf,0xc4,0xf3,0x0c,0x04,0x39,0x46,0x4f,0xf4,0x00,0x52,0x58,0x46,0x8c,0xbf, +0x34,0x1b,0x34,0x46,0x00,0xf0,0x60,0xfc,0xdd,0xf8,0x0c,0xc0,0x02,0x9b,0x0b,0xeb, +0x0c,0x00,0x03,0xeb,0x09,0x01,0x22,0x46,0x00,0xf0,0x56,0xfc,0x38,0x46,0x4f,0xf4, +0x00,0x51,0x08,0xf1,0x01,0x08,0xff,0xf7,0x9f,0xff,0x68,0xb9,0x39,0x46,0x58,0x46, +0x4f,0xf4,0x00,0x52,0x25,0x44,0x00,0xf0,0xaf,0xf8,0x36,0x1b,0xc5,0xf3,0x0c,0x0c, +0xa1,0x44,0x57,0x46,0xc9,0xe7,0x00,0x20,0x05,0xb0,0xbd,0xe8,0xf0,0x8f,0x00,0xbf, +0x70,0x13,0x00,0x20,0x00,0x60,0x00,0x20,0xb2,0xf5,0x00,0x5f,0xf8,0xb5,0x07,0x46, +0x0e,0x46,0x15,0x46,0x0b,0xd8,0x08,0x46,0x11,0x46,0xff,0xf7,0x7d,0xff,0x04,0x46, +0x40,0xb9,0x38,0x46,0x31,0x46,0x2a,0x46,0x00,0xf0,0x8e,0xf8,0x02,0xe0,0x4f,0xf4, +0x82,0x70,0xf8,0xbd,0x20,0x46,0xf8,0xbd,0x08,0xb5,0x00,0xf0,0x85,0xf8,0x00,0x20, +0x08,0xbd,0x00,0x00,0xf8,0xb5,0x31,0x48,0x31,0x49,0x32,0x4a,0x32,0x4c,0xff,0xf7, +0x3d,0xff,0x00,0x23,0x23,0x60,0x22,0x68,0x2c,0x4f,0x14,0x23,0x03,0xfb,0x02,0x73, +0x08,0x33,0x5b,0x68,0x00,0x2b,0xf7,0xd0,0x2c,0x4b,0x1a,0x68,0x11,0x07,0xfb,0xd4, +0x2b,0x4d,0x2c,0x4e,0x2a,0x68,0x32,0x60,0x42,0xf0,0x33,0x02,0x2a,0x60,0x1a,0x68, +0x12,0x07,0xfc,0xd4,0x21,0x68,0x14,0x22,0x02,0xfb,0x01,0x73,0x98,0x68,0x01,0x38, +0x13,0x46,0x04,0x28,0x26,0xd8,0xdf,0xe8,0x00,0xf0,0x03,0x06,0x0e,0x16,0x1e,0x00, +0xff,0xf7,0x28,0xff,0x20,0xe0,0x4b,0x43,0xfa,0x18,0x10,0x69,0xf9,0x58,0x52,0x68, +0xff,0xf7,0xc2,0xff,0x18,0xe0,0x4b,0x43,0xfa,0x18,0x10,0x69,0xf9,0x58,0x52,0x68, +0xff,0xf7,0xa2,0xff,0x10,0xe0,0x4b,0x43,0xfa,0x18,0x10,0x69,0xf9,0x58,0x52,0x68, +0xff,0xf7,0x44,0xff,0x08,0xe0,0x4b,0x43,0xfa,0x18,0xf8,0x58,0x51,0x68,0xff,0xf7, +0x1b,0xff,0x01,0xe0,0x40,0xf2,0x05,0x10,0x33,0x68,0x2b,0x60,0x0b,0x4b,0x1b,0x68, +0x1b,0x07,0xfb,0xd4,0x22,0x68,0x14,0x23,0x03,0xfb,0x02,0x77,0xfb,0x68,0xf8,0x60, +0x00,0xb1,0xfe,0xe7,0x82,0xf0,0x01,0x02,0x22,0x60,0xa4,0xe7,0xd8,0x1f,0x00,0x20, +0x00,0x20,0x00,0x20,0x00,0x40,0x00,0x20,0xf4,0x13,0x00,0x20,0x00,0x40,0x03,0x40, +0x04,0x40,0x03,0x40,0xf8,0x13,0x00,0x20,0xfe,0xe7,0x00,0x00,0x08,0xb5,0x04,0x4b, +0x1b,0x68,0x5b,0x69,0x98,0x47,0x03,0x4b,0x00,0x22,0x1a,0x60,0x08,0xbd,0x00,0xbf, +0xa8,0x01,0x00,0x10,0x84,0x04,0x60,0x42,0x08,0xb5,0x04,0x4b,0x1b,0x68,0x9b,0x69, +0x98,0x47,0x03,0x4b,0x00,0x22,0x1a,0x60,0x08,0xbd,0x00,0xbf,0xa8,0x01,0x00,0x10, +0x84,0x04,0x60,0x42,0x10,0xb5,0x33,0x4b,0x33,0x48,0x1b,0x68,0x33,0x4a,0x13,0xf0, +0x02,0x0f,0x03,0x68,0x43,0xf0,0x02,0x03,0x03,0x60,0x13,0x68,0x01,0x68,0x19,0xd0, +0x21,0xf4,0xe1,0x72,0xc3,0xf3,0xc1,0x04,0x22,0xf0,0x01,0x02,0x22,0x43,0xc3,0xf3, +0xc0,0x11,0x42,0xea,0x01,0x22,0xc3,0xf3,0x41,0x11,0x42,0xea,0x81,0x12,0x02,0x60, +0x02,0x68,0xd4,0x07,0x03,0xd5,0x26,0x4a,0x12,0x68,0x50,0x07,0xfb,0xd5,0x03,0xf0, +0x07,0x03,0x18,0xe0,0x21,0xf4,0xe1,0x72,0xc3,0xf3,0xc1,0x24,0x22,0xf0,0x01,0x02, +0xc3,0xf3,0xc0,0x31,0x22,0x43,0x42,0xea,0x01,0x22,0xc3,0xf3,0x41,0x31,0x42,0xea, +0x81,0x12,0x02,0x60,0x02,0x68,0xd1,0x07,0x03,0xd5,0x19,0x4a,0x12,0x68,0x52,0x07, +0xfb,0xd5,0xc3,0xf3,0x02,0x23,0x17,0x49,0x17,0x48,0x4a,0xf6,0xaa,0x22,0x0a,0x60, +0x02,0x68,0x1b,0x03,0xb3,0xf5,0xe0,0x4f,0x22,0xf4,0xe2,0x42,0x18,0xbf,0x43,0xf4, +0x80,0x73,0x13,0x43,0x03,0x60,0x45,0xf2,0xaa,0x53,0x0b,0x60,0x0f,0x4b,0x10,0x49, +0x01,0x22,0x1a,0x60,0x00,0x22,0x0a,0x60,0x1a,0x60,0x05,0x22,0xc3,0xf8,0x58,0x22, +0x4f,0xf0,0xff,0x32,0xc1,0xf8,0x8c,0x22,0xc1,0xf8,0x90,0x22,0x02,0x22,0xc3,0xf8, +0x58,0x22,0x10,0xbd,0x10,0x00,0x09,0x40,0x24,0x00,0x03,0x40,0x08,0x13,0x00,0x50, +0x1c,0x00,0x03,0x40,0x64,0x20,0x03,0x40,0xa8,0x20,0x03,0x40,0x30,0x20,0x03,0x40, +0x34,0x20,0x03,0x40,0x2d,0xe9,0xf8,0x4f,0xd4,0x4d,0x29,0x68,0x11,0xf0,0x01,0x01, +0x40,0xf0,0x95,0x81,0xdf,0xf8,0x90,0xe3,0xd1,0x4b,0xdf,0xf8,0x90,0xc3,0xdf,0xf8, +0x90,0x83,0xdf,0xf8,0x90,0x93,0x05,0x27,0xce,0xf8,0x00,0x70,0x1b,0x68,0xc3,0xf3, +0x03,0x23,0x4f,0xf4,0x40,0x72,0x01,0x33,0xb2,0xfb,0xf3,0xf3,0xdc,0xf8,0x00,0x20, +0xd8,0xf8,0x00,0x40,0x92,0xb2,0x5a,0x43,0xc2,0xf3,0x8f,0x16,0x22,0x0c,0x12,0x04, +0x32,0x43,0xc8,0xf8,0x00,0x20,0xc3,0x4a,0xc3,0x4c,0x12,0x68,0x26,0x68,0xc3,0x4e, +0x5a,0x43,0x92,0x09,0x22,0x60,0x32,0x68,0x54,0xf8,0x24,0x8c,0xc2,0xf3,0x07,0x42, +0x5a,0x43,0x28,0xf0,0xff,0x08,0xc2,0xf3,0x87,0x12,0x42,0xea,0x08,0x02,0xdf,0xf8, +0x38,0x83,0x44,0xf8,0x24,0x2c,0xd9,0xf8,0x00,0xa0,0xd8,0xf8,0x00,0x20,0xca,0xf3, +0x07,0x4a,0x22,0xf0,0xff,0x02,0x4a,0xea,0x02,0x02,0xc8,0xf8,0x00,0x20,0xd9,0xf8, +0x00,0x20,0xdf,0xf8,0x18,0xa3,0x12,0x0e,0xda,0xf8,0x00,0x80,0x5a,0x43,0x92,0x00, +0x28,0xf4,0x7f,0x48,0x02,0xf4,0x7f,0x42,0x42,0xea,0x08,0x02,0xdf,0xf8,0x00,0x83, +0xca,0xf8,0x00,0x20,0xd8,0xf8,0x00,0x20,0x4f,0xea,0x12,0x6b,0xda,0xf8,0x04,0x20, +0x0b,0xfb,0x03,0xfb,0x12,0x0c,0xcb,0xf3,0x8f,0x1b,0x12,0x04,0x4b,0xea,0x02,0x02, +0xca,0xf8,0x04,0x20,0xd9,0xf8,0x00,0x20,0xc2,0xf3,0x07,0x22,0x53,0x43,0xa0,0x4a, +0xd2,0xf8,0x00,0x90,0x9b,0x00,0x29,0xf4,0x7f,0x49,0x03,0xf4,0x7f,0x43,0x43,0xea, +0x09,0x03,0xdf,0xf8,0xc0,0x92,0x13,0x60,0xd9,0xf8,0x00,0xa0,0x52,0xf8,0x24,0x3c, +0x4f,0xea,0x1a,0x6a,0x23,0xf4,0x7f,0x43,0x43,0xea,0x0a,0x23,0x42,0xf8,0x24,0x3c, +0xd9,0xf8,0x00,0xa0,0x52,0xf8,0x24,0x3c,0xca,0xf3,0x07,0x4a,0x23,0xf0,0xff,0x03, +0x4a,0xea,0x03,0x03,0x42,0xf8,0x24,0x3c,0xd9,0xf8,0x00,0xa0,0x52,0xf8,0x1c,0x3c, +0x0a,0xf4,0x7f,0x4a,0x23,0xf4,0x7f,0x43,0x4a,0xea,0x03,0x03,0x42,0xf8,0x1c,0x3c, +0xd9,0xf8,0x00,0x90,0x52,0xf8,0x1c,0x3c,0x5f,0xfa,0x89,0xf9,0x23,0xf0,0xff,0x03, +0x49,0xea,0x03,0x03,0xdf,0xf8,0x60,0x92,0x42,0xf8,0x1c,0x3c,0x32,0x68,0xd9,0xf8, +0x00,0x30,0x02,0xf4,0x70,0x42,0x23,0xf4,0x70,0x43,0x13,0x43,0xc9,0xf8,0x00,0x30, +0xd8,0xf8,0x00,0x20,0xdf,0xf8,0x44,0x82,0xd8,0xf8,0x00,0x30,0x02,0xf4,0x70,0x42, +0x23,0xf4,0x70,0x43,0x13,0x43,0xc8,0xf8,0x00,0x30,0x32,0x68,0x54,0xf8,0x24,0x3c, +0x12,0x0e,0x23,0xf4,0x7f,0x43,0x43,0xea,0x02,0x23,0x44,0xf8,0x24,0x3c,0x71,0x4b, +0x1b,0x68,0x62,0x6a,0xc3,0xf3,0x0b,0x06,0x22,0xf4,0x7f,0x63,0x23,0xf0,0x0f,0x03, +0x33,0x43,0x6d,0x4e,0x63,0x62,0x32,0x68,0x63,0x6a,0x02,0xf4,0x70,0x22,0x23,0xf4, +0x70,0x23,0x13,0x43,0x63,0x62,0x69,0x4c,0x22,0x68,0xd8,0xf8,0x58,0x30,0xc2,0xf3, +0x83,0x42,0x23,0xf4,0x70,0x23,0x43,0xea,0x02,0x43,0xc8,0xf8,0x58,0x30,0xdc,0xf8, +0x00,0x30,0xd8,0xf8,0x58,0x20,0xc3,0xf3,0x0b,0x4c,0x22,0xf4,0x7f,0x63,0x23,0xf0, +0x0f,0x03,0x4c,0xea,0x03,0x03,0xc8,0xf8,0x58,0x30,0x23,0x68,0xd8,0xf8,0x5c,0x20, +0x4f,0xea,0xd3,0x5c,0x22,0xf0,0xff,0x73,0x23,0xf4,0x80,0x33,0x43,0xea,0x0c,0x43, +0xc8,0xf8,0x5c,0x30,0x33,0x68,0x56,0x4a,0xdf,0xf8,0xa4,0xc1,0x0f,0x33,0x03,0xf0, +0x0f,0x03,0x13,0x60,0x26,0x68,0x53,0x68,0xc6,0xf3,0x80,0x56,0x23,0xf4,0x00,0x03, +0x43,0xea,0xc6,0x53,0x53,0x60,0x53,0x68,0x4e,0x4e,0x43,0xf4,0x80,0x43,0x53,0x60, +0x02,0x23,0xce,0xf8,0x00,0x30,0xae,0xf5,0x09,0x7e,0x4a,0xf6,0xaa,0x23,0xce,0xf8, +0x00,0x30,0xdc,0xf8,0x00,0x30,0x32,0x68,0x03,0xf0,0x0f,0x08,0x22,0xf4,0x7f,0x02, +0x42,0xea,0x08,0x42,0xc3,0xf3,0x03,0x23,0x42,0xea,0x03,0x53,0xdf,0xf8,0x54,0x81, +0x33,0x60,0xd8,0xf8,0x00,0x30,0x32,0x68,0xc3,0xf3,0x03,0x49,0x22,0xf0,0xff,0x02, +0x49,0xea,0x02,0x02,0xc3,0xf3,0x03,0x63,0x42,0xea,0x03,0x13,0x33,0x60,0xdc,0xf8, +0x00,0x60,0xdf,0xf8,0x34,0xc1,0xdc,0xf8,0x00,0x30,0x06,0xf4,0x70,0x22,0x23,0xf4, +0x7f,0x03,0x1a,0x43,0xc6,0xf3,0x03,0x63,0x42,0xea,0x03,0x53,0x32,0x4e,0xcc,0xf8, +0x00,0x30,0x32,0x68,0x5c,0xf8,0x08,0x3c,0xc2,0xf3,0x03,0x22,0x23,0xf0,0x0f,0x03, +0x13,0x43,0x4c,0xf8,0x08,0x3c,0xd8,0xf8,0x00,0x20,0xdc,0xf8,0x08,0x30,0x02,0xf4, +0xf8,0x52,0x23,0xf4,0xf8,0x53,0x13,0x43,0xcc,0xf8,0x08,0x30,0x32,0x68,0xdc,0xf8, +0x0c,0x30,0x12,0x0b,0x02,0xf4,0x70,0x42,0x23,0xf4,0x70,0x43,0x13,0x43,0xcc,0xf8, +0x0c,0x30,0x32,0x68,0x21,0x4e,0x33,0x68,0xc2,0xf3,0x04,0x42,0x23,0xf0,0x1f,0x03, +0x13,0x43,0x33,0x60,0x22,0x68,0x1e,0x4c,0x23,0x68,0xc2,0xf3,0x01,0x42,0x23,0xf4, +0x40,0x13,0x43,0xea,0x02,0x53,0x1b,0x4a,0x23,0x60,0x45,0xf2,0xaa,0x53,0xce,0xf8, +0x00,0x30,0x17,0x60,0x2b,0x68,0x43,0xf0,0x01,0x03,0x2b,0x60,0x11,0x60,0x16,0x4b, +0x16,0x4c,0x1b,0x68,0x16,0x4a,0x17,0x4d,0x13,0xf0,0x02,0x0f,0x23,0x68,0x43,0xf0, +0x02,0x03,0x23,0x60,0x13,0x68,0x21,0x68,0x59,0xd0,0x3f,0xe0,0x40,0x00,0x03,0x40, +0x00,0x20,0x03,0x40,0x8c,0x11,0x00,0x50,0x44,0x22,0x03,0x40,0x74,0x11,0x00,0x50, +0x34,0x22,0x03,0x40,0x84,0x11,0x00,0x50,0x80,0x11,0x00,0x50,0xb0,0x12,0x00,0x50, +0x78,0x22,0x03,0x40,0x84,0x20,0x03,0x40,0x98,0x11,0x00,0x50,0x98,0x20,0x03,0x40, +0xa8,0x20,0x03,0x40,0x3c,0x00,0x03,0x40,0x10,0x00,0x09,0x40,0x24,0x00,0x03,0x40, +0x08,0x13,0x00,0x50,0x1c,0x00,0x03,0x40,0x88,0x22,0x03,0x40,0x88,0x11,0x00,0x50, +0x40,0x22,0x03,0x40,0x78,0x11,0x00,0x50,0x24,0x22,0x03,0x40,0x28,0x22,0x03,0x40, +0x7c,0x11,0x00,0x50,0x70,0x11,0x00,0x50,0x1c,0x22,0x03,0x40,0x14,0x22,0x03,0x40, +0x90,0x11,0x00,0x50,0x94,0x11,0x00,0x50,0x88,0x20,0x03,0x40,0x21,0xf4,0xe1,0x72, +0xc3,0xf3,0xc1,0x46,0x22,0xf0,0x01,0x02,0xc3,0xf3,0xc0,0x51,0x32,0x43,0x42,0xea, +0x01,0x22,0xc3,0xf3,0x41,0x51,0x42,0xea,0x81,0x12,0x22,0x60,0x22,0x68,0xd7,0x07, +0x02,0xd5,0x2a,0x68,0x56,0x07,0xfc,0xd5,0xc3,0xf3,0x02,0x43,0x16,0xe0,0xc3,0xf3, +0xc1,0x62,0xde,0x0f,0x42,0xea,0x06,0x26,0x21,0xf4,0xe1,0x72,0x22,0xf0,0x01,0x02, +0x32,0x43,0xc3,0xf3,0x41,0x71,0x42,0xea,0x81,0x12,0x22,0x60,0x22,0x68,0xd4,0x07, +0x02,0xd5,0x2a,0x68,0x51,0x07,0xfc,0xd5,0xc3,0xf3,0x02,0x63,0x3b,0x49,0x3c,0x4c, +0x4a,0xf6,0xaa,0x22,0x0a,0x60,0x22,0x68,0x1b,0x03,0xb3,0xf5,0xe0,0x4f,0x22,0xf4, +0xe2,0x42,0x18,0xbf,0x43,0xf4,0x80,0x73,0x13,0x43,0x23,0x60,0x45,0xf2,0xaa,0x53, +0x0b,0x60,0x34,0x4b,0x00,0x21,0x01,0x22,0x19,0x60,0x43,0xf8,0x20,0x2c,0x32,0x4a, +0x4f,0xf6,0xff,0x74,0x14,0x60,0x31,0x4c,0x43,0xf8,0x20,0x1c,0x02,0xf5,0xec,0x72, +0x4f,0xf0,0x05,0x0e,0x10,0x23,0xc4,0xf8,0x00,0xe0,0x13,0x60,0x2c,0x4b,0x15,0x26, +0x1e,0x60,0x02,0x26,0x26,0x60,0x2b,0x4e,0x37,0x68,0xc4,0xf8,0x00,0xe0,0xdf,0xf8, +0xb4,0xe0,0xce,0xf8,0x00,0x10,0xce,0xf8,0x04,0x10,0x18,0xb1,0x31,0x68,0x41,0xf4, +0x00,0x01,0x31,0x60,0x02,0x21,0x05,0x20,0x21,0x60,0x20,0x60,0x08,0x20,0x10,0x60, +0x15,0x22,0x1a,0x60,0x21,0x60,0x2b,0x68,0x9a,0x07,0xfc,0xd4,0x1e,0x4b,0x1b,0x68, +0x13,0xf0,0x10,0x0f,0x14,0xbf,0x04,0x25,0x00,0x25,0xff,0xf7,0x1b,0xfd,0x3b,0x02, +0x07,0xd4,0x05,0x23,0x23,0x60,0x33,0x68,0x23,0xf4,0x00,0x03,0x33,0x60,0x02,0x23, +0x23,0x60,0xc5,0xb9,0x15,0x4b,0x16,0x48,0x19,0x68,0x03,0xf5,0x10,0x53,0x04,0x33, +0x1a,0x68,0x1b,0x68,0x02,0xf0,0x0f,0x02,0xc9,0xb2,0x03,0xf0,0x0f,0x03,0x51,0x43, +0x9b,0x02,0xc3,0xeb,0x81,0x21,0x01,0xf5,0xfe,0x51,0x18,0x31,0x14,0x22,0xbd,0xe8, +0xf8,0x4f,0xff,0xf7,0xe9,0xbc,0x28,0x46,0xbd,0xe8,0xf8,0x8f,0x64,0x20,0x03,0x40, +0xa8,0x20,0x03,0x40,0x50,0x20,0x03,0x40,0x34,0x20,0x03,0x40,0x88,0x22,0x03,0x40, +0xb4,0x22,0x03,0x40,0x7c,0x22,0x03,0x40,0x54,0x20,0x03,0x40,0x2c,0x00,0x03,0x40, +0xf4,0x0e,0x00,0x20,0xc0,0x22,0x03,0x40,0x08,0xb5,0x01,0x1c,0x00,0x22,0x00,0x20, +0x00,0x23,0x00,0xf0,0xeb,0xf8,0x08,0xbc,0x02,0xbc,0x08,0x47,0x10,0xb5,0x00,0x21, +0x04,0x1c,0x00,0xf0,0x5d,0xf9,0x05,0x4b,0x18,0x68,0xc3,0x6b,0x00,0x2b,0x01,0xd0, +0x00,0xf0,0x06,0xf8,0x20,0x1c,0xff,0xf7,0xa7,0xfc,0xc0,0x46,0x0c,0x0f,0x00,0x20, +0x18,0x47,0xc0,0x46,0x38,0xb5,0x0a,0x4b,0x0a,0x4c,0xe4,0x1a,0xa4,0x10,0x0a,0xd0, +0x09,0x4a,0xa5,0x18,0xad,0x00,0xed,0x18,0x2b,0x68,0x01,0x3c,0x00,0xf0,0x0e,0xf8, +0x04,0x3d,0x00,0x2c,0xf8,0xd1,0x00,0xf0,0xcd,0xf9,0x38,0xbc,0x01,0xbc,0x00,0x47, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0x3f,0x18,0x47,0xc0,0x46, +0x70,0xb5,0x10,0x4e,0x10,0x4d,0xad,0x1b,0xad,0x10,0x00,0x24,0x00,0x2d,0x06,0xd0, +0xa3,0x00,0xf3,0x58,0x01,0x34,0x00,0xf0,0x1d,0xf8,0xa5,0x42,0xf8,0xd1,0x00,0xf0, +0xab,0xf9,0x0a,0x4e,0x0a,0x4d,0xad,0x1b,0xad,0x10,0x00,0x24,0x00,0x2d,0x06,0xd0, +0xa3,0x00,0xf3,0x58,0x01,0x34,0x00,0xf0,0x0d,0xf8,0xa5,0x42,0xf8,0xd1,0x70,0xbc, +0x01,0xbc,0x00,0x47,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x18,0x47,0xc0,0x46,0x70,0xb5,0x0f,0x2a,0x34,0xd9,0x04,0x1c, +0x0c,0x43,0x0b,0x1c,0xa4,0x07,0x33,0xd1,0x15,0x1c,0x04,0x1c,0x10,0x3d,0x2d,0x09, +0x01,0x35,0x2d,0x01,0x49,0x19,0x1e,0x68,0x26,0x60,0x5e,0x68,0x66,0x60,0x9e,0x68, +0xa6,0x60,0xde,0x68,0x10,0x33,0xe6,0x60,0x10,0x34,0x99,0x42,0xf3,0xd1,0x0f,0x23, +0x45,0x19,0x13,0x40,0x03,0x2b,0x1d,0xd9,0x1c,0x1f,0x00,0x23,0xa4,0x08,0x01,0x34, +0xa4,0x00,0xce,0x58,0xee,0x50,0x04,0x33,0xa3,0x42,0xfa,0xd1,0xed,0x18,0xc9,0x18, +0x03,0x23,0x1a,0x40,0x05,0xd0,0x00,0x23,0xcc,0x5c,0xec,0x54,0x01,0x33,0x93,0x42, +0xfa,0xd1,0x70,0xbc,0x02,0xbc,0x08,0x47,0x05,0x1c,0x00,0x2a,0xf3,0xd1,0xf8,0xe7, +0x05,0x1c,0xf0,0xe7,0x1a,0x1c,0xf8,0xe7,0x70,0xb5,0x83,0x07,0x43,0xd0,0x54,0x1e, +0x00,0x2a,0x3d,0xd0,0x0d,0x06,0x2d,0x0e,0x03,0x1c,0x03,0x26,0x03,0xe0,0x62,0x1e, +0x00,0x2c,0x35,0xd0,0x14,0x1c,0x01,0x33,0x5a,0x1e,0x15,0x70,0x33,0x42,0xf6,0xd1, +0x03,0x2c,0x24,0xd9,0xff,0x25,0x0d,0x40,0x2a,0x02,0x15,0x43,0x2a,0x04,0x15,0x43, +0x0f,0x2c,0x11,0xd9,0x26,0x1c,0x10,0x3e,0x36,0x09,0x01,0x36,0x36,0x01,0x1a,0x1c, +0x9b,0x19,0x15,0x60,0x55,0x60,0x95,0x60,0xd5,0x60,0x10,0x32,0x93,0x42,0xf8,0xd1, +0x0f,0x22,0x14,0x40,0x03,0x2c,0x0a,0xd9,0x26,0x1f,0xb6,0x08,0x01,0x36,0xb6,0x00, +0x1a,0x1c,0x9b,0x19,0x20,0xc2,0x93,0x42,0xfc,0xd1,0x03,0x22,0x14,0x40,0x00,0x2c, +0x06,0xd0,0x09,0x06,0x1c,0x19,0x09,0x0e,0x19,0x70,0x01,0x33,0xa3,0x42,0xfb,0xd1, +0x70,0xbc,0x02,0xbc,0x08,0x47,0x14,0x1c,0x03,0x1c,0xc9,0xe7,0xf8,0xb5,0x44,0x46, +0x5f,0x46,0x56,0x46,0x4d,0x46,0x9b,0x46,0x30,0x4b,0xf0,0xb4,0x1c,0x68,0xa4,0x23, +0x5b,0x00,0x05,0x1c,0xe0,0x58,0x0e,0x1c,0x90,0x46,0x00,0x28,0x4d,0xd0,0x43,0x68, +0x1f,0x2b,0x0f,0xdc,0x5c,0x1c,0x00,0x2d,0x23,0xd1,0x02,0x33,0x9b,0x00,0x44,0x60, +0x1e,0x50,0x00,0x20,0x3c,0xbc,0x90,0x46,0x99,0x46,0xa2,0x46,0xab,0x46,0xf8,0xbc, +0x02,0xbc,0x08,0x47,0x22,0x4b,0x00,0x2b,0x3c,0xd0,0xc8,0x20,0x40,0x00,0xaf,0xf3, +0x00,0x80,0x00,0x28,0x36,0xd0,0xa4,0x22,0x00,0x23,0x52,0x00,0xa1,0x58,0x43,0x60, +0x01,0x60,0xa0,0x50,0x40,0x32,0x83,0x50,0x04,0x32,0x83,0x50,0x01,0x24,0x00,0x2d, +0xdb,0xd0,0x9a,0x00,0x91,0x46,0x81,0x44,0x42,0x46,0x88,0x21,0x4f,0x46,0x7a,0x50, +0xc4,0x22,0x52,0x00,0x90,0x46,0x80,0x44,0x42,0x46,0x87,0x39,0x99,0x40,0x12,0x68, +0x0a,0x43,0x94,0x46,0x8a,0x46,0x42,0x46,0x61,0x46,0x11,0x60,0x84,0x22,0x49,0x46, +0x5f,0x46,0x52,0x00,0x8f,0x50,0x02,0x2d,0xbf,0xd1,0x02,0x1c,0x55,0x46,0x8d,0x32, +0xff,0x32,0x11,0x68,0x0d,0x43,0x15,0x60,0xb7,0xe7,0x20,0x1c,0x4d,0x30,0xff,0x30, +0xe0,0x50,0xac,0xe7,0x01,0x20,0x40,0x42,0xb4,0xe7,0xc0,0x46,0x0c,0x0f,0x00,0x20, +0x00,0x00,0x00,0x00,0x08,0xb5,0x04,0x4b,0x00,0x2b,0x02,0xd0,0x03,0x48,0xff,0xf7, +0x9b,0xfe,0x08,0xbc,0x01,0xbc,0x00,0x47,0x00,0x00,0x00,0x00,0x15,0x0b,0x00,0x20, +0xf0,0xb5,0x56,0x46,0x5f,0x46,0x4d,0x46,0x44,0x46,0xf0,0xb4,0x0e,0x1c,0x3f,0x4b, +0x1b,0x68,0x87,0xb0,0x03,0x93,0x49,0x33,0xff,0x33,0x01,0x90,0x04,0x93,0xa4,0x22, +0x03,0x9b,0x52,0x00,0x9f,0x58,0x00,0x2f,0x4d,0xd0,0x04,0x9b,0x98,0x46,0x00,0x23, +0x9b,0x46,0xc4,0x23,0x5b,0x00,0x9c,0x46,0xbc,0x44,0x63,0x46,0x02,0x93,0xc6,0x23, +0x5b,0x00,0x9a,0x46,0x7c,0x68,0xa5,0x00,0x7d,0x19,0xba,0x44,0x01,0x3c,0x08,0xd5, +0x27,0xe0,0x6b,0x1d,0xff,0x33,0x1b,0x68,0xb3,0x42,0x04,0xd0,0x04,0x3d,0x01,0x3c, +0x1f,0xd3,0x00,0x2e,0xf5,0xd1,0x7b,0x68,0x01,0x3b,0x6a,0x68,0xa3,0x42,0x3e,0xd0, +0x5b,0x46,0x6b,0x60,0x00,0x2a,0xf1,0xd0,0x7b,0x68,0x99,0x46,0x01,0x23,0xa3,0x40, +0x02,0x99,0x09,0x68,0x05,0x91,0x19,0x42,0x26,0xd1,0x00,0xf0,0x43,0xf8,0x7b,0x68, +0x4b,0x45,0xc4,0xd1,0x43,0x46,0x1b,0x68,0xbb,0x42,0xc0,0xd1,0x04,0x3d,0x01,0x3c, +0xdf,0xd2,0x1b,0x4b,0x00,0x2b,0x0e,0xd0,0x7b,0x68,0x00,0x2b,0x27,0xd1,0x3b,0x68, +0x00,0x2b,0x28,0xd0,0x42,0x46,0x38,0x1c,0x13,0x60,0xaf,0xf3,0x00,0x80,0x43,0x46, +0x1f,0x68,0x00,0x2f,0xb5,0xd1,0x07,0xb0,0x3c,0xbc,0x90,0x46,0x99,0x46,0xa2,0x46, +0xab,0x46,0xf0,0xbc,0x01,0xbc,0x00,0x47,0x51,0x46,0x09,0x68,0x19,0x42,0x08,0xd1, +0x2b,0x1c,0x84,0x33,0x19,0x68,0x01,0x98,0x00,0xf0,0x14,0xf8,0xcf,0xe7,0x7c,0x60, +0xc0,0xe7,0x2b,0x1c,0x84,0x33,0x18,0x68,0x00,0xf0,0x0c,0xf8,0xc7,0xe7,0x3b,0x68, +0xb8,0x46,0x1f,0x1c,0xdd,0xe7,0x00,0x23,0xfa,0xe7,0xc0,0x46,0x0c,0x0f,0x00,0x20, +0x00,0x00,0x00,0x00,0x10,0x47,0xc0,0x46,0xf8,0xb5,0xc0,0x46,0xf8,0xbc,0x08,0xbc, +0x9e,0x46,0x70,0x47,0xf8,0xb5,0xc0,0x46,0xf8,0xbc,0x08,0xbc,0x9e,0x46,0x70,0x47, +0x00,0x00,0x00,0x00,0x24,0xf2,0xff,0x7f,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x8c,0x15,0x00,0x20,0xff,0xff,0xff,0xc5,0xff,0xff,0xff,0xff,0xc5,0xff,0xff,0xff, +0xc5,0xc5,0xc5,0xff,0xc5,0xc5,0xc5,0xff,0x43,0x00,0x00,0x00,0x18,0x0f,0x00,0x20, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x12,0x00,0x20, +0x6c,0x12,0x00,0x20,0xd4,0x12,0x00,0x20,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,0x08,0x0f,0x00,0x20, +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,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, +0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0x33,0xcd,0xab,0x34,0x12,0x6d,0xe6, +0xec,0xde,0x05,0x00,0x0b,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,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,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, +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,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,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,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,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,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,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,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,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,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,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,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,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x18,0x0f,0x00,0x20,0xc1,0x00,0x00,0x20,0x91,0x00,0x00,0x20,0x00,0x00,0x00,0x00, +0x95,0x0d,0x00,0x20,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,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,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,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,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,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,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,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,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,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,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,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, +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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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, +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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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, +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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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, +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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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, +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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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, +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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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, +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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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, +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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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, +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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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, +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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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, +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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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, +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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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, +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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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, +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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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, +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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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, +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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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, +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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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, +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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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, +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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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, +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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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, +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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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, +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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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, +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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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, +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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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, +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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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, +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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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, +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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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, +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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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, +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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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, +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,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,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,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,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,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,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,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,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,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,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,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,0x00,0x00,0x00,0x00, diff --git a/contrib/loaders/flash/cc26xx/flash.c b/contrib/loaders/flash/cc26xx/flash.c new file mode 100644 index 0000000..c19cb73 --- /dev/null +++ b/contrib/loaders/flash/cc26xx/flash.c @@ -0,0 +1,977 @@ +/****************************************************************************** +* +* Copyright (C) 2016-2018 Texas Instruments Incorporated - http://www.ti.com/ +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the +* distribution. +* +* Neither the name of Texas Instruments Incorporated nor the names of +* its contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +******************************************************************************/ + +#include <stdint.h> +#include <stdbool.h> +#include "flash.h" + +/****************************************************************************** +* +* Defines for accesses to the security control in the customer configuration +* area in flash top sector. +* +******************************************************************************/ +#define CCFG_OFFSET_SECURITY CCFG_O_BL_CONFIG +#define CCFG_SIZE_SECURITY 0x00000014 + +/****************************************************************************** +* +* Default values for security control in customer configuration area in flash +* top sector. +* +******************************************************************************/ +const uint8_t g_ccfg_default_sec[] = { + 0xFF, 0xFF, 0xFF, 0xC5, + 0xFF, 0xFF, 0xFF, 0xFF, + 0xC5, 0xFF, 0xFF, 0xFF, + 0xC5, 0xC5, 0xC5, 0xFF, + 0xC5, 0xC5, 0xC5, 0xFF +}; + +typedef uint32_t (*flash_prg_pntr_t) (uint8_t *, uint32_t, uint32_t); +typedef uint32_t (*flash_sector_erase_pntr_t) (uint32_t); + +/****************************************************************************** +* +* Function prototypes for static functions +* +******************************************************************************/ +static void issue_fsm_command(flash_state_command_t command); +static void enable_sectors_for_write(void); +static uint32_t scale_cycle_values(uint32_t specified_timing, + uint32_t scale_value); +static void set_write_mode(void); +static void trim_for_write(void); +static void set_read_mode(void); + +/****************************************************************************** +* +* Erase a flash sector +* +******************************************************************************/ +uint32_t flash_sector_erase(uint32_t sector_address) +{ + uint32_t error_return; + flash_sector_erase_pntr_t func_pntr; + + /* Call ROM function */ + func_pntr = (uint32_t (*)(uint32_t))(ROM_API_FLASH_TABLE[5]); + error_return = func_pntr(sector_address); + + /* Enable standby because ROM function might have disabled it */ + HWREGBITW(FLASH_BASE + FLASH_O_CFG, FLASH_CFG_DIS_STANDBY_BITN) = 0; + + /* Return status of operation. */ + return error_return; +} + +/****************************************************************************** +* +* Erase all unprotected sectors in the flash main bank +* +******************************************************************************/ +uint32_t flash_bank_erase(bool force_precondition) +{ + uint32_t error_return; + uint32_t sector_address; + uint32_t reg_val; + + /* Enable all sectors for erase. */ + enable_sectors_for_write(); + + /* Clear the Status register. */ + issue_fsm_command(FAPI_CLEAR_STATUS); + + /* Enable erase of all sectors and enable precondition if required. */ + reg_val = HWREG(FLASH_BASE + FLASH_O_FSM_ST_MACHINE); + HWREG(FLASH_BASE + FLASH_O_FSM_WR_ENA) = FSM_REG_WRT_ENABLE; + HWREG(FLASH_BASE + FLASH_O_FSM_SECTOR1) = 0x00000000; + HWREG(FLASH_BASE + FLASH_O_FSM_SECTOR2) = 0x00000000; + if (force_precondition) + HWREG(FLASH_BASE + FLASH_O_FSM_ST_MACHINE) |= + FLASH_FSM_ST_MACHINE_DO_PRECOND; + HWREG(FLASH_BASE + FLASH_O_FSM_WR_ENA) = FSM_REG_WRT_DISABLE; + + /* Issue the bank erase command to the FSM. */ + issue_fsm_command(FAPI_ERASE_BANK); + + /* Wait for erase to finish. */ + while (flash_check_fsm_for_ready() == FAPI_STATUS_FSM_BUSY) + ; + + /* Update status. */ + error_return = flash_check_fsm_for_error(); + + /* Disable sectors for erase. */ + flash_disable_sectors_for_write(); + + /* Set configured precondition mode since it may have been forced on. */ + if (!(reg_val & FLASH_FSM_ST_MACHINE_DO_PRECOND)) { + HWREG(FLASH_BASE + FLASH_O_FSM_WR_ENA) = FSM_REG_WRT_ENABLE; + HWREG(FLASH_BASE + FLASH_O_FSM_ST_MACHINE) &= + ~FLASH_FSM_ST_MACHINE_DO_PRECOND; + HWREG(FLASH_BASE + FLASH_O_FSM_WR_ENA) = FSM_REG_WRT_DISABLE; + } + + /* Program security data to default values in the customer configuration */ + /* area within the flash top sector if erase was successful. */ + if (error_return == FAPI_STATUS_SUCCESS) { + sector_address = FLASHMEM_BASE + flash_size_get() - + flash_sector_size_get(); + error_return = flash_program((uint8_t *)g_ccfg_default_sec, + (sector_address + CCFG_OFFSET_SECURITY), + CCFG_SIZE_SECURITY); + } + + /* Return status of operation. */ + return error_return; +} + +/****************************************************************************** +* +* Programs unprotected main bank flash sectors +* +******************************************************************************/ +uint32_t flash_program(uint8_t *data_buffer, uint32_t address, uint32_t count) +{ + uint32_t error_return; + flash_prg_pntr_t func_pntr; + + /* Call ROM function */ + func_pntr = (uint32_t (*)(uint8_t *, uint32_t, uint32_t)) + (ROM_API_FLASH_TABLE[6]); + error_return = func_pntr(data_buffer, address, count); + + /* Enable standby because ROM function might have disabled it */ + HWREGBITW(FLASH_BASE + FLASH_O_CFG, FLASH_CFG_DIS_STANDBY_BITN) = 0; + + /* Return status of operation. */ + return error_return; +} + +/****************************************************************************** +* +* Disables all sectors for erase and programming on the active bank +* +******************************************************************************/ +void flash_disable_sectors_for_write(void) +{ + /* Configure flash back to read mode */ + set_read_mode(); + + /* Disable Level 1 Protection. */ + HWREG(FLASH_BASE + FLASH_O_FBPROT) = FLASH_FBPROT_PROTL1DIS; + + /* Disable all sectors for erase and programming. */ + HWREG(FLASH_BASE + FLASH_O_FBSE) = 0x0000; + + /* Enable Level 1 Protection. */ + HWREG(FLASH_BASE + FLASH_O_FBPROT) = 0; + + /* Protect sectors from sector erase. */ + HWREG(FLASH_BASE + FLASH_O_FSM_WR_ENA) = FSM_REG_WRT_ENABLE; + HWREG(FLASH_BASE + FLASH_O_FSM_SECTOR1) = 0xFFFFFFFF; + HWREG(FLASH_BASE + FLASH_O_FSM_SECTOR2) = 0xFFFFFFFF; + HWREG(FLASH_BASE + FLASH_O_FSM_WR_ENA) = FSM_REG_WRT_DISABLE; +} + +/****************************************************************************** +* +* Issues a command to the Flash State Machine. +* +******************************************************************************/ +static void issue_fsm_command(flash_state_command_t command) +{ + /* Enable write to FSM register. */ + HWREG(FLASH_BASE + FLASH_O_FSM_WR_ENA) = FSM_REG_WRT_ENABLE; + + /* Issue FSM command. */ + HWREG(FLASH_BASE + FLASH_O_FSM_CMD) = command; + + /* Start command execute. */ + HWREG(FLASH_BASE + FLASH_O_FSM_EXECUTE) = FLASH_CMD_EXEC; + + /* Disable write to FSM register. */ + HWREG(FLASH_BASE + FLASH_O_FSM_WR_ENA) = FSM_REG_WRT_DISABLE; +} + +/****************************************************************************** +* +* Enables all sectors for erase and programming on the active bank. +* +* This function disables the idle reading power reduction mode, selects the +* flash bank and enables all sectors for erase and programming on the active +* bank. +* Sectors may be protected from programming depending on the value of the +* FLASH_O_FSM_BSLPx registers. +* Sectors may be protected from erase depending on the value of the +* FLASH_O_FSM_BSLEx registers. Additional sector erase protection is set by +* the FLASH_O_FSM_SECTOR1 register. +* +******************************************************************************/ +static void enable_sectors_for_write(void) +{ + /* Trim flash module for program/erase operation. */ + trim_for_write(); + + /* Configure flash to write mode */ + set_write_mode(); + + /* Select flash bank. */ + HWREG(FLASH_BASE + FLASH_O_FMAC) = 0x00; + + /* Disable Level 1 Protection. */ + HWREG(FLASH_BASE + FLASH_O_FBPROT) = FLASH_FBPROT_PROTL1DIS; + + /* Enable all sectors for erase and programming. */ + HWREG(FLASH_BASE + FLASH_O_FBSE) = 0xFFFF; + + /* Enable Level 1 Protection */ + HWREG(FLASH_BASE + FLASH_O_FBPROT) = 0; +} + +/****************************************************************************** +* +* Trims the Flash Bank and Flash Pump for program/erase functionality +* +* This trimming will make it possible to perform erase and program operations +* of the flash. Trim values are loaded from factory configuration area +* (referred to as FCGF1). The trimming done by this function is valid until +* reset of the flash module. +* +* Some registers shall be written with a value that is a number of FCLK +* cycles. The trim values controlling these registers have a value of +* number of half us. FCLK = SysClk / ((RWAIT+1) x 2). +* +******************************************************************************/ +static void trim_for_write(void) +{ + uint32_t value; + uint32_t temp_val; + uint32_t fclk_scale; + uint32_t rwait; + + /* Return if flash is already trimmed for program/erase operations. */ + if (HWREG(FLASH_BASE + FLASH_O_FWFLAG) & FW_WRT_TRIMMED) + return; + + /* Configure the FSM registers */ + + /* Enable access to the FSM registers. */ + HWREG(FLASH_BASE + FLASH_O_FSM_WR_ENA) = FSM_REG_WRT_ENABLE; + + /* Determine the scaling value to be used on timing related trim values. */ + /* The value is based on the flash module clock frequency and RWAIT */ + rwait = (HWREG(FLASH_BASE + FLASH_O_FRDCTL) & + FLASH_FRDCTL_RWAIT_M) >> FLASH_FRDCTL_RWAIT_S; + fclk_scale = (16 * FLASH_MODULE_CLK_FREQ) / (rwait + 1); + + /* Configure Program pulse width bits 15:0. */ + /* (FCFG1 offset 0x188 bits 15:0). */ + value = (HWREG(FLASH_CFG_BASE + FCFG1_OFFSET + FCFG1_O_FLASH_PROG_EP) & + FCFG1_FLASH_PROG_EP_PROGRAM_PW_M) >> + FCFG1_FLASH_PROG_EP_PROGRAM_PW_S; + + value = scale_cycle_values(value, fclk_scale); + + HWREG(FLASH_BASE + FLASH_O_FSM_PRG_PW) = + (HWREG(FLASH_BASE + FLASH_O_FSM_PRG_PW) & + ~FLASH_FSM_PRG_PW_PROG_PUL_WIDTH_M) | + ((value << FLASH_FSM_PRG_PW_PROG_PUL_WIDTH_S) & + FLASH_FSM_PRG_PW_PROG_PUL_WIDTH_M); + + /* Configure Erase pulse width bits 31:0. */ + /* (FCFG1 offset 0x18C bits 31:0). */ + value = (HWREG(FLASH_CFG_BASE + FCFG1_OFFSET + FCFG1_O_FLASH_ERA_PW) & + FCFG1_FLASH_ERA_PW_ERASE_PW_M) >> + FCFG1_FLASH_ERA_PW_ERASE_PW_S; + + value = scale_cycle_values(value, fclk_scale); + + HWREG(FLASH_BASE + FLASH_O_FSM_ERA_PW) = + (HWREG(FLASH_BASE + FLASH_O_FSM_ERA_PW) & + ~FLASH_FSM_ERA_PW_FSM_ERA_PW_M) | + ((value << FLASH_FSM_ERA_PW_FSM_ERA_PW_S) & + FLASH_FSM_ERA_PW_FSM_ERA_PW_M); + + /* Configure no of flash clock cycles from EXECUTEZ going low to the the + verify data can be read in the program verify mode bits 7:0. */ + /* (FCFG1 offset 0x174 bits 23:16). */ + value = (HWREG(FLASH_CFG_BASE + FCFG1_OFFSET + FCFG1_O_FLASH_C_E_P_R) & + FCFG1_FLASH_C_E_P_R_PV_ACCESS_M) >> + FCFG1_FLASH_C_E_P_R_PV_ACCESS_S; + + value = scale_cycle_values(value, fclk_scale); + + HWREG(FLASH_BASE + FLASH_O_FSM_EX_VAL) = + (HWREG(FLASH_BASE + FLASH_O_FSM_EX_VAL) & + ~FLASH_FSM_EX_VAL_EXE_VALD_M) | + ((value << FLASH_FSM_EX_VAL_EXE_VALD_S) & + FLASH_FSM_EX_VAL_EXE_VALD_M); + + /* Configure the number of flash clocks from the start of the Read mode at + the end of the operations until the FSM clears the BUSY bit in FMSTAT. */ + /* (FCFG1 offset 0x178 bits 23:16). */ + value = (HWREG(FLASH_CFG_BASE + FCFG1_OFFSET + FCFG1_O_FLASH_P_R_PV) & + FCFG1_FLASH_P_R_PV_RH_M) >> + FCFG1_FLASH_P_R_PV_RH_S; + + HWREG(FLASH_BASE + FLASH_O_FSM_RD_H) = + (HWREG(FLASH_BASE + FLASH_O_FSM_RD_H) & + ~FLASH_FSM_RD_H_RD_H_M) | + ((value << FLASH_FSM_RD_H_RD_H_S) & + FLASH_FSM_RD_H_RD_H_M); + + /* Configure Program hold time */ + /* (FCFG1 offset 0x178 bits 31:24). */ + value = (HWREG(FLASH_CFG_BASE + FCFG1_OFFSET + FCFG1_O_FLASH_P_R_PV) & + FCFG1_FLASH_P_R_PV_PH_M) >> + FCFG1_FLASH_P_R_PV_PH_S; + + value = scale_cycle_values(value, fclk_scale); + + HWREG(FLASH_BASE + FLASH_O_FSM_P_OH) = + (HWREG(FLASH_BASE + FLASH_O_FSM_P_OH) & + ~FLASH_FSM_P_OH_PGM_OH_M) | + ((value << FLASH_FSM_P_OH_PGM_OH_S) & + FLASH_FSM_P_OH_PGM_OH_M); + + /* Configure Erase hold time */ + /* (FCFG1 offset 0x17C bits 31:24). */ + value = (HWREG(FLASH_CFG_BASE + FCFG1_OFFSET + FCFG1_O_FLASH_EH_SEQ) & + FCFG1_FLASH_EH_SEQ_EH_M) >> + FCFG1_FLASH_EH_SEQ_EH_S; + + value = scale_cycle_values(value, fclk_scale); + + HWREG(FLASH_BASE + FLASH_O_FSM_ERA_OH) = + (HWREG(FLASH_BASE + FLASH_O_FSM_ERA_OH) & + ~FLASH_FSM_ERA_OH_ERA_OH_M) | + ((value << FLASH_FSM_ERA_OH_ERA_OH_S) & + FLASH_FSM_ERA_OH_ERA_OH_M); + + /* Configure Program verify row switch time */ + /* (FCFG1 offset0x178 bits 15:8). */ + value = (HWREG(FLASH_CFG_BASE + FCFG1_OFFSET + FCFG1_O_FLASH_P_R_PV) & + FCFG1_FLASH_P_R_PV_PVH_M) >> + FCFG1_FLASH_P_R_PV_PVH_S; + + value = scale_cycle_values(value, fclk_scale); + + HWREG(FLASH_BASE + FLASH_O_FSM_PE_VH) = + (HWREG(FLASH_BASE + FLASH_O_FSM_PE_VH) & + ~FLASH_FSM_PE_VH_PGM_VH_M) | + ((value << FLASH_FSM_PE_VH_PGM_VH_S) & + FLASH_FSM_PE_VH_PGM_VH_M); + + /* Configure Program Operation Setup time */ + /* (FCFG1 offset 0x170 bits 31:24). */ + value = (HWREG(FLASH_CFG_BASE + FCFG1_OFFSET + FCFG1_O_FLASH_E_P) & + FCFG1_FLASH_E_P_PSU_M) >> + FCFG1_FLASH_E_P_PSU_S; + + HWREG(FLASH_BASE + FLASH_O_FSM_PE_OSU) = + (HWREG(FLASH_BASE + FLASH_O_FSM_PE_OSU) & + ~FLASH_FSM_PE_OSU_PGM_OSU_M) | + ((value << FLASH_FSM_PE_OSU_PGM_OSU_S) & + FLASH_FSM_PE_OSU_PGM_OSU_M); + + /* Configure Erase Operation Setup time */ + /* (FCGF1 offset 0x170 bits 23:16). */ + value = (HWREG(FLASH_CFG_BASE + FCFG1_OFFSET + FCFG1_O_FLASH_E_P) & + FCFG1_FLASH_E_P_ESU_M) >> + FCFG1_FLASH_E_P_ESU_S; + + HWREG(FLASH_BASE + FLASH_O_FSM_PE_OSU) = + (HWREG(FLASH_BASE + FLASH_O_FSM_PE_OSU) & + ~FLASH_FSM_PE_OSU_ERA_OSU_M) | + ((value << FLASH_FSM_PE_OSU_ERA_OSU_S) & + FLASH_FSM_PE_OSU_ERA_OSU_M); + + /* Confgure Program Verify Setup time */ + /* (FCFG1 offset 0x170 bits 15:8). */ + value = (HWREG(FLASH_CFG_BASE + FCFG1_OFFSET + FCFG1_O_FLASH_E_P) & + FCFG1_FLASH_E_P_PVSU_M) >> + FCFG1_FLASH_E_P_PVSU_S; + + HWREG(FLASH_BASE + FLASH_O_FSM_PE_VSU) = + (HWREG(FLASH_BASE + FLASH_O_FSM_PE_VSU) & + ~FLASH_FSM_PE_VSU_PGM_VSU_M) | + ((value << FLASH_FSM_PE_VSU_PGM_VSU_S) & + FLASH_FSM_PE_VSU_PGM_VSU_M); + + /* Configure Erase Verify Setup time */ + /* (FCFG1 offset 0x170 bits 7:0). */ + value = (HWREG(FLASH_CFG_BASE + FCFG1_OFFSET + FCFG1_O_FLASH_E_P) & + FCFG1_FLASH_E_P_EVSU_M) >> + FCFG1_FLASH_E_P_EVSU_S; + + HWREG(FLASH_BASE + FLASH_O_FSM_PE_VSU) = + (HWREG(FLASH_BASE + FLASH_O_FSM_PE_VSU) & + ~FLASH_FSM_PE_VSU_ERA_VSU_M) | + ((value << FLASH_FSM_PE_VSU_ERA_VSU_S) & + FLASH_FSM_PE_VSU_ERA_VSU_M); + + /* Configure Addr to EXECUTEZ low setup time */ + /* (FCFG1 offset 0x174 bits 15:12). */ + value = (HWREG(FLASH_CFG_BASE + FCFG1_OFFSET + FCFG1_O_FLASH_C_E_P_R) & + FCFG1_FLASH_C_E_P_R_A_EXEZ_SETUP_M) >> + FCFG1_FLASH_C_E_P_R_A_EXEZ_SETUP_S; + + HWREG(FLASH_BASE + FLASH_O_FSM_CMP_VSU) = + (HWREG(FLASH_BASE + FLASH_O_FSM_CMP_VSU) & + ~FLASH_FSM_CMP_VSU_ADD_EXZ_M) | + ((value << FLASH_FSM_CMP_VSU_ADD_EXZ_S) & + FLASH_FSM_CMP_VSU_ADD_EXZ_M); + + /* Configure Voltage Status Count */ + /* (FCFG1 offset 0x17C bits 15:12). */ + value = (HWREG(FLASH_CFG_BASE + FCFG1_OFFSET + FCFG1_O_FLASH_EH_SEQ) & + FCFG1_FLASH_EH_SEQ_VSTAT_M) >> + FCFG1_FLASH_EH_SEQ_VSTAT_S; + + HWREG(FLASH_BASE + FLASH_O_FSM_VSTAT) = + (HWREG(FLASH_BASE + FLASH_O_FSM_VSTAT) & + ~FLASH_FSM_VSTAT_VSTAT_CNT_M) | + ((value << FLASH_FSM_VSTAT_VSTAT_CNT_S) & + FLASH_FSM_VSTAT_VSTAT_CNT_M); + + /* Configure Repeat Verify action setup */ + /* (FCFG1 offset 0x174 bits 31:24). */ + value = (HWREG(FLASH_CFG_BASE + FCFG1_OFFSET + FCFG1_O_FLASH_C_E_P_R) & + FCFG1_FLASH_C_E_P_R_RVSU_M) >> + FCFG1_FLASH_C_E_P_R_RVSU_S; + + HWREG(FLASH_BASE + FLASH_O_FSM_EX_VAL) = + (HWREG(FLASH_BASE + FLASH_O_FSM_EX_VAL) & + ~FLASH_FSM_EX_VAL_REP_VSU_M) | + ((value << FLASH_FSM_EX_VAL_REP_VSU_S) & + FLASH_FSM_EX_VAL_REP_VSU_M); + + /* Configure Maximum Programming Pulses */ + /* (FCFG1 offset 0x184 bits 15:0). */ + value = (HWREG(FLASH_CFG_BASE + FCFG1_OFFSET + FCFG1_O_FLASH_PP) & + FCFG1_FLASH_PP_MAX_PP_M) >> + FCFG1_FLASH_PP_MAX_PP_S; + + HWREG(FLASH_BASE + FLASH_O_FSM_PRG_PUL) = + (HWREG(FLASH_BASE + FLASH_O_FSM_PRG_PUL) & + ~FLASH_FSM_PRG_PUL_MAX_PRG_PUL_M) | + ((value << FLASH_FSM_PRG_PUL_MAX_PRG_PUL_S) & + FLASH_FSM_PRG_PUL_MAX_PRG_PUL_M); + + /* Configure Beginning level for VHVCT used during erase modes */ + /* (FCFG1 offset 0x180 bits 31:16). */ + value = (HWREG(FLASH_CFG_BASE + FCFG1_OFFSET + FCFG1_O_FLASH_VHV_E) & + FCFG1_FLASH_VHV_E_VHV_E_START_M) >> + FCFG1_FLASH_VHV_E_VHV_E_START_S; + + HWREG(FLASH_BASE + FLASH_O_FSM_PRG_PUL) = + (HWREG(FLASH_BASE + FLASH_O_FSM_PRG_PUL) & + ~FLASH_FSM_PRG_PUL_BEG_EC_LEVEL_M) | + ((value << FLASH_FSM_PRG_PUL_BEG_EC_LEVEL_S) & + FLASH_FSM_PRG_PUL_BEG_EC_LEVEL_M); + + /* Configure Maximum EC Level */ + /* (FCFG1 offset 0x2B0 bits 21:18). */ + value = (HWREG(FLASH_CFG_BASE + FCFG1_OFFSET + FCFG1_O_FLASH_OTP_DATA3) & + FCFG1_FLASH_OTP_DATA3_MAX_EC_LEVEL_M) >> + FCFG1_FLASH_OTP_DATA3_MAX_EC_LEVEL_S; + + HWREG(FLASH_BASE + FLASH_O_FSM_ERA_PUL) = + (HWREG(FLASH_BASE + FLASH_O_FSM_ERA_PUL) & + ~FLASH_FSM_ERA_PUL_MAX_EC_LEVEL_M) | + ((value << FLASH_FSM_ERA_PUL_MAX_EC_LEVEL_S) & + FLASH_FSM_ERA_PUL_MAX_EC_LEVEL_M); + + /* Configure Maximum Erase Pulses */ + /* (FCFG1 offset 0x188 bits 31:16). */ + value = (HWREG(FLASH_CFG_BASE + FCFG1_OFFSET + FCFG1_O_FLASH_PROG_EP) & + FCFG1_FLASH_PROG_EP_MAX_EP_M) >> + FCFG1_FLASH_PROG_EP_MAX_EP_S; + + HWREG(FLASH_BASE + FLASH_O_FSM_ERA_PUL) = + (HWREG(FLASH_BASE + FLASH_O_FSM_ERA_PUL) & + ~FLASH_FSM_ERA_PUL_MAX_ERA_PUL_M) | + ((value << FLASH_FSM_ERA_PUL_MAX_ERA_PUL_S) & + FLASH_FSM_ERA_PUL_MAX_ERA_PUL_M); + + /* Configure the VHVCT Step Size. This is the number of erase pulses that + must be completed for each level before the FSM increments the + CUR_EC_LEVEL to the next higher level. Actual erase pulses per level + equals (EC_STEP_SIZE +1). The stepping is only needed for the VHVCT + voltage. */ + /* (FCFG1 offset 0x2B0 bits 31:23). */ + value = (HWREG(FLASH_CFG_BASE + FCFG1_OFFSET + FCFG1_O_FLASH_OTP_DATA3) & + FCFG1_FLASH_OTP_DATA3_EC_STEP_SIZE_M) >> + FCFG1_FLASH_OTP_DATA3_EC_STEP_SIZE_S; + + HWREG(FLASH_BASE + FLASH_O_FSM_STEP_SIZE) = + (HWREG(FLASH_BASE + FLASH_O_FSM_STEP_SIZE) & + ~FLASH_FSM_STEP_SIZE_EC_STEP_SIZE_M) | + ((value << FLASH_FSM_STEP_SIZE_EC_STEP_SIZE_S) & + FLASH_FSM_STEP_SIZE_EC_STEP_SIZE_M); + + /* Configure the hight of each EC step. This is the number of counts that + the CUR_EC_LEVEL will increment when going to a new level. Actual count + size equals (EC_STEP_HEIGHT + 1). The stepping applies only to the VHVCT + voltage. + The read trim value is decremented by 1 before written to the register + since actual counts equals (register value + 1). */ + /* (FCFG1 offset 0x180 bits 15:0). */ + value = (HWREG(FLASH_CFG_BASE + FCFG1_OFFSET + FCFG1_O_FLASH_VHV_E) & + FCFG1_FLASH_VHV_E_VHV_E_STEP_HIGHT_M) >> + FCFG1_FLASH_VHV_E_VHV_E_STEP_HIGHT_S; + + HWREG(FLASH_BASE + FLASH_O_FSM_EC_STEP_HEIGHT) = ((value - 1) & + FLASH_FSM_EC_STEP_HEIGHT_EC_STEP_HEIGHT_M); + + /* Configure Precondition used in erase operations */ + /* (FCFG1 offset 0x2B0 bit 22). */ + value = (HWREG(FLASH_CFG_BASE + FCFG1_OFFSET + FCFG1_O_FLASH_OTP_DATA3) & + FCFG1_FLASH_OTP_DATA3_DO_PRECOND_M) >> + FCFG1_FLASH_OTP_DATA3_DO_PRECOND_S; + + HWREG(FLASH_BASE + FLASH_O_FSM_ST_MACHINE) = + (HWREG(FLASH_BASE + FLASH_O_FSM_ST_MACHINE) & + ~FLASH_FSM_ST_MACHINE_DO_PRECOND_M) | + ((value << FLASH_FSM_ST_MACHINE_DO_PRECOND_S) & + FLASH_FSM_ST_MACHINE_DO_PRECOND_M); + + /* Enable the recommended Good Time function. */ + HWREG(FLASH_BASE + FLASH_O_FSM_ST_MACHINE) |= + FLASH_FSM_ST_MACHINE_ONE_TIME_GOOD; + + /* Disable write access to FSM registers. */ + HWREG(FLASH_BASE + FLASH_O_FSM_WR_ENA) = FSM_REG_WRT_DISABLE; + + /* Configure the voltage registers */ + + /* Unlock voltage registers (0x2080 - 0x2098). */ + HWREG(FLASH_BASE + FLASH_O_FLOCK) = 0xAAAA; + + /* Configure voltage level for the specified pump voltage of high + voltage supply input during erase operation VHVCT_E and TRIM13_E */ + /* (FCFG1 offset 0x190 bits[3:0] and bits[11:8]). */ + temp_val = HWREG(FLASH_CFG_BASE + FCFG1_OFFSET + FCFG1_O_FLASH_VHV); + + value = ((temp_val & FCFG1_FLASH_VHV_TRIM13_E_M)>> + FCFG1_FLASH_VHV_TRIM13_E_S) << FLASH_FVHVCT1_TRIM13_E_S; + value |= ((temp_val & FCFG1_FLASH_VHV_VHV_E_M)>> + FCFG1_FLASH_VHV_VHV_E_S) << FLASH_FVHVCT1_VHVCT_E_S; + + HWREG(FLASH_BASE + FLASH_O_FVHVCT1) = (HWREG(FLASH_BASE + FLASH_O_FVHVCT1) & + ~(FLASH_FVHVCT1_TRIM13_E_M | FLASH_FVHVCT1_VHVCT_E_M)) | value; + + /* Configure voltage level for the specified pump voltage of high voltage + supply input during program verify operation VHVCT_PV and TRIM13_PV */ + /* (OTP offset 0x194 bits[19:16] and bits[27:24]). */ + temp_val = HWREG(FLASH_CFG_BASE + FCFG1_OFFSET + FCFG1_O_FLASH_VHV_PV); + + value = ((temp_val & FCFG1_FLASH_VHV_PV_TRIM13_PV_M) >> + FCFG1_FLASH_VHV_PV_TRIM13_PV_S) << FLASH_FVHVCT1_TRIM13_PV_S; + value |= ((temp_val & FCFG1_FLASH_VHV_PV_VHV_PV_M) >> + FCFG1_FLASH_VHV_PV_VHV_PV_S) << FLASH_FVHVCT1_VHVCT_PV_S; + + HWREG(FLASH_BASE + FLASH_O_FVHVCT1) = (HWREG(FLASH_BASE + FLASH_O_FVHVCT1) & + ~(FLASH_FVHVCT1_TRIM13_PV_M | FLASH_FVHVCT1_VHVCT_PV_M)) | value; + + /* Configure voltage level for the specified pump voltage of high voltage + supply input during program operation VHVCT_P and TRIM13_P */ + /* (FCFG1 offset 0x190 bits[19:16] and bits[27:24]). */ + temp_val = HWREG(FLASH_CFG_BASE + FCFG1_OFFSET + FCFG1_O_FLASH_VHV); + + value = ((temp_val & FCFG1_FLASH_VHV_TRIM13_P_M) >> + FCFG1_FLASH_VHV_TRIM13_P_S) << FLASH_FVHVCT2_TRIM13_P_S; + value |= ((temp_val & FCFG1_FLASH_VHV_VHV_P_M) >> + FCFG1_FLASH_VHV_VHV_P_S) << FLASH_FVHVCT2_VHVCT_P_S; + + HWREG(FLASH_BASE + FLASH_O_FVHVCT2) = (HWREG(FLASH_BASE + FLASH_O_FVHVCT2) & + ~(FLASH_FVHVCT2_TRIM13_P_M | FLASH_FVHVCT2_VHVCT_P_M)) | value; + + /* Configure voltage level for the specified pump voltage of wordline power + supply for read mode */ + /* (FCFG1 offset 0x198 Bits 15:8). */ + value = (HWREG(FLASH_CFG_BASE + FCFG1_OFFSET + FCFG1_O_FLASH_V) & + FCFG1_FLASH_V_V_READ_M) >> FCFG1_FLASH_V_V_READ_S; + + HWREG(FLASH_BASE + FLASH_O_FVREADCT) = + (HWREG(FLASH_BASE + FLASH_O_FVREADCT) & + ~FLASH_FVREADCT_VREADCT_M) | + ((value << FLASH_FVREADCT_VREADCT_S) & + FLASH_FVREADCT_VREADCT_M); + + /* Configure the voltage level for the VCG 2.5 CT pump voltage */ + /* (FCFG1 offset 0x194 bits 15:8). */ + value = (HWREG(FLASH_CFG_BASE + FCFG1_OFFSET + FCFG1_O_FLASH_VHV_PV) & + FCFG1_FLASH_VHV_PV_VCG2P5_M) >> + FCFG1_FLASH_VHV_PV_VCG2P5_S; + + HWREG(FLASH_BASE + FLASH_O_FVNVCT) = + (HWREG(FLASH_BASE + FLASH_O_FVNVCT) & + ~FLASH_FVNVCT_VCG2P5CT_M) | + ((value << FLASH_FVNVCT_VCG2P5CT_S) & + FLASH_FVNVCT_VCG2P5CT_M); + + /* Configure the voltage level for the specified pump voltage of high + current power input during program operation */ + /* (FCFG1 offset 0x198 bits 31:24). */ + value = (HWREG(FLASH_CFG_BASE + FCFG1_OFFSET + FCFG1_O_FLASH_V) & + FCFG1_FLASH_V_VSL_P_M) >> + FCFG1_FLASH_V_VSL_P_S; + + HWREG(FLASH_BASE + FLASH_O_FVSLP) = + (HWREG(FLASH_BASE + FLASH_O_FVSLP) & + ~FLASH_FVSLP_VSL_P_M) | + ((value << FLASH_FVSLP_VSL_P_S) & + FLASH_FVSLP_VSL_P_M); + + /* Configure the voltage level for the specified pump voltage of wordline + power supply during programming operations */ + /* (OTP offset 0x198 bits 23:16). */ + value = (HWREG(FLASH_CFG_BASE + FCFG1_OFFSET + FCFG1_O_FLASH_V) & + FCFG1_FLASH_V_VWL_P_M) >> + FCFG1_FLASH_V_VWL_P_S; + + HWREG(FLASH_BASE + FLASH_O_FVWLCT) = + (HWREG(FLASH_BASE + FLASH_O_FVWLCT) & + ~FLASH_FVWLCT_VWLCT_P_M) | + ((value << FLASH_FVWLCT_VWLCT_P_S) & + FLASH_FVWLCT_VWLCT_P_M); + + /* Configure the pump's TRIM_1P7 port pins. */ + /* (FCFG1 offset 0x2B0 bits 17:16). */ + value = (HWREG(FLASH_CFG_BASE + FCFG1_OFFSET + FCFG1_O_FLASH_OTP_DATA3) & + FCFG1_FLASH_OTP_DATA3_TRIM_1P7_M) >> + FCFG1_FLASH_OTP_DATA3_TRIM_1P7_S; + + HWREG(FLASH_BASE + FLASH_O_FSEQPMP) = + (HWREG(FLASH_BASE + FLASH_O_FSEQPMP) & + ~FLASH_FSEQPMP_TRIM_1P7_M) | + ((value << FLASH_FSEQPMP_TRIM_1P7_S) & + FLASH_FSEQPMP_TRIM_1P7_M); + + /* Lock the voltage registers. */ + HWREG(FLASH_BASE + FLASH_O_FLOCK) = 0x55AA; + + /* Set trimmed flag. */ + HWREG(FLASH_BASE + FLASH_O_FWLOCK) = 5; + HWREG(FLASH_BASE + FLASH_O_FWFLAG) |= FW_WRT_TRIMMED; + HWREG(FLASH_BASE + FLASH_O_FWLOCK) = 0; +} + +/****************************************************************************** +* +* Used to scale the TI OTP values based on the FClk scaling value. +* +******************************************************************************/ +static uint32_t scale_cycle_values(uint32_t specified_timing, + uint32_t scale_value) +{ + uint32_t scaled_value = (specified_timing * scale_value) >> 6; + return scaled_value; +} + +/****************************************************************************** +* +* Used to set flash in read mode. +* +* Flash is configured with values loaded from OTP dependent on the current +* regulator mode. +* +******************************************************************************/ +static void set_read_mode(void) +{ + uint32_t trim_value; + uint32_t value; + + /* Configure the STANDBY_MODE_SEL, STANDBY_PW_SEL, DIS_STANDBY, DIS_IDLE, + VIN_AT_X and VIN_BY_PASS for read mode */ + if (HWREG(AON_PMCTL_BASE + AON_PMCTL_O_PWRCTL) & + AON_PMCTL_PWRCTL_EXT_REG_MODE) { + + /* Select trim values for external regulator mode: + Configure STANDBY_MODE_SEL (OTP offset 0x308 bit 7) + Configure STANDBY_PW_SEL (OTP offset 0x308 bit 6:5) + Must be done while the register bit field CONFIG.DIS_STANDBY = 1 */ + HWREG(FLASH_BASE + FLASH_O_CFG) |= FLASH_CFG_DIS_STANDBY; + + trim_value = + HWREG(FLASH_CFG_BASE + FCFG1_OFFSET + FCFG1_O_FLASH_OTP_DATA4); + + value = ((trim_value & + FCFG1_FLASH_OTP_DATA4_STANDBY_MODE_SEL_EXT_RD_M) >> + FCFG1_FLASH_OTP_DATA4_STANDBY_MODE_SEL_EXT_RD_S) << + FLASH_CFG_STANDBY_MODE_SEL_S; + + value |= ((trim_value & + FCFG1_FLASH_OTP_DATA4_STANDBY_PW_SEL_EXT_RD_M) >> + FCFG1_FLASH_OTP_DATA4_STANDBY_PW_SEL_EXT_RD_S) << + FLASH_CFG_STANDBY_PW_SEL_S; + + /* Configure DIS_STANDBY (OTP offset 0x308 bit 4). + Configure DIS_IDLE (OTP offset 0x308 bit 3). */ + value |= ((trim_value & + (FCFG1_FLASH_OTP_DATA4_DIS_STANDBY_EXT_RD_M | + FCFG1_FLASH_OTP_DATA4_DIS_IDLE_EXT_RD_M)) >> + FCFG1_FLASH_OTP_DATA4_DIS_IDLE_EXT_RD_S) << + FLASH_CFG_DIS_IDLE_S; + + HWREG(FLASH_BASE + FLASH_O_CFG) = (HWREG(FLASH_BASE + FLASH_O_CFG) & + ~(FLASH_CFG_STANDBY_MODE_SEL_M | FLASH_CFG_STANDBY_PW_SEL_M | + FLASH_CFG_DIS_STANDBY_M | FLASH_CFG_DIS_IDLE_M)) | value; + + /* Check if sample and hold functionality is disabled. */ + if (HWREG(FLASH_BASE + FLASH_O_CFG) & FLASH_CFG_DIS_IDLE) { + /* Wait for disabled sample and hold functionality to be stable. */ + while (!(HWREG(FLASH_BASE+FLASH_O_STAT) & FLASH_STAT_SAMHOLD_DIS)) + ; + } + + /* Configure VIN_AT_X (OTP offset 0x308 bits 2:0) */ + value = ((trim_value & + FCFG1_FLASH_OTP_DATA4_VIN_AT_X_EXT_RD_M) >> + FCFG1_FLASH_OTP_DATA4_VIN_AT_X_EXT_RD_S) << + FLASH_FSEQPMP_VIN_AT_X_S; + + /* Configure VIN_BY_PASS which is dependent on the VIN_AT_X value. + If VIN_AT_X = 7 then VIN_BY_PASS should be 0 otherwise + VIN_BY_PASS should be 1 */ + if (((value & FLASH_FSEQPMP_VIN_AT_X_M) >> + FLASH_FSEQPMP_VIN_AT_X_S) != 0x7) + value |= FLASH_FSEQPMP_VIN_BY_PASS; + + HWREG(FLASH_BASE + FLASH_O_FLOCK) = 0xAAAA; + HWREG(FLASH_BASE + FLASH_O_FSEQPMP) = + (HWREG(FLASH_BASE + FLASH_O_FSEQPMP) & + ~(FLASH_FSEQPMP_VIN_BY_PASS_M | + FLASH_FSEQPMP_VIN_AT_X_M)) | value; + HWREG(FLASH_BASE + FLASH_O_FLOCK) = 0x55AA; + } else { + + /* Select trim values for internal regulator mode: + Configure STANDBY_MODE_SEL (OTP offset 0x308 bit 15) + COnfigure STANDBY_PW_SEL (OTP offset 0x308 bit 14:13) + Must be done while the register bit field CONFIG.DIS_STANDBY = 1 */ + HWREG(FLASH_BASE + FLASH_O_CFG) |= FLASH_CFG_DIS_STANDBY; + + trim_value = + HWREG(FLASH_CFG_BASE + FCFG1_OFFSET + FCFG1_O_FLASH_OTP_DATA4); + + value = ((trim_value & + FCFG1_FLASH_OTP_DATA4_STANDBY_MODE_SEL_INT_RD_M) >> + FCFG1_FLASH_OTP_DATA4_STANDBY_MODE_SEL_INT_RD_S) << + FLASH_CFG_STANDBY_MODE_SEL_S; + + value |= ((trim_value & + FCFG1_FLASH_OTP_DATA4_STANDBY_PW_SEL_INT_RD_M) >> + FCFG1_FLASH_OTP_DATA4_STANDBY_PW_SEL_INT_RD_S) << + FLASH_CFG_STANDBY_PW_SEL_S; + + /* Configure DIS_STANDBY (OTP offset 0x308 bit 12). + Configure DIS_IDLE (OTP offset 0x308 bit 11). */ + value |= ((trim_value & + (FCFG1_FLASH_OTP_DATA4_DIS_STANDBY_INT_RD_M | + FCFG1_FLASH_OTP_DATA4_DIS_IDLE_INT_RD_M)) >> + FCFG1_FLASH_OTP_DATA4_DIS_IDLE_INT_RD_S) << + FLASH_CFG_DIS_IDLE_S; + + HWREG(FLASH_BASE + FLASH_O_CFG) = (HWREG(FLASH_BASE + FLASH_O_CFG) & + ~(FLASH_CFG_STANDBY_MODE_SEL_M | FLASH_CFG_STANDBY_PW_SEL_M | + FLASH_CFG_DIS_STANDBY_M | FLASH_CFG_DIS_IDLE_M)) | value; + + /* Check if sample and hold functionality is disabled. */ + if (HWREG(FLASH_BASE + FLASH_O_CFG) & FLASH_CFG_DIS_IDLE) { + /* Wait for disabled sample and hold functionality to be stable. */ + while (!(HWREG(FLASH_BASE + FLASH_O_STAT) & FLASH_STAT_SAMHOLD_DIS)) + ; + } + + /* Configure VIN_AT_X (OTP offset 0x308 bits 10:8) */ + value = (((trim_value & + FCFG1_FLASH_OTP_DATA4_VIN_AT_X_INT_RD_M) >> + FCFG1_FLASH_OTP_DATA4_VIN_AT_X_INT_RD_S) << + FLASH_FSEQPMP_VIN_AT_X_S); + + /* Configure VIN_BY_PASS which is dependent on the VIN_AT_X value. + If VIN_AT_X = 7 then VIN_BY_PASS should be 0 otherwise + VIN_BY_PASS should be 1 */ + if (((value & FLASH_FSEQPMP_VIN_AT_X_M) >> + FLASH_FSEQPMP_VIN_AT_X_S) != 0x7) + value |= FLASH_FSEQPMP_VIN_BY_PASS; + + HWREG(FLASH_BASE + FLASH_O_FLOCK) = 0xAAAA; + HWREG(FLASH_BASE + FLASH_O_FSEQPMP) = + (HWREG(FLASH_BASE + FLASH_O_FSEQPMP) & + ~(FLASH_FSEQPMP_VIN_BY_PASS_M | + FLASH_FSEQPMP_VIN_AT_X_M)) | value; + HWREG(FLASH_BASE + FLASH_O_FLOCK) = 0x55AA; + } +} + +/****************************************************************************** +* +* Used to set flash in write mode. +* +* Flash is configured with values loaded from OTP dependent on the current +* regulator mode. +* +******************************************************************************/ +static void set_write_mode(void) +{ + uint32_t trim_value; + uint32_t value; + + /* Configure the STANDBY_MODE_SEL, STANDBY_PW_SEL, DIS_STANDBY, DIS_IDLE, + VIN_AT_X and VIN_BY_PASS for program/erase mode */ + if (HWREG(AON_PMCTL_BASE + AON_PMCTL_O_PWRCTL) & + AON_PMCTL_PWRCTL_EXT_REG_MODE) { + + /* Select trim values for external regulator mode: + Configure STANDBY_MODE_SEL (OTP offset 0x308 bit 23) + Configure STANDBY_PW_SEL (OTP offset 0x308 bit 22:21) + Must be done while the register bit field CONFIG.DIS_STANDBY = 1 */ + HWREG(FLASH_BASE + FLASH_O_CFG) |= FLASH_CFG_DIS_STANDBY; + + trim_value = + HWREG(FLASH_CFG_BASE + FCFG1_OFFSET + FCFG1_O_FLASH_OTP_DATA4); + + value = ((trim_value & + FCFG1_FLASH_OTP_DATA4_STANDBY_MODE_SEL_EXT_WRT_M) >> + FCFG1_FLASH_OTP_DATA4_STANDBY_MODE_SEL_EXT_WRT_S) << + FLASH_CFG_STANDBY_MODE_SEL_S; + + value |= ((trim_value & + FCFG1_FLASH_OTP_DATA4_STANDBY_PW_SEL_EXT_WRT_M) >> + FCFG1_FLASH_OTP_DATA4_STANDBY_PW_SEL_EXT_WRT_S) << + FLASH_CFG_STANDBY_PW_SEL_S; + + /* Configure DIS_STANDBY (OTP offset 0x308 bit 20). + Configure DIS_IDLE (OTP offset 0x308 bit 19). */ + value |= ((trim_value & + (FCFG1_FLASH_OTP_DATA4_DIS_STANDBY_EXT_WRT_M | + FCFG1_FLASH_OTP_DATA4_DIS_IDLE_EXT_WRT_M)) >> + FCFG1_FLASH_OTP_DATA4_DIS_IDLE_EXT_WRT_S) << + FLASH_CFG_DIS_IDLE_S; + + HWREG(FLASH_BASE + FLASH_O_CFG) = (HWREG(FLASH_BASE + FLASH_O_CFG) & + ~(FLASH_CFG_STANDBY_MODE_SEL_M | FLASH_CFG_STANDBY_PW_SEL_M | + FLASH_CFG_DIS_STANDBY_M | FLASH_CFG_DIS_IDLE_M)) | value; + + /* Check if sample and hold functionality is disabled. */ + if (HWREG(FLASH_BASE + FLASH_O_CFG) & FLASH_CFG_DIS_IDLE) { + /* Wait for disabled sample and hold functionality to be stable. */ + while (!(HWREG(FLASH_BASE + FLASH_O_STAT) & FLASH_STAT_SAMHOLD_DIS)) + ; + } + + /* Configure VIN_AT_X (OTP offset 0x308 bits 18:16) */ + value = ((trim_value & + FCFG1_FLASH_OTP_DATA4_VIN_AT_X_EXT_WRT_M) >> + FCFG1_FLASH_OTP_DATA4_VIN_AT_X_EXT_WRT_S) << + FLASH_FSEQPMP_VIN_AT_X_S; + + /* Configure VIN_BY_PASS which is dependent on the VIN_AT_X value. + If VIN_AT_X = 7 then VIN_BY_PASS should be 0 otherwise + VIN_BY_PASS should be 1 */ + if (((value & FLASH_FSEQPMP_VIN_AT_X_M) >> + FLASH_FSEQPMP_VIN_AT_X_S) != 0x7) + value |= FLASH_FSEQPMP_VIN_BY_PASS; + + HWREG(FLASH_BASE + FLASH_O_FLOCK) = 0xAAAA; + HWREG(FLASH_BASE + FLASH_O_FSEQPMP) = + (HWREG(FLASH_BASE + FLASH_O_FSEQPMP) & + ~(FLASH_FSEQPMP_VIN_BY_PASS_M | + FLASH_FSEQPMP_VIN_AT_X_M)) | value; + HWREG(FLASH_BASE + FLASH_O_FLOCK) = 0x55AA; + } else { + /* Select trim values for internal regulator mode: + Configure STANDBY_MODE_SEL (OTP offset 0x308 bit 31) + COnfigure STANDBY_PW_SEL (OTP offset 0x308 bit 30:29) + Must be done while the register bit field CONFIG.DIS_STANDBY = 1 */ + HWREG(FLASH_BASE + FLASH_O_CFG) |= FLASH_CFG_DIS_STANDBY; + + trim_value = + HWREG(FLASH_CFG_BASE + FCFG1_OFFSET + FCFG1_O_FLASH_OTP_DATA4); + + value = ((trim_value & + FCFG1_FLASH_OTP_DATA4_STANDBY_MODE_SEL_INT_WRT_M) >> + FCFG1_FLASH_OTP_DATA4_STANDBY_MODE_SEL_INT_WRT_S) << + FLASH_CFG_STANDBY_MODE_SEL_S; + + value |= ((trim_value & + FCFG1_FLASH_OTP_DATA4_STANDBY_PW_SEL_INT_WRT_M) >> + FCFG1_FLASH_OTP_DATA4_STANDBY_PW_SEL_INT_WRT_S) << + FLASH_CFG_STANDBY_PW_SEL_S; + + /* Configure DIS_STANDBY (OTP offset 0x308 bit 28). + Configure DIS_IDLE (OTP offset 0x308 bit 27). */ + value |= ((trim_value & + (FCFG1_FLASH_OTP_DATA4_DIS_STANDBY_INT_WRT_M | + FCFG1_FLASH_OTP_DATA4_DIS_IDLE_INT_WRT_M)) >> + FCFG1_FLASH_OTP_DATA4_DIS_IDLE_INT_WRT_S) << + FLASH_CFG_DIS_IDLE_S; + + HWREG(FLASH_BASE + FLASH_O_CFG) = (HWREG(FLASH_BASE + FLASH_O_CFG) & + ~(FLASH_CFG_STANDBY_MODE_SEL_M | FLASH_CFG_STANDBY_PW_SEL_M | + FLASH_CFG_DIS_STANDBY_M | FLASH_CFG_DIS_IDLE_M)) | value; + + /* Check if sample and hold functionality is disabled. */ + if (HWREG(FLASH_BASE + FLASH_O_CFG) & FLASH_CFG_DIS_IDLE) { + /* Wait for disabled sample and hold functionality to be stable. */ + while (!(HWREG(FLASH_BASE + FLASH_O_STAT) & FLASH_STAT_SAMHOLD_DIS)) + ; + } + + /* Configure VIN_AT_X (OTP offset 0x308 bits 26:24) */ + value = ((trim_value & + FCFG1_FLASH_OTP_DATA4_VIN_AT_X_INT_WRT_M) >> + FCFG1_FLASH_OTP_DATA4_VIN_AT_X_INT_WRT_S) << + FLASH_FSEQPMP_VIN_AT_X_S; + + /* Configure VIN_BY_PASS which is dependent on the VIN_AT_X value. + If VIN_AT_X = 7 then VIN_BY_PASS should be 0 otherwise + VIN_BY_PASS should be 1 */ + if (((value & FLASH_FSEQPMP_VIN_AT_X_M) >> + FLASH_FSEQPMP_VIN_AT_X_S) != 0x7) + value |= FLASH_FSEQPMP_VIN_BY_PASS; + + HWREG(FLASH_BASE + FLASH_O_FLOCK) = 0xAAAA; + HWREG(FLASH_BASE + FLASH_O_FSEQPMP) = + (HWREG(FLASH_BASE + FLASH_O_FSEQPMP) & + ~(FLASH_FSEQPMP_VIN_BY_PASS_M | + FLASH_FSEQPMP_VIN_AT_X_M)) | value; + HWREG(FLASH_BASE + FLASH_O_FLOCK) = 0x55AA; + } +} diff --git a/contrib/loaders/flash/cc26xx/flash.h b/contrib/loaders/flash/cc26xx/flash.h new file mode 100644 index 0000000..ec1c24f --- /dev/null +++ b/contrib/loaders/flash/cc26xx/flash.h @@ -0,0 +1,378 @@ +/****************************************************************************** +* +* Copyright (C) 2016-2018 Texas Instruments Incorporated - http://www.ti.com/ +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the +* distribution. +* +* Neither the name of Texas Instruments Incorporated nor the names of +* its contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +******************************************************************************/ + +#ifndef OPENOCD_LOADERS_FLASH_CC26XX_FLASH_H +#define OPENOCD_LOADERS_FLASH_CC26XX_FLASH_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include <stdint.h> +#include <stdbool.h> +#include "hw_regs.h" + +/* Location of flash in memory map */ +#define FLASHMEM_BASE 0 + +/* Defines to access flash API calls in ROM */ +#define ROM_API_TABLE ((uint32_t *) 0x10000180) +#define ROM_VERSION (ROM_API_TABLE[0]) +#define ROM_API_FLASH_TABLE ((uint32_t *) (ROM_API_TABLE[10])) + +#if defined(DEVICE_CC26X2) + +/* Agama (CC26x2) specific definitions */ + +#define FLASH_ERASE_SIZE 8192 +/* Agama (and Agama 1M) has a maximum of 132 flash sectors (1056KB / 8KB) */ +#define FLASH_MAX_SECTOR_COUNT 132 +#define FLASH_SECTOR_BASE_M 0xFFFFE000 + +/* Bootloader Configuration */ +#define CCFG_O_BL_CONFIG 0x00001FD8 + +#elif defined(DEVICE_CC26X0) + +/* Chameleon (CC26x0) specific definitions */ + +#define FLASH_ERASE_SIZE 4096 +/* Chameleon has a maximum of 32 flash sectors (128KB / 4KB) */ +#define FLASH_MAX_SECTOR_COUNT 32 +#define FLASH_SECTOR_BASE_M 0xFFFFF000 + +/* Bootloader Configuration */ +#define CCFG_O_BL_CONFIG 0x00000FD8 + +#else +#error No DEVICE defined. +#endif + +/****************************************************************************** +* +* Values that can be returned from the API functions +* +******************************************************************************/ +#define FAPI_STATUS_SUCCESS 0x00000000 /* Function completed successfully */ +#define FAPI_STATUS_FSM_BUSY 0x00000001 /* FSM is Busy */ +#define FAPI_STATUS_FSM_READY 0x00000002 /* FSM is Ready */ +#define FAPI_STATUS_INCORRECT_DATABUFFER_LENGTH \ + 0x00000003 /* Incorrect parameter value */ +#define FAPI_STATUS_FSM_ERROR 0x00000004 /* Operation failed */ + +/****************************************************************************** +* +* Define used by the flash programming and erase functions +* +******************************************************************************/ +#define ADDR_OFFSET (0x1F800000 - FLASHMEM_BASE) + +/****************************************************************************** +* +* Define used for access to factory configuration area. +* +******************************************************************************/ +#define FCFG1_OFFSET 0x1000 + +/****************************************************************************** +* +* Define for the clock frequencey input to the flash module in number of MHz +* +******************************************************************************/ +#define FLASH_MODULE_CLK_FREQ 48 + +/****************************************************************************** +* +* Defined values for Flash State Machine commands +* +******************************************************************************/ +typedef enum { + FAPI_PROGRAM_DATA = 0x0002, /* Program data. */ + FAPI_ERASE_SECTOR = 0x0006, /* Erase sector. */ + FAPI_ERASE_BANK = 0x0008, /* Erase bank. */ + FAPI_VALIDATE_SECTOR = 0x000E, /* Validate sector. */ + FAPI_CLEAR_STATUS = 0x0010, /* Clear status. */ + FAPI_PROGRAM_RESUME = 0x0014, /* Program resume. */ + FAPI_ERASE_RESUME = 0x0016, /* Erase resume. */ + FAPI_CLEAR_MORE = 0x0018, /* Clear more. */ + FAPI_PROGRAM_SECTOR = 0x0020, /* Program sector. */ + FAPI_ERASE_OTP = 0x0030 /* Erase OTP. */ +} flash_state_command_t; + +/****************************************************************************** +* +* Defines for values written to the FLASH_O_FSM_WR_ENA register +* +******************************************************************************/ +#define FSM_REG_WRT_ENABLE 5 +#define FSM_REG_WRT_DISABLE 2 + +/****************************************************************************** +* +* Defines for the bank power mode field the FLASH_O_FBFALLBACK register +* +******************************************************************************/ +#define FBFALLBACK_SLEEP 0 +#define FBFALLBACK_DEEP_STDBY 1 +#define FBFALLBACK_ACTIVE 3 + +/****************************************************************************** +* +* Defines for the bank grace period and pump grace period +* +******************************************************************************/ +#define FLASH_BAGP 0x14 +#define FLASH_PAGP 0x14 + +/****************************************************************************** +* +* Defines for the FW flag bits in the FLASH_O_FWFLAG register +* +******************************************************************************/ +#define FW_WRT_TRIMMED 0x00000001 + +/****************************************************************************** +* +* Defines used by the flash programming functions +* +******************************************************************************/ +typedef volatile uint8_t fwp_write_byte; +#define FWPWRITE_BYTE_ADDRESS \ + ((fwp_write_byte *)((FLASH_BASE + FLASH_O_FWPWRITE0))) + +/****************************************************************************** +* +* Define for FSM command execution +* +******************************************************************************/ +#define FLASH_CMD_EXEC 0x15 + +/****************************************************************************** +* +* Get size of a flash sector in number of bytes. +* +* This function will return the size of a flash sector in number of bytes. +* +* Returns size of a flash sector in number of bytes. +* +******************************************************************************/ +static inline uint32_t flash_sector_size_get(void) +{ + uint32_t sector_size_in_kbyte; + + sector_size_in_kbyte = (HWREG(FLASH_BASE + FLASH_O_FCFG_B0_SSIZE0) & + FLASH_FCFG_B0_SSIZE0_B0_SECT_SIZE_M) >> + FLASH_FCFG_B0_SSIZE0_B0_SECT_SIZE_S; + + /* Return flash sector size in number of bytes. */ + return sector_size_in_kbyte * 1024; +} + +/****************************************************************************** +* +* Get the size of the flash. +* +* This function returns the size of the flash main bank in number of bytes. +* +* Returns the flash size in number of bytes. +* +******************************************************************************/ +static inline uint32_t flash_size_get(void) +{ + uint32_t num_of_sectors; + + /* Get number of flash sectors */ + num_of_sectors = (HWREG(FLASH_BASE + FLASH_O_FLASH_SIZE) & + FLASH_FLASH_SIZE_SECTORS_M) >> + FLASH_FLASH_SIZE_SECTORS_S; + + /* Return flash size in number of bytes */ + return num_of_sectors * flash_sector_size_get(); +} + +/****************************************************************************** +* +* Checks if the Flash state machine has detected an error. +* +* This function returns the status of the Flash State Machine indicating if +* an error is detected or not. Primary use is to check if an Erase or +* Program operation has failed. +* +* Please note that code can not execute in flash while any part of the flash +* is being programmed or erased. This function must be called from ROM or +* SRAM while any part of the flash is being programmed or erased. +* +* Returns status of Flash state machine: +* FAPI_STATUS_FSM_ERROR +* FAPI_STATUS_SUCCESS +* +******************************************************************************/ +static inline uint32_t flash_check_fsm_for_error(void) +{ + if (HWREG(FLASH_BASE + FLASH_O_FMSTAT) & FLASH_FMSTAT_CSTAT) + return FAPI_STATUS_FSM_ERROR; + else + return FAPI_STATUS_SUCCESS; +} + +/****************************************************************************** +* +* Checks if the Flash state machine is ready. +* +* This function returns the status of the Flash State Machine indicating if +* it is ready to accept a new command or not. Primary use is to check if an +* Erase or Program operation has finished. +* +* Please note that code can not execute in flash while any part of the flash +* is being programmed or erased. This function must be called from ROM or +* SRAM while any part of the flash is being programmed or erased. +* +* Returns readiness status of Flash state machine: +* FAPI_STATUS_FSM_READY +* FAPI_STATUS_FSM_BUSY +* +******************************************************************************/ +static inline uint32_t flash_check_fsm_for_ready(void) +{ + if (HWREG(FLASH_BASE + FLASH_O_STAT) & FLASH_STAT_BUSY) + return FAPI_STATUS_FSM_BUSY; + else + return FAPI_STATUS_FSM_READY; +} + +/****************************************************************************** +* +* Erase a flash sector. +* +* This function will erase the specified flash sector. The function will +* not return until the flash sector has been erased or an error condition +* occurred. If flash top sector is erased the function will program the +* the device security data bytes with default values. The device security +* data located in the customer configuration area of the flash top sector, +* must have valid values at all times. These values affect the configuration +* of the device during boot. +* +* Please note that code can not execute in flash while any part of the flash +* is being programmed or erased. This function must only be executed from ROM +* or SRAM. +* +* sector_address is the starting address in flash of the sector to be +* erased. +* +* Returns the status of the sector erase: +* FAPI_STATUS_SUCCESS : Success. +* FAPI_STATUS_INCORRECT_DATABUFFER_LENGTH : Invalid argument. +* FAPI_STATUS_FSM_ERROR : Programming error was encountered. +* +******************************************************************************/ +extern uint32_t flash_sector_erase(uint32_t sector_address); + +/****************************************************************************** +* +* Erase all unprotected sectors in the flash main bank. +* +* This function will erase all unprotected flash sectors. The function will +* not return until the flash sectors has been erased or an error condition +* occurred. Since the flash top sector is erased the function will program the +* the device security data bytes with default values. The device security +* data located in the customer configuration area of the flash top sector, +* must have valid values at all times. These values affect the configuration +* of the device during boot. The execution time of the operation increases if +* erase precondition is forced. This will cause the flash module to first +* program all 1 bits in the bank to 0 before the actual erase is started. +* +* force_precondition controls if erase precondition should be forced. +* +* Returns the status of the sector erase: +* FAPI_STATUS_SUCCESS : Success +* FAPI_STATUS_FSM_ERROR : Erase error was encountered. +* +******************************************************************************/ +extern uint32_t flash_bank_erase(bool force_precondition); + +/****************************************************************************** +* +* Programs unprotected main bank flash sectors. +* +* This function will program a sequence of bytes into the on-chip flash. +* Programming each location consists of the result of an AND operation +* of the new data and the existing data; in other words bits that contain +* 1 can remain 1 or be changed to 0, but bits that are 0 cannot be changed +* to 1. Therefore, a byte can be programmed multiple times as long as these +* rules are followed; if a program operation attempts to change a 0 bit to +* a 1 bit, that bit will not have its value changed. +* +* This function will not return until the data has been programmed or an +* programming error has occurred. +* +* Please note that code can not execute in flash while any part of the flash +* is being programmed or erased. This function must only be executed from ROM +* or SRAM. +* +* The data_buffer pointer cannot point to flash. +* +* data_buffer is a pointer to the data to be programmed. +* address is the starting address in flash to be programmed. +* count is the number of bytes to be programmed. +* +* Returns status of the flash programming: +* FAPI_STATUS_SUCCESS : Success. +* FAPI_STATUS_INCORRECT_DATABUFFER_LENGTH : Too many bytes were requested. +* FAPI_STATUS_FSM_ERROR : Programming error was encountered. +* +******************************************************************************/ +extern uint32_t flash_program(uint8_t *data_buffer, uint32_t address, + uint32_t count); + +/****************************************************************************** +* +* Disables all sectors for erase and programming on the active bank. +* +* This function disables all sectors for erase and programming on the active +* bank and enables the Idle Reading Power reduction mode if no low power +* mode is configured. Furthermore, an additional level of protection from +* erase is enabled. +* +* Please note that code can not execute in flash while any part of the flash +* is being programmed or erased. +* +******************************************************************************/ +extern void flash_disable_sectors_for_write(void); + +#ifdef __cplusplus +} +#endif + +#endif /* #ifndef OPENOCD_LOADERS_FLASH_CC26XX_FLASH_H */ diff --git a/contrib/loaders/flash/cc26xx/flashloader.c b/contrib/loaders/flash/cc26xx/flashloader.c new file mode 100644 index 0000000..2eaf618 --- /dev/null +++ b/contrib/loaders/flash/cc26xx/flashloader.c @@ -0,0 +1,177 @@ +/****************************************************************************** +* +* Copyright (C) 2017-2018 Texas Instruments Incorporated - http://www.ti.com/ +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the +* distribution. +* +* Neither the name of Texas Instruments Incorporated nor the names of +* its contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +******************************************************************************/ + +#include <stdint.h> +#include <stdbool.h> +#include "flashloader.h" +#include "flash.h" + +/* Array holding erased state of the flash sectors. */ +static bool g_is_erased[FLASH_MAX_SECTOR_COUNT]; + +extern uint8_t g_retain_buf[]; + +uint32_t flashloader_init(struct flash_params *params, uint8_t *buf1, + uint8_t *buf2) +{ + /* Initialize params buffers */ + memset((void *)params, 0, 2 * sizeof(struct flash_params)); + params[0].buf_addr = (uint32_t)buf1; + params[1].buf_addr = (uint32_t)buf2; + + /* Mark all sectors at "not erased" */ + memset(g_is_erased, false, sizeof(g_is_erased)); + + return STATUS_OK; +} + +uint32_t flashloader_erase_and_program(uint8_t *src, uint32_t address, + uint32_t byte_count) +{ + if (byte_count > BUFFER_LEN) + return STATUS_FAILED_INVALID_ARGUMENTS; + + /* Erase affected sectors */ + uint32_t status = flashloader_erase_sectors(address, byte_count); + + if (status != STATUS_OK) + return status; + + /* Program data */ + status = flashloader_program(src, address, byte_count); + + return status; +} + +uint32_t flashloader_program_with_retain(uint8_t *src, uint32_t address, + uint32_t byte_count) +{ +#if (BUFFER_LEN > FLASH_ERASE_SIZE) +#error Buffer size cannot be larger than the flash sector size! +#endif + + uint32_t first_sector_idx; + uint32_t last_sector_idx; + uint32_t status = STATUS_OK; + uint32_t i; + + first_sector_idx = flashloader_address_to_sector(address); + last_sector_idx = flashloader_address_to_sector(address + byte_count - 1); + + /* Mark all sectors as "not erased" before starting */ + memset(g_is_erased, false, sizeof(g_is_erased)); + + uint32_t sec_offset = address % FLASH_ERASE_SIZE; + uint32_t curr_count; + uint32_t src_offset = 0; + + for (i = first_sector_idx; i <= last_sector_idx; i++) { + + /* Chop off at sector boundary if data goes into the next sector. */ + curr_count = byte_count; + if ((address + byte_count) > ((i+1) * FLASH_ERASE_SIZE)) + curr_count -= (address + byte_count) % FLASH_ERASE_SIZE; + + /* Copy flash sector to retain buffer */ + memcpy(g_retain_buf, (void *)(i * FLASH_ERASE_SIZE), FLASH_ERASE_SIZE); + + /* Copy data buffer to retain buffer */ + memcpy(&g_retain_buf[sec_offset], &src[src_offset], curr_count); + + /* Erase and program from retain buffer */ + status = flashloader_erase_and_program(g_retain_buf, + (i * FLASH_ERASE_SIZE), FLASH_ERASE_SIZE); + if (status != STATUS_OK) + return status; + + address += curr_count; + sec_offset = address % FLASH_ERASE_SIZE; + byte_count -= curr_count; + src_offset += curr_count; + } + + return status; +} + +uint32_t flashloader_erase_all(void) +{ + if (flash_bank_erase(true) != FAPI_STATUS_SUCCESS) + return STATUS_FAILED_ERASE_ALL; + + memset(g_is_erased, true, sizeof(g_is_erased)); + + return STATUS_OK; +} + +uint32_t flashloader_erase_sectors(uint32_t address, uint32_t byte_count) +{ + uint32_t first_sector_idx; + uint32_t last_sector_idx; + uint32_t status; + uint32_t idx; + + /* Floor address to the start of the sector and convert to sector number */ + first_sector_idx = flashloader_address_to_sector(address); + last_sector_idx = flashloader_address_to_sector(address + byte_count - 1); + + /* Erase given sector(s) */ + for (idx = first_sector_idx; idx <= last_sector_idx; idx++) { + + /* Only erase sectors that haven't already been erased */ + if (g_is_erased[idx] == false) { + status = flash_sector_erase(idx * FLASH_ERASE_SIZE); + if (status != FAPI_STATUS_SUCCESS) { + status = (STATUS_FAILED_SECTOR_ERASE | + ((idx << STATUS_EXT_INFO_S) & STATUS_EXT_INFO_M) | + ((status << STATUS_ROM_CODE_S) & STATUS_ROM_CODE_M)); + return status; + } + g_is_erased[idx] = true; + } + } + + return STATUS_OK; +} + +uint32_t flashloader_program(uint8_t *src, uint32_t address, + uint32_t byte_count) +{ + uint32_t status = flash_program(src, address, byte_count); + if (status != FAPI_STATUS_SUCCESS) { + status = (STATUS_FAILED_PROGRAM | + ((status << STATUS_ROM_CODE_S) & STATUS_ROM_CODE_M)); + } + + return STATUS_OK; +} diff --git a/contrib/loaders/flash/cc26xx/flashloader.h b/contrib/loaders/flash/cc26xx/flashloader.h new file mode 100644 index 0000000..aec74aa --- /dev/null +++ b/contrib/loaders/flash/cc26xx/flashloader.h @@ -0,0 +1,187 @@ +/****************************************************************************** +* +* Copyright (C) 2017-2018 Texas Instruments Incorporated - http://www.ti.com/ +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the +* distribution. +* +* Neither the name of Texas Instruments Incorporated nor the names of +* its contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +******************************************************************************/ + +#ifndef OPENOCD_LOADERS_FLASH_CC26XX_FLASHLOADER_H +#define OPENOCD_LOADERS_FLASH_CC26XX_FLASHLOADER_H + +#include <stdint.h> +#include <stdbool.h> +#include <string.h> +#include "flash.h" + +/* Number of elements in an array */ +#define NELEMS(a) (sizeof(a) / sizeof(a[0])) + +struct __attribute__((__packed__)) flash_params { + uint32_t dest; /* Destination address in flash */ + uint32_t len; /* Number of bytes */ + uint32_t cmd; /* Command */ + uint32_t full; /* Handshake signal. Is buffer ready? */ + uint32_t buf_addr; /* Address of data buffer. */ +}; + +typedef enum { + CMD_NO_ACTION = 0, /* No action, default value */ + CMD_ERASE_ALL = 1, /* Erase all unprotected sectors */ + CMD_PROGRAM = 2, /* Program data */ + CMD_ERASE_AND_PROGRAM = 3, /* Erase and program data */ + CMD_ERASE_AND_PROGRAM_WITH_RETAIN = 4, /* Erase and program, but retain */ + /* sector data outside given range */ + CMD_ERASE_SECTORS = 5 /* Erase unprotected sectors */ +} flash_commands_t; + +typedef enum { + BUFFER_EMPTY = 0x0, /* No data in buffer, flags last task complete */ + BUFFER_FULL = 0xFFFFFFFF /* Buffer has data, flags next task to start */ +} flash_handshake_t; + +#define STATUS_FLASHLOADER_STATUS_M 0x0000FFFF +#define STATUS_FLASHLOADER_STATUS_S 0 +#define STATUS_ROM_CODE_M 0x00FF0000 +#define STATUS_ROM_CODE_S 16 +#define STATUS_EXT_INFO_M 0xFF000000 +#define STATUS_EXT_INFO_S 24 + +typedef enum { + STATUS_OK = 0, + STATUS_FAILED_ERASE_ALL = 0x101, + STATUS_FAILED_SECTOR_ERASE = 0x102, + STATUS_FAILED_PROGRAM = 0x103, + STATUS_FAILED_INVALID_ARGUMENTS = 0x104, + STATUS_FAILED_UNKNOWN_COMMAND = 0x105, +} flash_status_t; + +/* The buffer size used by the flashloader. The size of 1 flash sector. */ +#define BUFFER_LEN FLASH_ERASE_SIZE + +/* +* This function initializes the flashloader. The application must +* allocate memory for the two data buffers and the flash_params structures. +* +* params Pointer an flash_params array with 2 elements. +* buf1 Pointer to data buffer 1 +* buf2 Pointer to data buffer 2 +* +* Returns STATUS_OK +* +*/ +extern uint32_t flashloader_init(struct flash_params *params, uint8_t *buf1, + uint8_t *buf2); + +/* +* Erase and program the necessary sectors. Data outside the given +* range will be deleted. +* +* src Pointer to buffer containing the data. +* address Start address in device flash +* byte_count The number of bytes to program +* +* Returns STATUS_OK on success. For status on failure: +* See flashloader_program() and flashloader_erase_sectors(). +* +*/ +extern uint32_t flashloader_erase_and_program(uint8_t *src, uint32_t address, + uint32_t byte_count); + +/* +* Erase and program the device sectors. Data outside the given +* data range will be kept unchanged. +* +* src Pointer to buffer containing the data. +* address Start address in device flash +* byte_count The number of bytes to program +* +* Returns STATUS_OK on success. For status on failure: +* See flashloader_program() and flashloader_erase_sectors(). +* +*/ +extern uint32_t flashloader_program_with_retain(uint8_t *src, uint32_t address, + uint32_t byte_count); + +/* +* Erases all flash sectors (that are not write-protected). +* +* Returns STATUS_OK on success. +* +*/ +extern uint32_t flashloader_erase_all(void); + +/* +* Erases the flash sectors affected by the given range. +* +* This function only erases sectors that are not already erased. +* +* start_addr The first address in the range. +* byte_count The number of bytes in the range. +* +* Returns STATUS_OK on success. Returns a combined status on failure: +* [31:24] The sector that failed. +* [23:16] ROM function status code. 0 means success. +* [16: 0] STATUS_FAILED_SECTOR_ERASE +* +*/ +extern uint32_t flashloader_erase_sectors(uint32_t start_addr, + uint32_t byte_count); + +/* +* Program the given range. +* +* This function does not erase anything, it assumes the sectors are ready to +* be programmed. +* +* src Pointer to buffer containing the data. +* address Start address in device flash +* byte_count The number of bytes to program +* +* Returns STATUS_OK on success. Returns a combined status value on failure: +* [31:16] ROM function status code. 0 means success. +* [15:0 ] STATUS_FAILED_PROGRAM +* +*/ +extern uint32_t flashloader_program(uint8_t *src, uint32_t address, + uint32_t byte_count); + +/* +* Convert the input address into a sector number. +* +* address The address. +* +* Returns the flash sector which the address resides in. The first sector +* is sector 0. +* +*/ +static inline uint32_t flashloader_address_to_sector(uint32_t address) + { return (address / FLASH_ERASE_SIZE); }; + +#endif /* #ifndef OPENOCD_LOADERS_FLASH_CC26XX_FLASHLOADER_H */ diff --git a/contrib/loaders/flash/cc26xx/hw_regs.h b/contrib/loaders/flash/cc26xx/hw_regs.h new file mode 100644 index 0000000..830d3af --- /dev/null +++ b/contrib/loaders/flash/cc26xx/hw_regs.h @@ -0,0 +1,1382 @@ +/****************************************************************************** +* +* Copyright (C) 2017-2018 Texas Instruments Incorporated - http://www.ti.com/ +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the +* distribution. +* +* Neither the name of Texas Instruments Incorporated nor the names of +* its contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +******************************************************************************/ + +#ifndef OPENOCD_LOADERS_FLASH_CC26XX_HW_REGS_H +#define OPENOCD_LOADERS_FLASH_CC26XX_HW_REGS_H + +/****************************************************************************** +* +* Macros for direct hardware access. +* +* If using these macros the programmer should be aware of any limitations to +* the address accessed i.e. if it supports word and/or byte access. +* +******************************************************************************/ +/* Word (32 bit) access to address x */ +/* Read example : my32BitVar = HWREG(base_addr + offset) ; */ +/* Write example : HWREG(base_addr + offset) = my32BitVar ; */ +#define HWREG(x) (*((volatile unsigned long *)(x))) + +/* Half word (16 bit) access to address x */ +/* Read example : my16BitVar = HWREGH(base_addr + offset) ; */ +/* Write example : HWREGH(base_addr + offset) = my16BitVar ; */ +#define HWREGH(x) (*((volatile unsigned short *)(x))) + +/* Byte (8 bit) access to address x */ +/* Read example : my8BitVar = HWREGB(base_addr + offset) ; */ +/* Write example : HWREGB(base_addr + offset) = my8BitVar ; */ +#define HWREGB(x) (*((volatile unsigned char *)(x))) + +/****************************************************************************** +* +* Macro for access to bit-band supported addresses via the bit-band region. +* +* Macro calculates the corresponding address to access in the bit-band region +* based on the actual address of the memory/register and the bit number. +* +* Do NOT use this macro to access the bit-band region directly! +* +******************************************************************************/ +/* Bit-band access to address x bit number b using word access (32 bit) */ +#define HWREGBITW(x, b) \ + HWREG(((unsigned long)(x) & 0xF0000000) | 0x02000000 | \ + (((unsigned long)(x) & 0x000FFFFF) << 5) | ((b) << 2)) + +/****************************************************************************** +* +* Memory mapped components base address definitions +* +******************************************************************************/ +#define FLASH_BASE 0x40030000 +#define FLASH_CFG_BASE 0x50000000 +#define AON_PMCTL_BASE 0x40090000 + +/****************************************************************************** +* +* This section defines the register offsets of FLASH component +* +******************************************************************************/ + +/* FMC and Efuse Status */ +#define FLASH_O_STAT 0x0000001C + +/* Configuration */ +#define FLASH_O_CFG 0x00000024 + +/* Flash Size Configuration */ +#define FLASH_O_FLASH_SIZE 0x0000002C + +/* Firmware Lock */ +#define FLASH_O_FWLOCK 0x0000003C + +/* Firmware Flags */ +#define FLASH_O_FWFLAG 0x00000040 + +/* FMC Read Control */ +#define FLASH_O_FRDCTL 0x00002000 + +/* FMC Bank Protection */ +#define FLASH_O_FBPROT 0x00002030 + +/* FMC Bank Sector Enable */ +#define FLASH_O_FBSE 0x00002034 + +/* FMC Module Access Control */ +#define FLASH_O_FMAC 0x00002050 + +/* FMC Module Status */ +#define FLASH_O_FMSTAT 0x00002054 + +/* FMC Flash Lock */ +#define FLASH_O_FLOCK 0x00002064 + +/* FMC VREADCT Trim */ +#define FLASH_O_FVREADCT 0x00002080 + +/* FMC VHVCT1 Trim */ +#define FLASH_O_FVHVCT1 0x00002084 + +/* FMC VHVCT2 Trim */ +#define FLASH_O_FVHVCT2 0x00002088 + +/* FMC VNVCT Trim */ +#define FLASH_O_FVNVCT 0x00002090 + +/* FMC VSL_P Trim */ +#define FLASH_O_FVSLP 0x00002094 + +/* FMC VWLCT Trim */ +#define FLASH_O_FVWLCT 0x00002098 + +/* FMC Sequential Pump Information */ +#define FLASH_O_FSEQPMP 0x000020A8 + +/* FMC FSM Command */ +#define FLASH_O_FSM_CMD 0x0000220C + +/* FMC FSM Program/Erase Operation Setup */ +#define FLASH_O_FSM_PE_OSU 0x00002210 + +/* FMC FSM Voltage Status Setup */ +#define FLASH_O_FSM_VSTAT 0x00002214 + +/* FMC FSM Program/Erase Verify Setup */ +#define FLASH_O_FSM_PE_VSU 0x00002218 + +/* FMC FSM Compare Verify Setup */ +#define FLASH_O_FSM_CMP_VSU 0x0000221C + +/* FMC FSM EXECUTEZ to Valid Data */ +#define FLASH_O_FSM_EX_VAL 0x00002220 + +/* FMC FSM Read Mode Hold */ +#define FLASH_O_FSM_RD_H 0x00002224 + +/* FMC FSM Program Hold */ +#define FLASH_O_FSM_P_OH 0x00002228 + +/* FMC FSM Erase Operation Hold */ +#define FLASH_O_FSM_ERA_OH 0x0000222C + +/* FMC FSM Program/Erase Verify Hold */ +#define FLASH_O_FSM_PE_VH 0x00002234 + +/* FMC FSM Program Pulse Width */ +#define FLASH_O_FSM_PRG_PW 0x00002240 + +/* FMC FSM Erase Pulse Width */ +#define FLASH_O_FSM_ERA_PW 0x00002244 + +/* FMC FSM Maximum Programming Pulses */ +#define FLASH_O_FSM_PRG_PUL 0x00002268 + +/* FMC FSM Maximum Erase Pulses */ +#define FLASH_O_FSM_ERA_PUL 0x0000226C + +/* FMC FSM EC Step Size */ +#define FLASH_O_FSM_STEP_SIZE 0x00002270 + +/* FMC FSM EC Step Height */ +#define FLASH_O_FSM_EC_STEP_HEIGHT 0x00002278 + +/* FMC FSM_ST_MACHINE */ +#define FLASH_O_FSM_ST_MACHINE 0x0000227C + +/* FMC FSM Register Write Enable */ +#define FLASH_O_FSM_WR_ENA 0x00002288 + +/* FMC FSM Command Execute */ +#define FLASH_O_FSM_EXECUTE 0x000022B4 + +/* FMC FSM Sector Erased 1 */ +#define FLASH_O_FSM_SECTOR1 0x000022C0 + +/* FMC FSM Sector Erased 2 */ +#define FLASH_O_FSM_SECTOR2 0x000022C4 + +/* FMC Flash Bank 0 Starting Address */ +#define FLASH_O_FCFG_B0_START 0x00002410 + +/* FMC Flash Bank 0 Sector Size 0 */ +#define FLASH_O_FCFG_B0_SSIZE0 0x00002430 + +/****************************************************************************** +* +* Register: FLASH_O_STAT +* +******************************************************************************/ +/* Field: [2] SAMHOLD_DIS +* +* Status indicator of flash sample and hold sequencing logic. This bit will go +* to 1 some delay after CFG.DIS_IDLE is set to 1. +* 0: Not disabled +* 1: Sample and hold disabled and stable */ +#define FLASH_STAT_SAMHOLD_DIS 0x00000004 + +/* Field: [1] BUSY +* +* Fast version of the FMC FMSTAT.BUSY bit. +* This flag is valid immediately after the operation setting it (FMSTAT.BUSY +* is delayed some cycles) +* 0 : Not busy +* 1 : Busy */ +#define FLASH_STAT_BUSY 0x00000002 + +/****************************************************************************** +* +* Register: FLASH_O_CFG +* +******************************************************************************/ +/* Field: [8] STANDBY_MODE_SEL +* +* [Configured by boot firmware] +* STANDBY mode selection control. This bit, in conjunction with +* STANDBY_PW_SEL, determine which 1 of 4 sub-modes is selected for control of +* the behavior and timing of the STANDBY input to the pump. +* +* 0 : Legacy PG1 behavior is selected when STANDBY_PW_SEL = 00. This is +* referred to as sub-mode 1. When STANDBY_PW_SEL != 00, then sub-mode 2 +* behavior is selected. STANDBY will be glitchy in these modes. +* 1 : STANDBY pulse-width counter modes selected. In these two modes (referred +* to as sub-mode 3 and sub-mode 4), the low time pulse width of the STANDBY +* signal to the pump, is controlled by a programmable timer. STANDBY will not +* be glitchy in these modes. */ +#define FLASH_CFG_STANDBY_MODE_SEL_M 0x00000100 +#define FLASH_CFG_STANDBY_MODE_SEL_S 8 + +/* Field: [7:6] STANDBY_PW_SEL +* +* [Configured by boot firmware] +* STANDBY pulse width counter selection control. These bits, in conjunction +* with STANDBY_MODE_SEL, determine which 1 of 4 sub-modes is selected for +* control of the behavior and timing of the STANDBY input to the pump. +* +* 00 : Legacy PG1 behavior is selected when STANDBY_MODE_SEL=0. Sub-mode 4 is +* selected when STANDBY_MODE_SEL=1. In sub-mode 4, STANDBY will be low for at +* least 9 pump clock cycles. +* 01 : Sub-mode 2 or 3 is selected, and STANDBY will be low for at least 9 +* pump clock cycles. +* 10: Sub-mode 2 or 3 is selected, and STANDBY will be low for at least 5 pump +* clock cycles. +* 11: Sub-mode 2 or 3 is selected, and STANDBY will be low for at least 13 +* pump clock cycles. */ +#define FLASH_CFG_STANDBY_PW_SEL_M 0x000000C0 +#define FLASH_CFG_STANDBY_PW_SEL_S 6 + +/* Field: [1] DIS_STANDBY +* +* [Configured by boot firmware] +* Disable standby functionality in read idle state */ +#define FLASH_CFG_DIS_STANDBY 0x00000002 +#define FLASH_CFG_DIS_STANDBY_BITN 1 +#define FLASH_CFG_DIS_STANDBY_M 0x00000002 + +/* Field: [0] DIS_IDLE +* +* [Configured by boot firmware] +* Disable sample and hold functionality in read idle state */ +#define FLASH_CFG_DIS_IDLE 0x00000001 +#define FLASH_CFG_DIS_IDLE_M 0x00000001 +#define FLASH_CFG_DIS_IDLE_S 0 + +/****************************************************************************** +* +* Register: FLASH_O_FLASH_SIZE +* +******************************************************************************/ +/* Field: [7:0] SECTORS +* +* [Configured by boot firmware] +* Flash size. The number of flash sectors in the configured device. Read +* access to sectors equal to this number or higher will result in an error. +* The CCFG area is the sector (SECTORS - 1) Writing to this register is +* disabled by the CFG.CONFIGURED bit. */ +#define FLASH_FLASH_SIZE_SECTORS_M 0x000000FF +#define FLASH_FLASH_SIZE_SECTORS_S 0 + +/****************************************************************************** +* +* Register: FLASH_O_FRDCTL +* +******************************************************************************/ +/* Field: [11:8] RWAIT +* +* [Configured by boot firmware] +* FMC Wait State. This field determines the FLCLK period during FMC controlled +* flash accesses: +* - During power up/ power down / low power mode +* - During FSM operations like program, erase +* - During software interface mode (see FLOCK , FBSTROBES registers) +* FLCLK_period = HCLK_period X (RWAIT + 1), +* FSM state machine operations are usually twice this amount. This value +* should never be set less than 2. */ +#define FLASH_FRDCTL_RWAIT_M 0x00000F00 +#define FLASH_FRDCTL_RWAIT_S 8 + +/****************************************************************************** +* +* Register: FLASH_O_FBPROT +* +******************************************************************************/ +/* Field: [0] PROTL1DIS +* +* Level 1 Protection Disable bit. Setting this bit disables protection from +* writing to the FBAC.OTPPROTDIS bits as well as the Sector Enable registers +* FBSE for all banks. Clearing this bit enables protection and disables write +* access to the FBAC.OTPPROTDIS register bits and FBSE register. */ +#define FLASH_FBPROT_PROTL1DIS 0x00000001 + +/****************************************************************************** +* +* Register: FLASH_O_FMSTAT +* +******************************************************************************/ +/* Field: [4] CSTAT +* +* Command Status. Once the FSM starts any failure will set this bit. When set, +* this bit informs the host that the program, erase, or validate sector +* command failed and the command was stopped. This bit is cleared by the +* Clear_Status command. For some errors, this will be the only indication of +* an FSM error because the cause does not fall within the other error bit +* types. */ +#define FLASH_FMSTAT_CSTAT 0x00000010 + +/****************************************************************************** +* +* Register: FLASH_O_FVREADCT +* +******************************************************************************/ +/* Field: [3:0] VREADCT +* +* [Configured by boot firmware] +* These bits control the voltage level for the specified pump voltage of +* wordline power supply for read mode. */ +#define FLASH_FVREADCT_VREADCT_M 0x0000000F +#define FLASH_FVREADCT_VREADCT_S 0 + +/****************************************************************************** +* +* Register: FLASH_O_FVHVCT1 +* +******************************************************************************/ +/* Field: [23:20] TRIM13_E +* +* [Configured by boot firmware] +* These bits control the voltage level for the specified pump voltage of high +* voltage supply input during erase operation. */ +#define FLASH_FVHVCT1_TRIM13_E_M 0x00F00000 +#define FLASH_FVHVCT1_TRIM13_E_S 20 + +/* Field: [19:16] VHVCT_E +* +* [Configured by boot firmware] +* These bits control the voltage level for the specified pump voltage of high +* voltage supply input during erase operation. */ +#define FLASH_FVHVCT1_VHVCT_E_M 0x000F0000 +#define FLASH_FVHVCT1_VHVCT_E_S 16 + +/* Field: [7:4] TRIM13_PV +* +* [Configured by boot firmware] +* These bits control the voltage level for the specified pump voltage of high +* voltage supply input during program verify operation. */ +#define FLASH_FVHVCT1_TRIM13_PV_M 0x000000F0 +#define FLASH_FVHVCT1_TRIM13_PV_S 4 + +/* Field: [3:0] VHVCT_PV +* +* [Configured by boot firmware] +* These bits control the voltage level for the specified pump voltage of high +* voltage supply input during program verify operation. */ +#define FLASH_FVHVCT1_VHVCT_PV_M 0x0000000F +#define FLASH_FVHVCT1_VHVCT_PV_S 0 + +/****************************************************************************** +* +* Register: FLASH_O_FVHVCT2 +* +******************************************************************************/ +/* Field: [23:20] TRIM13_P +* +* [Configured by boot firmware] +* These bits control the voltage level for the specified pump voltage of high +* voltage supply input during program operation. */ +#define FLASH_FVHVCT2_TRIM13_P_M 0x00F00000 +#define FLASH_FVHVCT2_TRIM13_P_S 20 + +/* Field: [19:16] VHVCT_P +* +* [Configured by boot firmware] +* These bits control the voltage level for the specified pump voltage of high +* voltage supply input during program operation. */ +#define FLASH_FVHVCT2_VHVCT_P_M 0x000F0000 +#define FLASH_FVHVCT2_VHVCT_P_S 16 + +/****************************************************************************** +* +* Register: FLASH_O_FVNVCT +* +******************************************************************************/ +/* Field: [12:8] VCG2P5CT +* +* [Configured by boot firmware] +* These bits control the voltage level for the VCG 2.5 CT pump voltage. */ +#define FLASH_FVNVCT_VCG2P5CT_M 0x00001F00 +#define FLASH_FVNVCT_VCG2P5CT_S 8 + +/****************************************************************************** +* +* Register: FLASH_O_FVSLP +* +******************************************************************************/ +/* Field: [15:12] VSL_P +* +* [Configured by boot firmware] +* These bits control the voltage level for the specified pump voltage of high +* current power input during program operation. */ +#define FLASH_FVSLP_VSL_P_M 0x0000F000 +#define FLASH_FVSLP_VSL_P_S 12 + +/****************************************************************************** +* +* Register: FLASH_O_FVWLCT +* +******************************************************************************/ +/* Field: [4:0] VWLCT_P +* +* [Configured by boot firmware] +* These bits control the voltage level for the specified pump voltage of +* wordline power supply during programming operations. */ +#define FLASH_FVWLCT_VWLCT_P_M 0x0000001F +#define FLASH_FVWLCT_VWLCT_P_S 0 + +/****************************************************************************** +* +* Register: FLASH_O_FSEQPMP +* +******************************************************************************/ +/* Field: [21:20] TRIM_1P7 +* +* [Configured by boot firmware] +* This register goes directly to the pump's TRIM_1P7 port pins. */ +#define FLASH_FSEQPMP_TRIM_1P7_M 0x00300000 +#define FLASH_FSEQPMP_TRIM_1P7_S 20 + +/* Field: [14:12] VIN_AT_X +* +* This register controls to the pump's VIN_AT_XPX port pins with the following +* encoding; +* +* If VIN_BY_PASS=0 then pump VIN_AT_XPX is equal to VIN_AT_XIN input ports +* from the BATMON logic after clocking through synchronizers and the sequence +* checker FSM logic contained in the flash wrapper. +* +* If VIN_BY_PASS=1 and VIN_AT_X=??? +* +* 0: then all pump VIN_AT_XPX signals are 0. +* 1: then pump VIN_AT_1P7 is set. +* 2: then pump VIN_AT_2P1 is also set. +* 3: then pump VIN_AT_2P4 is also set. +* 4-7: then pump VIN_AT_3P0 is also set (ie all VIN_AT_XPX signals are 1). */ +#define FLASH_FSEQPMP_VIN_AT_X_M 0x00007000 +#define FLASH_FSEQPMP_VIN_AT_X_S 12 + +/* Field: [8] VIN_BY_PASS +* +* [Configured by boot firmware] +* +* When this bit is a zero, the pump's VIN_AT_XPX ports comes from the FMC +* input port VIN_AT_XIN. +* +* When this bit is a one, the pump's VIN_AT_XPX ports comes from the VIN_AT_X +* bits in 14:12. */ +#define FLASH_FSEQPMP_VIN_BY_PASS 0x00000100 +#define FLASH_FSEQPMP_VIN_BY_PASS_M 0x00000100 + +/****************************************************************************** +* +* Register: FLASH_O_FSM_PE_OSU +* +******************************************************************************/ +/* Field: [15:8] PGM_OSU +* +* [Configured by boot firmware] +* Program Operation Setup time. This determines the flash clocks from the mode +* change to program, to the start of the program pulse. */ +#define FLASH_FSM_PE_OSU_PGM_OSU_M 0x0000FF00 +#define FLASH_FSM_PE_OSU_PGM_OSU_S 8 + +/* Field: [7:0] ERA_OSU +* +* [Configured by boot firmware] +* Erase Operation Setup time. This determines the flash clocks from the mode +* change to erase, to the start of the erase pulse. */ +#define FLASH_FSM_PE_OSU_ERA_OSU_M 0x000000FF +#define FLASH_FSM_PE_OSU_ERA_OSU_S 0 + +/****************************************************************************** +* +* Register: FLASH_O_FSM_VSTAT +* +******************************************************************************/ +/* Field: [15:12] VSTAT_CNT +* +* [Configured by boot firmware] +* Voltage Status Count. Gives the number of consecutive HCLK pulses that must +* be out of range before a voltage-out-of-range status error is given in +* FMSTAT.VOLSTAT. One pulse in range will reset the counter. This is mainly a +* glitch filter on the voltage status pump signal. */ +#define FLASH_FSM_VSTAT_VSTAT_CNT_M 0x0000F000 +#define FLASH_FSM_VSTAT_VSTAT_CNT_S 12 + +/****************************************************************************** +* +* Register: FLASH_O_FSM_PE_VSU +* +******************************************************************************/ +/* Field: [15:8] PGM_VSU +* +* [Configured by boot firmware] +* Program Verify Setup time. This determines the flash clocks from the mode +* change to program verify, to the change of address and the beginning of the +* address setup time. */ +#define FLASH_FSM_PE_VSU_PGM_VSU_M 0x0000FF00 +#define FLASH_FSM_PE_VSU_PGM_VSU_S 8 + +/* Field: [7:0] ERA_VSU +* +* [Configured by boot firmware] +* Erase Verify Setup time. This determines the flash clocks from the mode +* change to erase verify, to the change of address and the beginning of the +* address setup time. */ +#define FLASH_FSM_PE_VSU_ERA_VSU_M 0x000000FF +#define FLASH_FSM_PE_VSU_ERA_VSU_S 0 + +/****************************************************************************** +* +* Register: FLASH_O_FSM_CMP_VSU +* +******************************************************************************/ +/* Field: [15:12] ADD_EXZ +* +* [Configured by boot firmware] +* Address to EXECUTEZ low setup time. This determines the flash clocks from +* the row address change to the time EXECUTEZ goes low. All operations use +* this value. */ +#define FLASH_FSM_CMP_VSU_ADD_EXZ_M 0x0000F000 +#define FLASH_FSM_CMP_VSU_ADD_EXZ_S 12 + +/****************************************************************************** +* +* Register: FLASH_O_FSM_EX_VAL +* +******************************************************************************/ +/* Field: [15:8] REP_VSU +* +* [Configured by boot firmware] +* Repeat Verify action setup. If a program or erase operation advances to the +* program_verify or erase_verify then this special shorter mode transition +* time will be used in place of FSM_PE_VSU.PGM_VSU or FSM_PE_VSU.ERA_VSU +* times. */ +#define FLASH_FSM_EX_VAL_REP_VSU_M 0x0000FF00 +#define FLASH_FSM_EX_VAL_REP_VSU_S 8 + +/* Field: [7:0] EXE_VALD +* +* [Configured by boot firmware] +* EXECUTEZ low to valid Data. Determines the number of Flash clock cycles from +* EXECUTEZ going low to the time the verify data can be read in the program +* verify mode. Erase and compact verify is always a constant value which is +* currently set at one flash clock. This value must be greater than 0. */ +#define FLASH_FSM_EX_VAL_EXE_VALD_M 0x000000FF +#define FLASH_FSM_EX_VAL_EXE_VALD_S 0 + +/****************************************************************************** +* +* Register: FLASH_O_FSM_RD_H +* +******************************************************************************/ +/* Field: [7:0] RD_H +* +* [Configured by boot firmware] +* Read mode hold. This determines the number of flash clocks from the start of +* the Read mode at the end of the operations until the FSM clears the +* FMSTAT.BUSY. Writing a zero to this register will result in a value of 1. +* The reset value of this register is 0x3Ah before FMC version 3.0.10.0 and +* 0x5Ah after this version. */ +#define FLASH_FSM_RD_H_RD_H_M 0x000000FF +#define FLASH_FSM_RD_H_RD_H_S 0 + +/****************************************************************************** +* +* Register: FLASH_O_FSM_P_OH +* +******************************************************************************/ +/* Field: [15:8] PGM_OH +* +* [Configured by boot firmware] +* EXECUTEZ high to mode change. This value determines the flash clocks from +* the EXECUTEZ going high at the end of a program operation to the time the +* mode can change. This value must be greater than or equal to one. */ +#define FLASH_FSM_P_OH_PGM_OH_M 0x0000FF00 +#define FLASH_FSM_P_OH_PGM_OH_S 8 + +/****************************************************************************** +* +* Register: FLASH_O_FSM_ERA_OH +* +******************************************************************************/ +/* Field: [15:0] ERA_OH +* +* [Configured by boot firmware] +* EXECUTEZ high to mode change. Determines the flash clocks from EXECUTEZ +* going high at the end of an erase operation to the time the mode can change. +* If a bank erase is happening, then this is the time to when the TEZ and TCR +* values for bank erase are released. The mode changes 10 flash clocks after +* they are released. This value must be greater than or equal to one. */ +#define FLASH_FSM_ERA_OH_ERA_OH_M 0x0000FFFF +#define FLASH_FSM_ERA_OH_ERA_OH_S 0 + +/****************************************************************************** +* +* Register: FLASH_O_FSM_PE_VH +* +******************************************************************************/ +/* Field: [15:8] PGM_VH +* +* [Configured by boot firmware] +* Program Verify Hold. This register determines the flash clocks from EXECUTEZ +* going high after a program verify to a mode change. This value must be +* greater than or equal to one */ +#define FLASH_FSM_PE_VH_PGM_VH_M 0x0000FF00 +#define FLASH_FSM_PE_VH_PGM_VH_S 8 + +/****************************************************************************** +* +* Register: FLASH_O_FSM_PRG_PW +* +******************************************************************************/ +/* Field: [15:0] PROG_PUL_WIDTH +* +* [Configured by boot firmware] +* Program Pulse width.This register gives the number of flash clocks that the +* EXECUTEZ signal is low in a program operation. */ +#define FLASH_FSM_PRG_PW_PROG_PUL_WIDTH_M 0x0000FFFF +#define FLASH_FSM_PRG_PW_PROG_PUL_WIDTH_S 0 + +/****************************************************************************** +* +* Register: FLASH_O_FSM_ERA_PW +* +******************************************************************************/ +/* Field: [31:0] FSM_ERA_PW +* +* [Configured by boot firmware] +* Erase Pulse width. This register gives the number flash clocks that the +* EXECUTEZ signal is low in an erase operation. */ +#define FLASH_FSM_ERA_PW_FSM_ERA_PW_M 0xFFFFFFFF +#define FLASH_FSM_ERA_PW_FSM_ERA_PW_S 0 + +/****************************************************************************** +* +* Register: FLASH_O_FSM_PRG_PUL +* +******************************************************************************/ +/* Field: [19:16] BEG_EC_LEVEL +* +* [Configured by boot firmware] +* Beginning level for VHVCT. This determines the beginning level for VHVCT +* that is used during erase modes. The pump voltage control registers supply +* the other values that do not change during FSM operations. The reset value +* is the same as FVHVCT1.VHVCT_E. */ +#define FLASH_FSM_PRG_PUL_BEG_EC_LEVEL_M 0x000F0000 +#define FLASH_FSM_PRG_PUL_BEG_EC_LEVEL_S 16 + +/* Field: [11:0] MAX_PRG_PUL +* +* [Configured by boot firmware] +* Maximum Programming Pulses. This register contains the maximum number of +* programming pulses allowed at one address. If it takes any more than this +* amount during a programming operation then the FSM will exit with an error +* and with the program violation, FMSTAT.PGV set, and the general error set, +* FMSTAT.CSTAT. Setting FSM_ST_MACHINE.OVERRIDE to 0 will allow more than this +* maximum value to occur without an error. During pre-conditioning for an +* erase operation the FSM programs all the bits to zero. If the maximum number +* of programming pulses is reached for an address, the FSM will continue with +* the next address and set the FMSTAT.PCV and the general error FMSTAT.CSTAT. +* If the FSM_ST_MACHINE.PREC_STOP_EN is set then the FSM will stop with errors +* when more than the maximum number of pulses is needed. The +* FSM_ST_MACHINE.OVERRIDE bit will take priority over the +* FSM_ST_MACHINE.PREC_STOP_EN and continue doing pulses without setting the +* error bits. Suspend operations will count a pulse if the program operation +* began no matter how long the pulse lasted before is was suspended. Frequent +* suspend or auto-suspend operations could result in max_pulse count error. */ +#define FLASH_FSM_PRG_PUL_MAX_PRG_PUL_M 0x00000FFF +#define FLASH_FSM_PRG_PUL_MAX_PRG_PUL_S 0 + +/****************************************************************************** +* +* Register: FLASH_O_FSM_ERA_PUL +* +******************************************************************************/ +/* Field: [19:16] MAX_EC_LEVEL +* +* [Configured by boot firmware] +* Maximum VHVCT Level. This determines the maximum level for VHVCT that is +* used during erase modes. The FSM will stop advancing VHVCT once it counts up +* to the MAX_EC_LEVEL level from the beginning level. The MAX_EC_LEVEL + +* FSM_EC_STEP_HEIGHT.EC_STEP_HEIGHT must be less than 0x200. The reset value +* is the same as FVHVCT1.VHVCT_E. */ +#define FLASH_FSM_ERA_PUL_MAX_EC_LEVEL_M 0x000F0000 +#define FLASH_FSM_ERA_PUL_MAX_EC_LEVEL_S 16 + +/* Field: [11:0] MAX_ERA_PUL +* +* [Configured by boot firmware] +* Maximum Erase Pulses. This register contains the maximum number of erase +* pulses allowed at one address. If it takes any more than this amount the FSM +* will exit with an error and with both the FMSTAT.EV and FMSTAT.CSTAT bits +* set. Setting FSM_ST_MACHINE.OVERRIDE to 1 will allow more than this maximum +* value to occur without an error. Suspend operations will count a pulse if +* the erase operation began no matter how long the pulse lasted before is was +* suspended. Frequent suspend or auto-suspend operations could result in +* max_pulse count error. */ +#define FLASH_FSM_ERA_PUL_MAX_ERA_PUL_M 0x00000FFF +#define FLASH_FSM_ERA_PUL_MAX_ERA_PUL_S 0 + +/****************************************************************************** +* +* Register: FLASH_O_FSM_STEP_SIZE +* +******************************************************************************/ +/* Field: [24:16] EC_STEP_SIZE +* +* [Configured by boot firmware] +* VHVCT Step Size. This is the number of erase pulses that must be completed +* for each level before the FSM increments the FSM_PUL_CNTR.CUR_EC_LEVEL to +* the next higher level. Actual erase pulses per level equals (EC_STEP_SIZE +* +1). The stepping is only needed for the VHVCT voltage. */ +#define FLASH_FSM_STEP_SIZE_EC_STEP_SIZE_M 0x01FF0000 +#define FLASH_FSM_STEP_SIZE_EC_STEP_SIZE_S 16 + +/****************************************************************************** +* +* Register: FLASH_O_FSM_EC_STEP_HEIGHT +* +******************************************************************************/ +/* Field: [3:0] EC_STEP_HEIGHT +* +* [Configured by boot firmware] +* Height of each EC step. This is the number of counts that the +* FSM_PUL_CNTR.CUR_EC_LEVEL will increment when going to a new level. Actual +* count size equals (EC_STEP_HEIGHT + 1). The stepping applies only to the +* VHVCT voltage. If adding the height to the FSM_PUL_CNTR.CUR_EC_LEVEL results +* in a value higher than the FSM_ERA_PUL.MAX_EC_LEVEL then the +* FSM_PUL_CNTR.CUR_EC_LEVEL will be lowered to the MAX LEVEL before it is used +* in the next erase pulse. */ +#define FLASH_FSM_EC_STEP_HEIGHT_EC_STEP_HEIGHT_M 0x0000000F + +/****************************************************************************** +* +* Register: FLASH_O_FSM_ST_MACHINE +* +******************************************************************************/ +/* Field: [23] DO_PRECOND +* +* [Configured by boot firmware] +* Do preconditioning. When this bit is a one, the FSM will precondition the +* sector or bank before doing an erase operation. When zero, the FSM will just +* begin with the erase verify and skip the preconditioning. */ +#define FLASH_FSM_ST_MACHINE_DO_PRECOND 0x00800000 +#define FLASH_FSM_ST_MACHINE_DO_PRECOND_M 0x00800000 +#define FLASH_FSM_ST_MACHINE_DO_PRECOND_S 23 + +/* Field: [14] ONE_TIME_GOOD +* +* [Configured by boot firmware] +* One Time Good function. If this bit is a one then the 'One Time Good' +* function is enabled for all program operations. This includes operations +* inside the erase functions and other functions. When zero, this function is +* disabled for all modes. When doing the One Time Good function, the FSM will +* attempt to program a location with data. If a desired zero bit reads back +* from the flash one time as good then that bit is blocked from writing a zero +* to the flash array again for this address. When the address changes, all +* bits are unblocked. This prevents a bit from reading 0 in one programming +* pulse and then 1 in the next programming pulse. On the second time the bit +* would get a programming pulse even though it read 0 in an earlier read. If +* this bit is a zero then the zero bits will be masked for each program verify +* operation. It is recommended for this bit to be set to 1. */ +#define FLASH_FSM_ST_MACHINE_ONE_TIME_GOOD 0x00004000 + +/****************************************************************************** +* +* Register: FLASH_O_FCFG_B0_SSIZE0 +* +******************************************************************************/ +/* Field: [3:0] B0_SECT_SIZE +* +* Size of sectors in Bank 0. Common sector size for all sectors in the bank in +* 1K bytes multiples. +* 0x0: 0K bytes +* 0x1: 1K bytes(FLES) +* 0x2: 2K bytes +* 0x4: 4K bytes (FLEE) +* ... +* 0xF: 15K bytes */ +#define FLASH_FCFG_B0_SSIZE0_B0_SECT_SIZE_M 0x0000000F +#define FLASH_FCFG_B0_SSIZE0_B0_SECT_SIZE_S 0 + +/****************************************************************************** +* +* This section defines the register offsets of FCFG1 component +* +******************************************************************************/ + +/* Flash Erase and Program Setup Time */ +#define FCFG1_O_FLASH_E_P 0x00000170 + +/* Flash Compaction, Execute, Program and Read */ +#define FCFG1_O_FLASH_C_E_P_R 0x00000174 + +/* Flash Program, Read, and Program Verify */ +#define FCFG1_O_FLASH_P_R_PV 0x00000178 + +/* Flash Erase Hold and Sequence */ +#define FCFG1_O_FLASH_EH_SEQ 0x0000017C + +/* Flash VHV Erase */ +#define FCFG1_O_FLASH_VHV_E 0x00000180 + +/* Flash Program Pulse */ +#define FCFG1_O_FLASH_PP 0x00000184 + +/* Flash Program and Erase Pulse */ +#define FCFG1_O_FLASH_PROG_EP 0x00000188 + +/* Flash Erase Pulse Width */ +#define FCFG1_O_FLASH_ERA_PW 0x0000018C + +/* Flash VHV */ +#define FCFG1_O_FLASH_VHV 0x00000190 + +/* Flash VHV Program Verify */ +#define FCFG1_O_FLASH_VHV_PV 0x00000194 + +/* Flash Voltages */ +#define FCFG1_O_FLASH_V 0x00000198 + +/* Flash OTP Data 3 */ +#define FCFG1_O_FLASH_OTP_DATA3 0x000002B0 + +/* Flash OTP Data 4 */ +#define FCFG1_O_FLASH_OTP_DATA4 0x00000308 + +/****************************************************************************** +* +* Register: FCFG1_O_FLASH_E_P +* +******************************************************************************/ +/* Field: [31:24] PSU +* +* Program setup time in cycles. Value will be written to +* FLASH:FSM_PE_OSU.PGM_OSU by the flash device driver when an erase/program +* operation is initiated. */ +#define FCFG1_FLASH_E_P_PSU_M 0xFF000000 +#define FCFG1_FLASH_E_P_PSU_S 24 + +/* Field: [23:16] ESU +* +* Erase setup time in cycles. Value will be written to +* FLASH:FSM_PE_OSU.ERA_OSU by the flash device driver when an erase/program +* operation is initiated. */ +#define FCFG1_FLASH_E_P_ESU_M 0x00FF0000 +#define FCFG1_FLASH_E_P_ESU_S 16 + +/* Field: [15:8] PVSU +* +* Program verify setup time in cycles. Value will be written to +* FLASH:FSM_PE_VSU.PGM_VSU by the flash device driver when an erase/program +* operation is initiated. */ +#define FCFG1_FLASH_E_P_PVSU_M 0x0000FF00 +#define FCFG1_FLASH_E_P_PVSU_S 8 + +/* Field: [7:0] EVSU +* +* Erase verify setup time in cycles. Value will be written to +* FLASH:FSM_PE_VSU.ERA_VSU by the flash device driver when an erase/program +* operation is initiated. */ +#define FCFG1_FLASH_E_P_EVSU_M 0x000000FF +#define FCFG1_FLASH_E_P_EVSU_S 0 + +/****************************************************************************** +* +* Register: FCFG1_O_FLASH_C_E_P_R +* +******************************************************************************/ +/* Field: [31:24] RVSU +* +* Repeat verify setup time in cycles. Used for repeated verifies during +* program and erase. Value will be written to FLASH:FSM_EX_VAL.REP_VSU by the +* flash device driver when an erase/program operation is initiated. */ +#define FCFG1_FLASH_C_E_P_R_RVSU_M 0xFF000000 +#define FCFG1_FLASH_C_E_P_R_RVSU_S 24 + +/* Field: [23:16] PV_ACCESS +* +* Program verify EXECUTEZ->data valid time in half-microseconds. Value +* will be converted to number of FCLK cycles by by flash device driver and the +* converted value is written to FLASH:FSM_EX_VAL.EXE_VALD when an +* erase/program operation is initiated. */ +#define FCFG1_FLASH_C_E_P_R_PV_ACCESS_M 0x00FF0000 +#define FCFG1_FLASH_C_E_P_R_PV_ACCESS_S 16 + +/* Field: [15:12] A_EXEZ_SETUP +* +* Address->EXECUTEZ setup time in cycles. Value will be written to +* FLASH:FSM_CMP_VSU.ADD_EXZ by the flash device driver when an erase/program +* operation is initiated. */ +#define FCFG1_FLASH_C_E_P_R_A_EXEZ_SETUP_M 0x0000F000 +#define FCFG1_FLASH_C_E_P_R_A_EXEZ_SETUP_S 12 + +/****************************************************************************** +* +* Register: FCFG1_O_FLASH_P_R_PV +* +******************************************************************************/ +/* Field: [31:24] PH +* +* Program hold time in half-microseconds after SAFELV goes high. Value will be +* converted to number of FCLK cycles by the flash device driver and the +* converted value is written to FLASH:FSM_P_OH.PGM_OH when an erase/program +* operation is initiated. */ +#define FCFG1_FLASH_P_R_PV_PH_M 0xFF000000 +#define FCFG1_FLASH_P_R_PV_PH_S 24 + +/* Field: [23:16] RH +* +* Read hold/mode transition time in cycles. Value will be written to the RD_H +* field bits[7:0] of the FSM_RD_H register in the flash module by the flash +* device driver when an erase/program operation is initiated. */ +#define FCFG1_FLASH_P_R_PV_RH_M 0x00FF0000 +#define FCFG1_FLASH_P_R_PV_RH_S 16 + +/* Field: [15:8] PVH +* +* Program verify hold time in half-microseconds after SAFELV goes high. Value +* will be converted to number of FCLK cycles by the flash device driver and +* the converted value is written to FLASH:FSM_PE_VH.PGM_VH when an +* erase/program operation is initiated. */ +#define FCFG1_FLASH_P_R_PV_PVH_M 0x0000FF00 +#define FCFG1_FLASH_P_R_PV_PVH_S 8 + +/****************************************************************************** +* +* Register: FCFG1_O_FLASH_EH_SEQ +* +******************************************************************************/ +/* Field: [31:24] EH +* +* Erase hold time in half-microseconds after SAFELV goes high. Value will be +* converted to number of FCLK cycles by the flash device driver and the +* converted value is written to FLASH:FSM_ERA_OH.ERA_OH when an erase/program +* operation is initiated. */ +#define FCFG1_FLASH_EH_SEQ_EH_M 0xFF000000 +#define FCFG1_FLASH_EH_SEQ_EH_S 24 + +/* Field: [15:12] VSTAT +* +* Max number of HCLK cycles allowed for pump brown-out. Value will be written +* to FLASH:FSM_VSTAT.VSTAT_CNT when an erase/program operation is initiated. */ +#define FCFG1_FLASH_EH_SEQ_VSTAT_M 0x0000F000 +#define FCFG1_FLASH_EH_SEQ_VSTAT_S 12 + +/****************************************************************************** +* +* Register: FCFG1_O_FLASH_VHV_E +* +******************************************************************************/ +/* Field: [31:16] VHV_E_START +* +* Starting VHV-Erase CT for stairstep erase. Value will be written to +* FLASH:FSM_PRG_PUL.BEG_EC_LEVEL when erase/program operation is initiated. */ +#define FCFG1_FLASH_VHV_E_VHV_E_START_M 0xFFFF0000 +#define FCFG1_FLASH_VHV_E_VHV_E_START_S 16 + +/* Field: [15:0] VHV_E_STEP_HIGHT +* +* Number of VHV CTs to step after each erase pulse (up to the max). The actual +* FMC register value should be one less than this since the FMC starts +* counting from zero. Value will be written to +* FLASH:FSM_EC_STEP_HEIGHT.EC_STEP_HEIGHT when an erase/program operation is +* initiated. */ +#define FCFG1_FLASH_VHV_E_VHV_E_STEP_HIGHT_M 0x0000FFFF +#define FCFG1_FLASH_VHV_E_VHV_E_STEP_HIGHT_S 0 + +/****************************************************************************** +* +* Register: FCFG1_O_FLASH_PP +* +******************************************************************************/ +/* Field: [15:0] MAX_PP +* +* Max program pulse limit per program operation. Value will be written to +* FLASH:FSM_PRG_PUL.MAX_PRG_PUL when an erase/program operation is initiated. */ +#define FCFG1_FLASH_PP_MAX_PP_M 0x0000FFFF +#define FCFG1_FLASH_PP_MAX_PP_S 0 + +/****************************************************************************** +* +* Register: FCFG1_O_FLASH_PROG_EP +* +******************************************************************************/ +/* Field: [31:16] MAX_EP +* +* Max erase pulse limit per erase operation. Value will be written to +* FLASH:FSM_ERA_PUL.MAX_ERA_PUL when an erase/program operation is initiated. */ +#define FCFG1_FLASH_PROG_EP_MAX_EP_M 0xFFFF0000 +#define FCFG1_FLASH_PROG_EP_MAX_EP_S 16 + +/* Field: [15:0] PROGRAM_PW +* +* Program pulse width in half-microseconds. Value will be converted to number +* of FCLK cycles by the flash device driver and the converted value is written +* to FLASH:FSM_PRG_PW.PROG_PUL_WIDTH when a erase/program operation is +* initiated. */ +#define FCFG1_FLASH_PROG_EP_PROGRAM_PW_M 0x0000FFFF +#define FCFG1_FLASH_PROG_EP_PROGRAM_PW_S 0 + +/****************************************************************************** +* +* Register: FCFG1_O_FLASH_ERA_PW +* +******************************************************************************/ +/* Field: [31:0] ERASE_PW +* +* Erase pulse width in half-microseconds. Value will be converted to number of +* FCLK cycles by the flash device driver and the converted value is written to +* FLASH:FSM_ERA_PW.FSM_ERA_PW when a erase/program operation is initiated. */ +#define FCFG1_FLASH_ERA_PW_ERASE_PW_M 0xFFFFFFFF +#define FCFG1_FLASH_ERA_PW_ERASE_PW_S 0 + +/****************************************************************************** +* +* Register: FCFG1_O_FLASH_VHV +* +******************************************************************************/ +/* Field: [27:24] TRIM13_P +* +* Value will be written to FLASH:FVHVCT2.TRIM13_P by the flash device driver +* when an erase/program operation is initiated. */ +#define FCFG1_FLASH_VHV_TRIM13_P_M 0x0F000000 +#define FCFG1_FLASH_VHV_TRIM13_P_S 24 + +/* Field: [19:16] VHV_P +* +* Value will be written to FLASH:FVHVCT2.VHVCT_P by the flash device driver +* when an erase/program operation is initiated. */ +#define FCFG1_FLASH_VHV_VHV_P_M 0x000F0000 +#define FCFG1_FLASH_VHV_VHV_P_S 16 + +/* Field: [11:8] TRIM13_E +* +* Value will be written to FLASH:FVHVCT1.TRIM13_E by the flash device driver +* when an erase/program operation is initiated. */ +#define FCFG1_FLASH_VHV_TRIM13_E_M 0x00000F00 +#define FCFG1_FLASH_VHV_TRIM13_E_S 8 + +/* Field: [3:0] VHV_E +* +* Value will be written to FLASH:FVHVCT1.VHVCT_E by the flash device driver +* when an erase/program operation is initiated */ +#define FCFG1_FLASH_VHV_VHV_E_M 0x0000000F +#define FCFG1_FLASH_VHV_VHV_E_S 0 + +/****************************************************************************** +* +* Register: FCFG1_O_FLASH_VHV_PV +* +******************************************************************************/ +/* Field: [27:24] TRIM13_PV +* +* Value will be written to FLASH:FVHVCT1.TRIM13_PV by the flash device driver +* when an erase/program operation is initiated. */ +#define FCFG1_FLASH_VHV_PV_TRIM13_PV_M 0x0F000000 +#define FCFG1_FLASH_VHV_PV_TRIM13_PV_S 24 + +/* Field: [19:16] VHV_PV +* +* Value will be written to FLASH:FVHVCT1.VHVCT_PV by the flash device driver +* when an erase/program operation is initiated. */ +#define FCFG1_FLASH_VHV_PV_VHV_PV_M 0x000F0000 +#define FCFG1_FLASH_VHV_PV_VHV_PV_S 16 + +/* Field: [15:8] VCG2P5 +* +* Control gate voltage during read, read margin, and erase verify. Value will +* be written to FLASH:FVNVCT.VCG2P5CT by the flash device driver when an +* erase/program operation is initiated. */ +#define FCFG1_FLASH_VHV_PV_VCG2P5_M 0x0000FF00 +#define FCFG1_FLASH_VHV_PV_VCG2P5_S 8 + +/****************************************************************************** +* +* Register: FCFG1_O_FLASH_V +* +******************************************************************************/ +/* Field: [31:24] VSL_P +* +* Sourceline voltage applied to the selected block during programming. Value +* will be written to FLASH:FVSLP.VSL_P by the flash device driver when an +* erase/program operation is initiated. */ +#define FCFG1_FLASH_V_VSL_P_M 0xFF000000 +#define FCFG1_FLASH_V_VSL_P_S 24 + +/* Field: [23:16] VWL_P +* +* Wordline voltage applied to the selected half-row during programming. Value +* will be written to FLASH:FVWLCT.VWLCT_P by the flash device driver when an +* erase/program operation is initiated. */ +#define FCFG1_FLASH_V_VWL_P_M 0x00FF0000 +#define FCFG1_FLASH_V_VWL_P_S 16 + +/* Field: [15:8] V_READ +* +* Wordline voltage applied to the selected block during reads and verifies. +* Value will be written to FLASH:FVREADCT.VREADCT by the flash device driver +* when an erase/program operation is initiated. */ +#define FCFG1_FLASH_V_V_READ_M 0x0000FF00 +#define FCFG1_FLASH_V_V_READ_S 8 + +/****************************************************************************** +* +* Register: FCFG1_O_FLASH_OTP_DATA3 +* +******************************************************************************/ +/* Field: [31:23] EC_STEP_SIZE +* +* Value will be written to FLASH:FSM_STEP_SIZE.EC_STEP_SIZE by the flash +* device driver when a erase/program operation is initiated. */ +#define FCFG1_FLASH_OTP_DATA3_EC_STEP_SIZE_M 0xFF800000 +#define FCFG1_FLASH_OTP_DATA3_EC_STEP_SIZE_S 23 + +/* Field: [22] DO_PRECOND +* +* Value will be written to FLASH:FSM_ST_MACHINE.DO_PRECOND by the flash device +* driver when a erase/program operation is initiated. +* +* Note that during a Total Erase operation the flash bank will always be +* erased with Precondition enabled independent of the value of this FCFG1 bit +* field. */ +#define FCFG1_FLASH_OTP_DATA3_DO_PRECOND_M 0x00400000 +#define FCFG1_FLASH_OTP_DATA3_DO_PRECOND_S 22 + +/* Field: [21:18] MAX_EC_LEVEL +* +* Value will be written to FLASH:FSM_ERA_PUL.MAX_EC_LEVEL by the flash device +* driver when a erase/program operation is initiated. */ +#define FCFG1_FLASH_OTP_DATA3_MAX_EC_LEVEL_M 0x003C0000 +#define FCFG1_FLASH_OTP_DATA3_MAX_EC_LEVEL_S 18 + +/* Field: [17:16] TRIM_1P7 +* +* Value will be written to FLASH:FSEQPMP.TRIM_1P7 by the flash device driver +* when a erase/program operation is initiated. */ +#define FCFG1_FLASH_OTP_DATA3_TRIM_1P7_M 0x00030000 +#define FCFG1_FLASH_OTP_DATA3_TRIM_1P7_S 16 + +/****************************************************************************** +* +* Register: FCFG1_O_FLASH_OTP_DATA4 +* +******************************************************************************/ +/* Field: [31] STANDBY_MODE_SEL_INT_WRT +* +* If AON_PMCTL:PWRCTL.EXT_REG_MODE = 0, this value will be written to +* FLASH:CFG.STANDBY_MODE_SEL by flash device driver FW when a flash write +* operation is initiated. */ +#define FCFG1_FLASH_OTP_DATA4_STANDBY_MODE_SEL_INT_WRT_M 0x80000000 +#define FCFG1_FLASH_OTP_DATA4_STANDBY_MODE_SEL_INT_WRT_S 31 + +/* Field: [30:29] STANDBY_PW_SEL_INT_WRT +* +* If AON_PMCTL:PWRCTL.EXT_REG_MODE = 0, this value will be written to +* FLASH:CFG.STANDBY_PW_SEL by flash device driver FW when a flash write +* operation is initiated. */ +#define FCFG1_FLASH_OTP_DATA4_STANDBY_PW_SEL_INT_WRT_M 0x60000000 +#define FCFG1_FLASH_OTP_DATA4_STANDBY_PW_SEL_INT_WRT_S 29 + +/* Field: [28] DIS_STANDBY_INT_WRT +* +* If AON_PMCTL:PWRCTL.EXT_REG_MODE = 0, this value will be written to +* FLASH:CFG.DIS_STANDBY by flash device driver FW when a flash write operation +* is initiated. */ +#define FCFG1_FLASH_OTP_DATA4_DIS_STANDBY_INT_WRT_M 0x10000000 + +/* Field: [27] DIS_IDLE_INT_WRT +* +* If AON_PMCTL:PWRCTL.EXT_REG_MODE = 0, this value will be written to +* FLASH:CFG.DIS_IDLE by flash device driver FW when a flash write operation is +* initiated. */ +#define FCFG1_FLASH_OTP_DATA4_DIS_IDLE_INT_WRT_M 0x08000000 +#define FCFG1_FLASH_OTP_DATA4_DIS_IDLE_INT_WRT_S 27 + +/* Field: [26:24] VIN_AT_X_INT_WRT +* +* If AON_PMCTL:PWRCTL.EXT_REG_MODE = 0, this value will be written to +* FLASH:FSEQPMP.VIN_AT_X by flash device driver FW when a flash write +* operation is initiated. */ +#define FCFG1_FLASH_OTP_DATA4_VIN_AT_X_INT_WRT_M 0x07000000 +#define FCFG1_FLASH_OTP_DATA4_VIN_AT_X_INT_WRT_S 24 + +/* Field: [23] STANDBY_MODE_SEL_EXT_WRT +* +* If AON_PMCTL:PWRCTL.EXT_REG_MODE = 1, this value will be written to +* FLASH:CFG.STANDBY_MODE_SEL by flash device driver FW when a flash write +* operation is initiated. */ +#define FCFG1_FLASH_OTP_DATA4_STANDBY_MODE_SEL_EXT_WRT_M 0x00800000 +#define FCFG1_FLASH_OTP_DATA4_STANDBY_MODE_SEL_EXT_WRT_S 23 + +/* Field: [22:21] STANDBY_PW_SEL_EXT_WRT +* +* If AON_PMCTL:PWRCTL.EXT_REG_MODE = 1, this value will be written to +* FLASH:CFG.STANDBY_PW_SEL by flash device driver FW when a flash write +* operation is initiated. */ +#define FCFG1_FLASH_OTP_DATA4_STANDBY_PW_SEL_EXT_WRT_M 0x00600000 +#define FCFG1_FLASH_OTP_DATA4_STANDBY_PW_SEL_EXT_WRT_S 21 + +/* Field: [20] DIS_STANDBY_EXT_WRT +* +* If AON_PMCTL:PWRCTL.EXT_REG_MODE = 1, this value will be written to +* FLASH:CFG.DIS_STANDBY by flash device driver FW when a flash write operation +* is initiated. */ +#define FCFG1_FLASH_OTP_DATA4_DIS_STANDBY_EXT_WRT_M 0x00100000 + +/* Field: [19] DIS_IDLE_EXT_WRT +* +* If AON_PMCTL:PWRCTL.EXT_REG_MODE = 1, this value will be written to +* FLASH:CFG.DIS_IDLE by flash device driver FW when a flash write operation is +* initiated. */ +#define FCFG1_FLASH_OTP_DATA4_DIS_IDLE_EXT_WRT_M 0x00080000 +#define FCFG1_FLASH_OTP_DATA4_DIS_IDLE_EXT_WRT_S 19 + +/* Field: [18:16] VIN_AT_X_EXT_WRT +* +* If AON_PMCTL:PWRCTL.EXT_REG_MODE = 1, this value will be written to +* FLASH:FSEQPMP.VIN_AT_X by flash device driver FW when a flash write +* operation is initiated. */ +#define FCFG1_FLASH_OTP_DATA4_VIN_AT_X_EXT_WRT_M 0x00070000 +#define FCFG1_FLASH_OTP_DATA4_VIN_AT_X_EXT_WRT_S 16 + +/* Field: [15] STANDBY_MODE_SEL_INT_RD +* +* If AON_PMCTL:PWRCTL.EXT_REG_MODE = 0, this value will be written to +* FLASH:CFG.STANDBY_MODE_SEL both by boot FW while in safezone, and by flash +* device driver FW after completion of a flash write operation. */ +#define FCFG1_FLASH_OTP_DATA4_STANDBY_MODE_SEL_INT_RD_M 0x00008000 +#define FCFG1_FLASH_OTP_DATA4_STANDBY_MODE_SEL_INT_RD_S 15 + +/* Field: [14:13] STANDBY_PW_SEL_INT_RD +* +* If AON_PMCTL:PWRCTL.EXT_REG_MODE = 0, this value will be written to +* FLASH:CFG.STANDBY_PW_SEL both by boot FW while in safezone, and by flash +* device driver FW after completion of a flash write operation. */ +#define FCFG1_FLASH_OTP_DATA4_STANDBY_PW_SEL_INT_RD_M 0x00006000 +#define FCFG1_FLASH_OTP_DATA4_STANDBY_PW_SEL_INT_RD_S 13 + +/* Field: [12] DIS_STANDBY_INT_RD +* +* If AON_PMCTL:PWRCTL.EXT_REG_MODE = 0, this value will be written to +* FLASH:CFG.DIS_STANDBY both by boot FW while in safezone, and by flash device +* driver FW after completion of a flash write operation. */ +#define FCFG1_FLASH_OTP_DATA4_DIS_STANDBY_INT_RD_M 0x00001000 + +/* Field: [11] DIS_IDLE_INT_RD +* +* If AON_PMCTL:PWRCTL.EXT_REG_MODE = 0, this value will be written to +* FLASH:CFG.DIS_IDLE both by boot FW while in safezone, and by flash device +* driver FW after completion of a flash write operation. */ +#define FCFG1_FLASH_OTP_DATA4_DIS_IDLE_INT_RD_M 0x00000800 +#define FCFG1_FLASH_OTP_DATA4_DIS_IDLE_INT_RD_S 11 + +/* Field: [10:8] VIN_AT_X_INT_RD +* +* If AON_PMCTL:PWRCTL.EXT_REG_MODE = 0, this value will be written to +* FLASH:FSEQPMP.VIN_AT_X both by boot FW while in safezone, and by flash +* device driver FW after completion of a flash write operation. */ +#define FCFG1_FLASH_OTP_DATA4_VIN_AT_X_INT_RD_M 0x00000700 +#define FCFG1_FLASH_OTP_DATA4_VIN_AT_X_INT_RD_S 8 + +/* Field: [7] STANDBY_MODE_SEL_EXT_RD +* +* If AON_PMCTL:PWRCTL.EXT_REG_MODE = 1, this value will be written to +* FLASH:CFG.STANDBY_MODE_SEL both by boot FW while in safezone, and by flash +* device driver FW after completion of a flash write operation. */ +#define FCFG1_FLASH_OTP_DATA4_STANDBY_MODE_SEL_EXT_RD_M 0x00000080 +#define FCFG1_FLASH_OTP_DATA4_STANDBY_MODE_SEL_EXT_RD_S 7 + +/* Field: [6:5] STANDBY_PW_SEL_EXT_RD +* +* If AON_PMCTL:PWRCTL.EXT_REG_MODE = 1, this value will be written to +* FLASH:CFG.STANDBY_PW_SEL both by boot FW while in safezone, and by flash +* device driver FW after completion of a flash write operation. */ +#define FCFG1_FLASH_OTP_DATA4_STANDBY_PW_SEL_EXT_RD_M 0x00000060 +#define FCFG1_FLASH_OTP_DATA4_STANDBY_PW_SEL_EXT_RD_S 5 + +/* Field: [4] DIS_STANDBY_EXT_RD +* +* If AON_PMCTL:PWRCTL.EXT_REG_MODE = 1, this value will be written to +* FLASH:CFG.DIS_STANDBY both by boot FW while in safezone, and by flash device +* driver FW after completion of a flash write operation. */ +#define FCFG1_FLASH_OTP_DATA4_DIS_STANDBY_EXT_RD_M 0x00000010 + +/* Field: [3] DIS_IDLE_EXT_RD +* +* If AON_PMCTL:PWRCTL.EXT_REG_MODE = 1, this value will be written to +* FLASH:CFG.DIS_IDLE both by boot FW while in safezone, and by flash device +* driver FW after completion of a flash write operation. */ +#define FCFG1_FLASH_OTP_DATA4_DIS_IDLE_EXT_RD_M 0x00000008 +#define FCFG1_FLASH_OTP_DATA4_DIS_IDLE_EXT_RD_S 3 + +/* Field: [2:0] VIN_AT_X_EXT_RD +* +* If AON_PMCTL:PWRCTL.EXT_REG_MODE = 1, this value will be written to +* FLASH:FSEQPMP.VIN_AT_X both by boot FW while in safezone, and by flash +* device driver FW after completion of a flash write operation. */ +#define FCFG1_FLASH_OTP_DATA4_VIN_AT_X_EXT_RD_M 0x00000007 +#define FCFG1_FLASH_OTP_DATA4_VIN_AT_X_EXT_RD_S 0 + +/****************************************************************************** +* +* This section defines the register offsets of AON_PMCTL component +* +******************************************************************************/ + +/* Power Management Control */ +#if defined(DEVICE_CC26X2) +/* Agama (CC26x2) specific definition */ +#define AON_PMCTL_O_PWRCTL 0x00000010 +#elif defined(DEVICE_CC26X0) +/* Chameleon (CC26x0) specific definition */ +#define AON_PMCTL_O_PWRCTL 0x00000000 +#endif + +/* Field: [1] EXT_REG_MODE +* +* Status of source for VDDRsupply: +* +* 0: DCDC or GLDO are generating VDDR +* 1: DCDC and GLDO are bypassed and an external regulator supplies VDDR */ +#define AON_PMCTL_PWRCTL_EXT_REG_MODE 0x00000002 + +#endif /* #ifndef OPENOCD_LOADERS_FLASH_CC26XX_HW_REGS_H */ diff --git a/contrib/loaders/flash/cc26xx/main.c b/contrib/loaders/flash/cc26xx/main.c new file mode 100644 index 0000000..13204b4 --- /dev/null +++ b/contrib/loaders/flash/cc26xx/main.c @@ -0,0 +1,179 @@ +/****************************************************************************** +* +* Copyright (C) 2017-2018 Texas Instruments Incorporated - http://www.ti.com/ +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the +* distribution. +* +* Neither the name of Texas Instruments Incorporated nor the names of +* its contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +******************************************************************************/ + +#include <stdint.h> +#include <stdbool.h> +#include "flashloader.h" + +/* Data buffers used by host to communicate with flashloader */ + +/* Flashloader parameter structure. */ +__attribute__ ((section(".buffers.g_cfg"))) +volatile struct flash_params g_cfg[2]; +/* Data buffer 1. */ +__attribute__ ((section(".buffers.g_buf1"))) +uint8_t g_buf1[BUFFER_LEN]; +/* Data buffer 2. */ +__attribute__ ((section(".buffers.g_buf2"))) +uint8_t g_buf2[BUFFER_LEN]; + +/* Buffer used for program with retain feature */ +__attribute__ ((section(".buffers.g_retain_buf"))) +uint8_t g_retain_buf[BUFFER_LEN]; + +uint32_t g_curr_buf; /* Current buffer used. */ +uint32_t g_vims_ctl; /* Saved flash cache state. */ + +/****************************************************************************** +* +* This function stores the current VIMS configuration before +* - disabling VIMS flash cache +* - flushing the flash line buffers. +* +* Note Not using driverlib calls because it requires using "NO_ROM" define in +* order to work for both Cha. R1 and R2 using the same code. Manually +* doing the steps to minimize code footprint. +* +******************************************************************************/ +static void disable_flash_cache() +{ + /* 1. Make sure VIMS is not currently changing mode (VIMS:STAT register) */ + while ((HWREG(0x40034000) & 0x00000008) == 0x8) + ; + + /* Save current VIMS:CTL state */ + g_vims_ctl = HWREG(0x40034004); + + /* 2. Set VIMS mode to OFF and disable flash line buffers */ + uint32_t new_vims_ctl = g_vims_ctl | 0x33; + HWREG(0x40034004) = new_vims_ctl; + + /* 3. Wait for VIMS to have changed mode (VIMS:STAT register) */ + while ((HWREG(0x40034000) & 0x00000008) == 0x8) + ; +} + +/****************************************************************************** +* +* This function restores the VIMS configuration saved off by +* disable_flash_cache(). +* +* Note Not using driverlib calls because it requires using "NO_ROM" define in +* order to work for both Cha. R1 and R2 using the same code. Manually +* doing the steps to minimize code footprint. +* +******************************************************************************/ +static void restore_cache_state() +{ + HWREG(0x40034004) = g_vims_ctl; + + /* Wait for VIMS to have changed mode (VIMS:STAT register) */ + while ((HWREG(0x40034000) & 0x00000008) == 0x8) + ; +} + +/****************************************************************************** +* +* CC13xx/CC26xx flashloader main function. +* +******************************************************************************/ +int main(void) +{ + flashloader_init((struct flash_params *)g_cfg, g_buf1, g_buf2); + + g_curr_buf = 0; /* start with the first buffer */ + uint32_t status; + + while (1) { + /* Wait for host to signal buffer is ready */ + while (g_cfg[g_curr_buf].full == BUFFER_EMPTY) + ; + + disable_flash_cache(); + + /* Perform requested task */ + switch (g_cfg[g_curr_buf].cmd) { + case CMD_ERASE_ALL: + status = flashloader_erase_all(); + break; + case CMD_PROGRAM: + status = + flashloader_program( + (uint8_t *)g_cfg[g_curr_buf].buf_addr, + g_cfg[g_curr_buf].dest, g_cfg[g_curr_buf].len); + break; + case CMD_ERASE_AND_PROGRAM: + status = + flashloader_erase_and_program( + (uint8_t *)g_cfg[g_curr_buf].buf_addr, + g_cfg[g_curr_buf].dest, g_cfg[g_curr_buf].len); + break; + case CMD_ERASE_AND_PROGRAM_WITH_RETAIN: + status = + flashloader_program_with_retain( + (uint8_t *)g_cfg[g_curr_buf].buf_addr, + g_cfg[g_curr_buf].dest, g_cfg[g_curr_buf].len); + break; + case CMD_ERASE_SECTORS: + status = + flashloader_erase_sectors(g_cfg[g_curr_buf].dest, + g_cfg[g_curr_buf].len); + break; + default: + status = STATUS_FAILED_UNKNOWN_COMMAND; + break; + } + + restore_cache_state(); + + /* Enter infinite loop on error condition */ + if (status != STATUS_OK) { + g_cfg[g_curr_buf].full = status; + while (1) + ; + } + + /* Mark current task complete, and begin looking at next buffer */ + g_cfg[g_curr_buf].full = BUFFER_EMPTY; + g_curr_buf ^= 1; + } +} + +void _exit(int status) +{ + /* Enter infinite loop on hitting an exit condition */ + (void)status; /* Unused parameter */ + while (1) + ; +} diff --git a/contrib/loaders/flash/cc26xx/startup.c b/contrib/loaders/flash/cc26xx/startup.c new file mode 100644 index 0000000..70fd836 --- /dev/null +++ b/contrib/loaders/flash/cc26xx/startup.c @@ -0,0 +1,97 @@ +/****************************************************************************** +* +* Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/ +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the +* distribution. +* +* Neither the name of Texas Instruments Incorporated nor the names of +* its contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +******************************************************************************/ + +#include <stdint.h> + +/****************************************************************************** +* +* The entry point for the application startup code. +* +******************************************************************************/ +extern int main(void); + +/****************************************************************************** +* +* Reserve space for the system stack. +* +******************************************************************************/ +__attribute__ ((section(".stack"))) +static uint32_t stack[100]; +const uint32_t stack_pntr = (uint32_t)stack + sizeof(stack); + +/****************************************************************************** +* +* The following are constructs created by the linker indicating where the +* the "bss" and "ebss" segments reside in memory. +* +******************************************************************************/ +extern uint32_t _bss; +extern uint32_t _ebss; + +/****************************************************************************** +* +* This is the entry point that handles setting the stack within the allowed +* workspace, initializing the .bss segment, and then jumping to main. +* +******************************************************************************/ +__attribute__ ((section(".entry"))) +void entry(void) +{ + /* Workaround for ITT instructions. */ + __asm(" NOP"); + __asm(" NOP"); + __asm(" NOP"); + __asm(" NOP"); + + /* Initialize stack pointer */ + __asm(" ldr sp, =stack_pntr"); + + /* Zero fill the bss segment. */ + __asm(" ldr r0, =_bss\n" + " ldr r1, =_ebss\n" + " mov r2, #0\n" + " .thumb_func\n" + " zero_loop:\n" + " cmp r0, r1\n" + " it lt\n" + " strlt r2, [r0], #4\n" + " blt zero_loop"); + + /* Call the application's entry point. */ + main(); + + /* If we ever return, enter an infinite loop */ + while (1) + ; +} diff --git a/contrib/loaders/flash/cc3220sf/Makefile b/contrib/loaders/flash/cc3220sf/Makefile new file mode 100644 index 0000000..d1dcc25 --- /dev/null +++ b/contrib/loaders/flash/cc3220sf/Makefile @@ -0,0 +1,19 @@ +BIN2C = ../../../../src/helper/bin2char.sh + +CROSS_COMPILE ?= arm-none-eabi- +AS = $(CROSS_COMPILE)as +OBJCOPY = $(CROSS_COMPILE)objcopy + +all: cc3220sf.inc + +%.elf: %.s + $(AS) $< -o $@ + +%.bin: %.elf + $(OBJCOPY) -Obinary $< $@ + +%.inc: %.bin + $(BIN2C) < $< > $@ + +clean: + -rm -f *.elf *.bin *.inc diff --git a/contrib/loaders/flash/cc3220sf/cc3220sf.inc b/contrib/loaders/flash/cc3220sf/cc3220sf.inc new file mode 100644 index 0000000..29c54c6 --- /dev/null +++ b/contrib/loaders/flash/cc3220sf/cc3220sf.inc @@ -0,0 +1,10 @@ +/* Autogenerated with ../../../../src/helper/bin2char.sh */ +0xdf,0xf8,0x7c,0xa0,0xdf,0xf8,0x7c,0xb0,0xdf,0xf8,0x7c,0xc0,0x01,0xf0,0x7f,0x03, +0x00,0x2b,0x1e,0xd1,0x4f,0xf0,0x00,0x04,0xcc,0xf8,0x00,0x10,0x03,0x68,0xcb,0xf8, +0x00,0x30,0x0b,0xf1,0x04,0x0b,0x00,0xf1,0x04,0x00,0xa2,0xf1,0x01,0x02,0x04,0xf1, +0x01,0x04,0x01,0xf1,0x04,0x01,0x00,0x2a,0x01,0xd0,0x20,0x2c,0xee,0xd1,0xcc,0xf8, +0x20,0xa0,0xdc,0xf8,0x20,0x30,0x13,0xf0,0x01,0x0f,0xfa,0xd1,0x00,0x2a,0xd7,0xd1, +0x13,0xe0,0xcc,0xf8,0x00,0x10,0x03,0x68,0xcc,0xf8,0x04,0x30,0xcc,0xf8,0x08,0xa0, +0xdc,0xf8,0x08,0x30,0x13,0xf0,0x01,0x0f,0xfa,0xd1,0xa2,0xf1,0x01,0x02,0x00,0xf1, +0x04,0x00,0x01,0xf1,0x04,0x01,0x00,0x2a,0xc2,0xd1,0x00,0xbe,0x01,0xbe,0xfc,0xe7, +0x01,0x00,0x42,0xa4,0x00,0xd1,0x0f,0x40,0x00,0xd0,0x0f,0x40, diff --git a/contrib/loaders/flash/cc3220sf/cc3220sf.s b/contrib/loaders/flash/cc3220sf/cc3220sf.s new file mode 100644 index 0000000..cffcfa0 --- /dev/null +++ b/contrib/loaders/flash/cc3220sf/cc3220sf.s @@ -0,0 +1,93 @@ +/*************************************************************************** + * Copyright (C) 2017 by Texas Instruments, Inc. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ + + /* Params: + * r0 = buffer start address (in) + * r1 = flash destination address (in) + * r2 = number of words to write (in/out) + */ + + .text + .cpu cortex-m4 + .code 16 + .thumb + .syntax unified + + .align 2 + + /* r3 = scratchpad + * r4 = buffer word counter + * r10 = flash programming key + * r11 = base FWB address + * r12 = base flash regs address + */ + +start: + ldr r10, =0xa4420001 /* flash programming key */ + ldr r11, =0x400fd100 /* base of FWB */ + ldr r12, =0x400fd000 /* base of flash regs */ + and r3, r1, #0x7f /* is the dest address 32 word aligned? */ + cmp r3, #0 + bne program_word /* if not aligned do one word at a time */ + + /* program using the write buffers */ +program_buffer: + mov r4, #0 /* start the buffer word counter at 0 */ + str r1, [r12] /* store the dest addr in FMA */ +fill_buffer: + ldr r3, [r0] /* get the word to write to FWB */ + str r3, [r11] /* store the word in the FWB */ + add r11, r11, #4 /* increment the FWB pointer */ + add r0, r0, #4 /* increment the source pointer */ + sub r2, r2, #1 /* decrement the total word counter */ + add r4, r4, #1 /* increment the buffer word counter */ + add r1, r1, #4 /* increment the dest pointer */ + cmp r2, #0 /* is the total word counter now 0? */ + beq buffer_ready /* go to end if total word counter is 0 */ + cmp r4, #32 /* is the buffer word counter now 32? */ + bne fill_buffer /* go to continue to fill buffer */ +buffer_ready: + str r10, [r12, #0x20] /* store the key and write bit to FMC2 */ +wait_buffer_done: + ldr r3, [r12, #0x20] /* read FMC2 */ + tst r3, #1 /* see if the write bit is cleared */ + bne wait_buffer_done /* go to read FMC2 if bit not cleared */ + cmp r2, #0 /* is the total word counter now 0? */ + bne start /* go if there is more to program */ + b exit + + /* program just one word */ +program_word: + str r1, [r12] /* store the dest addr in FMA */ + ldr r3, [r0] /* get the word to write to FMD */ + str r3, [r12, #0x4] /* store the word in FMD */ + str r10, [r12, #0x8] /* store the key and write bit to FMC */ +wait_word_done: + ldr r3, [r12, #0x8] /* read FMC */ + tst r3, #1 /* see if the write bit is cleared */ + bne wait_word_done /* go to read FMC if bit not cleared */ + sub r2, r2, #1 /* decrement the total word counter */ + add r0, r0, #4 /* increment the source pointer */ + add r1, r1, #4 /* increment the dest pointer */ + cmp r2, #0 /* is the total word counter now 0 */ + bne start /* go if there is more to program */ + + /* end */ +exit: + bkpt #0 + bkpt #1 + b exit diff --git a/contrib/loaders/flash/msp432/MSP432E4_FlashLibIf.h b/contrib/loaders/flash/msp432/MSP432E4_FlashLibIf.h new file mode 100644 index 0000000..d406d60 --- /dev/null +++ b/contrib/loaders/flash/msp432/MSP432E4_FlashLibIf.h @@ -0,0 +1,126 @@ +/****************************************************************************** +* +* Copyright (C) 2014-2018 Texas Instruments Incorporated - http://www.ti.com/ +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the +* distribution. +* +* Neither the name of Texas Instruments Incorporated nor the names of +* its contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +******************************************************************************/ + +#ifndef OPENOCD_LOADERS_FLASH_MSP432_MSP432E4_FLASHLIBIF_H +#define OPENOCD_LOADERS_FLASH_MSP432_MSP432E4_FLASHLIBIF_H + +#include <stddef.h> +#include <stdint.h> + +/* RAM loader */ +static const uint32_t RAM_LOADER_START = 0x20000000u; /* Code space */ +static const uint32_t RAM_LOADER_MAIN = 0x20000110u; /* Code space */ +static const uint32_t RAM_LOADER_BUFFER1 = 0x20002000u; /* SBUS data space */ +static const uint32_t RAM_LOADER_BUFFER2 = 0x20003000u; /* SBUS data space */ +static const uint32_t RAM_LOADER_STACK = 0x20002000u; /* SBUS data space */ + +/* Address for flash function to be executed */ +static const uint32_t FLASH_FUNCTION_ADDRESS = 0x20000150u; + +enum flash_command { + FLASH_NO_COMMAND = 0, + FLASH_MASS_ERASE = 1, + FLASH_SECTOR_ERASE = 2, + FLASH_PROGRAM = 4, + FLASH_INIT = 8, + FLASH_EXIT = 16, + FLASH_CONTINUOUS_PROGRAM = 32 +}; + +/* Address for algorithm program and flash buffer */ +static const uint32_t DST_ADDRESS = 0x2000015Cu; +static const uint32_t SRC_LENGTH_ADDRESS = 0x20000160u; +static const uint32_t BUFFER1_STATUS_REGISTER = 0x20000164u; +static const uint32_t BUFFER2_STATUS_REGISTER = 0x20000168u; +static const uint32_t BUFFER_INACTIVE = 0x00000000u; +static const uint32_t BUFFER_ACTIVE = 0x00000001u; +static const uint32_t BUFFER_DATA_READY = 0x00000010u; +static const size_t SRC_LENGTH_MAX = 4096u; + +/* Erase options */ +static const uint32_t ERASE_PARAM_ADDRESS = 0x2000016Cu; +static const uint32_t ERASE_MAIN = 0x00000001u; +static const uint32_t ERASE_INFO = 0x00000002u; + +/* Unlock BSL */ +static const uint32_t UNLOCK_BSL_ADDRESS = 0x20000170u; +static const uint32_t LOCK_BSL_KEY = 0x00000000u; +static const uint32_t UNLOCK_BSL_KEY = 0x0000000Bu; + +/* Address for return code */ +static const uint32_t RETURN_CODE_ADDRESS = 0x20000154u; + +/* Return codes */ +static const uint32_t FLASH_BUSY = 0x00000001u; +static const uint32_t FLASH_SUCCESS = 0x00000ACEu; +static const uint32_t FLASH_ERROR = 0x0000DEADu; +static const uint32_t FLASH_TIMEOUT_ERROR = 0xDEAD0000u; +static const uint32_t FLASH_VERIFY_ERROR = 0xDEADDEADu; +static const uint32_t FLASH_WRONG_COMMAND = 0x00000BADu; +static const uint32_t FLASH_POWER_ERROR = 0x00DEAD00u; + +/* Device ID address */ +static const uint32_t DEVICE_ID_ADDRESS = 0x0020100Cu; +static const uint32_t PC_REGISTER = 15u; +static const uint32_t SP_REGISTER = 13u; + +/* CS silicon and boot code revisions */ +static const uint32_t SILICON_REV_ADDRESS = 0x00201010u; +static const uint32_t SILICON_REV_A = 0x00000041u; +static const uint32_t SILICON_REV_B = 0x00000042u; +static const uint32_t SILICON_REV_C = 0x00000043u; +static const uint32_t SILICON_REV_D = 0x00000044u; +static const uint32_t SILICON_REV_E = 0x00000045u; +static const uint32_t SILICON_REV_F = 0x00000046u; +static const uint32_t SILICON_REV_G = 0x00000047u; +static const uint32_t SILICON_REV_H = 0x00000048u; +static const uint32_t SILICON_REV_I = 0x00000049u; +static const uint32_t SILICON_REV_B_WRONG = 0x00004100u; + +struct flash_interface { + volatile uint32_t FLASH_FUNCTION; + volatile uint32_t RETURN_CODE; + volatile uint32_t _RESERVED0; + volatile uint32_t DST_ADDRESS; + volatile uint32_t SRC_LENGTH; + volatile uint32_t BUFFER1_STATUS_REGISTER; + volatile uint32_t BUFFER2_STATUS_REGISTER; + volatile uint32_t ERASE_PARAM; + volatile uint32_t UNLOCK_BSL; +}; + +#define FLASH_LOADER_BASE ((uint32_t)0x20000150u) +#define FLASH_LOADER ((struct flash_interface *) FLASH_LOADER_BASE) + +#endif /* OPENOCD_LOADERS_FLASH_MSP432_MSP432E4_FLASHLIBIF_H */ diff --git a/contrib/loaders/flash/msp432/MSP432P4_FlashLibIf.h b/contrib/loaders/flash/msp432/MSP432P4_FlashLibIf.h new file mode 100644 index 0000000..c438097 --- /dev/null +++ b/contrib/loaders/flash/msp432/MSP432P4_FlashLibIf.h @@ -0,0 +1,126 @@ +/****************************************************************************** +* +* Copyright (C) 2014-2018 Texas Instruments Incorporated - http://www.ti.com/ +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the +* distribution. +* +* Neither the name of Texas Instruments Incorporated nor the names of +* its contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +******************************************************************************/ + +#ifndef OPENOCD_LOADERS_FLASH_MSP432_MSP432P4_FLASHLIBIF_H +#define OPENOCD_LOADERS_FLASH_MSP432_MSP432P4_FLASHLIBIF_H + +#include <stddef.h> +#include <stdint.h> + +/* RAM loader */ +static const uint32_t RAM_LOADER_START = 0x01000000u; /* Code space */ +static const uint32_t RAM_LOADER_MAIN = 0x01000110u; /* Code space */ +static const uint32_t RAM_LOADER_BUFFER1 = 0x20002000u; /* SBUS data space */ +static const uint32_t RAM_LOADER_BUFFER2 = 0x20003000u; /* SBUS data space */ +static const uint32_t RAM_LOADER_STACK = 0x20002000u; /* SBUS data space */ + +/* Address for flash function to be executed */ +static const uint32_t FLASH_FUNCTION_ADDRESS = 0x20000150u; + +enum flash_command { + FLASH_NO_COMMAND = 0, + FLASH_MASS_ERASE = 1, + FLASH_SECTOR_ERASE = 2, + FLASH_PROGRAM = 4, + FLASH_INIT = 8, + FLASH_EXIT = 16, + FLASH_CONTINUOUS_PROGRAM = 32 +}; + +/* Address for algorithm program and flash buffer */ +static const uint32_t DST_ADDRESS = 0x2000015Cu; +static const uint32_t SRC_LENGTH_ADDRESS = 0x20000160u; +static const uint32_t BUFFER1_STATUS_REGISTER = 0x20000164u; +static const uint32_t BUFFER2_STATUS_REGISTER = 0x20000168u; +static const uint32_t BUFFER_INACTIVE = 0x00000000u; +static const uint32_t BUFFER_ACTIVE = 0x00000001u; +static const uint32_t BUFFER_DATA_READY = 0x00000010u; +static const size_t SRC_LENGTH_MAX = 4096u; + +/* erase options */ +static const uint32_t ERASE_PARAM_ADDRESS = 0x2000016Cu; +static const uint32_t ERASE_MAIN = 0x00000001u; +static const uint32_t ERASE_INFO = 0x00000002u; + +/* Unlock BSL */ +static const uint32_t UNLOCK_BSL_ADDRESS = 0x20000170u; +static const uint32_t LOCK_BSL_KEY = 0x00000000u; +static const uint32_t UNLOCK_BSL_KEY = 0x0000000Bu; + +/* Address for return code */ +static const uint32_t RETURN_CODE_ADDRESS = 0x20000154u; + +/* Return codes */ +static const uint32_t FLASH_BUSY = 0x00000001u; +static const uint32_t FLASH_SUCCESS = 0x00000ACEu; +static const uint32_t FLASH_ERROR = 0x0000DEADu; +static const uint32_t FLASH_TIMEOUT_ERROR = 0xDEAD0000u; +static const uint32_t FLASH_VERIFY_ERROR = 0xDEADDEADu; +static const uint32_t FLASH_WRONG_COMMAND = 0x00000BADu; +static const uint32_t FLASH_POWER_ERROR = 0x00DEAD00u; + +/* Device ID address */ +static const uint32_t DEVICE_ID_ADDRESS = 0x0020100Cu; +static const uint32_t PC_REGISTER = 15u; +static const uint32_t SP_REGISTER = 13u; + +/* CS silicon and boot code revisions */ +static const uint32_t SILICON_REV_ADDRESS = 0x00201010u; +static const uint32_t SILICON_REV_A = 0x00000041u; +static const uint32_t SILICON_REV_B = 0x00000042u; +static const uint32_t SILICON_REV_C = 0x00000043u; +static const uint32_t SILICON_REV_D = 0x00000044u; +static const uint32_t SILICON_REV_E = 0x00000045u; +static const uint32_t SILICON_REV_F = 0x00000046u; +static const uint32_t SILICON_REV_G = 0x00000047u; +static const uint32_t SILICON_REV_H = 0x00000048u; +static const uint32_t SILICON_REV_I = 0x00000049u; +static const uint32_t SILICON_REV_B_WRONG = 0x00004100u; + +struct flash_interface { + volatile uint32_t FLASH_FUNCTION; + volatile uint32_t RETURN_CODE; + volatile uint32_t _RESERVED0; + volatile uint32_t DST_ADDRESS; + volatile uint32_t SRC_LENGTH; + volatile uint32_t BUFFER1_STATUS_REGISTER; + volatile uint32_t BUFFER2_STATUS_REGISTER; + volatile uint32_t ERASE_PARAM; + volatile uint32_t UNLOCK_BSL; +}; + +#define FLASH_LOADER_BASE ((uint32_t)0x20000150u) +#define FLASH_LOADER ((struct flash_interface *) FLASH_LOADER_BASE) + +#endif /* OPENOCD_LOADERS_FLASH_MSP432_MSP432P4_FLASHLIBIF_H */ diff --git a/contrib/loaders/flash/msp432/Makefile b/contrib/loaders/flash/msp432/Makefile new file mode 100644 index 0000000..6083331 --- /dev/null +++ b/contrib/loaders/flash/msp432/Makefile @@ -0,0 +1,99 @@ +BIN2C = ../../../../src/helper/bin2char.sh + +CROSS_COMPILE ?= arm-none-eabi- +GCC = $(CROSS_COMPILE)gcc +OBJCOPY = $(CROSS_COMPILE)objcopy + +FLAGS = -mcpu=cortex-m4 -march=armv7e-m -mfloat-abi=hard -mfpu=fpv4-sp-d16 -mthumb + +CFLAGS = -c -DNO_MSP_CLASSIC_DEFINES -Dgcc -Wall -ffunction-sections +CFLAGS += -fdata-sections -std=c99 -O4 + +LDFLAGS = -lc -lnosys -Wl,--gc-sections + +MSP432E4X_OBJS := \ +msp432e4x/driverlib.o \ +msp432e4x/main_msp432e4x.o \ +msp432e4x/startup_msp432e4.o + +MSP432P401X_OBJS := \ +msp432p401x/driverlib.o \ +msp432p401x/main_msp432p401x.o \ +msp432p401x/startup_msp432p4.o + +MSP432P411X_OBJS := \ +msp432p411x/driverlib.o \ +msp432p411x/main_msp432p411x.o \ +msp432p411x/startup_msp432p4.o + +all: msp432e4x_algo.inc msp432p401x_algo.inc msp432p411x_algo.inc + +msp432e4x/%.o: %.c + @echo 'Building file: $<' + @echo 'Invoking: GNU Compiler' + $(GCC) -D__MSP432E4X__ $(FLAGS) $(CFLAGS) -o"$@" "$(shell echo $<)" + @echo 'Finished building: $<' + @echo ' ' + +msp432p401x/%.o: %.c + @echo 'Building file: $<' + @echo 'Invoking: GNU Compiler' + $(GCC) -D__MSP432P401X__ $(FLAGS) $(CFLAGS) -o"$@" "$(shell echo $<)" + @echo 'Finished building: $<' + @echo ' ' + +msp432p411x/%.o: %.c + @echo 'Building file: $<' + @echo 'Invoking: GNU Compiler' + $(GCC) -D__MSP432P411X__ $(FLAGS) $(CFLAGS) -o"$@" "$(shell echo $<)" + @echo 'Finished building: $<' + @echo ' ' + +msp432e4x_algo.out: $(MSP432E4X_OBJS) + @echo 'Building target: $@' + @echo 'Invoking: GNU Linker' + $(GCC) $(FLAGS) $(LDFLAGS) -o$@ $(MSP432E4X_OBJS) -Tmsp432e4x/msp432e4x.lds + @echo 'Finished building target: $@' + @echo ' ' + +msp432p401x_algo.out: $(MSP432P401X_OBJS) + @echo 'Building target: $@' + @echo 'Invoking: GNU Linker' + $(GCC) $(FLAGS) $(LDFLAGS) -o$@ $(MSP432P401X_OBJS) -Tmsp432p401x/msp432p401x.lds + @echo 'Finished building target: $@' + @echo ' ' + +msp432p411x_algo.out: $(MSP432P411X_OBJS) + @echo 'Building target: $@' + @echo 'Invoking: GNU Linker' + $(GCC) $(FLAGS) $(LDFLAGS) -o$@ $(MSP432P411X_OBJS) -Tmsp432p411x/msp432p411x.lds + @echo 'Finished building target: $@' + @echo ' ' + +%.bin: %.out + @echo 'Building target: $@' + @echo 'Invoking: GNU Objcopy Utility' + $(OBJCOPY) -Obinary $< $@ + @echo 'Finished building target: $@' + @echo ' ' + +%.inc: %.bin + @echo 'Building target: $@' + @echo 'Invoking Bin2Char Script' + $(BIN2C) < $< > $@ + rm $< $*.out + @echo 'Finished building target: $@' + @echo ' ' + +clean: + @echo 'Cleaning Targets and Build Artifacts' + rm -rf *.inc *.bin *.out *.map + rm -rf msp432e4x/*.o msp432e4x/*.d + rm -rf msp432p401x/*.o msp432p401x/*.d + rm -rf msp432p411x/*.o msp432p411x/*.d + @echo 'Finished clean' + @echo ' ' + +.PRECIOUS: %.bin + +.PHONY: all clean diff --git a/contrib/loaders/flash/msp432/driverlib.c b/contrib/loaders/flash/msp432/driverlib.c new file mode 100644 index 0000000..a4f5416 --- /dev/null +++ b/contrib/loaders/flash/msp432/driverlib.c @@ -0,0 +1,472 @@ +/****************************************************************************** +* +* Copyright (C) 2017-2018 Texas Instruments Incorporated - http://www.ti.com/ +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the +* distribution. +* +* Neither the name of Texas Instruments Incorporated nor the names of +* its contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +******************************************************************************/ + +#include <stdint.h> +#include <stdbool.h> +#include "driverlib.h" + +/* + * Wrapper function for the CPSID instruction. + * Returns the state of PRIMASK on entry. + */ +uint32_t __attribute__((naked)) cpu_cpsid(void) +{ + uint32_t ret; + + /* Read PRIMASK and disable interrupts. */ + __asm(" mrs r0, PRIMASK\n" + " cpsid i\n" + " bx lr\n" + : "=r" (ret)); + + /* + * The return is handled in the inline assembly, but the compiler will + * still complain if there is not an explicit return here (despite the fact + * that this does not result in any code being produced because of the + * naked attribute). + */ + return ret; +} + +/* Wrapper function for the CPUWFI instruction. */ +void __attribute__((naked)) cpu_wfi(void) +{ + /* Wait for the next interrupt. */ + __asm(" wfi\n" + " bx lr\n"); +} + +/* Power Control Module APIs */ +#if defined(PCM) + +static bool __pcm_set_core_voltage_level_advanced(uint_fast8_t voltage_level, + uint32_t time_out, bool blocking) +{ + uint8_t power_mode; + uint8_t current_voltage_level; + uint32_t reg_value; + bool bool_timeout; + + /* Getting current power mode and level */ + power_mode = pcm_get_power_mode(); + current_voltage_level = pcm_get_core_voltage_level(); + + bool_timeout = time_out > 0 ? true : false; + + /* If we are already at the power mode they requested, return */ + if (current_voltage_level == voltage_level) + return true; + + while (current_voltage_level != voltage_level) { + + reg_value = PCM->CTL0; + + switch (pcm_get_power_state()) { + case PCM_AM_LF_VCORE1: + case PCM_AM_DCDC_VCORE1: + case PCM_AM_LDO_VCORE0: + PCM->CTL0 = (PCM_KEY | (PCM_AM_LDO_VCORE1) + | (reg_value & ~(PCM_CTL0_KEY_MASK | PCM_CTL0_AMR_MASK))); + break; + case PCM_AM_LF_VCORE0: + case PCM_AM_DCDC_VCORE0: + case PCM_AM_LDO_VCORE1: + PCM->CTL0 = (PCM_KEY | (PCM_AM_LDO_VCORE0) + | (reg_value & ~(PCM_CTL0_KEY_MASK | PCM_CTL0_AMR_MASK))); + break; + default: + break; + } + + if (blocking) { + while (BITBAND_PERI(PCM->CTL1, PCM_CTL1_PMR_BUSY_OFS)) { + if (bool_timeout && !(--time_out)) + return false; + } + } else + return true; + + current_voltage_level = pcm_get_core_voltage_level(); + } + + /* Changing the power mode if we are stuck in LDO mode */ + if (power_mode != pcm_get_power_mode()) { + if (power_mode == PCM_DCDC_MODE) + return pcm_set_power_mode(PCM_DCDC_MODE); + else + return pcm_set_power_mode(PCM_LF_MODE); + } + + return true; +} + +bool pcm_set_core_voltage_level(uint_fast8_t voltage_level) +{ + return __pcm_set_core_voltage_level_advanced(voltage_level, 0, true); +} + +uint8_t pcm_get_power_mode(void) +{ + uint8_t current_power_state; + + current_power_state = pcm_get_power_state(); + + switch (current_power_state) { + case PCM_AM_LDO_VCORE0: + case PCM_AM_LDO_VCORE1: + case PCM_LPM0_LDO_VCORE0: + case PCM_LPM0_LDO_VCORE1: + default: + return PCM_LDO_MODE; + case PCM_AM_DCDC_VCORE0: + case PCM_AM_DCDC_VCORE1: + case PCM_LPM0_DCDC_VCORE0: + case PCM_LPM0_DCDC_VCORE1: + return PCM_DCDC_MODE; + case PCM_LPM0_LF_VCORE0: + case PCM_LPM0_LF_VCORE1: + case PCM_AM_LF_VCORE1: + case PCM_AM_LF_VCORE0: + return PCM_LF_MODE; + } +} + +uint8_t pcm_get_core_voltage_level(void) +{ + uint8_t current_power_state = pcm_get_power_state(); + + switch (current_power_state) { + case PCM_AM_LDO_VCORE0: + case PCM_AM_DCDC_VCORE0: + case PCM_AM_LF_VCORE0: + case PCM_LPM0_LDO_VCORE0: + case PCM_LPM0_DCDC_VCORE0: + case PCM_LPM0_LF_VCORE0: + default: + return PCM_VCORE0; + case PCM_AM_LDO_VCORE1: + case PCM_AM_DCDC_VCORE1: + case PCM_AM_LF_VCORE1: + case PCM_LPM0_LDO_VCORE1: + case PCM_LPM0_DCDC_VCORE1: + case PCM_LPM0_LF_VCORE1: + return PCM_VCORE1; + case PCM_LPM3: + return PCM_VCORELPM3; + } +} + +static bool __pcm_set_power_mode_advanced(uint_fast8_t power_mode, + uint32_t time_out, bool blocking) +{ + uint8_t current_power_mode; + uint8_t current_power_state; + uint32_t reg_value; + bool bool_timeout; + + /* Getting Current Power Mode */ + current_power_mode = pcm_get_power_mode(); + + /* If the power mode being set it the same as the current mode, return */ + if (power_mode == current_power_mode) + return true; + + current_power_state = pcm_get_power_state(); + + bool_timeout = time_out > 0 ? true : false; + + /* Go through the while loop while we haven't achieved the power mode */ + while (current_power_mode != power_mode) { + + reg_value = PCM->CTL0; + + switch (current_power_state) { + case PCM_AM_DCDC_VCORE0: + case PCM_AM_LF_VCORE0: + PCM->CTL0 = (PCM_KEY | PCM_AM_LDO_VCORE0 + | (reg_value & ~(PCM_CTL0_KEY_MASK | PCM_CTL0_AMR_MASK))); + break; + case PCM_AM_LF_VCORE1: + case PCM_AM_DCDC_VCORE1: + PCM->CTL0 = (PCM_KEY | PCM_AM_LDO_VCORE1 + | (reg_value & ~(PCM_CTL0_KEY_MASK | PCM_CTL0_AMR_MASK))); + break; + case PCM_AM_LDO_VCORE1: { + if (power_mode == PCM_DCDC_MODE) { + PCM->CTL0 = (PCM_KEY | PCM_AM_DCDC_VCORE1 + | (reg_value & ~(PCM_CTL0_KEY_MASK + | PCM_CTL0_AMR_MASK))); + } else if (power_mode == PCM_LF_MODE) { + PCM->CTL0 = (PCM_KEY | PCM_AM_LF_VCORE1 + | (reg_value & ~(PCM_CTL0_KEY_MASK + | PCM_CTL0_AMR_MASK))); + } else + return false; + break; + } + case PCM_AM_LDO_VCORE0: { + if (power_mode == PCM_DCDC_MODE) { + PCM->CTL0 = (PCM_KEY | PCM_AM_DCDC_VCORE0 + | (reg_value & ~(PCM_CTL0_KEY_MASK + | PCM_CTL0_AMR_MASK))); + } else if (power_mode == PCM_LF_MODE) { + PCM->CTL0 = (PCM_KEY | PCM_AM_LF_VCORE0 + | (reg_value & ~(PCM_CTL0_KEY_MASK + | PCM_CTL0_AMR_MASK))); + } else + return false; + break; + } + default: + break; + } + + if (blocking) { + while (BITBAND_PERI(PCM->CTL1, PCM_CTL1_PMR_BUSY_OFS)) { + if (bool_timeout && !(--time_out)) + return false; + } + } else + return true; + + current_power_mode = pcm_get_power_mode(); + current_power_state = pcm_get_power_state(); + } + + return true; +} + +bool pcm_set_power_mode(uint_fast8_t power_mode) +{ + return __pcm_set_power_mode_advanced(power_mode, 0, true); +} + +static bool __pcm_set_power_state_advanced(uint_fast8_t power_state, + uint32_t timeout, bool blocking) +{ + uint8_t current_power_state; + current_power_state = pcm_get_power_state(); + + if (current_power_state == power_state) + return true; + + switch (power_state) { + case PCM_AM_LDO_VCORE0: + return __pcm_set_core_voltage_level_advanced(PCM_VCORE0, timeout, + blocking) && __pcm_set_power_mode_advanced(PCM_LDO_MODE, + timeout, blocking); + case PCM_AM_LDO_VCORE1: + return __pcm_set_core_voltage_level_advanced(PCM_VCORE1, timeout, + blocking) && __pcm_set_power_mode_advanced(PCM_LDO_MODE, + timeout, blocking); + case PCM_AM_DCDC_VCORE0: + return __pcm_set_core_voltage_level_advanced(PCM_VCORE0, timeout, + blocking) && __pcm_set_power_mode_advanced(PCM_DCDC_MODE, + timeout, blocking); + case PCM_AM_DCDC_VCORE1: + return __pcm_set_core_voltage_level_advanced(PCM_VCORE1, timeout, + blocking) && __pcm_set_power_mode_advanced(PCM_DCDC_MODE, + timeout, blocking); + case PCM_AM_LF_VCORE0: + return __pcm_set_core_voltage_level_advanced(PCM_VCORE0, timeout, + blocking) && __pcm_set_power_mode_advanced(PCM_LF_MODE, + timeout, blocking); + case PCM_AM_LF_VCORE1: + return __pcm_set_core_voltage_level_advanced(PCM_VCORE1, timeout, + blocking) && __pcm_set_power_mode_advanced(PCM_LF_MODE, + timeout, blocking); + case PCM_LPM0_LDO_VCORE0: + if (!__pcm_set_core_voltage_level_advanced(PCM_VCORE0, timeout, + blocking) || !__pcm_set_power_mode_advanced(PCM_LDO_MODE, + timeout, blocking)) + break; + return pcm_goto_lpm0(); + case PCM_LPM0_LDO_VCORE1: + if (!__pcm_set_core_voltage_level_advanced(PCM_VCORE1, timeout, + blocking) || !__pcm_set_power_mode_advanced(PCM_LDO_MODE, + timeout, blocking)) + break; + return pcm_goto_lpm0(); + case PCM_LPM0_DCDC_VCORE0: + if (!__pcm_set_core_voltage_level_advanced(PCM_VCORE0, timeout, + blocking) || !__pcm_set_power_mode_advanced(PCM_DCDC_MODE, + timeout, blocking)) + break; + return pcm_goto_lpm0(); + case PCM_LPM0_DCDC_VCORE1: + if (!__pcm_set_core_voltage_level_advanced(PCM_VCORE1, timeout, + blocking) || !__pcm_set_power_mode_advanced(PCM_DCDC_MODE, + timeout, blocking)) + break; + return pcm_goto_lpm0(); + case PCM_LPM0_LF_VCORE0: + if (!__pcm_set_core_voltage_level_advanced(PCM_VCORE0, timeout, + blocking) || !__pcm_set_power_mode_advanced(PCM_LF_MODE, + timeout, blocking)) + break; + return pcm_goto_lpm0(); + case PCM_LPM0_LF_VCORE1: + if (!__pcm_set_core_voltage_level_advanced(PCM_VCORE1, timeout, + blocking) || !__pcm_set_power_mode_advanced(PCM_LF_MODE, + timeout, blocking)) + break; + return pcm_goto_lpm0(); + case PCM_LPM3: + return pcm_goto_lpm3(); + case PCM_LPM4: + return pcm_goto_lpm4(); + case PCM_LPM45: + return pcm_shutdown_device(PCM_LPM45); + case PCM_LPM35_VCORE0: + return pcm_shutdown_device(PCM_LPM35_VCORE0); + default: + return false; + } + + return false; +} + +bool pcm_set_power_state(uint_fast8_t power_state) +{ + return __pcm_set_power_state_advanced(power_state, 0, true); +} + +bool pcm_shutdown_device(uint32_t shutdown_mode) +{ + uint32_t shutdown_mode_bits = (shutdown_mode == PCM_LPM45) ? + PCM_CTL0_LPMR_12 : PCM_CTL0_LPMR_10; + + /* If a power transition is occuring, return false */ + if (BITBAND_PERI(PCM->CTL1, PCM_CTL1_PMR_BUSY_OFS)) + return false; + + /* Initiating the shutdown */ + SCB->SCR |= SCB_SCR_SLEEPDEEP_MSK; + + PCM->CTL0 = (PCM_KEY | shutdown_mode_bits + | (PCM->CTL0 & ~(PCM_CTL0_KEY_MASK | PCM_CTL0_LPMR_MASK))); + + cpu_wfi(); + + return true; +} + +bool pcm_goto_lpm4(void) +{ + /* Disabling RTC_C and WDT_A */ + wdt_a_hold_timer(); + rtc_c_hold_clock(); + + /* LPM4 is just LPM3 with WDT_A/RTC_C disabled... */ + return pcm_goto_lpm3(); +} + +bool pcm_goto_lpm0(void) +{ + /* If we are in the middle of a state transition, return false */ + if (BITBAND_PERI(PCM->CTL1, PCM_CTL1_PMR_BUSY_OFS)) + return false; + + SCB->SCR &= ~SCB_SCR_SLEEPDEEP_MSK; + + cpu_wfi(); + + return true; +} + +bool pcm_goto_lpm3(void) +{ + uint_fast8_t current_power_state; + uint_fast8_t current_power_mode; + + /* If we are in the middle of a state transition, return false */ + if (BITBAND_PERI(PCM->CTL1, PCM_CTL1_PMR_BUSY_OFS)) + return false; + + /* If we are in the middle of a shutdown, return false */ + if ((PCM->CTL0 & PCM_CTL0_LPMR_MASK) == PCM_CTL0_LPMR_10 + || (PCM->CTL0 & PCM_CTL0_LPMR_MASK) == PCM_CTL0_LPMR_12) + return false; + + current_power_mode = pcm_get_power_mode(); + current_power_state = pcm_get_power_state(); + + if (current_power_mode == PCM_DCDC_MODE) + pcm_set_power_mode(PCM_LDO_MODE); + + /* Clearing the SDR */ + PCM->CTL0 = + (PCM->CTL0 & ~(PCM_CTL0_KEY_MASK | PCM_CTL0_LPMR_MASK)) | PCM_KEY; + + /* Setting the sleep deep bit */ + SCB->SCR |= SCB_SCR_SLEEPDEEP_MSK; + + cpu_wfi(); + + SCB->SCR &= ~SCB_SCR_SLEEPDEEP_MSK; + + return pcm_set_power_state(current_power_state); +} + +uint8_t pcm_get_power_state(void) +{ + return (PCM->CTL0 & PCM_CTL0_CPM_MASK) >> PCM_CTL0_CPM_OFS; +} + +#endif + +/* Real Time Clock APIs */ +#if defined(RTC_C) + +void rtc_c_hold_clock(void) +{ + RTC_C->CTL0 = (RTC_C->CTL0 & ~RTC_C_CTL0_KEY_MASK) | RTC_C_KEY; + BITBAND_PERI(RTC_C->CTL13, RTC_C_CTL13_HOLD_OFS) = 1; + BITBAND_PERI(RTC_C->CTL0, RTC_C_CTL0_KEY_OFS) = 0; +} + +#endif + +/* Watch Dog Timer APIs */ +#if defined(WDT_A) + +void wdt_a_hold_timer(void) +{ + /* Set Hold bit */ + uint8_t new_wdt_status = (WDT_A->CTL | WDT_A_CTL_HOLD); + + WDT_A->CTL = WDT_A_CTL_PW + new_wdt_status; +} + +#endif diff --git a/contrib/loaders/flash/msp432/driverlib.h b/contrib/loaders/flash/msp432/driverlib.h new file mode 100644 index 0000000..23ba7b5 --- /dev/null +++ b/contrib/loaders/flash/msp432/driverlib.h @@ -0,0 +1,384 @@ +/****************************************************************************** +* +* Copyright (C) 2017-2018 Texas Instruments Incorporated - http://www.ti.com/ +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the +* distribution. +* +* Neither the name of Texas Instruments Incorporated nor the names of +* its contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +******************************************************************************/ + +#ifndef OPENOCD_LOADERS_FLASH_MSP432_DRIVERLIB_H +#define OPENOCD_LOADERS_FLASH_MSP432_DRIVERLIB_H + +#include <stdint.h> +#include <stdbool.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(__MSP432E4X__) +#include "msp432e4x.h" +#elif defined(__MSP432P401X__) +#include "msp432p401x.h" +#elif defined(__MSP432P411X__) +#include "msp432p411x.h" +#else +#error "Failed to match a device specific include file" +#endif + +/* Structure type to access the System Control Block (SCB). */ +struct SCB_Type { + volatile uint32_t CPUID; /* CPUID Base Register */ + volatile uint32_t ICSR; /* Interrupt Control and State Register */ + volatile uint32_t VTOR; /* Vector Table Offset Register */ + volatile uint32_t AIRCR; /* Application Interrupt and Reset Control */ + volatile uint32_t SCR; /* System Control Register */ + volatile uint32_t CCR; /* Configuration Control Register */ + volatile uint8_t SHP[12U]; /* System Handlers Priority Registers */ + volatile uint32_t SHCSR; /* System Handler Control and State */ + volatile uint32_t CFSR; /* Configurable Fault Status Register */ + volatile uint32_t HFSR; /* HardFault Status Register */ + volatile uint32_t DFSR; /* Debug Fault Status Register */ + volatile uint32_t MMFAR; /* MemManage Fault Address Register */ + volatile uint32_t BFAR; /* BusFault Address Register */ + volatile uint32_t AFSR; /* Auxiliary Fault Status Register */ + volatile uint32_t PFR[2U]; /* Processor Feature Register */ + volatile uint32_t DFR; /* Debug Feature Register */ + volatile uint32_t ADR; /* Auxiliary Feature Register */ + volatile uint32_t MMFR[4U]; /* Memory Model Feature Register */ + volatile uint32_t ISAR[5U]; /* Instruction Set Attributes Register */ + uint32_t RESERVED0[5U]; + volatile uint32_t CPACR; /* Coprocessor Access Control Register */ +}; + +/* SCB:SCR register bits */ +#define SCB_SCR_SLEEPDEEP_POS 2U +#define SCB_SCR_SLEEPDEEP_MSK (1UL << SCB_SCR_SLEEPDEEP_POS) + +/* Memory mapping of Core Hardware */ +#define SCS_BASE (0xE000E000UL) /* System Control Space Base Address */ +#define SCB_BASE (SCS_BASE + 0x0D00UL) /* System Control Block Base Address */ +#define SCB ((struct SCB_Type *)SCB_BASE) /* SCB configuration struct */ + +/* Definitions of standard bits */ +#define BIT0 (uint16_t)(0x0001) +#define BIT1 (uint16_t)(0x0002) +#define BIT2 (uint16_t)(0x0004) +#define BIT3 (uint16_t)(0x0008) +#define BIT4 (uint16_t)(0x0010) +#define BIT5 (uint16_t)(0x0020) +#define BIT6 (uint16_t)(0x0040) +#define BIT7 (uint16_t)(0x0080) +#define BIT8 (uint16_t)(0x0100) +#define BIT9 (uint16_t)(0x0200) +#define BITA (uint16_t)(0x0400) +#define BITB (uint16_t)(0x0800) +#define BITC (uint16_t)(0x1000) +#define BITD (uint16_t)(0x2000) +#define BITE (uint16_t)(0x4000) +#define BITF (uint16_t)(0x8000) +#define BIT(x) ((uint16_t)1 << (x)) + +/* CPU Module prototypes */ +extern uint32_t cpu_cpsid(void); +extern void cpu_wfi(void); + +/* Clock Signal Module constants */ +#define CS_DCO_FREQUENCY_3 CS_CTL0_DCORSEL_1 +#define CS_DCO_FREQUENCY_24 CS_CTL0_DCORSEL_4 + +/* Power Control Module constants */ +#define PCM_KEY 0x695A0000 +#define PCM_AM_LDO_VCORE0 0x00 +#define PCM_AM_LDO_VCORE1 0x01 +#define PCM_AM_DCDC_VCORE0 0x04 +#define PCM_AM_DCDC_VCORE1 0x05 +#define PCM_AM_LF_VCORE0 0x08 +#define PCM_AM_LF_VCORE1 0x09 +#define PCM_LPM0_LDO_VCORE0 0x10 +#define PCM_LPM0_LDO_VCORE1 0x11 +#define PCM_LPM0_DCDC_VCORE0 0x14 +#define PCM_LPM0_DCDC_VCORE1 0x15 +#define PCM_LPM0_LF_VCORE0 0x18 +#define PCM_LPM0_LF_VCORE1 0x19 +#define PCM_LPM3 0x20 +#define PCM_LPM4 0x21 +#define PCM_LPM35_VCORE0 0xC0 +#define PCM_LPM45 0xA0 +#define PCM_VCORE0 0x00 +#define PCM_VCORE1 0x01 +#define PCM_VCORELPM3 0x02 +#define PCM_LDO_MODE 0x00 +#define PCM_DCDC_MODE 0x01 +#define PCM_LF_MODE 0x02 + +/* Power Control Module prototypes */ +extern bool pcm_set_core_voltage_level(uint_fast8_t voltage_level); +extern uint8_t pcm_get_core_voltage_level(void); +extern bool pcm_set_power_mode(uint_fast8_t power_mode); +extern uint8_t pcm_get_power_mode(void); +extern bool pcm_set_power_state(uint_fast8_t power_state); +extern uint8_t pcm_get_power_state(void); +extern bool pcm_shutdown_device(uint32_t shutdown_mode); +extern bool pcm_goto_lpm0(void); +extern bool pcm_goto_lpm3(void); +extern bool pcm_goto_lpm4(void); + +/* ROM API Function Pointers */ +#define ROM_API_TABLE ((unsigned long *)0x02000800) +#define ROM_FLASH_CTL_TABLE ((unsigned long *)(ROM_API_TABLE[7])) +#define ROM_PCM_TABLE ((unsigned long *)(ROM_API_TABLE[13])) +#define ROM_WDT_TABLE ((unsigned long *)(ROM_API_TABLE[25])) +#define ROM_SYS_CTL_A_TABLE ((unsigned long *)(ROM_API_TABLE[26])) +#define ROM_FLASH_CTL_A_TABLE ((unsigned long *)(ROM_API_TABLE[27])) + +#if defined(__MSP432P401X__) +#define ROM_FLASH_CTL_UNPROTECT_SECTOR \ + ((bool (*)(uint_fast8_t memory_space, \ + uint32_t sector_mask))ROM_FLASH_CTL_TABLE[4]) +#endif +#if defined(__MSP432P401X__) +#define ROM_FLASH_CTL_PROTECT_SECTOR \ + ((bool (*)(uint_fast8_t memory_space, \ + uint32_t sector_mask))ROM_FLASH_CTL_TABLE[5]) +#endif +#if defined(__MSP432P401X__) +#define ROM_FLASH_CTL_PERFORM_MASS_ERASE \ + ((bool (*)(void))ROM_FLASH_CTL_TABLE[8]) +#endif +#if defined(__MSP432P401X__) +#define ROM_FLASH_CTL_ERASE_SECTOR \ + ((bool (*)(uint32_t addr))ROM_FLASH_CTL_TABLE[9]) +#endif +#if defined(__MSP432P401X__) +#define ROM_FLASH_CTL_PROGRAM_MEMORY \ + ((bool (*)(void *src, void *dest, uint32_t length))ROM_FLASH_CTL_TABLE[10]) +#endif +#if defined(__MSP432P401X__) +#define ROM_FLASH_CTL_SET_WAIT_STATE \ + ((void (*)(uint32_t bank, uint32_t wait_state))ROM_FLASH_CTL_TABLE[21]) +#endif +#if defined(__MSP432P401X__) +#define ROM_FLASH_CTL_GET_WAIT_STATE \ + ((uint32_t (*)(uint32_t bank))ROM_FLASH_CTL_TABLE[22]) +#endif +#if defined(__MSP432P401X__) +#define ROM_PCM_SET_CORE_VOLTAGE_LEVEL \ + ((bool (*)(uint_fast8_t voltage_level))ROM_PCM_TABLE[0]) +#endif +#if defined(__MSP432P401X__) +#define ROM_PCM_GET_CORE_VOLTAGE_LEVEL \ + ((uint8_t (*)(void))ROM_PCM_TABLE[1]) +#endif +#if defined(__MSP432P401X__) +#define ROM_PCM_SET_POWER_STATE \ + ((bool (*)(uint_fast8_t power_state))ROM_PCM_TABLE[6]) +#endif +#if defined(__MSP432P401X__) +#define ROM_PCM_GET_POWER_STATE \ + ((uint8_t (*)(void))ROM_PCM_TABLE[8]) +#endif +#if defined(__MSP432P401X__) || defined(__MSP432P411X__) +#define ROM_WDT_A_HOLD_TIMER \ + ((void (*)(void))ROM_WDT_TABLE[0]) +#endif +#if defined(__MSP432P411X__) +#define ROM_SYS_CTL_A_GET_FLASH_SIZE \ + ((uint_least32_t (*)(void))ROM_SYS_CTL_A_TABLE[1]) +#endif +#if defined(__MSP432P411X__) +#define ROM_SYS_CTL_A_GET_INFO_FLASH_SIZE \ + ((uint_least32_t (*)(void))ROM_SYS_CTL_A_TABLE[18]) +#endif +#if defined(__MSP432P411X__) +#define ROM_FLASH_CTL_A_UNPROTECT_MEMORY \ + ((bool (*)(uint32_t start_addr, uint32_t end_addr))ROM_FLASH_CTL_A_TABLE[4]) +#endif +#if defined(__MSP432P411X__) +#define ROM_FLASH_CTL_A_PROTECT_MEMORY \ + ((bool (*)(uint32_t start_addr, uint32_t end_addr))ROM_FLASH_CTL_A_TABLE[5]) +#endif +#if defined(__MSP432P411X__) +#define ROM_FLASH_CTL_A_PERFORM_MASS_ERASE \ + ((bool (*)(void))ROM_FLASH_CTL_A_TABLE[8]) +#endif +#if defined(__MSP432P411X__) +#define ROM_FLASH_CTL_A_ERASE_SECTOR \ + ((bool (*)(uint32_t addr))ROM_FLASH_CTL_A_TABLE[9]) +#endif +#if defined(__MSP432P411X__) +#define ROM_FLASH_CTL_A_PROGRAM_MEMORY \ + ((bool (*)(void *src, void *dest, uint32_t length)) \ + ROM_FLASH_CTL_A_TABLE[10]) +#endif +#if defined(__MSP432P411X__) +#define ROM_FLASH_CTL_A_SET_WAIT_STATE \ + ((void (*)(uint32_t bank, uint32_t wait_state))ROM_FLASH_CTL_A_TABLE[21]) +#endif +#if defined(__MSP432P411X__) +#define ROM_FLASH_CTL_A_GET_WAIT_STATE \ + ((uint32_t (*)(uint32_t bank))ROM_FLASH_CTL_A_TABLE[22]) +#endif + +/* Map API functions to ROM or locally built functions */ +#ifdef ROM_FLASH_CTL_UNPROTECT_SECTOR +#define MAP_FLASH_CTL_UNPROTECT_SECTOR ROM_FLASH_CTL_UNPROTECT_SECTOR +#else +#define MAP_FLASH_CTL_UNPROTECT_SECTOR flash_ctl_unprotect_sector +#endif +#ifdef ROM_FLASH_CTL_PROTECT_SECTOR +#define MAP_FLASH_CTL_PROTECT_SECTOR ROM_FLASH_CTL_PROTECT_SECTOR +#else +#define MAP_FLASH_CTL_PROTECT_SECTOR flash_ctl_protect_sector +#endif +#ifdef ROM_FLASH_CTL_PERFORM_MASS_ERASE +#define MAP_FLASH_CTL_PERFORM_MASS_ERASE ROM_FLASH_CTL_PERFORM_MASS_ERASE +#else +#define MAP_FLASH_CTL_PERFORM_MASS_ERASE flash_ctl_perform_mass_erase +#endif +#ifdef ROM_FLASH_CTL_ERASE_SECTOR +#define MAP_FLASH_CTL_ERASE_SECTOR ROM_FLASH_CTL_ERASE_SECTOR +#else +#define MAP_FLASH_CTL_ERASE_SECTOR flash_ctl_erase_sector +#endif +#ifdef ROM_FLASH_CTL_PROGRAM_MEMORY +#define MAP_FLASH_CTL_PROGRAM_MEMORY ROM_FLASH_CTL_PROGRAM_MEMORY +#else +#define MAP_FLASH_CTL_PROGRAM_MEMORY flash_ctl_program_memory +#endif +#ifdef ROM_FLASH_CTL_SET_WAIT_STATE +#define MAP_FLASH_CTL_SET_WAIT_STATE ROM_FLASH_CTL_SET_WAIT_STATE +#else +#define MAP_FLASH_CTL_SET_WAIT_STATE flash_ctl_set_wait_state +#endif +#ifdef ROM_FLASH_CTL_GET_WAIT_STATE +#define MAP_FLASH_CTL_GET_WAIT_STATE ROM_FLASH_CTL_GET_WAIT_STATE +#else +#define MAP_FLASH_CTL_GET_WAIT_STATE flash_ctl_get_wait_state +#endif +#ifdef ROM_PCM_SET_CORE_VOLTAGE_LEVEL +#define MAP_PCM_SET_CORE_VOLTAGE_LEVEL ROM_PCM_SET_CORE_VOLTAGE_LEVEL +#else +#define MAP_PCM_SET_CORE_VOLTAGE_LEVEL pcm_set_core_voltage_level +#endif +#ifdef ROM_PCM_GET_CORE_VOLTAGE_LEVEL +#define MAP_PCM_GET_CORE_VOLTAGE_LEVEL ROM_PCM_GET_CORE_VOLTAGE_LEVEL +#else +#define MAP_PCM_GET_CORE_VOLTAGE_LEVEL pcm_get_core_voltage_level +#endif +#ifdef ROM_PCM_SET_POWER_STATE +#define MAP_PCM_SET_POWER_STATE ROM_PCM_SET_POWER_STATE +#else +#define MAP_PCM_SET_POWER_STATE pcm_set_power_state +#endif +#ifdef ROM_PCM_GET_POWER_STATE +#define MAP_PCM_GET_POWER_STATE ROM_PCM_GET_POWER_STATE +#else +#define MAP_PCM_GET_POWER_STATE pcm_get_power_state +#endif +#ifdef ROM_WDT_A_HOLD_TIMER +#define MAP_WDT_A_HOLD_TIMER ROM_WDT_A_HOLD_TIMER +#else +#define MAP_WDT_A_HOLD_TIMER wdt_a_hold_timer +#endif +#ifdef ROM_SYS_CTL_A_GET_FLASH_SIZE +#define MAP_SYS_CTL_A_GET_FLASH_SIZE ROM_SYS_CTL_A_GET_FLASH_SIZE +#else +#define MAP_SYS_CTL_A_GET_FLASH_SIZE sys_ctl_a_get_flash_size +#endif +#ifdef ROM_SYS_CTL_A_GET_INFO_FLASH_SIZE +#define MAP_SYS_CTL_A_GET_INFO_FLASH_SIZE ROM_SYS_CTL_A_GET_INFO_FLASH_SIZE +#else +#define MAP_SYS_CTL_A_GET_INFO_FLASH_SIZE sys_ctl_a_get_info_flash_size +#endif +#ifdef ROM_FLASH_CTL_A_UNPROTECT_MEMORY +#define MAP_FLASH_CTL_A_UNPROTECT_MEMORY ROM_FLASH_CTL_A_UNPROTECT_MEMORY +#else +#define MAP_FLASH_CTL_A_UNPROTECT_MEMORY flash_ctl_a_unprotect_memory +#endif +#ifdef ROM_FLASH_CTL_A_PROTECT_MEMORY +#define MAP_FLASH_CTL_A_PROTECT_MEMORY ROM_FLASH_CTL_A_PROTECT_MEMORY +#else +#define MAP_FLASH_CTL_A_PROTECT_MEMORY flash_ctl_a_protect_memory +#endif +#ifdef ROM_FLASH_CTL_A_PERFORM_MASS_ERASE +#define MAP_FLASH_CTL_A_PERFORM_MASS_ERASE ROM_FLASH_CTL_A_PERFORM_MASS_ERASE +#else +#define MAP_FLASH_CTL_A_PERFORM_MASS_ERASE flash_ctl_a_perform_mass_erase +#endif +#ifdef ROM_FLASH_CTL_A_ERASE_SECTOR +#define MAP_FLASH_CTL_A_ERASE_SECTOR ROM_FLASH_CTL_A_ERASE_SECTOR +#else +#define MAP_FLASH_CTL_A_ERASE_SECTOR flash_ctl_a_erase_sector +#endif +#ifdef ROM_FLASH_CTL_A_PROGRAM_MEMORY +#define MAP_FLASH_CTL_A_PROGRAM_MEMORY ROM_FLASH_CTL_A_PROGRAM_MEMORY +#else +#define MAP_FLASH_CTL_A_PROGRAM_MEMORY flash_ctl_a_program_memory +#endif +#ifdef ROM_FLASH_CTL_A_SET_WAIT_STATE +#define MAP_FLASH_CTL_A_SET_WAIT_STATE ROM_FLASH_CTL_A_SET_WAIT_STATE +#else +#define MAP_FLASH_CTL_A_SET_WAIT_STATE flash_ctl_a_set_wait_state +#endif +#ifdef ROM_FLASH_CTL_A_GET_WAIT_STATE +#define MAP_FLASH_CTL_A_GET_WAIT_STATE ROM_FLASH_CTL_A_GET_WAIT_STATE +#else +#define MAP_FLASH_CTL_A_GET_WAIT_STATE flash_ctl_a_get_wait_state +#endif + +/* Real Time Clock Module prototypes */ +extern void rtc_c_hold_clock(void); + +/* Watchdog Timer Module prototypes */ +extern void wdt_a_hold_timer(void); + +#if defined(__MCU_HAS_FLCTL_A__) +#define FLASH_A_BANK0 0x00 +#define FLASH_A_BANK1 0x01 +#define __INFO_FLASH_A_TECH_START__ 0x00200000 +#define __INFO_FLASH_A_TECH_MIDDLE__ 0x00204000 +#endif + +#if defined(__MCU_HAS_FLCTL__) +#define FLASH_BANK0 0x00 +#define FLASH_BANK1 0x01 +#define FLASH_MAIN_MEMORY_SPACE_BANK0 0x01 +#define FLASH_MAIN_MEMORY_SPACE_BANK1 0x02 +#define FLASH_INFO_MEMORY_SPACE_BANK0 0x03 +#define FLASH_INFO_MEMORY_SPACE_BANK1 0x04 +#define FLASH_SECTOR0 FLCTL_BANK0_MAIN_WEPROT_PROT0 +#define FLASH_SECTOR1 FLCTL_BANK0_MAIN_WEPROT_PROT1 +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* OPENOCD_LOADERS_FLASH_MSP432_DRIVERLIB_H */ diff --git a/contrib/loaders/flash/msp432/main_msp432e4x.c b/contrib/loaders/flash/msp432/main_msp432e4x.c new file mode 100644 index 0000000..23540ac --- /dev/null +++ b/contrib/loaders/flash/msp432/main_msp432e4x.c @@ -0,0 +1,351 @@ +/****************************************************************************** +* +* Copyright (C) 2017-2018 Texas Instruments Incorporated - http://www.ti.com/ +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the +* distribution. +* +* Neither the name of Texas Instruments Incorporated nor the names of +* its contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +******************************************************************************/ + +#include <stdint.h> +#include <stdbool.h> +#include "driverlib.h" + +#include "MSP432E4_FlashLibIf.h" + +/* Local prototypes */ +void msp432_flash_init(void); +void msp432_flash_mass_erase(void); +void msp432_flash_sector_erase(void); +void msp432_flash_write(void); +void msp432_flash_continous_write(void); +void msp432_flash_exit(void); + +int main(void) +{ + /* Disable interrupts */ + __asm(" cpsid i"); + + /* Halt watchdog */ + SYSCTL->RCGCWD &= ~(SYSCTL_RCGCWD_R1 + SYSCTL_RCGCWD_R0); + + while (1) { + switch (FLASH_LOADER->FLASH_FUNCTION) { + case FLASH_INIT: + FLASH_LOADER->RETURN_CODE = FLASH_BUSY; + msp432_flash_init(); + FLASH_LOADER->FLASH_FUNCTION = 0; + break; + case FLASH_MASS_ERASE: + FLASH_LOADER->RETURN_CODE = FLASH_BUSY; + msp432_flash_mass_erase(); + FLASH_LOADER->FLASH_FUNCTION = 0; + break; + case FLASH_SECTOR_ERASE: + FLASH_LOADER->RETURN_CODE = FLASH_BUSY; + msp432_flash_sector_erase(); + FLASH_LOADER->FLASH_FUNCTION = 0; + break; + case FLASH_PROGRAM: + case FLASH_CONTINUOUS_PROGRAM: + FLASH_LOADER->RETURN_CODE = FLASH_BUSY; + msp432_flash_continous_write(); + FLASH_LOADER->FLASH_FUNCTION = 0; + break; + case FLASH_EXIT: + FLASH_LOADER->RETURN_CODE = FLASH_BUSY; + msp432_flash_exit(); + FLASH_LOADER->FLASH_FUNCTION = 0; + break; + case FLASH_NO_COMMAND: + break; + default: + FLASH_LOADER->RETURN_CODE = FLASH_WRONG_COMMAND; + break; + } + } +} + +/* Initialize flash */ +void msp432_flash_init(void) +{ + SCB->VTOR = 0x20000000; + FLASH_LOADER->RETURN_CODE = FLASH_SUCCESS; +} + +/* Erase entire flash */ +void msp432_flash_mass_erase(void) +{ + bool success = false; + + /* Clear the flash access and error interrupts. */ + FLASH_CTRL->FCMISC = (FLASH_FCMISC_AMISC | FLASH_FCMISC_VOLTMISC | + FLASH_FCMISC_ERMISC | FLASH_FCMISC_PMISC); + + /* Trigger mass erase */ + FLASH_CTRL->FMC = FLASH_FMC_WRKEY | FLASH_FMC_MERASE; + while (FLASH_CTRL->FMC & FLASH_FMC_MERASE) + ; + + /* Return an error if an access violation occurred. */ + success = !(FLASH_CTRL->FCRIS & (FLASH_FCRIS_ARIS | FLASH_FCRIS_VOLTRIS | + FLASH_FCRIS_ERRIS)); + if (!success) + FLASH_LOADER->RETURN_CODE = FLASH_VERIFY_ERROR; + else + FLASH_LOADER->RETURN_CODE = FLASH_SUCCESS; +} + +/* Erase one flash sector */ +void msp432_flash_sector_erase(void) +{ + bool success = false; + + /* Clear the flash access and error interrupts. */ + FLASH_CTRL->FCMISC = (FLASH_FCMISC_AMISC | FLASH_FCMISC_VOLTMISC | + FLASH_FCMISC_ERMISC | FLASH_FCMISC_PMISC); + + /* Set 16kB aligned flash page address to be erased (16kB block) */ + FLASH_CTRL->FMA = FLASH_LOADER->DST_ADDRESS; + /* Trigger sector erase (erase flash page) */ + FLASH_CTRL->FMC = FLASH_FMC_WRKEY | FLASH_FMC_ERASE; + while (FLASH_CTRL->FMC & FLASH_FMC_ERASE) + ; + + /* Return an error if an access violation occurred. */ + success = !(FLASH_CTRL->FCRIS & (FLASH_FCRIS_ARIS | FLASH_FCRIS_VOLTRIS | + FLASH_FCRIS_ERRIS)); + + if (!success) + FLASH_LOADER->RETURN_CODE = FLASH_ERROR; + else + FLASH_LOADER->RETURN_CODE = FLASH_SUCCESS; +} + +/* Write data to flash */ +void msp432_flash_continous_write(void) +{ + bool buffer1_in_use = false; + bool buffer2_in_use = false; + uint32_t *src_address = NULL; + bool success = true; + uint32_t i = 0; + uint32_t address = FLASH_LOADER->DST_ADDRESS; + uint32_t data_to_write = FLASH_LOADER->SRC_LENGTH; + int32_t write_package = 0; + + /* Clear the flash access and error interrupts. */ + FLASH_CTRL->FCMISC = (FLASH_FCMISC_AMISC | FLASH_FCMISC_VOLTMISC | + FLASH_FCMISC_INVDMISC | FLASH_FCMISC_PROGMISC | FLASH_FCMISC_PMISC); + do { + if (data_to_write > SRC_LENGTH_MAX) { + write_package = SRC_LENGTH_MAX; + data_to_write -= write_package; + } else { + write_package = data_to_write; + data_to_write -= write_package; + } + while (!(FLASH_LOADER->BUFFER1_STATUS_REGISTER & BUFFER_DATA_READY) && + !(FLASH_LOADER->BUFFER2_STATUS_REGISTER & BUFFER_DATA_READY)) + ; + + if (FLASH_LOADER->BUFFER1_STATUS_REGISTER & BUFFER_DATA_READY) { + FLASH_LOADER->BUFFER1_STATUS_REGISTER |= BUFFER_ACTIVE; + src_address = (uint32_t *) RAM_LOADER_BUFFER1; + buffer1_in_use = true; + } else if (FLASH_LOADER->BUFFER2_STATUS_REGISTER & BUFFER_DATA_READY) { + FLASH_LOADER->BUFFER2_STATUS_REGISTER |= BUFFER_ACTIVE; + src_address = (uint32_t *) RAM_LOADER_BUFFER2; + buffer2_in_use = true; + } + + /* + * The flash hardware can only write complete words to flash. If + * an unaligned address is passed in, we must do a read-modify-write + * on a word with enough bytes to align the rest of the buffer. And + * if less than a whole word remains at the end, we must also do a + * read-modify-write on a final word to finish up. + */ + if (0 != (address & 0x3)) { + uint32_t head; + uint8_t *ui8head = (uint8_t *)&head; + uint8_t *buffer = (uint8_t *)src_address; + + /* Get starting offset for data to write (will be 1 to 3) */ + uint32_t head_offset = address & 0x03; + + /* Get the aligned address to write this first word to */ + uint32_t head_address = address & 0xfffffffc; + + /* Retrieve what is already in flash at the head address */ + head = *(uint32_t *)head_address; + + /* Substitute in the new data to write */ + while ((write_package > 0) && (head_offset < 4)) { + ui8head[head_offset] = *buffer; + head_offset++; + address++; + buffer++; + write_package--; + } + src_address = (uint32_t *)buffer; + + FLASH_CTRL->FMD = head; + FLASH_CTRL->FMA = head_address; + FLASH_CTRL->FMC = FLASH_FMC_WRKEY | FLASH_FMC_WRITE; + + /* Wait until the word has been programmed. */ + while (FLASH_CTRL->FMC & FLASH_FMC_WRITE) + ; + + /* Return an error if an access violation occurred. */ + success = !(FLASH_CTRL->FCRIS & (FLASH_FCRIS_ARIS | + FLASH_FCRIS_ERIS | FLASH_FCRIS_INVDRIS | FLASH_FCRIS_PROGRIS)); + } + + /* Program a word at a time until aligned on 32-word boundary */ + while ((write_package >= 4) && ((address & 0x7f) != 0) && success) { + FLASH_CTRL->FMD = *src_address++; + FLASH_CTRL->FMA = address; + FLASH_CTRL->FMC = FLASH_FMC_WRKEY | FLASH_FMC_WRITE; + + /* Wait until the word has been programmed. */ + while (FLASH_CTRL->FMC & FLASH_FMC_WRITE) + ; + + /* Prepare for next word to write */ + write_package -= 4; + address += 4; + + /* Return an error if an access violation occurred. */ + success = !(FLASH_CTRL->FCRIS & (FLASH_FCRIS_ARIS | + FLASH_FCRIS_ERIS | FLASH_FCRIS_INVDRIS | FLASH_FCRIS_PROGRIS)); + } + + /* Program data in 32-word blocks */ + while ((write_package >= 32) && success) { + /* Loop over the words in this 32-word block. */ + i = 0; + do { + FLASH_CTRL->FWBN[i] = *src_address++; + write_package -= 4; + i++; + } while ((write_package > 0) && (i < 32)); + FLASH_CTRL->FMA = address; + FLASH_CTRL->FMC2 = FLASH_FMC_WRKEY | FLASH_FMC2_WRBUF; + + /* Wait until the write buffer has been programmed. */ + while (FLASH_CTRL->FMC2 & FLASH_FMC2_WRBUF) + ; + + /* Increment destination address by words written */ + address += 128; + + /* Return an error if an access violation occurred. */ + success = !(FLASH_CTRL->FCRIS & (FLASH_FCRIS_ARIS | + FLASH_FCRIS_ERIS | FLASH_FCRIS_INVDRIS | FLASH_FCRIS_PROGRIS)); + } + + /* Program a word at a time on left over data */ + while ((write_package >= 4) && success) { + FLASH_CTRL->FMD = *src_address++; + FLASH_CTRL->FMA = address; + FLASH_CTRL->FMC = FLASH_FMC_WRKEY | FLASH_FMC_WRITE; + + /* Wait until the word has been programmed. */ + while (FLASH_CTRL->FMC & FLASH_FMC_WRITE) + ; + + /* Prepare for next word to write */ + write_package -= 4; + address += 4; + + /* Return an error if an access violation occurred. */ + success = !(FLASH_CTRL->FCRIS & (FLASH_FCRIS_ARIS | + FLASH_FCRIS_ERIS | FLASH_FCRIS_INVDRIS | FLASH_FCRIS_PROGRIS)); + } + + if ((write_package > 0) && success) { + uint32_t tail; + uint8_t *ui8tail = (uint8_t *)&tail; + uint8_t *buffer = (uint8_t *)src_address; + + /* Set starting offset for data to write */ + uint32_t tail_offset = 0; + + /* Get the address to write this last word to */ + uint32_t tail_address = address; + + /* Retrieve what is already in flash at the tail address */ + tail = *(uint32_t *)address; + + /* Substitute in the new data to write */ + while (write_package > 0) { + ui8tail[tail_offset] = *buffer; + tail_offset++; + address++; + buffer++; + write_package--; + } + + FLASH_CTRL->FMD = tail; + FLASH_CTRL->FMA = tail_address; + FLASH_CTRL->FMC = FLASH_FMC_WRKEY | FLASH_FMC_WRITE; + + /* Wait until the word has been programmed. */ + while (FLASH_CTRL->FMC & FLASH_FMC_WRITE) + ; + + /* Return an error if an access violation occurred. */ + success = !(FLASH_CTRL->FCRIS & (FLASH_FCRIS_ARIS | + FLASH_FCRIS_ERIS | FLASH_FCRIS_INVDRIS | FLASH_FCRIS_PROGRIS)); + } + + if (buffer1_in_use) { + FLASH_LOADER->BUFFER1_STATUS_REGISTER &= + ~(BUFFER_ACTIVE | BUFFER_DATA_READY); + buffer1_in_use = false; + } else if (buffer2_in_use) { + FLASH_LOADER->BUFFER2_STATUS_REGISTER &= + ~(BUFFER_ACTIVE | BUFFER_DATA_READY); + buffer2_in_use = false; + } + } while (success && data_to_write); + + if (!success) + FLASH_LOADER->RETURN_CODE = FLASH_ERROR; + else + FLASH_LOADER->RETURN_CODE = FLASH_SUCCESS; +} + +/* Exit flash programming */ +void msp432_flash_exit(void) +{ + SCB->VTOR = 0x00000000; + FLASH_LOADER->RETURN_CODE = FLASH_SUCCESS; +} diff --git a/contrib/loaders/flash/msp432/main_msp432p401x.c b/contrib/loaders/flash/msp432/main_msp432p401x.c new file mode 100644 index 0000000..7992f11 --- /dev/null +++ b/contrib/loaders/flash/msp432/main_msp432p401x.c @@ -0,0 +1,385 @@ +/****************************************************************************** +* +* Copyright (C) 2013-2018 Texas Instruments Incorporated - http://www.ti.com/ +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the +* distribution. +* +* Neither the name of Texas Instruments Incorporated nor the names of +* its contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +******************************************************************************/ + +#include <stdint.h> +#include <stdbool.h> +#include "driverlib.h" + +#include "MSP432P4_FlashLibIf.h" + +/* Number of erase repeats until timeout */ +#define FLASH_MAX_REPEATS 5 + +/* Local prototypes */ +void msp432_flash_init(void); +void msp432_flash_mass_erase(void); +void msp432_flash_sector_erase(void); +void msp432_flash_write(void); +void msp432_flash_continous_write(void); +void msp432_flash_exit(void); +void unlock_flash_sectors(void); +void unlock_all_flash_sectors(void); +void lock_all_flash_sectors(void); +void __cs_set_dco_frequency_range(uint32_t dco_freq); +static bool program_device(void *src, void *dest, uint32_t length); + +struct backup_params { + uint32_t BANK0_WAIT_RESTORE; + uint32_t BANK1_WAIT_RESTORE; + uint32_t CS_DC0_FREQ_RESTORE; + uint8_t VCORE_LEVEL_RESTORE; + uint8_t PCM_VCORE_LEVEL_RESTORE; +}; + +#define BACKUP_PARAMS ((struct backup_params *) 0x20000180) + +/* Main with trampoline */ +int main(void) +{ + /* Halt watchdog */ + MAP_WDT_A_HOLD_TIMER(); + + /* Disable interrupts */ + cpu_cpsid(); + + while (1) { + switch (FLASH_LOADER->FLASH_FUNCTION) { + case FLASH_INIT: + FLASH_LOADER->RETURN_CODE = FLASH_BUSY; + msp432_flash_init(); + FLASH_LOADER->FLASH_FUNCTION = 0; + break; + case FLASH_MASS_ERASE: + FLASH_LOADER->RETURN_CODE = FLASH_BUSY; + msp432_flash_mass_erase(); + FLASH_LOADER->FLASH_FUNCTION = 0; + break; + case FLASH_SECTOR_ERASE: + FLASH_LOADER->RETURN_CODE = FLASH_BUSY; + msp432_flash_sector_erase(); + FLASH_LOADER->FLASH_FUNCTION = 0; + break; + case FLASH_PROGRAM: + FLASH_LOADER->RETURN_CODE = FLASH_BUSY; + msp432_flash_write(); + FLASH_LOADER->FLASH_FUNCTION = 0; + break; + case FLASH_CONTINUOUS_PROGRAM: + FLASH_LOADER->RETURN_CODE = FLASH_BUSY; + msp432_flash_continous_write(); + FLASH_LOADER->FLASH_FUNCTION = 0; + break; + case FLASH_EXIT: + FLASH_LOADER->RETURN_CODE = FLASH_BUSY; + msp432_flash_exit(); + FLASH_LOADER->FLASH_FUNCTION = 0; + break; + case FLASH_NO_COMMAND: + break; + default: + FLASH_LOADER->RETURN_CODE = FLASH_WRONG_COMMAND; + break; + } + } +} + +/* Initialize flash */ +void msp432_flash_init(void) +{ + bool success = false; + + /* Point to vector table in RAM */ + SCB->VTOR = (uint32_t)0x01000000; + + /* backup system parameters */ + BACKUP_PARAMS->BANK0_WAIT_RESTORE = + MAP_FLASH_CTL_GET_WAIT_STATE(FLASH_BANK0); + BACKUP_PARAMS->BANK1_WAIT_RESTORE = + MAP_FLASH_CTL_GET_WAIT_STATE(FLASH_BANK1); + BACKUP_PARAMS->VCORE_LEVEL_RESTORE = MAP_PCM_GET_CORE_VOLTAGE_LEVEL(); + BACKUP_PARAMS->PCM_VCORE_LEVEL_RESTORE = MAP_PCM_GET_POWER_STATE(); + BACKUP_PARAMS->CS_DC0_FREQ_RESTORE = CS->CTL0 & CS_CTL0_DCORSEL_MASK; + + /* set parameters for flashing */ + success = MAP_PCM_SET_POWER_STATE(PCM_AM_LDO_VCORE0); + + /* Set Flash wait states to 2 */ + MAP_FLASH_CTL_SET_WAIT_STATE(FLASH_BANK0, 2); + MAP_FLASH_CTL_SET_WAIT_STATE(FLASH_BANK1, 2); + + /* Set CPU speed to 24MHz */ + __cs_set_dco_frequency_range(CS_DCO_FREQUENCY_24); + + if (!success) { + /* Indicate failed power switch */ + FLASH_LOADER->RETURN_CODE = FLASH_POWER_ERROR; + } else + FLASH_LOADER->RETURN_CODE = FLASH_SUCCESS; +} + +/* Erase entire flash */ +void msp432_flash_mass_erase(void) +{ + bool success = false; + + /* Allow flash writes */ + unlock_flash_sectors(); + + /* Allow some mass erase repeats before timeout with error */ + int erase_repeats = FLASH_MAX_REPEATS; + while (!success && (erase_repeats > 0)) { + /* Mass erase with post-verify */ + success = MAP_FLASH_CTL_PERFORM_MASS_ERASE(); + erase_repeats--; + } + + if (erase_repeats == 0) + FLASH_LOADER->RETURN_CODE = FLASH_VERIFY_ERROR; + else + FLASH_LOADER->RETURN_CODE = FLASH_SUCCESS; + + /* Block flash writes */ + lock_all_flash_sectors(); +} + +/* Erase one flash sector */ +void msp432_flash_sector_erase(void) +{ + bool success = false; + + /* Allow flash writes */ + unlock_all_flash_sectors(); + + /* Allow some sector erase repeats before timeout with error */ + int erase_repeats = FLASH_MAX_REPEATS; + while (!success && (erase_repeats > 0)) { + /* Sector erase with post-verify */ + success = MAP_FLASH_CTL_ERASE_SECTOR(FLASH_LOADER->DST_ADDRESS); + erase_repeats--; + } + + if (erase_repeats == 0) + FLASH_LOADER->RETURN_CODE = FLASH_ERROR; + else + FLASH_LOADER->RETURN_CODE = FLASH_SUCCESS; + + /* Block flash writes */ + lock_all_flash_sectors(); +} + +/* Write data to flash with the help of DriverLib */ +void msp432_flash_write(void) +{ + bool success = false; + + /* Allow flash writes */ + unlock_all_flash_sectors(); + + while (!(FLASH_LOADER->BUFFER1_STATUS_REGISTER & BUFFER_DATA_READY)) + ; + + FLASH_LOADER->BUFFER1_STATUS_REGISTER |= BUFFER_ACTIVE; + + /* Program memory */ + success = program_device((uint32_t *)RAM_LOADER_BUFFER1, + (void *)FLASH_LOADER->DST_ADDRESS, FLASH_LOADER->SRC_LENGTH); + + FLASH_LOADER->BUFFER1_STATUS_REGISTER &= + ~(BUFFER_ACTIVE | BUFFER_DATA_READY); + + /* Block flash writes */ + lock_all_flash_sectors(); + + if (!success) + FLASH_LOADER->RETURN_CODE = FLASH_ERROR; + else + FLASH_LOADER->RETURN_CODE = FLASH_SUCCESS; +} + +/* Write data to flash with the help of DriverLib with auto-increment */ +void msp432_flash_continous_write(void) +{ + bool buffer1_in_use = false; + bool buffer2_in_use = false; + uint32_t *src_address = NULL; + bool success = false; + + uint32_t bytes_to_write = FLASH_LOADER->SRC_LENGTH; + uint32_t write_package = 0; + uint32_t start_addr = FLASH_LOADER->DST_ADDRESS; + + while (bytes_to_write > 0) { + if (bytes_to_write > SRC_LENGTH_MAX) { + write_package = SRC_LENGTH_MAX; + bytes_to_write -= write_package; + } else { + write_package = bytes_to_write; + bytes_to_write -= write_package; + } + unlock_all_flash_sectors(); + + while (!(FLASH_LOADER->BUFFER1_STATUS_REGISTER & BUFFER_DATA_READY) && + !(FLASH_LOADER->BUFFER2_STATUS_REGISTER & BUFFER_DATA_READY)) + ; + + if (FLASH_LOADER->BUFFER1_STATUS_REGISTER & BUFFER_DATA_READY) { + FLASH_LOADER->BUFFER1_STATUS_REGISTER |= BUFFER_ACTIVE; + src_address = (uint32_t *)RAM_LOADER_BUFFER1; + buffer1_in_use = true; + } else if (FLASH_LOADER->BUFFER2_STATUS_REGISTER & BUFFER_DATA_READY) { + FLASH_LOADER->BUFFER2_STATUS_REGISTER |= BUFFER_ACTIVE; + src_address = (uint32_t *)RAM_LOADER_BUFFER2; + buffer2_in_use = true; + } + if (buffer1_in_use || buffer2_in_use) { + success = program_device(src_address, + (void *)start_addr, write_package); + + if (buffer1_in_use) + P6->OUT &= ~BIT4; /* Program from B1 */ + else if (buffer2_in_use) + P3->OUT &= ~BIT6; /* Program from B1 */ + + start_addr += write_package; + } + if (buffer1_in_use) { + FLASH_LOADER->BUFFER1_STATUS_REGISTER &= + ~(BUFFER_ACTIVE | BUFFER_DATA_READY); + buffer1_in_use = false; + } else if (buffer2_in_use) { + FLASH_LOADER->BUFFER2_STATUS_REGISTER &= + ~(BUFFER_ACTIVE | BUFFER_DATA_READY); + buffer2_in_use = false; + } + /* Block flash writes */ + lock_all_flash_sectors(); + + if (!success) { + FLASH_LOADER->RETURN_CODE = FLASH_ERROR; + break; + } + } + if (success) + FLASH_LOADER->RETURN_CODE = FLASH_SUCCESS; +} + +/* Unlock Main/Info Flash sectors */ +void unlock_flash_sectors(void) +{ + if (FLASH_LOADER->ERASE_PARAM & ERASE_MAIN) { + MAP_FLASH_CTL_UNPROTECT_SECTOR(FLASH_MAIN_MEMORY_SPACE_BANK0, + 0xFFFFFFFF); + MAP_FLASH_CTL_UNPROTECT_SECTOR(FLASH_MAIN_MEMORY_SPACE_BANK1, + 0xFFFFFFFF); + } + if (FLASH_LOADER->ERASE_PARAM & ERASE_INFO) { + MAP_FLASH_CTL_UNPROTECT_SECTOR(FLASH_INFO_MEMORY_SPACE_BANK0, + FLASH_SECTOR0 | FLASH_SECTOR1); + if (FLASH_LOADER->UNLOCK_BSL == UNLOCK_BSL_KEY) + MAP_FLASH_CTL_UNPROTECT_SECTOR(FLASH_INFO_MEMORY_SPACE_BANK1, + FLASH_SECTOR0 | FLASH_SECTOR1); + } +} + +/* Unlock All Flash sectors */ +void unlock_all_flash_sectors(void) +{ + MAP_FLASH_CTL_UNPROTECT_SECTOR(FLASH_MAIN_MEMORY_SPACE_BANK0, 0xFFFFFFFF); + MAP_FLASH_CTL_UNPROTECT_SECTOR(FLASH_MAIN_MEMORY_SPACE_BANK1, 0xFFFFFFFF); + MAP_FLASH_CTL_UNPROTECT_SECTOR(FLASH_INFO_MEMORY_SPACE_BANK0, + FLASH_SECTOR0 | FLASH_SECTOR1); + if (FLASH_LOADER->UNLOCK_BSL == UNLOCK_BSL_KEY) + MAP_FLASH_CTL_UNPROTECT_SECTOR(FLASH_INFO_MEMORY_SPACE_BANK1, + FLASH_SECTOR0 | FLASH_SECTOR1); +} + + +/* Lock all Flash sectors */ +void lock_all_flash_sectors(void) +{ + MAP_FLASH_CTL_PROTECT_SECTOR(FLASH_MAIN_MEMORY_SPACE_BANK0, 0xFFFFFFFF); + MAP_FLASH_CTL_PROTECT_SECTOR(FLASH_MAIN_MEMORY_SPACE_BANK1, 0xFFFFFFFF); + MAP_FLASH_CTL_PROTECT_SECTOR(FLASH_INFO_MEMORY_SPACE_BANK0, + FLASH_SECTOR0 | FLASH_SECTOR1); + MAP_FLASH_CTL_PROTECT_SECTOR(FLASH_INFO_MEMORY_SPACE_BANK1, + FLASH_SECTOR0 | FLASH_SECTOR1); +} + + +/* Force DCO frequency range */ +void __cs_set_dco_frequency_range(uint32_t dco_freq) +{ + /* Unlocking the CS Module */ + CS->KEY = CS_KEY_VAL; + + /* Resetting Tuning Parameters and Setting the frequency */ + CS->CTL0 = (CS->CTL0 & ~CS_CTL0_DCORSEL_MASK) | dco_freq; + + /* Locking the CS Module */ + CS->KEY = 0; +} + +/* Exit flash programming */ +void msp432_flash_exit(void) +{ + bool success = false; + + /* Restore modified registers, in reverse order */ + __cs_set_dco_frequency_range(CS_DCO_FREQUENCY_3); + + MAP_FLASH_CTL_SET_WAIT_STATE(FLASH_BANK0, + BACKUP_PARAMS->BANK0_WAIT_RESTORE); + MAP_FLASH_CTL_SET_WAIT_STATE(FLASH_BANK1, + BACKUP_PARAMS->BANK1_WAIT_RESTORE); + + success = MAP_PCM_SET_POWER_STATE(BACKUP_PARAMS->PCM_VCORE_LEVEL_RESTORE); + + success &= MAP_PCM_SET_CORE_VOLTAGE_LEVEL( + BACKUP_PARAMS->VCORE_LEVEL_RESTORE); + + __cs_set_dco_frequency_range(BACKUP_PARAMS->CS_DC0_FREQ_RESTORE); + + /* Point to vector table in Flash */ + SCB->VTOR = (uint32_t)0x00000000; + + if (!success) + FLASH_LOADER->RETURN_CODE = FLASH_ERROR; + else + FLASH_LOADER->RETURN_CODE = FLASH_SUCCESS; +} + +static bool program_device(void *src, void *dest, uint32_t length) +{ + return MAP_FLASH_CTL_PROGRAM_MEMORY(src, dest, length); +} diff --git a/contrib/loaders/flash/msp432/main_msp432p411x.c b/contrib/loaders/flash/msp432/main_msp432p411x.c new file mode 100644 index 0000000..be1f709 --- /dev/null +++ b/contrib/loaders/flash/msp432/main_msp432p411x.c @@ -0,0 +1,391 @@ +/****************************************************************************** +* +* Copyright (C) 2013-2018 Texas Instruments Incorporated - http://www.ti.com/ +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the +* distribution. +* +* Neither the name of Texas Instruments Incorporated nor the names of +* its contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +******************************************************************************/ + +#include <stdint.h> +#include <stdbool.h> +#include "driverlib.h" + +#include "MSP432P4_FlashLibIf.h" + +/* Number of erase repeats until timeout */ +#define FLASH_MAX_REPEATS 5 + +/* Local prototypes */ +void msp432_flash_init(void); +void msp432_flash_mass_erase(void); +void msp432_flash_sector_erase(void); +void msp432_flash_write(void); +void msp432_flash_continous_write(void); +void msp432_flash_exit(void); +void unlock_flash_sectors(void); +void unlock_all_flash_sectors(void); +void lock_all_flash_sectors(void); +void __cs_set_dco_frequency_range(uint32_t dco_freq); +static bool program_device(void *src, void *dest, uint32_t length); + +struct backup_params { + uint32_t BANK0_WAIT_RESTORE; + uint32_t BANK1_WAIT_RESTORE; + uint32_t CS_DC0_FREQ_RESTORE; + uint8_t VCORE_LEVEL_RESTORE; + uint8_t PCM_VCORE_LEVEL_RESTORE; +}; + +#define BACKUP_PARAMS ((struct backup_params *) 0x20000180) +#define INFO_FLASH_START __INFO_FLASH_A_TECH_START__ +#define INFO_FLASH_MIDDLE __INFO_FLASH_A_TECH_MIDDLE__ +#define BSL_FLASH_START BSL_API_TABLE_ADDR + +/* Main with trampoline */ +int main(void) +{ + /* Halt watchdog */ + MAP_WDT_A_HOLD_TIMER(); + + /* Disable interrupts */ + cpu_cpsid(); + + while (1) { + switch (FLASH_LOADER->FLASH_FUNCTION) { + case FLASH_INIT: + FLASH_LOADER->RETURN_CODE = FLASH_BUSY; + msp432_flash_init(); + FLASH_LOADER->FLASH_FUNCTION = 0; + break; + case FLASH_MASS_ERASE: + FLASH_LOADER->RETURN_CODE = FLASH_BUSY; + msp432_flash_mass_erase(); + FLASH_LOADER->FLASH_FUNCTION = 0; + break; + case FLASH_SECTOR_ERASE: + FLASH_LOADER->RETURN_CODE = FLASH_BUSY; + msp432_flash_sector_erase(); + FLASH_LOADER->FLASH_FUNCTION = 0; + break; + case FLASH_PROGRAM: + FLASH_LOADER->RETURN_CODE = FLASH_BUSY; + msp432_flash_write(); + FLASH_LOADER->FLASH_FUNCTION = 0; + break; + case FLASH_CONTINUOUS_PROGRAM: + FLASH_LOADER->RETURN_CODE = FLASH_BUSY; + msp432_flash_continous_write(); + FLASH_LOADER->FLASH_FUNCTION = 0; + break; + case FLASH_EXIT: + FLASH_LOADER->RETURN_CODE = FLASH_BUSY; + msp432_flash_exit(); + FLASH_LOADER->FLASH_FUNCTION = 0; + break; + case FLASH_NO_COMMAND: + break; + default: + FLASH_LOADER->RETURN_CODE = FLASH_WRONG_COMMAND; + break; + } + } +} + +/* Initialize flash */ +void msp432_flash_init(void) +{ + bool success = false; + + /* Point to vector table in RAM */ + SCB->VTOR = (uint32_t)0x01000000; + + /* backup system parameters */ + BACKUP_PARAMS->BANK0_WAIT_RESTORE = + MAP_FLASH_CTL_A_GET_WAIT_STATE(FLASH_A_BANK0); + BACKUP_PARAMS->BANK1_WAIT_RESTORE = + MAP_FLASH_CTL_A_GET_WAIT_STATE(FLASH_A_BANK1); + BACKUP_PARAMS->VCORE_LEVEL_RESTORE = MAP_PCM_GET_CORE_VOLTAGE_LEVEL(); + BACKUP_PARAMS->PCM_VCORE_LEVEL_RESTORE = MAP_PCM_GET_POWER_STATE(); + BACKUP_PARAMS->CS_DC0_FREQ_RESTORE = CS->CTL0 & CS_CTL0_DCORSEL_MASK; + + /* set parameters for flashing */ + success = MAP_PCM_SET_POWER_STATE(PCM_AM_LDO_VCORE0); + + /* Set Flash wait states to 2 */ + MAP_FLASH_CTL_A_SET_WAIT_STATE(FLASH_A_BANK0, 2); + MAP_FLASH_CTL_A_SET_WAIT_STATE(FLASH_A_BANK1, 2); + + /* Set CPU speed to 24MHz */ + __cs_set_dco_frequency_range(CS_DCO_FREQUENCY_24); + + if (!success) { + /* Indicate failed power switch */ + FLASH_LOADER->RETURN_CODE = FLASH_POWER_ERROR; + } else + FLASH_LOADER->RETURN_CODE = FLASH_SUCCESS; +} + +/* Erase entire flash */ +void msp432_flash_mass_erase(void) +{ + bool success = false; + + /* Allow flash writes */ + unlock_flash_sectors(); + + /* Allow some mass erase repeats before timeout with error */ + int erase_repeats = FLASH_MAX_REPEATS; + while (!success && (erase_repeats > 0)) { + /* Mass erase with post-verify */ + success = ROM_FLASH_CTL_A_PERFORM_MASS_ERASE(); + erase_repeats--; + } + + if (erase_repeats == 0) + FLASH_LOADER->RETURN_CODE = FLASH_VERIFY_ERROR; + else + FLASH_LOADER->RETURN_CODE = FLASH_SUCCESS; + + /* Block flash writes */ + lock_all_flash_sectors(); +} + +/* Erase one flash sector */ +void msp432_flash_sector_erase(void) +{ + bool success = false; + + /* Allow flash writes */ + unlock_all_flash_sectors(); + + /* Allow some sector erase repeats before timeout with error */ + int erase_repeats = FLASH_MAX_REPEATS; + while (!success && (erase_repeats > 0)) { + /* Sector erase with post-verify */ + success = MAP_FLASH_CTL_A_ERASE_SECTOR(FLASH_LOADER->DST_ADDRESS); + erase_repeats--; + } + + if (erase_repeats == 0) + FLASH_LOADER->RETURN_CODE = FLASH_ERROR; + else + FLASH_LOADER->RETURN_CODE = FLASH_SUCCESS; + + /* Block flash writes */ + lock_all_flash_sectors(); +} + +/* Write data to flash with the help of DriverLib */ +void msp432_flash_write(void) +{ + bool success = false; + + /* Allow flash writes */ + unlock_all_flash_sectors(); + + while (!(FLASH_LOADER->BUFFER1_STATUS_REGISTER & BUFFER_DATA_READY)) + ; + + FLASH_LOADER->BUFFER1_STATUS_REGISTER |= BUFFER_ACTIVE; + + /* Program memory */ + success = program_device((uint32_t *)RAM_LOADER_BUFFER1, + (void *)FLASH_LOADER->DST_ADDRESS, FLASH_LOADER->SRC_LENGTH); + + FLASH_LOADER->BUFFER1_STATUS_REGISTER &= + ~(BUFFER_ACTIVE | BUFFER_DATA_READY); + + /* Block flash writes */ + lock_all_flash_sectors(); + + if (!success) + FLASH_LOADER->RETURN_CODE = FLASH_ERROR; + else + FLASH_LOADER->RETURN_CODE = FLASH_SUCCESS; +} + +/* Write data to flash with the help of DriverLib with auto-increment */ +void msp432_flash_continous_write(void) +{ + bool buffer1_in_use = false; + bool buffer2_in_use = false; + uint32_t *src_address = NULL; + bool success = false; + + uint32_t bytes_to_write = FLASH_LOADER->SRC_LENGTH; + uint32_t write_package = 0; + uint32_t start_addr = FLASH_LOADER->DST_ADDRESS; + + while (bytes_to_write > 0) { + if (bytes_to_write > SRC_LENGTH_MAX) { + write_package = SRC_LENGTH_MAX; + bytes_to_write -= write_package; + } else { + write_package = bytes_to_write; + bytes_to_write -= write_package; + } + unlock_all_flash_sectors(); + while (!(FLASH_LOADER->BUFFER1_STATUS_REGISTER & BUFFER_DATA_READY) && + !(FLASH_LOADER->BUFFER2_STATUS_REGISTER & BUFFER_DATA_READY)) + ; + + if (FLASH_LOADER->BUFFER1_STATUS_REGISTER & BUFFER_DATA_READY) { + FLASH_LOADER->BUFFER1_STATUS_REGISTER |= BUFFER_ACTIVE; + src_address = (uint32_t *) RAM_LOADER_BUFFER1; + buffer1_in_use = true; + } else if (FLASH_LOADER->BUFFER2_STATUS_REGISTER & BUFFER_DATA_READY) { + FLASH_LOADER->BUFFER2_STATUS_REGISTER |= BUFFER_ACTIVE; + src_address = (uint32_t *) RAM_LOADER_BUFFER2; + buffer2_in_use = true; + } + if (buffer1_in_use || buffer2_in_use) { + success = program_device(src_address, (void *) start_addr, write_package); + start_addr += write_package; + } + if (buffer1_in_use) { + FLASH_LOADER->BUFFER1_STATUS_REGISTER &= ~(BUFFER_ACTIVE | BUFFER_DATA_READY); + buffer1_in_use = false; + } else if (buffer2_in_use) { + FLASH_LOADER->BUFFER2_STATUS_REGISTER &= ~(BUFFER_ACTIVE | BUFFER_DATA_READY); + buffer2_in_use = false; + } + /* Block flash writes */ + lock_all_flash_sectors(); + + if (!success) { + FLASH_LOADER->RETURN_CODE = FLASH_ERROR; + break; + } + } + if (success) + FLASH_LOADER->RETURN_CODE = FLASH_SUCCESS; +} + +/* Unlock Main/Info Flash sectors */ +void unlock_flash_sectors(void) +{ + if (FLASH_LOADER->ERASE_PARAM & ERASE_MAIN) + MAP_FLASH_CTL_A_UNPROTECT_MEMORY(FLASH_BASE, FLASH_BASE + + MAP_SYS_CTL_A_GET_FLASH_SIZE() - 1); + + if (FLASH_LOADER->ERASE_PARAM & ERASE_INFO) { + MAP_FLASH_CTL_A_UNPROTECT_MEMORY(INFO_FLASH_START, TLV_BASE - 1); + if (FLASH_LOADER->UNLOCK_BSL == UNLOCK_BSL_KEY) + MAP_FLASH_CTL_A_UNPROTECT_MEMORY(BSL_FLASH_START, + INFO_FLASH_MIDDLE - 1); + MAP_FLASH_CTL_A_UNPROTECT_MEMORY(INFO_FLASH_MIDDLE, INFO_FLASH_MIDDLE + + MAP_SYS_CTL_A_GET_INFO_FLASH_SIZE() - 1); + } +} + +/* Unlock All Flash sectors */ +void unlock_all_flash_sectors(void) +{ + MAP_FLASH_CTL_A_UNPROTECT_MEMORY(FLASH_BASE, FLASH_BASE + + MAP_SYS_CTL_A_GET_FLASH_SIZE() - 1); + MAP_FLASH_CTL_A_UNPROTECT_MEMORY(INFO_FLASH_START, TLV_BASE - 1); + if (FLASH_LOADER->UNLOCK_BSL == UNLOCK_BSL_KEY) + MAP_FLASH_CTL_A_UNPROTECT_MEMORY(BSL_FLASH_START, + INFO_FLASH_MIDDLE - 1); + MAP_FLASH_CTL_A_UNPROTECT_MEMORY(INFO_FLASH_MIDDLE, INFO_FLASH_MIDDLE + + MAP_SYS_CTL_A_GET_INFO_FLASH_SIZE() - 1); +} + +/* Lock all Flash sectors */ +void lock_all_flash_sectors(void) +{ + MAP_FLASH_CTL_A_PROTECT_MEMORY(FLASH_BASE, FLASH_BASE + + MAP_SYS_CTL_A_GET_FLASH_SIZE() - 1); + MAP_FLASH_CTL_A_PROTECT_MEMORY(INFO_FLASH_START, INFO_FLASH_START + + MAP_SYS_CTL_A_GET_INFO_FLASH_SIZE() - 1); +} + +/* Force DCO frequency range */ +void __cs_set_dco_frequency_range(uint32_t dco_freq) +{ + /* Unlocking the CS Module */ + CS->KEY = CS_KEY_VAL; + + /* Resetting Tuning Parameters and Setting the frequency */ + CS->CTL0 = (CS->CTL0 & ~CS_CTL0_DCORSEL_MASK) | dco_freq; + + /* Locking the CS Module */ + CS->KEY = 0; +} + +/* Exit flash programming */ +void msp432_flash_exit(void) +{ + bool success = false; + + /* Restore modified registers, in reverse order */ + __cs_set_dco_frequency_range(CS_DCO_FREQUENCY_3); + + MAP_FLASH_CTL_A_SET_WAIT_STATE(FLASH_A_BANK0, + BACKUP_PARAMS->BANK0_WAIT_RESTORE); + MAP_FLASH_CTL_A_SET_WAIT_STATE(FLASH_A_BANK1, + BACKUP_PARAMS->BANK1_WAIT_RESTORE); + + success = MAP_PCM_SET_POWER_STATE(BACKUP_PARAMS->PCM_VCORE_LEVEL_RESTORE); + + success &= MAP_PCM_SET_CORE_VOLTAGE_LEVEL( + BACKUP_PARAMS->VCORE_LEVEL_RESTORE); + + __cs_set_dco_frequency_range(BACKUP_PARAMS->CS_DC0_FREQ_RESTORE); + + /* Point to vector table in Flash */ + SCB->VTOR = (uint32_t)0x00000000; + + if (!success) + FLASH_LOADER->RETURN_CODE = FLASH_ERROR; + else + FLASH_LOADER->RETURN_CODE = FLASH_SUCCESS; +} + +static bool program_device(void *src, void *dest, uint32_t length) +{ + uint32_t dst_address = (uint32_t)dest; + + /* Flash main memory first, then information memory */ + if ((dst_address < INFO_FLASH_START) && ((dst_address + length) > + INFO_FLASH_START)) { + uint32_t block_length = INFO_FLASH_START - dst_address; + uint32_t src_address = (uint32_t)src; + /* Main memory block */ + bool success = MAP_FLASH_CTL_A_PROGRAM_MEMORY(src, dest, block_length); + + src_address = src_address + block_length; + block_length = length - block_length; + /* Information memory block */ + success &= MAP_FLASH_CTL_A_PROGRAM_MEMORY((void *)src_address, + (void *)INFO_FLASH_START, block_length); + return success; + } else + return MAP_FLASH_CTL_A_PROGRAM_MEMORY(src, dest, length); +} diff --git a/contrib/loaders/flash/msp432/msp432e4x.h b/contrib/loaders/flash/msp432/msp432e4x.h new file mode 100644 index 0000000..2a9d155 --- /dev/null +++ b/contrib/loaders/flash/msp432/msp432e4x.h @@ -0,0 +1,229 @@ +/****************************************************************************** +* +* Copyright (C) 2017-2018 Texas Instruments Incorporated - http://www.ti.com/ +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the +* distribution. +* +* Neither the name of Texas Instruments Incorporated nor the names of +* its contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +******************************************************************************/ + +#ifndef OPENOCD_LOADERS_FLASH_MSP432_MSP432E4X_H +#define OPENOCD_LOADERS_FLASH_MSP432_MSP432E4X_H + +#include <stdint.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* Register map for FLASH_CTRL peripheral (FLASH_CTRL) */ +struct flash_ctrl { + volatile uint32_t FMA; /* Flash Memory Address */ + volatile uint32_t FMD; /* Flash Memory Data */ + volatile uint32_t FMC; /* Flash Memory Control */ + volatile uint32_t FCRIS; /* Flash Controller Raw Interrupt Status */ + volatile uint32_t FCIM; /* Flash Controller Interrupt Mask */ + volatile uint32_t FCMISC; /* Flash Cont. Masked Int. Status and Clear */ + volatile uint32_t RESERVED0[2]; + volatile uint32_t FMC2; /* Flash Memory Control 2 */ + volatile uint32_t RESERVED1[3]; + volatile uint32_t FWBVAL; /* Flash Write Buffer Valid */ + volatile uint32_t RESERVED2[2]; + volatile uint32_t FLPEKEY; /* Flash Program/Erase Key */ + volatile uint32_t RESERVED3[48]; + volatile uint32_t FWBN[32]; /* Flash Write Buffer n */ +}; + +/* Register map for SYSCTL peripheral (SYSCTL) */ +struct sys_ctrl { + volatile uint32_t DID0; /* Device Identification 0 */ + volatile uint32_t DID1; /* Device Identification 1 */ + volatile uint32_t RESERVED0[12]; + volatile uint32_t PTBOCTL; /* Power-Temp Brown Out Control */ + volatile uint32_t RESERVED1[5]; + volatile uint32_t RIS; /* Raw Interrupt Status */ + volatile uint32_t IMC; /* Interrupt Mask Control */ + volatile uint32_t MISC; /* Masked Interrupt Status and Clear */ + volatile uint32_t RESC; /* Reset Cause */ + volatile uint32_t PWRTC; /* Power-Temperature Cause */ + volatile uint32_t NMIC; /* NMI Cause Register */ + volatile uint32_t RESERVED2[5]; + volatile uint32_t MOSCCTL; /* Main Oscillator Control */ + volatile uint32_t RESERVED3[12]; + volatile uint32_t RSCLKCFG; /* Run and Sleep Mode Configuration Register */ + volatile uint32_t RESERVED4[3]; + volatile uint32_t MEMTIM0; /* Memory Timing Register 0 for Main Flash */ + volatile uint32_t RESERVED5[29]; + volatile uint32_t ALTCLKCFG; /* Alternate Clock Configuration */ + volatile uint32_t RESERVED6[2]; + union { + volatile uint32_t DSLPCLKCFG; /* Deep Sleep Clock Configuration */ + volatile uint32_t DSCLKCFG; /* Deep Sleep Clock Register */ + }; + volatile uint32_t DIVSCLK; /* Divisor and Source Clock Configuration */ + volatile uint32_t SYSPROP; /* System Properties */ + volatile uint32_t PIOSCCAL; /* Precision Internal Oscillator Calibration */ + volatile uint32_t PIOSCSTAT; /* Precision Internal Oscillator Statistics */ + volatile uint32_t RESERVED7[2]; + volatile uint32_t PLLFREQ0; /* PLL Frequency 0 */ + volatile uint32_t PLLFREQ1; /* PLL Frequency 1 */ + volatile uint32_t PLLSTAT; /* PLL Status */ + volatile uint32_t RESERVED8[7]; + volatile uint32_t SLPPWRCFG; /* Sleep Power Configuration */ + volatile uint32_t DSLPPWRCFG; /* Deep-Sleep Power Configuration */ + volatile uint32_t RESERVED9[4]; + volatile uint32_t NVMSTAT; /* Non-Volatile Memory Information */ + volatile uint32_t RESERVED10[4]; + volatile uint32_t LDOSPCTL; /* LDO Sleep Power Control */ + volatile uint32_t RESERVED11; + volatile uint32_t LDODPCTL; /* LDO Deep-Sleep Power Control */ + volatile uint32_t RESERVED12[6]; + volatile uint32_t RESBEHAVCTL; /* Reset Behavior Control Register */ + volatile uint32_t RESERVED13[6]; + volatile uint32_t HSSR; /* Hardware System Service Request */ + volatile uint32_t RESERVED14[34]; + volatile uint32_t USBPDS; /* USB Power Domain Status */ + volatile uint32_t USBMPC; /* USB Memory Power Control */ + volatile uint32_t EMACPDS; /* Ethernet MAC Power Domain Status */ + volatile uint32_t EMACMPC; /* Ethernet MAC Memory Power Control */ + volatile uint32_t RESERVED15; + volatile uint32_t LCDMPC; /* LCD Memory Power Control */ + volatile uint32_t RESERVED16[26]; + volatile uint32_t PPWD; /* Watchdog Timer Peripheral Present */ + volatile uint32_t PPTIMER; /* General-Purpose Timer Peripheral Present */ + volatile uint32_t PPGPIO; /* General-Purpose I/O Peripheral Present */ + volatile uint32_t PPDMA; /* Micro DMA Peripheral Present */ + volatile uint32_t PPEPI; /* EPI Peripheral Present */ + volatile uint32_t PPHIB; /* Hibernation Peripheral Present */ + volatile uint32_t PPUART; /* UART Peripheral Present */ + volatile uint32_t PPSSI; /* Synchronous Serial Inter. Periph. Present */ + volatile uint32_t PPI2C; /* Inter-Integrated Circuit Periph. Present */ + volatile uint32_t RESERVED17; + volatile uint32_t PPUSB; /* Universal Serial Bus Peripheral Present */ + volatile uint32_t RESERVED18; + volatile uint32_t PPEPHY; /* Ethernet PHY Peripheral Present */ + volatile uint32_t PPCAN; /* Controller Area Network Periph. Present */ + volatile uint32_t PPADC; /* Analog-to-Dig. Converter Periph. Present */ + volatile uint32_t PPACMP; /* Analog Comparator Peripheral Present */ + volatile uint32_t PPPWM; /* Pulse Width Modulator Peripheral Present */ + volatile uint32_t PPQEI; /* Quadrature Encoder Inter. Periph. Present */ + volatile uint32_t RESERVED19[4]; + volatile uint32_t PPEEPROM; /* EEPROM Peripheral Present */ + volatile uint32_t RESERVED20[6]; + volatile uint32_t PPCCM; /* CRC/Cryptographic Modules Periph. Present */ + volatile uint32_t RESERVED21[6]; + volatile uint32_t PPLCD; /* LCD Peripheral Present */ + volatile uint32_t RESERVED22; + volatile uint32_t PPOWIRE; /* 1-Wire Peripheral Present */ + volatile uint32_t PPEMAC; /* Ethernet MAC Peripheral Present */ + volatile uint32_t RESERVED23[88]; + volatile uint32_t SRWD; /* Watchdog Timer Software Reset */ + volatile uint32_t SRTIMER; /* General-Purpose Timer Software Reset */ + volatile uint32_t SRGPIO; /* General-Purpose I/O Software Reset */ + volatile uint32_t SRDMA; /* Micro Direct Memory Access Software Reset */ + volatile uint32_t SREPI; /* EPI Software Reset */ + volatile uint32_t SRHIB; /* Hibernation Software Reset */ + volatile uint32_t SRUART; /* UART Software Reset */ + volatile uint32_t SRSSI; /* Synchronous Serial Inter. Software Reset */ + volatile uint32_t SRI2C; /* Inter-Integrated Circuit Software Reset */ + volatile uint32_t RESERVED24; + volatile uint32_t SRUSB; /* Universal Serial Bus Software Reset */ + volatile uint32_t RESERVED25; + volatile uint32_t SREPHY; /* Ethernet PHY Software Reset */ + volatile uint32_t SRCAN; /* Controller Area Network Software Reset */ + volatile uint32_t SRADC; /* Analog-to-Dig. Converter Software Reset */ + volatile uint32_t SRACMP; /* Analog Comparator Software Reset */ + volatile uint32_t SRPWM; /* Pulse Width Modulator Software Reset */ + volatile uint32_t SRQEI; /* Quadrature Encoder Inter. Software Reset */ + volatile uint32_t RESERVED26[4]; + volatile uint32_t SREEPROM; /* EEPROM Software Reset */ + volatile uint32_t RESERVED27[6]; + volatile uint32_t SRCCM; /* CRC/Cryptographic Modules Software Reset */ + volatile uint32_t RESERVED28[6]; + volatile uint32_t SRLCD; /* LCD Controller Software Reset */ + volatile uint32_t RESERVED29; + volatile uint32_t SROWIRE; /* 1-Wire Software Reset */ + volatile uint32_t SREMAC; /* Ethernet MAC Software Reset */ + volatile uint32_t RESERVED30[24]; + volatile uint32_t RCGCWD; /* Watchdog Run Mode Clock Gating Control */ +}; + +/* Peripheral Memory Map */ +#define FLASH_CTRL_BASE 0x400FD000UL +#define SYSCTL_BASE 0x400FE000UL + +/* Peripheral Declarations */ +#define FLASH_CTRL ((struct flash_ctrl *) FLASH_CTRL_BASE) +#define SYSCTL ((struct sys_ctrl *) SYSCTL_BASE) + +/* The following are defines for the bit fields in the FLASH_FMC register. */ +#define FLASH_FMC_WRKEY 0xA4420000 /* FLASH write key */ +#define FLASH_FMC_COMT 0x00000008 /* Commit Register Value */ +#define FLASH_FMC_MERASE 0x00000004 /* Mass Erase Flash Memory */ +#define FLASH_FMC_ERASE 0x00000002 /* Erase a Page of Flash Memory */ +#define FLASH_FMC_WRITE 0x00000001 /* Write a Word into Flash Memory */ + +/* The following are defines for the bit fields in the FLASH_FCRIS register. */ +#define FLASH_FCRIS_PROGRIS 0x00002000 /* Program Verify Raw Interrupt Status */ +#define FLASH_FCRIS_ERRIS 0x00000800 /* Erase Verify Raw Interrupt Status */ +#define FLASH_FCRIS_INVDRIS 0x00000400 /* Invalid Data Raw Interrupt Status */ +#define FLASH_FCRIS_VOLTRIS 0x00000200 /* Pump Voltage Raw Interrupt Status */ +#define FLASH_FCRIS_ERIS 0x00000004 /* EEPROM Raw Interrupt Status */ +#define FLASH_FCRIS_PRIS 0x00000002 /* Programming Raw Interrupt Status */ +#define FLASH_FCRIS_ARIS 0x00000001 /* Access Raw Interrupt Status */ + +/* The following are defines for the bit fields in the FLASH_FCIM register. */ +#define FLASH_FCIM_PROGMASK 0x00002000 /* PROGVER Interrupt Mask */ +#define FLASH_FCIM_ERMASK 0x00000800 /* ERVER Interrupt Mask */ +#define FLASH_FCIM_INVDMASK 0x00000400 /* Invalid Data Interrupt Mask */ +#define FLASH_FCIM_VOLTMASK 0x00000200 /* VOLT Interrupt Mask */ +#define FLASH_FCIM_EMASK 0x00000004 /* EEPROM Interrupt Mask */ +#define FLASH_FCIM_PMASK 0x00000002 /* Programming Interrupt Mask */ +#define FLASH_FCIM_AMASK 0x00000001 /* Access Interrupt Mask */ + +/* The following are defines for the bit fields in the FLASH_FCMISC register. */ +#define FLASH_FCMISC_PROGMISC 0x00002000 /* PROGVER Interrupt Status/Clear */ +#define FLASH_FCMISC_ERMISC 0x00000800 /* ERVER Interrupt Status/Clear */ +#define FLASH_FCMISC_INVDMISC 0x00000400 /* Invalid Data Int. Status/Clear */ +#define FLASH_FCMISC_VOLTMISC 0x00000200 /* VOLT Interrupt Status/Clear */ +#define FLASH_FCMISC_EMISC 0x00000004 /* EEPROM Interrupt Status/Clear */ +#define FLASH_FCMISC_PMISC 0x00000002 /* Programming Int. Status/Clear */ +#define FLASH_FCMISC_AMISC 0x00000001 /* Access Interrupt Status/Clear */ + +/* The following are defines for the bit fields in the FLASH_FMC2 register. */ +#define FLASH_FMC2_WRBUF 0x00000001 /* Buffered Flash Memory Write */ + +/* The following are defines for the bit fields in the SYSCTL_RCGCWD reg. */ +#define SYSCTL_RCGCWD_R1 0x00000002 /* Watchdog 1 Run Mode Clock Gating Cont. */ +#define SYSCTL_RCGCWD_R0 0x00000001 /* Watchdog 0 Run Mode Clock Gating Cont. */ + +#ifdef __cplusplus +} +#endif + +#endif /* OPENOCD_LOADERS_FLASH_MSP432_MSP432E4X_H */ diff --git a/contrib/loaders/flash/msp432/msp432e4x/msp432e4x.lds b/contrib/loaders/flash/msp432/msp432e4x/msp432e4x.lds new file mode 100644 index 0000000..af97458 --- /dev/null +++ b/contrib/loaders/flash/msp432/msp432e4x/msp432e4x.lds @@ -0,0 +1,149 @@ +/****************************************************************************** +* +* Copyright (C) 2017-2018 Texas Instruments Incorporated - http://www.ti.com/ +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the +* distribution. +* +* Neither the name of Texas Instruments Incorporated nor the names of +* its contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +******************************************************************************/ + +MEMORY { + MAIN_FLASH (RX) : ORIGIN = 0x00000000, LENGTH = 0x00100000 + SRAM_CODE_0(RWX): ORIGIN = 0x20000000, LENGTH = 0x00000110 + SRAM_CODE_1(RWX): ORIGIN = 0x20000110, LENGTH = 0x00000030 + SRAM_CODE_2(RWX): ORIGIN = 0x20000150, LENGTH = 0x00000040 + SRAM_CODE_3(RWX): ORIGIN = 0x20000190, LENGTH = 0x00000F70 + SRAM_CODE_4(RWX): ORIGIN = 0x20001170, LENGTH = 0x00000200 + SRAM_DATA (RW) : ORIGIN = 0x20002000, LENGTH = 0x00001000 +} + +REGION_ALIAS("REGION_INTVECT", SRAM_CODE_0); +REGION_ALIAS("REGION_RESET", SRAM_CODE_1); +REGION_ALIAS("REGION_DESCRIPTOR", SRAM_CODE_2); +REGION_ALIAS("REGION_TEXT", SRAM_CODE_3); +REGION_ALIAS("REGION_BSS", SRAM_CODE_3); +REGION_ALIAS("REGION_DATA", SRAM_DATA); +REGION_ALIAS("REGION_STACK", SRAM_CODE_4); +REGION_ALIAS("REGION_HEAP", SRAM_DATA); +REGION_ALIAS("REGION_ARM_EXIDX", SRAM_CODE_3); +REGION_ALIAS("REGION_ARM_EXTAB", SRAM_CODE_3); + +SECTIONS { + /* section for the interrupt vector area */ + .intvecs : { + KEEP (*(.intvecs)) + } > REGION_INTVECT + + PROVIDE (_vtable_base_address = + DEFINED(_vtable_base_address) ? _vtable_base_address : 0x20000000); + + .vtable (_vtable_base_address) : AT (_vtable_base_address) { + KEEP (*(.vtable)) + } > REGION_DATA + + .descriptor :{ + FILL(0x00000000); + . = ORIGIN(REGION_DESCRIPTOR) + LENGTH(REGION_DESCRIPTOR) - 1; + BYTE(0x00); + __ROM_AT = .; + } > REGION_DESCRIPTOR + + .reset : { + KEEP(*(.reset)) + } > REGION_RESET AT> REGION_RESET + + .text : { + CREATE_OBJECT_SYMBOLS + KEEP (*(.text)) + *(.text.*) + . = ALIGN(0x4); + KEEP (*(.ctors)) + . = ALIGN(0x4); + KEEP (*(.dtors)) + . = ALIGN(0x4); + __init_array_start = .; + KEEP (*(.init_array*)) + __init_array_end = .; + KEEP (*(.init)) + KEEP (*(.fini*)) + } > REGION_TEXT AT> REGION_TEXT + + .rodata : { + *(.rodata) + *(.rodata.*) + } > REGION_TEXT AT> REGION_TEXT + + .ARM.exidx : { + __exidx_start = .; + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + __exidx_end = .; + } > REGION_ARM_EXIDX AT> REGION_ARM_EXIDX + + .ARM.extab : { + KEEP (*(.ARM.extab* .gnu.linkonce.armextab.*)) + } > REGION_ARM_EXTAB AT> REGION_ARM_EXTAB + + __etext = .; + + .data : { + __data_load__ = LOADADDR (.data); + __data_start__ = .; + KEEP (*(.data)) + KEEP (*(.data*)) + . = ALIGN (4); + __data_end__ = .; + } > REGION_DATA AT> REGION_TEXT + + .bss : { + __bss_start__ = .; + *(.shbss) + KEEP (*(.bss)) + *(.bss.*) + *(COMMON) + . = ALIGN (4); + __bss_end__ = .; + } > REGION_BSS AT> REGION_BSS + + .heap : { + __heap_start__ = .; + end = __heap_start__; + _end = end; + __end = end; + KEEP (*(.heap)) + __heap_end__ = .; + __HeapLimit = __heap_end__; + } > REGION_HEAP AT> REGION_HEAP + + .stack (NOLOAD) : ALIGN(0x8) { + _stack = .; + KEEP(*(.stack)) + } > REGION_STACK AT> REGION_STACK + + __stack_top = ORIGIN(REGION_STACK) + LENGTH(REGION_STACK); + PROVIDE(__stack = __stack_top); +} diff --git a/contrib/loaders/flash/msp432/msp432e4x_algo.inc b/contrib/loaders/flash/msp432/msp432e4x_algo.inc new file mode 100644 index 0000000..1f36a21 --- /dev/null +++ b/contrib/loaders/flash/msp432/msp432e4x_algo.inc @@ -0,0 +1,245 @@ +/* Autogenerated with ../../../../src/helper/bin2char.sh */ +0x70,0x13,0x00,0x20,0x11,0x01,0x00,0x20,0xc9,0x0a,0x00,0x20,0xc9,0x0a,0x00,0x20, +0xc9,0x0a,0x00,0x20,0xc9,0x0a,0x00,0x20,0xc9,0x0a,0x00,0x20,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc9,0x0a,0x00,0x20, +0xc9,0x0a,0x00,0x20,0x00,0x00,0x00,0x00,0xc9,0x0a,0x00,0x20,0xc9,0x0a,0x00,0x20, +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,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,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,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, +0x41,0xf2,0x00,0x70,0xc2,0xf2,0x00,0x00,0x85,0x46,0x05,0x48,0x05,0x49,0x4f,0xf0, +0x00,0x02,0x88,0x42,0xb8,0xbf,0x40,0xf8,0x04,0x2b,0xfa,0xdb,0x00,0xf0,0x16,0xbc, +0x34,0x0f,0x00,0x20,0x50,0x0f,0x00,0x20,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,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, +0x04,0x4b,0x05,0x48,0x1b,0x1a,0x06,0x2b,0x02,0xd9,0x04,0x4b,0x03,0xb1,0x18,0x47, +0x70,0x47,0x00,0xbf,0x37,0x24,0x00,0x20,0x34,0x24,0x00,0x20,0x00,0x00,0x00,0x00, +0x05,0x49,0x06,0x48,0x09,0x1a,0x89,0x10,0x01,0xeb,0xd1,0x71,0x49,0x10,0x02,0xd0, +0x03,0x4b,0x03,0xb1,0x18,0x47,0x70,0x47,0x34,0x24,0x00,0x20,0x34,0x24,0x00,0x20, +0x00,0x00,0x00,0x00,0x10,0xb5,0x06,0x4c,0x23,0x78,0x43,0xb9,0xff,0xf7,0xd8,0xff, +0x04,0x4b,0x13,0xb1,0x04,0x48,0xaf,0xf3,0x00,0x80,0x01,0x23,0x23,0x70,0x10,0xbd, +0x34,0x0f,0x00,0x20,0x00,0x00,0x00,0x00,0xf8,0x0a,0x00,0x20,0x08,0xb5,0x08,0x4b, +0x1b,0xb1,0x08,0x48,0x08,0x49,0xaf,0xf3,0x00,0x80,0x08,0x48,0x03,0x68,0x13,0xb9, +0xbd,0xe8,0x08,0x40,0xcc,0xe7,0x06,0x4b,0x00,0x2b,0xf9,0xd0,0x98,0x47,0xf7,0xe7, +0x00,0x00,0x00,0x00,0xf8,0x0a,0x00,0x20,0x38,0x0f,0x00,0x20,0x34,0x24,0x00,0x20, +0x00,0x00,0x00,0x00,0x13,0x4b,0x00,0x2b,0x08,0xbf,0x11,0x4b,0x9d,0x46,0xa3,0xf5, +0x80,0x3a,0x00,0x21,0x8b,0x46,0x0f,0x46,0x11,0x48,0x12,0x4a,0x12,0x1a,0x00,0xf0, +0x13,0xf9,0x0d,0x4b,0x00,0x2b,0x00,0xd0,0x98,0x47,0x0c,0x4b,0x00,0x2b,0x00,0xd0, +0x98,0x47,0x00,0x20,0x00,0x21,0x04,0x00,0x0d,0x00,0x0b,0x48,0x00,0xf0,0xb0,0xf8, +0x00,0xf0,0xda,0xf8,0x20,0x00,0x29,0x00,0x00,0xf0,0x70,0xfb,0x00,0xf0,0xae,0xf8, +0x00,0x00,0x08,0x00,0x70,0x13,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x34,0x0f,0x00,0x20,0x50,0x0f,0x00,0x20,0xfd,0x03,0x00,0x20,0x84,0x46,0x41,0xea, +0x00,0x03,0x13,0xf0,0x03,0x03,0x6d,0xd1,0x40,0x3a,0x41,0xd3,0x51,0xf8,0x04,0x3b, +0x40,0xf8,0x04,0x3b,0x51,0xf8,0x04,0x3b,0x40,0xf8,0x04,0x3b,0x51,0xf8,0x04,0x3b, +0x40,0xf8,0x04,0x3b,0x51,0xf8,0x04,0x3b,0x40,0xf8,0x04,0x3b,0x51,0xf8,0x04,0x3b, +0x40,0xf8,0x04,0x3b,0x51,0xf8,0x04,0x3b,0x40,0xf8,0x04,0x3b,0x51,0xf8,0x04,0x3b, +0x40,0xf8,0x04,0x3b,0x51,0xf8,0x04,0x3b,0x40,0xf8,0x04,0x3b,0x51,0xf8,0x04,0x3b, +0x40,0xf8,0x04,0x3b,0x51,0xf8,0x04,0x3b,0x40,0xf8,0x04,0x3b,0x51,0xf8,0x04,0x3b, +0x40,0xf8,0x04,0x3b,0x51,0xf8,0x04,0x3b,0x40,0xf8,0x04,0x3b,0x51,0xf8,0x04,0x3b, +0x40,0xf8,0x04,0x3b,0x51,0xf8,0x04,0x3b,0x40,0xf8,0x04,0x3b,0x51,0xf8,0x04,0x3b, +0x40,0xf8,0x04,0x3b,0x51,0xf8,0x04,0x3b,0x40,0xf8,0x04,0x3b,0x40,0x3a,0xbd,0xd2, +0x30,0x32,0x11,0xd3,0x51,0xf8,0x04,0x3b,0x40,0xf8,0x04,0x3b,0x51,0xf8,0x04,0x3b, +0x40,0xf8,0x04,0x3b,0x51,0xf8,0x04,0x3b,0x40,0xf8,0x04,0x3b,0x51,0xf8,0x04,0x3b, +0x40,0xf8,0x04,0x3b,0x10,0x3a,0xed,0xd2,0x0c,0x32,0x05,0xd3,0x51,0xf8,0x04,0x3b, +0x40,0xf8,0x04,0x3b,0x04,0x3a,0xf9,0xd2,0x04,0x32,0x08,0xd0,0xd2,0x07,0x1c,0xbf, +0x11,0xf8,0x01,0x3b,0x00,0xf8,0x01,0x3b,0x01,0xd3,0x0b,0x88,0x03,0x80,0x60,0x46, +0x70,0x47,0x00,0xbf,0x08,0x2a,0x13,0xd3,0x8b,0x07,0x8d,0xd0,0x10,0xf0,0x03,0x03, +0x8a,0xd0,0xc3,0xf1,0x04,0x03,0xd2,0x1a,0xdb,0x07,0x1c,0xbf,0x11,0xf8,0x01,0x3b, +0x00,0xf8,0x01,0x3b,0x80,0xd3,0x31,0xf8,0x02,0x3b,0x20,0xf8,0x02,0x3b,0x7b,0xe7, +0x04,0x3a,0xd9,0xd3,0x01,0x3a,0x11,0xf8,0x01,0x3b,0x00,0xf8,0x01,0x3b,0xf9,0xd2, +0x0b,0x78,0x03,0x70,0x4b,0x78,0x43,0x70,0x8b,0x78,0x83,0x70,0x60,0x46,0x70,0x47, +0x01,0x46,0x00,0x20,0x02,0x46,0x03,0x46,0x00,0xf0,0x9c,0xb8,0x08,0xb5,0x00,0x21, +0x04,0x46,0x00,0xf0,0xf3,0xf8,0x04,0x4b,0x18,0x68,0xc3,0x6b,0x03,0xb1,0x98,0x47, +0x20,0x46,0x00,0xf0,0x55,0xf9,0x00,0xbf,0xf4,0x0a,0x00,0x20,0x38,0xb5,0x08,0x4b, +0x08,0x4d,0xed,0x1a,0xac,0x10,0x18,0xbf,0xed,0x18,0x05,0xd0,0x01,0x3c,0x55,0xf8, +0x04,0x3d,0x98,0x47,0x00,0x2c,0xf9,0xd1,0xbd,0xe8,0x38,0x40,0x00,0xf0,0x60,0xbb, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0xb5,0x0f,0x4e,0x0f,0x4d,0x76,0x1b, +0xb6,0x10,0x18,0xbf,0x00,0x24,0x05,0xd0,0x01,0x34,0x55,0xf8,0x04,0x3b,0x98,0x47, +0xa6,0x42,0xf9,0xd1,0x0a,0x4e,0x0b,0x4d,0x76,0x1b,0x00,0xf0,0x43,0xfb,0xb6,0x10, +0x18,0xbf,0x00,0x24,0x06,0xd0,0x01,0x34,0x55,0xf8,0x04,0x3b,0x98,0x47,0xa6,0x42, +0xf9,0xd1,0x70,0xbd,0x70,0xbd,0x00,0xbf,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0xd4,0x0a,0x00,0x20,0xcc,0x0a,0x00,0x20,0x70,0xb4,0x84,0x07,0x46,0xd0,0x54,0x1e, +0x00,0x2a,0x41,0xd0,0xcd,0xb2,0x03,0x46,0x02,0xe0,0x62,0x1e,0xe4,0xb3,0x14,0x46, +0x03,0xf8,0x01,0x5b,0x9a,0x07,0xf8,0xd1,0x03,0x2c,0x2e,0xd9,0xcd,0xb2,0x45,0xea, +0x05,0x25,0x0f,0x2c,0x45,0xea,0x05,0x45,0x19,0xd9,0x03,0xf1,0x10,0x02,0x26,0x46, +0x10,0x3e,0x0f,0x2e,0x42,0xf8,0x10,0x5c,0x42,0xf8,0x0c,0x5c,0x42,0xf8,0x08,0x5c, +0x42,0xf8,0x04,0x5c,0x02,0xf1,0x10,0x02,0xf2,0xd8,0xa4,0xf1,0x10,0x02,0x22,0xf0, +0x0f,0x02,0x04,0xf0,0x0f,0x04,0x10,0x32,0x03,0x2c,0x13,0x44,0x0d,0xd9,0x1e,0x46, +0x22,0x46,0x04,0x3a,0x03,0x2a,0x46,0xf8,0x04,0x5b,0xfa,0xd8,0x22,0x1f,0x22,0xf0, +0x03,0x02,0x04,0x32,0x13,0x44,0x04,0xf0,0x03,0x04,0x2c,0xb1,0xc9,0xb2,0x1c,0x44, +0x03,0xf8,0x01,0x1b,0xa3,0x42,0xfb,0xd1,0x70,0xbc,0x70,0x47,0x14,0x46,0x03,0x46, +0xc2,0xe7,0x00,0xbf,0x2d,0xe9,0xf0,0x47,0x25,0x4c,0x25,0x68,0xd5,0xf8,0x48,0x41, +0x06,0x46,0x88,0x46,0x92,0x46,0x99,0x46,0xcc,0xb3,0x60,0x68,0x1f,0x28,0x18,0xdc, +0x43,0x1c,0x7e,0xb1,0x04,0xeb,0x80,0x05,0x01,0x21,0xc5,0xf8,0x88,0xa0,0xd4,0xf8, +0x88,0x71,0x01,0xfa,0x00,0xf2,0x17,0x43,0x02,0x2e,0xc4,0xf8,0x88,0x71,0xc5,0xf8, +0x08,0x91,0x1e,0xd0,0x02,0x30,0x63,0x60,0x44,0xf8,0x20,0x80,0x00,0x20,0xbd,0xe8, +0xf0,0x87,0x14,0x4b,0x03,0xb3,0x4f,0xf4,0xc8,0x70,0xaf,0xf3,0x00,0x80,0x04,0x46, +0xd0,0xb1,0xd5,0xf8,0x48,0x31,0x00,0x27,0x80,0xe8,0x88,0x00,0xc5,0xf8,0x48,0x41, +0x38,0x46,0x01,0x23,0xc4,0xf8,0x88,0x71,0xc4,0xf8,0x8c,0x71,0x00,0x2e,0xe1,0xd0, +0xd0,0xe7,0xd4,0xf8,0x8c,0x11,0x0a,0x43,0xc4,0xf8,0x8c,0x21,0xda,0xe7,0x05,0xf5, +0xa6,0x74,0xc5,0xf8,0x48,0x41,0xc0,0xe7,0x4f,0xf0,0xff,0x30,0xbd,0xe8,0xf0,0x87, +0xf4,0x0a,0x00,0x20,0x00,0x00,0x00,0x00,0x02,0x4b,0x13,0xb1,0x02,0x48,0xff,0xf7, +0x07,0xbf,0x70,0x47,0x00,0x00,0x00,0x00,0xfd,0x03,0x00,0x20,0x2d,0xe9,0xf0,0x4f, +0x31,0x4b,0x83,0xb0,0x1b,0x68,0x00,0x93,0x03,0xf5,0xa4,0x73,0x81,0x46,0x0e,0x46, +0x01,0x93,0x00,0x9b,0xd3,0xf8,0x48,0x71,0x27,0xb3,0xdd,0xf8,0x04,0xa0,0x7c,0x68, +0x65,0x1e,0x0e,0xd4,0x01,0x34,0x07,0xeb,0x84,0x04,0x4f,0xf0,0x00,0x08,0xe6,0xb1, +0xd4,0xf8,0x00,0x31,0xb3,0x42,0x18,0xd0,0x01,0x3d,0x6b,0x1c,0xa4,0xf1,0x04,0x04, +0xf5,0xd1,0x22,0x4b,0x73,0xb1,0x7b,0x68,0x00,0x2b,0x36,0xd1,0x3b,0x68,0x00,0x2b, +0x34,0xd0,0x38,0x46,0xca,0xf8,0x00,0x30,0xaf,0xf3,0x00,0x80,0xda,0xf8,0x00,0x70, +0x00,0x2f,0xdc,0xd1,0x03,0xb0,0xbd,0xe8,0xf0,0x8f,0x7b,0x68,0x22,0x68,0x01,0x3b, +0xab,0x42,0x0c,0xbf,0x7d,0x60,0xc4,0xf8,0x00,0x80,0x00,0x2a,0xdc,0xd0,0xd7,0xf8, +0x88,0x31,0xd7,0xf8,0x04,0xb0,0x01,0x21,0xa9,0x40,0x19,0x42,0x08,0xd1,0x90,0x47, +0x7b,0x68,0x5b,0x45,0xbd,0xd1,0xda,0xf8,0x00,0x30,0xbb,0x42,0xcc,0xd0,0xb8,0xe7, +0xd7,0xf8,0x8c,0x31,0x19,0x42,0x04,0xd1,0x48,0x46,0xd4,0xf8,0x80,0x10,0x90,0x47, +0xee,0xe7,0xd4,0xf8,0x80,0x00,0x90,0x47,0xea,0xe7,0x3b,0x68,0xba,0x46,0x1f,0x46, +0x00,0x2f,0xac,0xd1,0xce,0xe7,0x00,0xbf,0xf4,0x0a,0x00,0x20,0x00,0x00,0x00,0x00, +0xfe,0xe7,0x00,0xbf,0x2d,0xe9,0xf0,0x4f,0xa8,0x4b,0xa9,0x4a,0xde,0x68,0xd3,0xf8, +0x10,0xb0,0x85,0xb0,0x42,0xf2,0x03,0x61,0x00,0x24,0x99,0x46,0xa5,0x4b,0x51,0x61, +0x15,0x46,0x90,0x46,0x00,0x94,0xbb,0xf5,0x80,0x5f,0x93,0xbf,0x5f,0x46,0xab,0xf5, +0x80,0x5b,0x4f,0xf4,0x80,0x57,0x4f,0xf0,0x00,0x0b,0x03,0xe0,0xd9,0xf8,0x18,0x20, +0xd2,0x06,0x03,0xd4,0xd9,0xf8,0x14,0x20,0xd1,0x06,0xf7,0xd5,0xd9,0xf8,0x14,0x20, +0x12,0xf0,0x10,0x02,0x00,0xf0,0xb9,0x80,0xd9,0xf8,0x14,0x20,0x42,0xf0,0x01,0x02, +0xc9,0xf8,0x14,0x20,0x4f,0xf0,0x20,0x24,0x4f,0xf0,0x01,0x0a,0x16,0xf0,0x03,0x02, +0x00,0xf0,0xa9,0x80,0x26,0xf0,0x03,0x0c,0xdc,0xf8,0x00,0x10,0x03,0x91,0x47,0xb3, +0x21,0x46,0x78,0x1e,0x11,0xf8,0x01,0xeb,0x01,0x91,0x04,0xa9,0x11,0x44,0x01,0xf8, +0x04,0xec,0x02,0xf1,0x01,0x01,0x06,0xf1,0x01,0x0e,0x00,0xf0,0x01,0x81,0x04,0x29, +0x00,0xf0,0xfe,0x80,0x04,0xa8,0x01,0x44,0x60,0x78,0x01,0xf8,0x04,0x0c,0xb9,0x1e, +0x00,0x29,0x06,0xf1,0x02,0x00,0x04,0xf1,0x02,0x0e,0x40,0xf3,0xec,0x80,0x01,0x2a, +0x40,0xf0,0xe9,0x80,0xa2,0x78,0x8d,0xf8,0x0f,0x20,0x03,0x99,0x03,0x36,0x03,0x3f, +0x03,0x34,0x78,0x4a,0x69,0x60,0xc5,0xf8,0x00,0xc0,0xaa,0x60,0xaa,0x68,0xd0,0x07, +0xfc,0xd4,0xd8,0xf8,0x0c,0x10,0x42,0xf2,0x05,0x42,0x0a,0x40,0xb2,0xfa,0x82,0xf2, +0x52,0x09,0x03,0x2f,0x1a,0xdd,0x71,0x06,0x79,0xd0,0x00,0x2a,0x75,0xd0,0x54,0xf8, +0x04,0x2b,0x6a,0x60,0x2e,0x60,0xab,0x60,0xaa,0x68,0xd2,0x07,0xfc,0xd4,0xd8,0xf8, +0x0c,0x10,0x04,0x3f,0x42,0xf2,0x05,0x42,0x03,0x2f,0x02,0xea,0x01,0x02,0x06,0xf1, +0x04,0x06,0xb2,0xfa,0x82,0xf2,0x4f,0xea,0x52,0x12,0xe4,0xdc,0x00,0x2f,0x15,0xdc, +0xba,0xf1,0x00,0x0f,0x33,0xd0,0xd9,0xf8,0x14,0x10,0x21,0xf0,0x11,0x01,0xc9,0xf8, +0x14,0x10,0x00,0x2a,0x38,0xd0,0xbb,0xf1,0x00,0x0f,0x7f,0xf4,0x6c,0xaf,0x57,0x4b, +0x40,0xf6,0xce,0x22,0x5a,0x60,0x05,0xb0,0xbd,0xe8,0xf0,0x8f,0x00,0x2a,0xe7,0xd0, +0x04,0xa8,0x32,0x68,0x40,0xf8,0x04,0x2d,0x21,0x46,0x3a,0x46,0x01,0x93,0xff,0xf7, +0x45,0xfd,0x03,0x9a,0x4f,0x4b,0x6a,0x60,0x2e,0x60,0xab,0x60,0x01,0x9b,0x37,0x44, +0xaa,0x68,0xd2,0x07,0xfc,0xd4,0xd8,0xf8,0x0c,0x10,0x42,0xf2,0x05,0x42,0x0a,0x40, +0x3e,0x46,0xb2,0xfa,0x82,0xf2,0x52,0x09,0xba,0xf1,0x00,0x0f,0xcb,0xd1,0x00,0x99, +0x00,0x29,0xce,0xd0,0xd9,0xf8,0x18,0x10,0xcd,0xf8,0x00,0xa0,0x21,0xf0,0x11,0x01, +0xc9,0xf8,0x18,0x10,0x00,0x2a,0xc6,0xd1,0x3c,0x4b,0x4d,0xf6,0xad,0x62,0x5a,0x60, +0x05,0xb0,0xbd,0xe8,0xf0,0x8f,0x01,0x22,0x93,0xe7,0xd9,0xf8,0x18,0x10,0x11,0xf0, +0x10,0x01,0x5e,0xd0,0xd9,0xf8,0x18,0x10,0x37,0x4c,0x41,0xf0,0x01,0x01,0x92,0x46, +0x01,0x22,0xc9,0xf8,0x18,0x10,0x00,0x92,0x40,0xe7,0x00,0x22,0xa0,0xe7,0x1f,0x2f, +0x32,0xdd,0x00,0x2a,0xf9,0xd0,0x07,0xf1,0xff,0x3e,0x2e,0xf0,0x03,0x0e,0x0e,0xf1, +0x04,0x0e,0xa6,0x44,0x39,0x46,0x04,0xf1,0x80,0x0c,0x00,0x22,0x01,0xe0,0x64,0x45, +0x0b,0xd0,0x54,0xf8,0x04,0x7b,0x02,0xf1,0x40,0x00,0x74,0x45,0xa1,0xf1,0x04,0x01, +0x45,0xf8,0x20,0x70,0x02,0xf1,0x01,0x02,0xf1,0xd1,0x2e,0x60,0x0f,0x46,0x2b,0x62, +0x2a,0x6a,0xd0,0x07,0xfc,0xd4,0xd8,0xf8,0x0c,0x00,0x42,0xf2,0x05,0x42,0x1f,0x29, +0x02,0xea,0x00,0x02,0x06,0xf1,0x80,0x06,0xb2,0xfa,0x82,0xf2,0x4f,0xea,0x52,0x12, +0xcf,0xdc,0x03,0x29,0x7f,0xf7,0x6a,0xaf,0x00,0x2a,0xc6,0xd0,0x54,0xf8,0x04,0x2b, +0x6a,0x60,0x2e,0x60,0xab,0x60,0xaa,0x68,0xd1,0x07,0xfc,0xd4,0xd8,0xf8,0x0c,0x10, +0x04,0x3f,0x42,0xf2,0x05,0x42,0x03,0x2f,0x02,0xea,0x01,0x02,0x06,0xf1,0x04,0x06, +0xb2,0xfa,0x82,0xf2,0x4f,0xea,0x52,0x12,0xe6,0xdc,0x00,0x2f,0x7f,0xf7,0x50,0xaf, +0x64,0xe7,0x8a,0x46,0xea,0xe6,0x0f,0x46,0x74,0x46,0x06,0x46,0x03,0x99,0x18,0xe7, +0x01,0x9c,0x03,0x99,0x07,0x46,0x76,0x46,0x13,0xe7,0x00,0xbf,0x50,0x01,0x00,0x20, +0x00,0xd0,0x0f,0x40,0x01,0x00,0x42,0xa4,0x00,0x30,0x00,0x20,0x80,0xb5,0x72,0xb6, +0x52,0x4a,0x53,0x4c,0xd2,0xf8,0x00,0x36,0x52,0x4d,0x53,0x4f,0x53,0x4e,0x23,0xf0, +0x03,0x03,0xc2,0xf8,0x00,0x36,0xa0,0x46,0x2b,0x68,0x20,0x2b,0x00,0xf2,0x8d,0x80, +0x01,0xa2,0x52,0xf8,0x23,0xf0,0x00,0xbf,0x79,0x09,0x00,0x20,0x75,0x0a,0x00,0x20, +0x4b,0x0a,0x00,0x20,0x9b,0x0a,0x00,0x20,0x3d,0x0a,0x00,0x20,0x9b,0x0a,0x00,0x20, +0x9b,0x0a,0x00,0x20,0x9b,0x0a,0x00,0x20,0x21,0x0a,0x00,0x20,0x9b,0x0a,0x00,0x20, +0x9b,0x0a,0x00,0x20,0x9b,0x0a,0x00,0x20,0x9b,0x0a,0x00,0x20,0x9b,0x0a,0x00,0x20, +0x9b,0x0a,0x00,0x20,0x9b,0x0a,0x00,0x20,0x0d,0x0a,0x00,0x20,0x9b,0x0a,0x00,0x20, +0x9b,0x0a,0x00,0x20,0x9b,0x0a,0x00,0x20,0x9b,0x0a,0x00,0x20,0x9b,0x0a,0x00,0x20, +0x9b,0x0a,0x00,0x20,0x9b,0x0a,0x00,0x20,0x9b,0x0a,0x00,0x20,0x9b,0x0a,0x00,0x20, +0x9b,0x0a,0x00,0x20,0x9b,0x0a,0x00,0x20,0x9b,0x0a,0x00,0x20,0x9b,0x0a,0x00,0x20, +0x9b,0x0a,0x00,0x20,0x9b,0x0a,0x00,0x20,0x3d,0x0a,0x00,0x20,0x2c,0x49,0x00,0x23, +0x01,0x20,0x40,0xf6,0xce,0x22,0x68,0x60,0x8b,0x60,0x6a,0x60,0x2b,0x60,0xab,0xe7, +0x27,0x49,0x4f,0xf0,0x01,0x0e,0x4f,0xf0,0x00,0x50,0x40,0xf6,0xce,0x22,0x00,0x23, +0xc5,0xf8,0x04,0xe0,0x88,0x60,0x6a,0x60,0x2b,0x60,0x9d,0xe7,0x01,0x23,0x6b,0x60, +0xff,0xf7,0x30,0xfe,0x00,0x23,0x2b,0x60,0x96,0xe7,0x40,0xf6,0x03,0x23,0x01,0x22, +0x6a,0x60,0x63,0x61,0xeb,0x68,0x23,0x60,0xa7,0x60,0xa3,0x68,0x9b,0x07,0xfc,0xd4, +0xd8,0xf8,0x0c,0x20,0x40,0xf6,0x01,0x23,0x13,0x40,0xd3,0xb9,0x40,0xf6,0xce,0x23, +0x6b,0x60,0xe7,0xe7,0x01,0x22,0x40,0xf6,0x03,0x23,0x6a,0x60,0x63,0x61,0xa6,0x60, +0xa3,0x68,0x5a,0x07,0xfc,0xd4,0xd8,0xf8,0x0c,0x20,0x40,0xf6,0x01,0x23,0x13,0x40, +0x00,0x2b,0xeb,0xd0,0x0b,0x4b,0x6b,0x60,0xd4,0xe7,0x40,0xf6,0xad,0x33,0x6b,0x60, +0x6a,0xe7,0x4d,0xf6,0xad,0x63,0x6b,0x60,0xcc,0xe7,0x00,0xbf,0x00,0xe0,0x0f,0x40, +0x00,0xd0,0x0f,0x40,0x50,0x01,0x00,0x20,0x02,0x00,0x42,0xa4,0x04,0x00,0x42,0xa4, +0x00,0xed,0x00,0xe0,0xad,0xde,0xad,0xde,0xfe,0xe7,0x00,0xbf,0xfd,0x01,0x00,0x20, +0xb9,0x05,0x00,0x20,0xf8,0xb5,0x00,0xbf,0xf8,0xbc,0x08,0xbc,0x9e,0x46,0x70,0x47, +0xf8,0xb5,0x00,0xbf,0xd5,0x01,0x00,0x20,0xf8,0xbc,0x08,0xbc,0x9e,0x46,0x70,0x47, +0x43,0x00,0x00,0x00,0x08,0x20,0x00,0x20,0x3c,0xf7,0xff,0x7f,0x01,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf4,0x22,0x00,0x20, +0x5c,0x23,0x00,0x20,0xc4,0x23,0x00,0x20,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,0xf0,0x0a,0x00,0x20, +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,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, +0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0x33,0xcd,0xab,0x34,0x12,0x6d,0xe6, +0xec,0xde,0x05,0x00,0x0b,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,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,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, +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,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,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,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,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,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,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,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,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,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,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,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,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x08,0x20,0x00,0x20, diff --git a/contrib/loaders/flash/msp432/msp432p401x.h b/contrib/loaders/flash/msp432/msp432p401x.h new file mode 100644 index 0000000..ca219fd --- /dev/null +++ b/contrib/loaders/flash/msp432/msp432p401x.h @@ -0,0 +1,102 @@ +/****************************************************************************** +* +* Copyright (C) 2012-2018 Texas Instruments Incorporated - http://www.ti.com/ +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the +* distribution. +* +* Neither the name of Texas Instruments Incorporated nor the names of +* its contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +******************************************************************************/ + +#ifndef OPENOCD_LOADERS_FLASH_MSP432_MSP432P401X_H +#define OPENOCD_LOADERS_FLASH_MSP432_MSP432P401X_H + +#include <stdint.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#define __MCU_HAS_FLCTL__ /* Module FLCTL is available */ + +/* Device and peripheral memory map */ +#define FLASH_BASE ((uint32_t)0x00000000) /* Flash memory start address */ +#define SRAM_BASE ((uint32_t)0x20000000) /* SRAM memory start address */ +#define PERIPH_BASE ((uint32_t)0x40000000) /* Peripherals start address */ +#define CS_BASE (PERIPH_BASE + 0x00010400) /* Address of module CS regs. */ +#define DIO_BASE (PERIPH_BASE + 0x00004C00) /* Address of module DIO regs. */ + +/* Register map for Clock Signal peripheral (CS) */ +struct cs { + volatile uint32_t KEY; /* Key Register */ + volatile uint32_t CTL0; /* Control 0 Register */ + volatile uint32_t CTL1; /* Control 1 Register */ + volatile uint32_t CTL2; /* Control 2 Register */ + volatile uint32_t CTL3; /* Control 3 Register */ +}; + +/* Register map for DIO port (odd interrupt) */ +struct dio_port_odd_int { + volatile uint8_t IN; /* Port Input */ + uint8_t RESERVED0; + volatile uint8_t OUT; /* Port Output */ +}; + +/* Register map for DIO port (even interrupt) */ +struct dio_port_even_int { + uint8_t RESERVED0; + volatile uint8_t IN; /* Port Input */ + uint8_t RESERVED1; + volatile uint8_t OUT; /* Port Output */ +}; + +/* Peripheral declarations */ +#define CS ((struct cs *) CS_BASE) +#define P3 ((struct dio_port_odd_int *) (DIO_BASE + 0x0020)) +#define P6 ((struct dio_port_even_int *) (DIO_BASE + 0x0040)) + +/* Peripheral bit definitions */ + +/* DCORSEL Bit Mask */ +#define CS_CTL0_DCORSEL_MASK ((uint32_t)0x00070000) +/* Nominal DCO Frequency Range (MHz): 2 to 4 */ +#define CS_CTL0_DCORSEL_1 ((uint32_t)0x00010000) +/* Nominal DCO Frequency Range (MHz): 16 to 32 */ +#define CS_CTL0_DCORSEL_4 ((uint32_t)0x00040000) +/* CS control key value */ +#define CS_KEY_VAL ((uint32_t)0x0000695A) + +/* Protects Sector 0 from program or erase */ +#define FLCTL_BANK0_MAIN_WEPROT_PROT0 ((uint32_t)0x00000001) +/* Protects Sector 1 from program or erase */ +#define FLCTL_BANK0_MAIN_WEPROT_PROT1 ((uint32_t)0x00000002) + +#ifdef __cplusplus +} +#endif + +#endif /* OPENOCD_LOADERS_FLASH_MSP432_MSP432P401X_H */ diff --git a/contrib/loaders/flash/msp432/msp432p401x/msp432p401x.lds b/contrib/loaders/flash/msp432/msp432p401x/msp432p401x.lds new file mode 100644 index 0000000..f9d04ed --- /dev/null +++ b/contrib/loaders/flash/msp432/msp432p401x/msp432p401x.lds @@ -0,0 +1,151 @@ +/****************************************************************************** +* +* Copyright (C) 2012-2018 Texas Instruments Incorporated - http://www.ti.com/ +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the +* distribution. +* +* Neither the name of Texas Instruments Incorporated nor the names of +* its contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +******************************************************************************/ + +MEMORY { + MAIN_FLASH (RX) : ORIGIN = 0x00000000, LENGTH = 0x00040000 + INFO_FLASH (RX) : ORIGIN = 0x00200000, LENGTH = 0x00004000 + SRAM_CODE_0(RWX): ORIGIN = 0x01000000, LENGTH = 0x00000110 + SRAM_CODE_1(RWX): ORIGIN = 0x01000110, LENGTH = 0x00000030 + SRAM_CODE_2(RWX): ORIGIN = 0x01000150, LENGTH = 0x00000040 + SRAM_CODE_3(RWX): ORIGIN = 0x01000190, LENGTH = 0x00000F70 + SRAM_CODE_4(RWX): ORIGIN = 0x01001170, LENGTH = 0x00000200 + SRAM_DATA (RW) : ORIGIN = 0x20002000, LENGTH = 0x00001000 +} + +REGION_ALIAS("REGION_INTVECT", SRAM_CODE_0); +REGION_ALIAS("REGION_RESET", SRAM_CODE_1); +REGION_ALIAS("REGION_DESCRIPTOR", SRAM_CODE_2); +REGION_ALIAS("REGION_TEXT", SRAM_CODE_3); +REGION_ALIAS("REGION_BSS", SRAM_CODE_3); +REGION_ALIAS("REGION_DATA", SRAM_DATA); +REGION_ALIAS("REGION_STACK", SRAM_CODE_4); +REGION_ALIAS("REGION_HEAP", SRAM_DATA); +REGION_ALIAS("REGION_ARM_EXIDX", SRAM_CODE_3); +REGION_ALIAS("REGION_ARM_EXTAB", SRAM_CODE_3); + + +SECTIONS { + /* section for the interrupt vector area */ + .intvecs : { + KEEP (*(.intvecs)) + } > REGION_INTVECT + + PROVIDE (_vtable_base_address = + DEFINED(_vtable_base_address) ? _vtable_base_address : 0x20000000); + + .vtable (_vtable_base_address) : AT (_vtable_base_address) { + KEEP (*(.vtable)) + } > REGION_DATA + + .descriptor :{ + FILL(0x00000000); + . = ORIGIN(REGION_DESCRIPTOR) + LENGTH(REGION_DESCRIPTOR) - 1; + BYTE(0x00); + __ROM_AT = .; + } > REGION_DESCRIPTOR + + .reset : { + KEEP(*(.reset)) + } > REGION_RESET AT> REGION_RESET + + .text : { + CREATE_OBJECT_SYMBOLS + KEEP (*(.text)) + *(.text.*) + . = ALIGN(0x4); + KEEP (*(.ctors)) + . = ALIGN(0x4); + KEEP (*(.dtors)) + . = ALIGN(0x4); + __init_array_start = .; + KEEP (*(.init_array*)) + __init_array_end = .; + KEEP (*(.init)) + KEEP (*(.fini*)) + } > REGION_TEXT AT> REGION_TEXT + + .rodata : { + *(.rodata) + *(.rodata.*) + } > REGION_TEXT AT> REGION_TEXT + + .ARM.exidx : { + __exidx_start = .; + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + __exidx_end = .; + } > REGION_ARM_EXIDX AT> REGION_ARM_EXIDX + + .ARM.extab : { + KEEP (*(.ARM.extab* .gnu.linkonce.armextab.*)) + } > REGION_ARM_EXTAB AT> REGION_ARM_EXTAB + + __etext = .; + + .data : { + __data_load__ = LOADADDR (.data); + __data_start__ = .; + KEEP (*(.data)) + KEEP (*(.data*)) + . = ALIGN (4); + __data_end__ = .; + } > REGION_DATA AT> REGION_TEXT + + .bss : { + __bss_start__ = .; + *(.shbss) + KEEP (*(.bss)) + *(.bss.*) + *(COMMON) + . = ALIGN (4); + __bss_end__ = .; + } > REGION_BSS AT> REGION_BSS + + .heap : { + __heap_start__ = .; + end = __heap_start__; + _end = end; + __end = end; + KEEP (*(.heap)) + __heap_end__ = .; + __HeapLimit = __heap_end__; + } > REGION_HEAP AT> REGION_HEAP + + .stack (NOLOAD) : ALIGN(0x8) { + _stack = .; + KEEP(*(.stack)) + } > REGION_STACK AT> REGION_STACK + + __stack_top = ORIGIN(REGION_STACK) + LENGTH(REGION_STACK); + PROVIDE(__stack = __stack_top); +} diff --git a/contrib/loaders/flash/msp432/msp432p401x_algo.inc b/contrib/loaders/flash/msp432/msp432p401x_algo.inc new file mode 100644 index 0000000..c302342 --- /dev/null +++ b/contrib/loaders/flash/msp432/msp432p401x_algo.inc @@ -0,0 +1,242 @@ +/* Autogenerated with ../../../../src/helper/bin2char.sh */ +0x70,0x13,0x00,0x01,0x11,0x01,0x00,0x01,0xa1,0x0a,0x00,0x01,0xa1,0x0a,0x00,0x01, +0xa1,0x0a,0x00,0x01,0xa1,0x0a,0x00,0x01,0xa1,0x0a,0x00,0x01,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xa1,0x0a,0x00,0x01, +0xa1,0x0a,0x00,0x01,0x00,0x00,0x00,0x00,0xa1,0x0a,0x00,0x01,0xa1,0x0a,0x00,0x01, +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,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,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,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, +0x41,0xf2,0x00,0x70,0xc0,0xf2,0x00,0x10,0x85,0x46,0x05,0x48,0x05,0x49,0x4f,0xf0, +0x00,0x02,0x88,0x42,0xb8,0xbf,0x40,0xf8,0x04,0x2b,0xfa,0xdb,0x00,0xf0,0x96,0xbb, +0x0c,0x0f,0x00,0x01,0x28,0x0f,0x00,0x01,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,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, +0x04,0x4b,0x05,0x48,0x1b,0x1a,0x06,0x2b,0x02,0xd9,0x04,0x4b,0x03,0xb1,0x18,0x47, +0x70,0x47,0x00,0xbf,0x37,0x24,0x00,0x20,0x34,0x24,0x00,0x20,0x00,0x00,0x00,0x00, +0x05,0x49,0x06,0x48,0x09,0x1a,0x89,0x10,0x01,0xeb,0xd1,0x71,0x49,0x10,0x02,0xd0, +0x03,0x4b,0x03,0xb1,0x18,0x47,0x70,0x47,0x34,0x24,0x00,0x20,0x34,0x24,0x00,0x20, +0x00,0x00,0x00,0x00,0x10,0xb5,0x06,0x4c,0x23,0x78,0x43,0xb9,0xff,0xf7,0xd8,0xff, +0x04,0x4b,0x13,0xb1,0x04,0x48,0xaf,0xf3,0x00,0x80,0x01,0x23,0x23,0x70,0x10,0xbd, +0x0c,0x0f,0x00,0x01,0x00,0x00,0x00,0x00,0xd0,0x0a,0x00,0x01,0x08,0xb5,0x08,0x4b, +0x1b,0xb1,0x08,0x48,0x08,0x49,0xaf,0xf3,0x00,0x80,0x08,0x48,0x03,0x68,0x13,0xb9, +0xbd,0xe8,0x08,0x40,0xcc,0xe7,0x06,0x4b,0x00,0x2b,0xf9,0xd0,0x98,0x47,0xf7,0xe7, +0x00,0x00,0x00,0x00,0xd0,0x0a,0x00,0x01,0x10,0x0f,0x00,0x01,0x34,0x24,0x00,0x20, +0x00,0x00,0x00,0x00,0x13,0x4b,0x00,0x2b,0x08,0xbf,0x11,0x4b,0x9d,0x46,0xa3,0xf5, +0x80,0x3a,0x00,0x21,0x8b,0x46,0x0f,0x46,0x11,0x48,0x12,0x4a,0x12,0x1a,0x00,0xf0, +0x79,0xf8,0x0d,0x4b,0x00,0x2b,0x00,0xd0,0x98,0x47,0x0c,0x4b,0x00,0x2b,0x00,0xd0, +0x98,0x47,0x00,0x20,0x00,0x21,0x04,0x00,0x0d,0x00,0x0b,0x48,0x00,0xf0,0x16,0xf8, +0x00,0xf0,0x40,0xf8,0x20,0x00,0x29,0x00,0x00,0xf0,0xf0,0xfa,0x00,0xf0,0x14,0xf8, +0x00,0x00,0x08,0x00,0x70,0x13,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x0c,0x0f,0x00,0x01,0x28,0x0f,0x00,0x01,0xc9,0x02,0x00,0x01,0x01,0x46,0x00,0x20, +0x02,0x46,0x03,0x46,0x00,0xf0,0x9c,0xb8,0x08,0xb5,0x00,0x21,0x04,0x46,0x00,0xf0, +0xf3,0xf8,0x04,0x4b,0x18,0x68,0xc3,0x6b,0x03,0xb1,0x98,0x47,0x20,0x46,0x00,0xf0, +0x55,0xf9,0x00,0xbf,0xcc,0x0a,0x00,0x01,0x38,0xb5,0x08,0x4b,0x08,0x4d,0xed,0x1a, +0xac,0x10,0x18,0xbf,0xed,0x18,0x05,0xd0,0x01,0x3c,0x55,0xf8,0x04,0x3d,0x98,0x47, +0x00,0x2c,0xf9,0xd1,0xbd,0xe8,0x38,0x40,0x00,0xf0,0xe6,0xbb,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x70,0xb5,0x0f,0x4e,0x0f,0x4d,0x76,0x1b,0xb6,0x10,0x18,0xbf, +0x00,0x24,0x05,0xd0,0x01,0x34,0x55,0xf8,0x04,0x3b,0x98,0x47,0xa6,0x42,0xf9,0xd1, +0x0a,0x4e,0x0b,0x4d,0x76,0x1b,0x00,0xf0,0xc9,0xfb,0xb6,0x10,0x18,0xbf,0x00,0x24, +0x06,0xd0,0x01,0x34,0x55,0xf8,0x04,0x3b,0x98,0x47,0xa6,0x42,0xf9,0xd1,0x70,0xbd, +0x70,0xbd,0x00,0xbf,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xac,0x0a,0x00,0x01, +0xa4,0x0a,0x00,0x01,0x70,0xb4,0x84,0x07,0x46,0xd0,0x54,0x1e,0x00,0x2a,0x41,0xd0, +0xcd,0xb2,0x03,0x46,0x02,0xe0,0x62,0x1e,0xe4,0xb3,0x14,0x46,0x03,0xf8,0x01,0x5b, +0x9a,0x07,0xf8,0xd1,0x03,0x2c,0x2e,0xd9,0xcd,0xb2,0x45,0xea,0x05,0x25,0x0f,0x2c, +0x45,0xea,0x05,0x45,0x19,0xd9,0x03,0xf1,0x10,0x02,0x26,0x46,0x10,0x3e,0x0f,0x2e, +0x42,0xf8,0x10,0x5c,0x42,0xf8,0x0c,0x5c,0x42,0xf8,0x08,0x5c,0x42,0xf8,0x04,0x5c, +0x02,0xf1,0x10,0x02,0xf2,0xd8,0xa4,0xf1,0x10,0x02,0x22,0xf0,0x0f,0x02,0x04,0xf0, +0x0f,0x04,0x10,0x32,0x03,0x2c,0x13,0x44,0x0d,0xd9,0x1e,0x46,0x22,0x46,0x04,0x3a, +0x03,0x2a,0x46,0xf8,0x04,0x5b,0xfa,0xd8,0x22,0x1f,0x22,0xf0,0x03,0x02,0x04,0x32, +0x13,0x44,0x04,0xf0,0x03,0x04,0x2c,0xb1,0xc9,0xb2,0x1c,0x44,0x03,0xf8,0x01,0x1b, +0xa3,0x42,0xfb,0xd1,0x70,0xbc,0x70,0x47,0x14,0x46,0x03,0x46,0xc2,0xe7,0x00,0xbf, +0x2d,0xe9,0xf0,0x47,0x25,0x4c,0x25,0x68,0xd5,0xf8,0x48,0x41,0x06,0x46,0x88,0x46, +0x92,0x46,0x99,0x46,0xcc,0xb3,0x60,0x68,0x1f,0x28,0x18,0xdc,0x43,0x1c,0x7e,0xb1, +0x04,0xeb,0x80,0x05,0x01,0x21,0xc5,0xf8,0x88,0xa0,0xd4,0xf8,0x88,0x71,0x01,0xfa, +0x00,0xf2,0x17,0x43,0x02,0x2e,0xc4,0xf8,0x88,0x71,0xc5,0xf8,0x08,0x91,0x1e,0xd0, +0x02,0x30,0x63,0x60,0x44,0xf8,0x20,0x80,0x00,0x20,0xbd,0xe8,0xf0,0x87,0x14,0x4b, +0x03,0xb3,0x4f,0xf4,0xc8,0x70,0xaf,0xf3,0x00,0x80,0x04,0x46,0xd0,0xb1,0xd5,0xf8, +0x48,0x31,0x00,0x27,0x80,0xe8,0x88,0x00,0xc5,0xf8,0x48,0x41,0x38,0x46,0x01,0x23, +0xc4,0xf8,0x88,0x71,0xc4,0xf8,0x8c,0x71,0x00,0x2e,0xe1,0xd0,0xd0,0xe7,0xd4,0xf8, +0x8c,0x11,0x0a,0x43,0xc4,0xf8,0x8c,0x21,0xda,0xe7,0x05,0xf5,0xa6,0x74,0xc5,0xf8, +0x48,0x41,0xc0,0xe7,0x4f,0xf0,0xff,0x30,0xbd,0xe8,0xf0,0x87,0xcc,0x0a,0x00,0x01, +0x00,0x00,0x00,0x00,0x02,0x4b,0x13,0xb1,0x02,0x48,0xff,0xf7,0x07,0xbf,0x70,0x47, +0x00,0x00,0x00,0x00,0xc9,0x02,0x00,0x01,0x2d,0xe9,0xf0,0x4f,0x31,0x4b,0x83,0xb0, +0x1b,0x68,0x00,0x93,0x03,0xf5,0xa4,0x73,0x81,0x46,0x0e,0x46,0x01,0x93,0x00,0x9b, +0xd3,0xf8,0x48,0x71,0x27,0xb3,0xdd,0xf8,0x04,0xa0,0x7c,0x68,0x65,0x1e,0x0e,0xd4, +0x01,0x34,0x07,0xeb,0x84,0x04,0x4f,0xf0,0x00,0x08,0xe6,0xb1,0xd4,0xf8,0x00,0x31, +0xb3,0x42,0x18,0xd0,0x01,0x3d,0x6b,0x1c,0xa4,0xf1,0x04,0x04,0xf5,0xd1,0x22,0x4b, +0x73,0xb1,0x7b,0x68,0x00,0x2b,0x36,0xd1,0x3b,0x68,0x00,0x2b,0x34,0xd0,0x38,0x46, +0xca,0xf8,0x00,0x30,0xaf,0xf3,0x00,0x80,0xda,0xf8,0x00,0x70,0x00,0x2f,0xdc,0xd1, +0x03,0xb0,0xbd,0xe8,0xf0,0x8f,0x7b,0x68,0x22,0x68,0x01,0x3b,0xab,0x42,0x0c,0xbf, +0x7d,0x60,0xc4,0xf8,0x00,0x80,0x00,0x2a,0xdc,0xd0,0xd7,0xf8,0x88,0x31,0xd7,0xf8, +0x04,0xb0,0x01,0x21,0xa9,0x40,0x19,0x42,0x08,0xd1,0x90,0x47,0x7b,0x68,0x5b,0x45, +0xbd,0xd1,0xda,0xf8,0x00,0x30,0xbb,0x42,0xcc,0xd0,0xb8,0xe7,0xd7,0xf8,0x8c,0x31, +0x19,0x42,0x04,0xd1,0x48,0x46,0xd4,0xf8,0x80,0x10,0x90,0x47,0xee,0xe7,0xd4,0xf8, +0x80,0x00,0x90,0x47,0xea,0xe7,0x3b,0x68,0xba,0x46,0x1f,0x46,0x00,0x2f,0xac,0xd1, +0xce,0xe7,0x00,0xbf,0xcc,0x0a,0x00,0x01,0x00,0x00,0x00,0x00,0xfe,0xe7,0x00,0xbf, +0xef,0xf3,0x10,0x80,0x72,0xb6,0x70,0x47,0xf8,0xb5,0x20,0x4e,0x20,0x4a,0x33,0x68, +0x20,0x4d,0x21,0x4f,0x21,0x4c,0x4f,0xf0,0x80,0x71,0x91,0x60,0x9b,0x6d,0x00,0x20, +0x98,0x47,0x33,0x68,0x28,0x60,0x9b,0x6d,0x01,0x20,0x98,0x47,0x3b,0x68,0x68,0x60, +0x5b,0x68,0x98,0x47,0x3b,0x68,0x28,0x73,0x1b,0x6a,0x98,0x47,0x63,0x68,0x3a,0x68, +0x68,0x73,0x03,0xf4,0xe0,0x23,0xab,0x60,0x93,0x69,0x00,0x20,0x98,0x47,0x33,0x68, +0x02,0x21,0x5b,0x6d,0x05,0x46,0x00,0x20,0x98,0x47,0x33,0x68,0x01,0x20,0x5b,0x6d, +0x02,0x21,0x98,0x47,0x46,0xf6,0x5a,0x13,0x23,0x60,0x63,0x68,0x23,0xf4,0xe0,0x23, +0x43,0xf4,0x80,0x23,0x00,0x22,0x63,0x60,0x22,0x60,0x09,0x4b,0x1d,0xb1,0x40,0xf6, +0xce,0x22,0x5a,0x60,0xf8,0xbd,0x07,0x4a,0x5a,0x60,0xf8,0xbd,0x1c,0x08,0x00,0x02, +0x00,0xed,0x00,0xe0,0x80,0x01,0x00,0x20,0x34,0x08,0x00,0x02,0x00,0x04,0x01,0x40, +0x50,0x01,0x00,0x20,0x00,0xad,0xde,0x00,0x2d,0xe9,0xf8,0x4f,0x4e,0x4c,0x25,0x69, +0xe7,0x68,0x00,0x2d,0x6d,0xd0,0xdf,0xf8,0x38,0xb1,0xdf,0xf8,0x38,0xa1,0xdf,0xf8, +0x38,0x91,0x4f,0xf0,0x00,0x08,0xdb,0xf8,0x00,0x30,0xb5,0xf5,0x80,0x5f,0x1b,0x69, +0x4f,0xf0,0xff,0x31,0x4f,0xf0,0x01,0x00,0x93,0xbf,0x2e,0x46,0xa5,0xf5,0x80,0x55, +0x4f,0xf4,0x80,0x56,0x00,0x25,0x98,0x47,0xdb,0xf8,0x00,0x30,0x4f,0xf0,0xff,0x31, +0x1b,0x69,0x02,0x20,0x98,0x47,0xdb,0xf8,0x00,0x30,0x03,0x20,0x1b,0x69,0x01,0x46, +0x98,0x47,0x23,0x6a,0x0b,0x2b,0x03,0xd1,0x60,0xe0,0xa3,0x69,0xd9,0x06,0x02,0xd4, +0x63,0x69,0xd8,0x06,0xf9,0xd5,0x63,0x69,0xda,0x06,0x3c,0xd5,0x63,0x69,0xdb,0xf8, +0x00,0x20,0x43,0xf0,0x01,0x03,0x63,0x61,0x93,0x6a,0x39,0x46,0x4f,0xf0,0x20,0x20, +0x32,0x46,0x98,0x47,0x99,0xf8,0x03,0x30,0x03,0xf0,0xef,0x03,0x89,0xf8,0x03,0x30, +0x63,0x69,0x23,0xf0,0x11,0x03,0x80,0x46,0x37,0x44,0x63,0x61,0xdb,0xf8,0x00,0x30, +0x4f,0xf0,0xff,0x31,0x5b,0x69,0x01,0x20,0x98,0x47,0xdb,0xf8,0x00,0x30,0x4f,0xf0, +0xff,0x31,0x5b,0x69,0x02,0x20,0x98,0x47,0xdb,0xf8,0x00,0x30,0x03,0x20,0x5b,0x69, +0x01,0x46,0x98,0x47,0xdb,0xf8,0x00,0x30,0x04,0x20,0x5b,0x69,0x03,0x21,0x98,0x47, +0xb8,0xf1,0x00,0x0f,0x29,0xd0,0x00,0x2d,0x9d,0xd1,0x17,0x4b,0x40,0xf6,0xce,0x22, +0x5a,0x60,0xbd,0xe8,0xf8,0x8f,0xa3,0x69,0xdb,0x06,0xd7,0xd5,0xa3,0x69,0xdb,0xf8, +0x00,0x20,0x12,0x48,0x43,0xf0,0x01,0x03,0xa3,0x61,0x93,0x6a,0x39,0x46,0x32,0x46, +0x98,0x47,0x9a,0xf8,0x02,0x30,0x03,0xf0,0xbf,0x03,0x8a,0xf8,0x02,0x30,0xa3,0x69, +0x23,0xf0,0x11,0x03,0x80,0x46,0x37,0x44,0xa3,0x61,0xbf,0xe7,0xdb,0xf8,0x00,0x30, +0x03,0x21,0x1b,0x69,0x04,0x20,0x98,0x47,0x9a,0xe7,0x03,0x4b,0x4d,0xf6,0xad,0x62, +0x5a,0x60,0xbd,0xe8,0xf8,0x8f,0x00,0xbf,0x50,0x01,0x00,0x20,0x00,0x30,0x00,0x20, +0x1c,0x08,0x00,0x02,0x20,0x4c,0x00,0x40,0x40,0x4c,0x00,0x40,0x13,0x4b,0xdb,0x69, +0xda,0x07,0x70,0xb5,0x14,0xd4,0x11,0x4c,0xe3,0x69,0x9b,0x07,0x00,0xd4,0x70,0xbd, +0x0f,0x4d,0x2b,0x68,0x03,0x20,0x1b,0x69,0x01,0x46,0x98,0x47,0x23,0x6a,0x0b,0x2b, +0xf5,0xd1,0x2b,0x68,0x04,0x20,0x1b,0x69,0x03,0x21,0xbd,0xe8,0x70,0x40,0x18,0x47, +0x07,0x4c,0x23,0x68,0x4f,0xf0,0xff,0x31,0x1b,0x69,0x01,0x20,0x98,0x47,0x23,0x68, +0x4f,0xf0,0xff,0x31,0x1b,0x69,0x02,0x20,0x98,0x47,0xdc,0xe7,0x50,0x01,0x00,0x20, +0x1c,0x08,0x00,0x02,0x2d,0xe9,0xf8,0x43,0x1e,0x4c,0x1f,0x4d,0x1f,0x4f,0x29,0x68, +0x3a,0x68,0xdf,0xf8,0x84,0x90,0x46,0xf6,0x5a,0x18,0xc4,0xf8,0x00,0x80,0x63,0x68, +0x23,0xf4,0xe0,0x23,0x00,0x26,0x43,0xf4,0x80,0x33,0x63,0x60,0x26,0x60,0x53,0x6d, +0x30,0x46,0x98,0x47,0x3b,0x68,0x69,0x68,0x5b,0x6d,0x01,0x20,0x98,0x47,0xd9,0xf8, +0x00,0x30,0x68,0x7b,0x9b,0x69,0x98,0x47,0xd9,0xf8,0x00,0x30,0x07,0x46,0x1b,0x68, +0x28,0x7b,0x98,0x47,0xc4,0xf8,0x00,0x80,0x63,0x68,0xaa,0x68,0x0c,0x49,0x23,0xf4, +0xe0,0x23,0x13,0x43,0x63,0x60,0x26,0x60,0x0a,0x4b,0x8e,0x60,0x28,0xb1,0x27,0xb1, +0x40,0xf6,0xce,0x22,0x5a,0x60,0xbd,0xe8,0xf8,0x83,0x4d,0xf6,0xad,0x62,0x5a,0x60, +0xbd,0xe8,0xf8,0x83,0x00,0x04,0x01,0x40,0x80,0x01,0x00,0x20,0x1c,0x08,0x00,0x02, +0x00,0xed,0x00,0xe0,0x50,0x01,0x00,0x20,0x34,0x08,0x00,0x02,0x8c,0x4b,0x8d,0x4c, +0x1b,0x68,0x8d,0x4d,0x1b,0x68,0x80,0xb5,0x98,0x47,0xff,0xf7,0x81,0xfe,0x27,0x46, +0x23,0x68,0x20,0x2b,0x00,0xf2,0xeb,0x80,0x01,0xa2,0x52,0xf8,0x23,0xf0,0x00,0xbf, +0x71,0x08,0x00,0x01,0xff,0x09,0x00,0x01,0xb9,0x09,0x00,0x01,0x4f,0x0a,0x00,0x01, +0x2f,0x09,0x00,0x01,0x4f,0x0a,0x00,0x01,0x4f,0x0a,0x00,0x01,0x4f,0x0a,0x00,0x01, +0x21,0x09,0x00,0x01,0x4f,0x0a,0x00,0x01,0x4f,0x0a,0x00,0x01,0x4f,0x0a,0x00,0x01, +0x4f,0x0a,0x00,0x01,0x4f,0x0a,0x00,0x01,0x4f,0x0a,0x00,0x01,0x4f,0x0a,0x00,0x01, +0x13,0x09,0x00,0x01,0x4f,0x0a,0x00,0x01,0x4f,0x0a,0x00,0x01,0x4f,0x0a,0x00,0x01, +0x4f,0x0a,0x00,0x01,0x4f,0x0a,0x00,0x01,0x4f,0x0a,0x00,0x01,0x4f,0x0a,0x00,0x01, +0x4f,0x0a,0x00,0x01,0x4f,0x0a,0x00,0x01,0x4f,0x0a,0x00,0x01,0x4f,0x0a,0x00,0x01, +0x4f,0x0a,0x00,0x01,0x4f,0x0a,0x00,0x01,0x4f,0x0a,0x00,0x01,0x4f,0x0a,0x00,0x01, +0x05,0x09,0x00,0x01,0x01,0x23,0x63,0x60,0xff,0xf7,0x86,0xfe,0x00,0x23,0x23,0x60, +0xae,0xe7,0x01,0x23,0x63,0x60,0xff,0xf7,0x55,0xff,0x00,0x23,0x23,0x60,0xa7,0xe7, +0x01,0x23,0x63,0x60,0xff,0xf7,0x28,0xfe,0x00,0x23,0x23,0x60,0xa0,0xe7,0x2b,0x68, +0x01,0x20,0x60,0x60,0x1b,0x69,0x4f,0xf0,0xff,0x31,0x98,0x47,0x2b,0x68,0x4f,0xf0, +0xff,0x31,0x1b,0x69,0x02,0x20,0x98,0x47,0x2b,0x68,0x03,0x20,0x1b,0x69,0x01,0x46, +0x98,0x47,0x23,0x6a,0x0b,0x2b,0x00,0xf0,0x82,0x80,0x63,0x69,0xdb,0x06,0xfc,0xd5, +0x7b,0x69,0x28,0x68,0x43,0xf0,0x01,0x03,0x7b,0x61,0xf9,0x68,0x83,0x6a,0x3a,0x69, +0x4f,0xf0,0x20,0x20,0x98,0x47,0x7b,0x69,0x2a,0x68,0x23,0xf0,0x11,0x03,0x7b,0x61, +0x53,0x69,0x06,0x46,0x4f,0xf0,0xff,0x31,0x01,0x20,0x98,0x47,0x2b,0x68,0x4f,0xf0, +0xff,0x31,0x5b,0x69,0x02,0x20,0x98,0x47,0x2b,0x68,0x03,0x20,0x5b,0x69,0x01,0x46, +0x98,0x47,0x2b,0x68,0x04,0x20,0x5b,0x69,0x03,0x21,0x98,0x47,0x00,0x2e,0x52,0xd0, +0x40,0xf6,0xce,0x23,0x7b,0x60,0xb0,0xe7,0x2b,0x68,0x01,0x20,0x60,0x60,0x1b,0x69, +0x4f,0xf0,0xff,0x31,0x98,0x47,0x2b,0x68,0x4f,0xf0,0xff,0x31,0x1b,0x69,0x02,0x20, +0x98,0x47,0x2b,0x68,0x03,0x20,0x1b,0x69,0x01,0x46,0x98,0x47,0x23,0x6a,0x0b,0x2b, +0x43,0xd0,0x05,0x26,0x2b,0x68,0xe0,0x68,0x5b,0x6a,0x98,0x47,0x01,0x3e,0x00,0x28, +0x47,0xd1,0x00,0x2e,0xf6,0xd1,0x4d,0xf6,0xad,0x63,0x63,0x60,0x0e,0xe0,0x01,0x23, +0x63,0x60,0xff,0xf7,0xb3,0xfe,0x05,0x26,0x2b,0x68,0x1b,0x6a,0x98,0x47,0x01,0x3e, +0x00,0x28,0x30,0xd1,0x00,0x2e,0xf7,0xd1,0x20,0x4b,0x63,0x60,0x2b,0x68,0x4f,0xf0, +0xff,0x31,0x5b,0x69,0x01,0x20,0x98,0x47,0x2b,0x68,0x4f,0xf0,0xff,0x31,0x5b,0x69, +0x02,0x20,0x98,0x47,0x2b,0x68,0x03,0x20,0x5b,0x69,0x01,0x46,0x98,0x47,0x2b,0x68, +0x04,0x20,0x5b,0x69,0x03,0x21,0x98,0x47,0x00,0x23,0x23,0x60,0x10,0xe7,0x40,0xf6, +0xad,0x33,0x63,0x60,0x0c,0xe7,0x4d,0xf6,0xad,0x63,0x7b,0x60,0x5d,0xe7,0x2b,0x68, +0x03,0x21,0x1b,0x69,0x04,0x20,0x98,0x47,0x77,0xe7,0x2b,0x68,0x03,0x21,0x1b,0x69, +0x04,0x20,0x98,0x47,0xb5,0xe7,0x00,0x2e,0xce,0xd0,0x40,0xf6,0xce,0x23,0x63,0x60, +0xcc,0xe7,0x00,0x2e,0xb7,0xd0,0x40,0xf6,0xce,0x23,0x7b,0x60,0xc6,0xe7,0x00,0xbf, +0x64,0x08,0x00,0x02,0x50,0x01,0x00,0x20,0x1c,0x08,0x00,0x02,0xad,0xde,0xad,0xde, +0xfe,0xe7,0x00,0xbf,0xfd,0x01,0x00,0x01,0x85,0x04,0x00,0x01,0xf8,0xb5,0x00,0xbf, +0xf8,0xbc,0x08,0xbc,0x9e,0x46,0x70,0x47,0xf8,0xb5,0x00,0xbf,0xd5,0x01,0x00,0x01, +0xf8,0xbc,0x08,0xbc,0x9e,0x46,0x70,0x47,0x43,0x00,0x00,0x00,0x08,0x20,0x00,0x20, +0x64,0xf7,0xff,0x7f,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0xf4,0x22,0x00,0x20,0x5c,0x23,0x00,0x20,0xc4,0x23,0x00,0x20, +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,0xc8,0x0a,0x00,0x01,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,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,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x0e,0x33,0xcd,0xab,0x34,0x12,0x6d,0xe6,0xec,0xde,0x05,0x00,0x0b,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,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,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,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,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,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,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,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,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,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,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, +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,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,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,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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x20,0x00,0x20, diff --git a/contrib/loaders/flash/msp432/msp432p411x.h b/contrib/loaders/flash/msp432/msp432p411x.h new file mode 100644 index 0000000..6482dd3 --- /dev/null +++ b/contrib/loaders/flash/msp432/msp432p411x.h @@ -0,0 +1,164 @@ +/****************************************************************************** +* +* Copyright (C) 2012-2018 Texas Instruments Incorporated - http://www.ti.com/ +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the +* distribution. +* +* Neither the name of Texas Instruments Incorporated nor the names of +* its contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +******************************************************************************/ + +#ifndef OPENOCD_LOADERS_FLASH_MSP432_MSP432P411X_H +#define OPENOCD_LOADERS_FLASH_MSP432_MSP432P411X_H + +#include <stdint.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* Available Peripherals */ +#define __MCU_HAS_FLCTL_A__ /* Module FLCTL_A is available */ +#define __MCU_HAS_SYSCTL_A__ /* Module SYSCTL_A is available */ + +/* Device and Peripheral Memory Map */ +#define FLASH_BASE ((uint32_t)0x00000000) /* Flash memory address */ +#define PERIPH_BASE ((uint32_t)0x40000000) /* Peripherals address */ +#define CS_BASE (PERIPH_BASE + 0x00010400) /* Address of CS regs. */ +#define PCM_BASE (PERIPH_BASE + 0x00010000) /* Address of PCM regs. */ +#define RTC_C_BASE (PERIPH_BASE + 0x00004400) /* Address of RTC_C regs */ +#define TLV_BASE ((uint32_t)0x00201000) /* Address of TLV regs. */ +#define WDT_A_BASE (PERIPH_BASE + 0x00004800) /* Address of WDT_A regs */ +#define BITBAND_PERI_BASE ((uint32_t)(0x42000000)) + +/* + * Peripherals with 8-bit or 16-bit register access allow only 8-bit or + * 16-bit bit band access, so cast to 8 bit always + */ +#define BITBAND_PERI(x, b) (*((volatile uint8_t *) (BITBAND_PERI_BASE + \ + (((uint32_t)(uint32_t *)&(x)) - PERIPH_BASE)*32 + (b)*4))) + +/* Register map for CLock Signal peripheral (CS) */ +struct cs { + volatile uint32_t KEY; /* Key Register */ + volatile uint32_t CTL0; /* Control 0 Register */ + volatile uint32_t CTL1; /* Control 1 Register */ + volatile uint32_t CTL2; /* Control 2 Register */ + volatile uint32_t CTL3; /* Control 3 Register */ +}; + +/* Register map for Power Control Module peripheral (PCM) */ +struct pcm { + volatile uint32_t CTL0; /* Control 0 Register */ + volatile uint32_t CTL1; /* Control 1 Register */ + volatile uint32_t IE; /* Interrupt Enable Register */ + volatile uint32_t IFG; /* Interrupt Flag Register */ + volatile uint32_t CLRIFG; /* Clear Interrupt Flag Register */ +}; + +/* Register map for Real-Time Clock peripheral (RTC_C) */ +struct rtc_c { + volatile uint16_t CTL0; /* RTCCTL0 Register */ + volatile uint16_t CTL13; /* RTCCTL13 Register */ + volatile uint16_t OCAL; /* RTCOCAL Register */ + volatile uint16_t TCMP; /* RTCTCMP Register */ + volatile uint16_t PS0CTL; /* RTC Prescale Timer 0 Control Register */ + volatile uint16_t PS1CTL; /* RTC Prescale Timer 1 Control Register */ + volatile uint16_t PS; /* Real-Time Clock Prescale Timer Register */ + volatile uint16_t IV; /* Real-Time Clock Interrupt Vector Register */ + volatile uint16_t TIM0; /* RTCTIM0 Register Hexadecimal Format */ + volatile uint16_t TIM1; /* Real-Time Clock Hour, Day of Week */ + volatile uint16_t DATE; /* RTCDATE - Hexadecimal Format */ + volatile uint16_t YEAR; /* RTCYEAR Register - Hexadecimal Format */ + volatile uint16_t AMINHR; /* RTCMINHR - Hexadecimal Format */ + volatile uint16_t ADOWDAY; /* RTCADOWDAY - Hexadecimal Format */ + volatile uint16_t BIN2BCD; /* Binary-to-BCD Conversion Register */ + volatile uint16_t BCD2BIN; /* BCD-to-Binary Conversion Register */ +}; + +/* Register map for Watchdog Timer peripheral (WDT_A) */ +struct wdt_a { + uint16_t RESERVED0[6]; + volatile uint16_t CTL; /* Watchdog Timer Control Register */ +}; + +/* Peripheral Declarations */ +#define CS ((struct cs *) CS_BASE) +#define PCM ((struct pcm *) PCM_BASE) +#define RTC_C ((struct rtc_c *) RTC_C_BASE) +#define WDT_A ((struct wdt_a *) WDT_A_BASE) + +/* Peripheral Register Bit Definitions */ + +/* DCORSEL Bit Mask */ +#define CS_CTL0_DCORSEL_MASK ((uint32_t)0x00070000) +/* Nominal DCO Frequency Range (MHz): 2 to 4 */ +#define CS_CTL0_DCORSEL_1 ((uint32_t)0x00010000) +/* Nominal DCO Frequency Range (MHz): 16 to 32 */ +#define CS_CTL0_DCORSEL_4 ((uint32_t)0x00040000) +/* CS control key value */ +#define CS_KEY_VAL ((uint32_t)0x0000695A) + +/* AMR Bit Mask */ +#define PCM_CTL0_AMR_MASK ((uint32_t)0x0000000F) +/* LPMR Bit Mask */ +#define PCM_CTL0_LPMR_MASK ((uint32_t)0x000000F0) +/* LPM3.5. Core voltage setting 0. */ +#define PCM_CTL0_LPMR_10 ((uint32_t)0x000000A0) +/* LPM4.5 */ +#define PCM_CTL0_LPMR_12 ((uint32_t)0x000000C0) +/* CPM Bit Offset */ +#define PCM_CTL0_CPM_OFS (8) +/* CPM Bit Mask */ +#define PCM_CTL0_CPM_MASK ((uint32_t)0x00003F00) +/* PCMKEY Bit Mask */ +#define PCM_CTL0_KEY_MASK ((uint32_t)0xFFFF0000) +/* PMR_BUSY Bit Offset */ +#define PCM_CTL1_PMR_BUSY_OFS (8) + +/* RTCKEY Bit Offset */ +#define RTC_C_CTL0_KEY_OFS (8) +/* RTCKEY Bit Mask */ +#define RTC_C_CTL0_KEY_MASK ((uint16_t)0xFF00) +/* RTCHOLD Bit Offset */ +#define RTC_C_CTL13_HOLD_OFS (6) +/* RTC_C Key Value for RTC_C write access */ +#define RTC_C_KEY ((uint16_t)0xA500) + +/* Watchdog timer hold */ +#define WDT_A_CTL_HOLD ((uint16_t)0x0080) +/* WDT Key Value for WDT write access */ +#define WDT_A_CTL_PW ((uint16_t)0x5A00) + +/* Address of BSL API table */ +#define BSL_API_TABLE_ADDR ((uint32_t)0x00202000) + +#ifdef __cplusplus +} +#endif + +#endif /* OPENOCD_LOADERS_FLASH_MSP432_MSP432P411X_H */ diff --git a/contrib/loaders/flash/msp432/msp432p411x/msp432p411x.lds b/contrib/loaders/flash/msp432/msp432p411x/msp432p411x.lds new file mode 100644 index 0000000..7798b30 --- /dev/null +++ b/contrib/loaders/flash/msp432/msp432p411x/msp432p411x.lds @@ -0,0 +1,151 @@ +/****************************************************************************** +* +* Copyright (C) 2012-2018 Texas Instruments Incorporated - http://www.ti.com/ +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the +* distribution. +* +* Neither the name of Texas Instruments Incorporated nor the names of +* its contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +******************************************************************************/ + +MEMORY { + MAIN_FLASH (RX) : ORIGIN = 0x00000000, LENGTH = 0x00200000 + INFO_FLASH (RX) : ORIGIN = 0x00200000, LENGTH = 0x00008000 + SRAM_CODE_0(RWX): ORIGIN = 0x01000000, LENGTH = 0x00000110 + SRAM_CODE_1(RWX): ORIGIN = 0x01000110, LENGTH = 0x00000030 + SRAM_CODE_2(RWX): ORIGIN = 0x01000150, LENGTH = 0x00000040 + SRAM_CODE_3(RWX): ORIGIN = 0x01000190, LENGTH = 0x00001E70 + SRAM_CODE_4(RWX): ORIGIN = 0x01002000, LENGTH = 0x00000200 + SRAM_DATA (RW) : ORIGIN = 0x20002000, LENGTH = 0x00001000 +} + +REGION_ALIAS("REGION_INTVECT", SRAM_CODE_0); +REGION_ALIAS("REGION_RESET", SRAM_CODE_1); +REGION_ALIAS("REGION_DESCRIPTOR", SRAM_CODE_2); +REGION_ALIAS("REGION_TEXT", SRAM_CODE_3); +REGION_ALIAS("REGION_BSS", SRAM_CODE_3); +REGION_ALIAS("REGION_DATA", SRAM_DATA); +REGION_ALIAS("REGION_STACK", SRAM_CODE_4); +REGION_ALIAS("REGION_HEAP", SRAM_DATA); +REGION_ALIAS("REGION_ARM_EXIDX", SRAM_CODE_3); +REGION_ALIAS("REGION_ARM_EXTAB", SRAM_CODE_3); + +SECTIONS { + /* section for the interrupt vector area */ + .intvecs : { + KEEP (*(.intvecs)) + } > REGION_INTVECT + + PROVIDE (_vtable_base_address = + DEFINED(_vtable_base_address) ? _vtable_base_address : 0x20000000); + + .vtable (_vtable_base_address) : AT (_vtable_base_address) { + KEEP (*(.vtable)) + } > REGION_DATA + + .descriptor :{ + FILL(0x00000000); + . = ORIGIN(REGION_DESCRIPTOR) + LENGTH(REGION_DESCRIPTOR) - 1; + BYTE(0x00); + __ROM_AT = .; + } > REGION_DESCRIPTOR + + .reset : { + KEEP(*(.reset)) + } > REGION_RESET AT> REGION_RESET + + .text : { + CREATE_OBJECT_SYMBOLS + KEEP (*(.text)) + *(.text.*) + . = ALIGN(0x4); + KEEP (*(.ctors)) + . = ALIGN(0x4); + KEEP (*(.dtors)) + . = ALIGN(0x4); + __init_array_start = .; + KEEP (*(.init_array*)) + __init_array_end = .; + KEEP (*(.init)) + KEEP (*(.fini*)) + } > REGION_TEXT AT> REGION_TEXT + + .rodata : { + *(.rodata) + *(.rodata.*) + } > REGION_TEXT AT> REGION_TEXT + + .ARM.exidx : { + __exidx_start = .; + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + __exidx_end = .; + } > REGION_ARM_EXIDX AT> REGION_ARM_EXIDX + + .ARM.extab : { + KEEP (*(.ARM.extab* .gnu.linkonce.armextab.*)) + } > REGION_ARM_EXTAB AT> REGION_ARM_EXTAB + + __etext = .; + + .data : { + __data_load__ = LOADADDR (.data); + __data_start__ = .; + KEEP (*(.data)) + KEEP (*(.data*)) + . = ALIGN (4); + __data_end__ = .; + } > REGION_DATA AT> REGION_TEXT + + .bss : { + __bss_start__ = .; + *(.shbss) + KEEP (*(.bss)) + *(.bss.*) + *(COMMON) + . = ALIGN (4); + __bss_end__ = .; + } > REGION_BSS AT> REGION_BSS + + .heap : { + __heap_start__ = .; + end = __heap_start__; + _end = end; + __end = end; + KEEP (*(.heap)) + __heap_end__ = .; + __HeapLimit = __heap_end__; + } > REGION_HEAP AT> REGION_HEAP + + .stack (NOLOAD) : ALIGN(0x8) { + _stack = .; + KEEP(*(.stack)) + } > REGION_STACK AT> REGION_STACK + + __stack_top = ORIGIN(REGION_STACK) + LENGTH(REGION_STACK); + PROVIDE(__stack = __stack_top); +} + diff --git a/contrib/loaders/flash/msp432/msp432p411x_algo.inc b/contrib/loaders/flash/msp432/msp432p411x_algo.inc new file mode 100644 index 0000000..da41bb7 --- /dev/null +++ b/contrib/loaders/flash/msp432/msp432p411x_algo.inc @@ -0,0 +1,361 @@ +/* Autogenerated with ../../../../src/helper/bin2char.sh */ +0x00,0x22,0x00,0x01,0x11,0x01,0x00,0x01,0x0d,0x12,0x00,0x01,0x0d,0x12,0x00,0x01, +0x0d,0x12,0x00,0x01,0x0d,0x12,0x00,0x01,0x0d,0x12,0x00,0x01,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0d,0x12,0x00,0x01, +0x0d,0x12,0x00,0x01,0x00,0x00,0x00,0x00,0x0d,0x12,0x00,0x01,0x0d,0x12,0x00,0x01, +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,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,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,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, +0x41,0xf2,0x00,0x70,0xc0,0xf2,0x00,0x10,0x85,0x46,0x05,0x48,0x05,0x49,0x4f,0xf0, +0x00,0x02,0x88,0x42,0xb8,0xbf,0x40,0xf8,0x04,0x2b,0xfa,0xdb,0x00,0xf0,0xaa,0xbf, +0x78,0x16,0x00,0x01,0x94,0x16,0x00,0x01,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,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, +0x04,0x4b,0x05,0x48,0x1b,0x1a,0x06,0x2b,0x02,0xd9,0x04,0x4b,0x03,0xb1,0x18,0x47, +0x70,0x47,0x00,0xbf,0x37,0x24,0x00,0x20,0x34,0x24,0x00,0x20,0x00,0x00,0x00,0x00, +0x05,0x49,0x06,0x48,0x09,0x1a,0x89,0x10,0x01,0xeb,0xd1,0x71,0x49,0x10,0x02,0xd0, +0x03,0x4b,0x03,0xb1,0x18,0x47,0x70,0x47,0x34,0x24,0x00,0x20,0x34,0x24,0x00,0x20, +0x00,0x00,0x00,0x00,0x10,0xb5,0x06,0x4c,0x23,0x78,0x43,0xb9,0xff,0xf7,0xd8,0xff, +0x04,0x4b,0x13,0xb1,0x04,0x48,0xaf,0xf3,0x00,0x80,0x01,0x23,0x23,0x70,0x10,0xbd, +0x78,0x16,0x00,0x01,0x00,0x00,0x00,0x00,0x3c,0x12,0x00,0x01,0x08,0xb5,0x08,0x4b, +0x1b,0xb1,0x08,0x48,0x08,0x49,0xaf,0xf3,0x00,0x80,0x08,0x48,0x03,0x68,0x13,0xb9, +0xbd,0xe8,0x08,0x40,0xcc,0xe7,0x06,0x4b,0x00,0x2b,0xf9,0xd0,0x98,0x47,0xf7,0xe7, +0x00,0x00,0x00,0x00,0x3c,0x12,0x00,0x01,0x7c,0x16,0x00,0x01,0x34,0x24,0x00,0x20, +0x00,0x00,0x00,0x00,0x13,0x4b,0x00,0x2b,0x08,0xbf,0x11,0x4b,0x9d,0x46,0xa3,0xf5, +0x80,0x3a,0x00,0x21,0x8b,0x46,0x0f,0x46,0x11,0x48,0x12,0x4a,0x12,0x1a,0x00,0xf0, +0x79,0xf8,0x0d,0x4b,0x00,0x2b,0x00,0xd0,0x98,0x47,0x0c,0x4b,0x00,0x2b,0x00,0xd0, +0x98,0x47,0x00,0x20,0x00,0x21,0x04,0x00,0x0d,0x00,0x0b,0x48,0x00,0xf0,0x16,0xf8, +0x00,0xf0,0x40,0xf8,0x20,0x00,0x29,0x00,0x00,0xf0,0x04,0xff,0x00,0xf0,0x14,0xf8, +0x00,0x00,0x08,0x00,0x00,0x22,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x78,0x16,0x00,0x01,0x94,0x16,0x00,0x01,0xc9,0x02,0x00,0x01,0x01,0x46,0x00,0x20, +0x02,0x46,0x03,0x46,0x00,0xf0,0x9c,0xb8,0x08,0xb5,0x00,0x21,0x04,0x46,0x00,0xf0, +0xf3,0xf8,0x04,0x4b,0x18,0x68,0xc3,0x6b,0x03,0xb1,0x98,0x47,0x20,0x46,0x00,0xf0, +0x55,0xf9,0x00,0xbf,0x38,0x12,0x00,0x01,0x38,0xb5,0x08,0x4b,0x08,0x4d,0xed,0x1a, +0xac,0x10,0x18,0xbf,0xed,0x18,0x05,0xd0,0x01,0x3c,0x55,0xf8,0x04,0x3d,0x98,0x47, +0x00,0x2c,0xf9,0xd1,0xbd,0xe8,0x38,0x40,0x00,0xf0,0x9c,0xbf,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x70,0xb5,0x0f,0x4e,0x0f,0x4d,0x76,0x1b,0xb6,0x10,0x18,0xbf, +0x00,0x24,0x05,0xd0,0x01,0x34,0x55,0xf8,0x04,0x3b,0x98,0x47,0xa6,0x42,0xf9,0xd1, +0x0a,0x4e,0x0b,0x4d,0x76,0x1b,0x00,0xf0,0x7f,0xff,0xb6,0x10,0x18,0xbf,0x00,0x24, +0x06,0xd0,0x01,0x34,0x55,0xf8,0x04,0x3b,0x98,0x47,0xa6,0x42,0xf9,0xd1,0x70,0xbd, +0x70,0xbd,0x00,0xbf,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x12,0x00,0x01, +0x10,0x12,0x00,0x01,0x70,0xb4,0x84,0x07,0x46,0xd0,0x54,0x1e,0x00,0x2a,0x41,0xd0, +0xcd,0xb2,0x03,0x46,0x02,0xe0,0x62,0x1e,0xe4,0xb3,0x14,0x46,0x03,0xf8,0x01,0x5b, +0x9a,0x07,0xf8,0xd1,0x03,0x2c,0x2e,0xd9,0xcd,0xb2,0x45,0xea,0x05,0x25,0x0f,0x2c, +0x45,0xea,0x05,0x45,0x19,0xd9,0x03,0xf1,0x10,0x02,0x26,0x46,0x10,0x3e,0x0f,0x2e, +0x42,0xf8,0x10,0x5c,0x42,0xf8,0x0c,0x5c,0x42,0xf8,0x08,0x5c,0x42,0xf8,0x04,0x5c, +0x02,0xf1,0x10,0x02,0xf2,0xd8,0xa4,0xf1,0x10,0x02,0x22,0xf0,0x0f,0x02,0x04,0xf0, +0x0f,0x04,0x10,0x32,0x03,0x2c,0x13,0x44,0x0d,0xd9,0x1e,0x46,0x22,0x46,0x04,0x3a, +0x03,0x2a,0x46,0xf8,0x04,0x5b,0xfa,0xd8,0x22,0x1f,0x22,0xf0,0x03,0x02,0x04,0x32, +0x13,0x44,0x04,0xf0,0x03,0x04,0x2c,0xb1,0xc9,0xb2,0x1c,0x44,0x03,0xf8,0x01,0x1b, +0xa3,0x42,0xfb,0xd1,0x70,0xbc,0x70,0x47,0x14,0x46,0x03,0x46,0xc2,0xe7,0x00,0xbf, +0x2d,0xe9,0xf0,0x47,0x25,0x4c,0x25,0x68,0xd5,0xf8,0x48,0x41,0x06,0x46,0x88,0x46, +0x92,0x46,0x99,0x46,0xcc,0xb3,0x60,0x68,0x1f,0x28,0x18,0xdc,0x43,0x1c,0x7e,0xb1, +0x04,0xeb,0x80,0x05,0x01,0x21,0xc5,0xf8,0x88,0xa0,0xd4,0xf8,0x88,0x71,0x01,0xfa, +0x00,0xf2,0x17,0x43,0x02,0x2e,0xc4,0xf8,0x88,0x71,0xc5,0xf8,0x08,0x91,0x1e,0xd0, +0x02,0x30,0x63,0x60,0x44,0xf8,0x20,0x80,0x00,0x20,0xbd,0xe8,0xf0,0x87,0x14,0x4b, +0x03,0xb3,0x4f,0xf4,0xc8,0x70,0xaf,0xf3,0x00,0x80,0x04,0x46,0xd0,0xb1,0xd5,0xf8, +0x48,0x31,0x00,0x27,0x80,0xe8,0x88,0x00,0xc5,0xf8,0x48,0x41,0x38,0x46,0x01,0x23, +0xc4,0xf8,0x88,0x71,0xc4,0xf8,0x8c,0x71,0x00,0x2e,0xe1,0xd0,0xd0,0xe7,0xd4,0xf8, +0x8c,0x11,0x0a,0x43,0xc4,0xf8,0x8c,0x21,0xda,0xe7,0x05,0xf5,0xa6,0x74,0xc5,0xf8, +0x48,0x41,0xc0,0xe7,0x4f,0xf0,0xff,0x30,0xbd,0xe8,0xf0,0x87,0x38,0x12,0x00,0x01, +0x00,0x00,0x00,0x00,0x02,0x4b,0x13,0xb1,0x02,0x48,0xff,0xf7,0x07,0xbf,0x70,0x47, +0x00,0x00,0x00,0x00,0xc9,0x02,0x00,0x01,0x2d,0xe9,0xf0,0x4f,0x31,0x4b,0x83,0xb0, +0x1b,0x68,0x00,0x93,0x03,0xf5,0xa4,0x73,0x81,0x46,0x0e,0x46,0x01,0x93,0x00,0x9b, +0xd3,0xf8,0x48,0x71,0x27,0xb3,0xdd,0xf8,0x04,0xa0,0x7c,0x68,0x65,0x1e,0x0e,0xd4, +0x01,0x34,0x07,0xeb,0x84,0x04,0x4f,0xf0,0x00,0x08,0xe6,0xb1,0xd4,0xf8,0x00,0x31, +0xb3,0x42,0x18,0xd0,0x01,0x3d,0x6b,0x1c,0xa4,0xf1,0x04,0x04,0xf5,0xd1,0x22,0x4b, +0x73,0xb1,0x7b,0x68,0x00,0x2b,0x36,0xd1,0x3b,0x68,0x00,0x2b,0x34,0xd0,0x38,0x46, +0xca,0xf8,0x00,0x30,0xaf,0xf3,0x00,0x80,0xda,0xf8,0x00,0x70,0x00,0x2f,0xdc,0xd1, +0x03,0xb0,0xbd,0xe8,0xf0,0x8f,0x7b,0x68,0x22,0x68,0x01,0x3b,0xab,0x42,0x0c,0xbf, +0x7d,0x60,0xc4,0xf8,0x00,0x80,0x00,0x2a,0xdc,0xd0,0xd7,0xf8,0x88,0x31,0xd7,0xf8, +0x04,0xb0,0x01,0x21,0xa9,0x40,0x19,0x42,0x08,0xd1,0x90,0x47,0x7b,0x68,0x5b,0x45, +0xbd,0xd1,0xda,0xf8,0x00,0x30,0xbb,0x42,0xcc,0xd0,0xb8,0xe7,0xd7,0xf8,0x8c,0x31, +0x19,0x42,0x04,0xd1,0x48,0x46,0xd4,0xf8,0x80,0x10,0x90,0x47,0xee,0xe7,0xd4,0xf8, +0x80,0x00,0x90,0x47,0xea,0xe7,0x3b,0x68,0xba,0x46,0x1f,0x46,0x00,0x2f,0xac,0xd1, +0xce,0xe7,0x00,0xbf,0x38,0x12,0x00,0x01,0x00,0x00,0x00,0x00,0xfe,0xe7,0x00,0xbf, +0x4f,0x4a,0x13,0x68,0xc3,0xf3,0x05,0x23,0x04,0x3b,0xdb,0xb2,0x15,0x2b,0x70,0xb4, +0x00,0xf2,0x8c,0x80,0x01,0x22,0x02,0xfa,0x03,0xf3,0x13,0xf0,0x30,0x1f,0x61,0xd0, +0x02,0x23,0x98,0x42,0x31,0xd0,0x46,0x4b,0x1b,0x68,0xc3,0xf3,0x05,0x23,0x44,0x4c, +0x44,0x49,0x01,0x25,0x22,0x68,0x09,0x2b,0x10,0xd8,0xdf,0xe8,0x03,0xf0,0x05,0x35, +0x0f,0x0f,0x45,0x29,0x0f,0x0f,0x45,0x29,0x01,0x28,0x63,0xd0,0x02,0x28,0x73,0xd1, +0x4f,0xf6,0xf0,0x76,0x3c,0x4b,0x16,0x40,0x33,0x43,0x23,0x60,0x0b,0x78,0x03,0xf0, +0xff,0x02,0x00,0x2b,0xfa,0xd1,0x23,0x68,0xc3,0xf3,0x05,0x23,0x04,0x3b,0xdb,0xb2, +0x15,0x2b,0x05,0xd8,0x05,0xfa,0x03,0xf3,0x13,0xf0,0x30,0x1f,0x38,0xd0,0x02,0x22, +0x23,0x68,0x90,0x42,0xc3,0xf3,0x05,0x23,0xd4,0xd1,0x01,0x20,0x70,0xbc,0x70,0x47, +0x4f,0xf6,0xf0,0x76,0x2d,0x4b,0x16,0x40,0x33,0x43,0x23,0x60,0x0b,0x78,0x03,0xf0, +0xff,0x02,0x00,0x2b,0xda,0xd1,0xde,0xe7,0x01,0x28,0x27,0xd0,0x02,0x28,0x43,0xd1, +0x4f,0xf6,0xf0,0x76,0x26,0x4b,0x16,0x40,0x33,0x43,0x23,0x60,0x0b,0x78,0x03,0xf0, +0xff,0x02,0x00,0x2b,0xca,0xd1,0xce,0xe7,0x4f,0xf6,0xf0,0x73,0x13,0x40,0x43,0xf0, +0xd2,0x43,0x43,0xf4,0xb4,0x03,0x23,0x60,0x0b,0x78,0x03,0xf0,0xff,0x02,0x00,0x2b, +0xbc,0xd1,0xc0,0xe7,0x13,0xf0,0x03,0x1f,0x14,0xbf,0x13,0x46,0x00,0x23,0x98,0xe7, +0x13,0xf0,0x03,0x1f,0x14,0xbf,0x01,0x22,0x00,0x22,0xc1,0xe7,0x4f,0xf6,0xf0,0x76, +0x14,0x4b,0x16,0x40,0x33,0x43,0x23,0x60,0x0b,0x78,0x03,0xf0,0xff,0x02,0x00,0x2b, +0xa4,0xd1,0xa8,0xe7,0x4f,0xf6,0xf0,0x76,0x0f,0x4b,0x16,0x40,0x33,0x43,0x23,0x60, +0x0b,0x78,0x03,0xf0,0xff,0x02,0x00,0x2b,0x98,0xd1,0x9c,0xe7,0x00,0x28,0xac,0xd0, +0x13,0x68,0xc3,0xf3,0x05,0x23,0x7a,0xe7,0x00,0x20,0x70,0xbc,0x70,0x47,0x00,0xbf, +0x00,0x00,0x01,0x40,0xa0,0x00,0x20,0x42,0x08,0x00,0x5a,0x69,0x01,0x00,0x5a,0x69, +0x09,0x00,0x5a,0x69,0x05,0x00,0x5a,0x69,0x04,0x00,0x5a,0x69,0x4a,0x4b,0x1b,0x68, +0xc3,0xf3,0x05,0x23,0x04,0x3b,0xdb,0xb2,0x15,0x2b,0xf0,0xb4,0x7e,0xd8,0x01,0x22, +0x02,0xfa,0x03,0xf3,0x13,0xf0,0x30,0x1f,0x5f,0xd0,0x02,0x26,0x42,0x4b,0x1b,0x68, +0xc3,0xf3,0x05,0x23,0x01,0x3b,0xdb,0xb2,0x1f,0x2b,0x69,0xd8,0x01,0x22,0x02,0xfa, +0x03,0xf3,0x03,0xf0,0x11,0x31,0x21,0xf0,0x10,0x21,0x00,0x29,0x68,0xd1,0x00,0x2b, +0xb4,0xbf,0x02,0x23,0x00,0x23,0x98,0x42,0x5d,0xd0,0x37,0x4c,0x37,0x49,0x01,0x25, +0x22,0x68,0x23,0x68,0xc3,0xf3,0x05,0x23,0x09,0x2b,0x0e,0xd8,0x05,0xfa,0x03,0xf3, +0x13,0xf4,0x89,0x7f,0x41,0xd1,0x40,0xf2,0x21,0x27,0x1f,0x40,0x2f,0xb1,0x4f,0xf6, +0xf0,0x77,0x2f,0x4b,0x17,0x40,0x3b,0x43,0x23,0x60,0x0b,0x78,0x03,0xf0,0xff,0x02, +0x00,0x2b,0xfa,0xd1,0x23,0x68,0xc3,0xf3,0x05,0x23,0x01,0x3b,0xdb,0xb2,0x1f,0x2b, +0x29,0xd8,0x05,0xfa,0x03,0xf3,0x03,0xf0,0x11,0x37,0x27,0xf0,0x10,0x27,0x6f,0xbb, +0x00,0x2b,0xb4,0xbf,0x02,0x23,0x00,0x23,0x98,0x42,0xd1,0xd1,0x1e,0x4b,0x1b,0x68, +0xc3,0xf3,0x05,0x23,0x04,0x3b,0xdb,0xb2,0x15,0x2b,0x06,0xd8,0x01,0x22,0x02,0xfa, +0x03,0xf3,0x13,0xf0,0x30,0x1f,0x25,0xd0,0x02,0x22,0x96,0x42,0x1b,0xd0,0x01,0x2e, +0x25,0xd0,0x02,0x20,0xf0,0xbc,0xff,0xf7,0xe3,0xbe,0x13,0xf0,0x03,0x1f,0x14,0xbf, +0x16,0x46,0x00,0x26,0x9a,0xe7,0x13,0x46,0xde,0xe7,0x4f,0xf6,0xf0,0x73,0x13,0x40, +0x43,0xf0,0xd2,0x43,0x43,0xf4,0xb4,0x03,0x23,0x60,0xbe,0xe7,0x01,0x23,0xd3,0xe7, +0x00,0x23,0x98,0x42,0xa1,0xd1,0x01,0x20,0xf0,0xbc,0x70,0x47,0x00,0x26,0x85,0xe7, +0x13,0x46,0x98,0xe7,0x13,0xf0,0x03,0x1f,0x08,0xbf,0x00,0x22,0xd5,0xe7,0x30,0x46, +0xf0,0xbc,0xff,0xf7,0xbd,0xbe,0x00,0xbf,0x00,0x00,0x01,0x40,0xa0,0x00,0x20,0x42, +0x01,0x00,0x5a,0x69,0xef,0xf3,0x10,0x80,0x72,0xb6,0x70,0x47,0x30,0xbf,0x70,0x47, +0x04,0x4a,0x08,0xb5,0x13,0x69,0x23,0xf0,0x04,0x03,0x13,0x61,0xff,0xf7,0xf6,0xff, +0x01,0x20,0x08,0xbd,0x00,0xed,0x00,0xe0,0xff,0xf7,0x50,0xbf,0x0b,0x4b,0x1b,0x68, +0xc3,0xf3,0x05,0x23,0x01,0x3b,0xdb,0xb2,0x1f,0x2b,0x0c,0xd8,0x01,0x20,0x00,0xfa, +0x03,0xf2,0x02,0xf0,0x11,0x33,0x23,0xf0,0x10,0x23,0x2b,0xb9,0x00,0x2a,0xb4,0xbf, +0x02,0x20,0x00,0x20,0x70,0x47,0x00,0x20,0x70,0x47,0x00,0xbf,0x00,0x00,0x01,0x40, +0x2d,0xe9,0xf8,0x43,0x7b,0x4e,0x7c,0x4c,0xdf,0xf8,0x00,0x82,0x7b,0x4f,0x7c,0x4d, +0x33,0x78,0x00,0x2b,0x43,0xd1,0x23,0x68,0x03,0xf0,0xf0,0x03,0xa0,0x2b,0x3e,0xd0, +0x23,0x68,0x03,0xf0,0xf0,0x03,0xc0,0x2b,0x39,0xd0,0x23,0x68,0xc3,0xf3,0x05,0x23, +0x04,0x3b,0xdb,0xb2,0x15,0x2b,0x08,0xd8,0x01,0x22,0x02,0xfa,0x03,0xf3,0x13,0xf0, +0x30,0x10,0x02,0xd1,0x13,0xf0,0x03,0x1f,0x55,0xd1,0x23,0x68,0xc3,0xf3,0x05,0x29, +0x22,0x68,0x4f,0xf6,0x0f,0x73,0x13,0x40,0x43,0xf0,0xd2,0x43,0x43,0xf4,0xb4,0x03, +0x23,0x60,0x2b,0x69,0x43,0xf0,0x04,0x03,0x2b,0x61,0xff,0xf7,0x9f,0xff,0x2b,0x69, +0x23,0xf0,0x04,0x03,0x2b,0x61,0x23,0x68,0xc3,0xf3,0x05,0x23,0x4b,0x45,0x29,0xd0, +0xb9,0xf1,0x11,0x0f,0x6b,0xd0,0x0d,0xd9,0xb9,0xf1,0x19,0x0f,0x72,0xd0,0x4b,0xd9, +0xb9,0xf1,0x21,0x0f,0x35,0xd0,0x02,0xd8,0xb9,0xf1,0x20,0x0f,0xb8,0xd0,0x00,0x20, +0xbd,0xe8,0xf8,0x83,0xb9,0xf1,0x05,0x0f,0x6f,0xd0,0x16,0xd9,0xb9,0xf1,0x09,0x0f, +0x00,0xf0,0x8c,0x80,0xb9,0xf1,0x10,0x0f,0x00,0xf0,0x81,0x80,0xb9,0xf1,0x08,0x0f, +0xed,0xd1,0x00,0x20,0xff,0xf7,0xd2,0xfe,0x98,0xb1,0x02,0x20,0xbd,0xe8,0xf8,0x43, +0xff,0xf7,0x1e,0xbe,0x01,0x20,0xbd,0xe8,0xf8,0x83,0xb9,0xf1,0x01,0x0f,0x68,0xd0, +0x5d,0xd3,0xb9,0xf1,0x04,0x0f,0xda,0xd1,0x00,0x20,0xff,0xf7,0xbf,0xfe,0x00,0x28, +0x50,0xd1,0xbd,0xe8,0xf8,0x83,0x23,0x68,0xc3,0xf3,0x05,0x29,0xff,0xf7,0x08,0xfe, +0xa6,0xe7,0x40,0x49,0x40,0x4a,0x8b,0x89,0x03,0xf0,0x7f,0x03,0x43,0xf4,0xb5,0x43, +0x8b,0x81,0x13,0x88,0xdb,0xb2,0x43,0xf4,0x25,0x43,0x01,0x20,0x00,0x21,0x13,0x80, +0x88,0xf8,0x00,0x00,0x39,0x70,0x72,0xe7,0xb9,0xf1,0x15,0x0f,0x5b,0xd0,0xb9,0xf1, +0x18,0x0f,0x51,0xd0,0xb9,0xf1,0x14,0x0f,0xb1,0xd1,0x00,0x20,0xff,0xf7,0x96,0xfe, +0x00,0x28,0xac,0xd0,0x01,0x20,0xff,0xf7,0xe3,0xfd,0x00,0x28,0xa7,0xd0,0x29,0x4b, +0x1b,0x78,0x00,0x2b,0xa3,0xd1,0xbd,0xe8,0xf8,0x43,0xff,0xf7,0x29,0xbf,0x01,0x20, +0xff,0xf7,0x84,0xfe,0x00,0x28,0x9a,0xd0,0x00,0x20,0xff,0xf7,0xd1,0xfd,0x00,0x28, +0xed,0xd1,0x94,0xe7,0x01,0x20,0xff,0xf7,0x79,0xfe,0x00,0x28,0x8f,0xd0,0x02,0x20, +0xff,0xf7,0xc6,0xfd,0x00,0x28,0xe2,0xd1,0x89,0xe7,0x01,0x20,0xff,0xf7,0x6e,0xfe, +0x00,0x28,0xae,0xd0,0x01,0x20,0xbd,0xe8,0xf8,0x43,0xff,0xf7,0xb9,0xbd,0x00,0x20, +0xff,0xf7,0x64,0xfe,0x00,0x28,0xa4,0xd0,0x00,0x20,0xbd,0xe8,0xf8,0x43,0xff,0xf7, +0xaf,0xbd,0x48,0x46,0xff,0xf7,0x5a,0xfe,0x00,0x28,0x9a,0xd0,0xf4,0xe7,0x00,0x20, +0xff,0xf7,0x54,0xfe,0x00,0x28,0x3f,0xf4,0x6a,0xaf,0xcd,0xe7,0x01,0x20,0xff,0xf7, +0x4d,0xfe,0x00,0x28,0x8d,0xd0,0x78,0xe7,0x00,0x20,0xff,0xf7,0x47,0xfe,0x00,0x28, +0x3f,0xf4,0x5d,0xaf,0xcb,0xe7,0x01,0x20,0xff,0xf7,0x40,0xfe,0x00,0x28,0x3f,0xf4, +0x56,0xaf,0xa7,0xe7,0xa0,0x00,0x20,0x42,0x00,0x00,0x01,0x40,0x20,0x80,0x08,0x42, +0x00,0xed,0x00,0xe0,0x00,0x48,0x00,0x40,0x00,0x44,0x00,0x40,0x58,0x80,0x08,0x42, +0x6b,0x49,0x30,0xb5,0x0a,0x68,0xc2,0xf3,0x05,0x22,0x90,0x42,0x83,0xb0,0x21,0xd0, +0x11,0x28,0x00,0xf0,0xbf,0x80,0x20,0xd9,0x19,0x28,0x00,0xf0,0x95,0x80,0x3a,0xd9, +0x21,0x28,0x5d,0xd0,0x55,0xd9,0xa0,0x28,0x00,0xf0,0x86,0x80,0xc0,0x28,0x1e,0xd1, +0x60,0x4b,0x1b,0x78,0xdb,0xb9,0x60,0x48,0x5d,0x49,0x02,0x69,0x5f,0x4b,0x42,0xf0, +0x04,0x02,0x02,0x61,0x08,0x68,0x4f,0xf6,0x0f,0x72,0x02,0x40,0x13,0x43,0x0b,0x60, +0xff,0xf7,0xa4,0xfe,0x01,0x20,0x03,0xb0,0x30,0xbd,0x05,0x28,0x00,0xf0,0xa1,0x80, +0x08,0xd9,0x09,0x28,0x62,0xd0,0x10,0x28,0x55,0xd0,0x08,0x28,0x4c,0xd0,0x00,0x20, +0x03,0xb0,0x30,0xbd,0x01,0x28,0x00,0xf0,0x87,0x80,0x7d,0xd3,0x04,0x28,0xf6,0xd1, +0x00,0x20,0xff,0xf7,0xeb,0xfd,0x00,0x28,0xe5,0xd0,0x01,0x20,0x03,0xb0,0xbd,0xe8, +0x30,0x40,0xff,0xf7,0x35,0xbd,0x15,0x28,0x67,0xd0,0x18,0x28,0x5f,0xd0,0x14,0x28, +0xe5,0xd1,0x00,0x20,0xff,0xf7,0xda,0xfd,0x00,0x28,0xe0,0xd0,0x01,0x20,0xff,0xf7, +0x27,0xfd,0x00,0x28,0xdb,0xd0,0x3f,0x4b,0x1b,0x78,0x00,0x2b,0xd7,0xd1,0x3e,0x4a, +0x01,0x90,0x13,0x69,0x23,0xf0,0x04,0x03,0x13,0x61,0xff,0xf7,0x67,0xfe,0x01,0x98, +0xc1,0xe7,0x20,0x28,0xcb,0xd1,0x03,0xb0,0xbd,0xe8,0x30,0x40,0xff,0xf7,0x88,0xbe, +0x37,0x49,0x38,0x4a,0x8b,0x89,0x38,0x4c,0x38,0x48,0x03,0xf0,0x7f,0x03,0x43,0xf4, +0xb5,0x43,0x8b,0x81,0x13,0x88,0xdb,0xb2,0x43,0xf4,0x25,0x43,0x01,0x25,0x00,0x21, +0x13,0x80,0x25,0x70,0x01,0x70,0xe6,0xe7,0x00,0x20,0xff,0xf7,0xa7,0xfd,0x00,0x28, +0xa1,0xd0,0x02,0x20,0xba,0xe7,0x00,0x20,0xff,0xf7,0xa0,0xfd,0x00,0x28,0xa6,0xd0, +0x00,0x20,0xff,0xf7,0xed,0xfc,0x00,0x28,0xc5,0xd1,0xa0,0xe7,0x01,0x20,0xff,0xf7, +0x95,0xfd,0x00,0x28,0x8f,0xd0,0xec,0xe7,0x1e,0x4b,0x1b,0x78,0x00,0x2b,0x96,0xd1, +0x1d,0x48,0x23,0x4b,0x02,0x69,0x7a,0xe7,0x01,0x20,0xff,0xf7,0x87,0xfd,0x00,0x28, +0x8d,0xd0,0x02,0x20,0xff,0xf7,0xd4,0xfc,0x00,0x28,0xac,0xd1,0x87,0xe7,0x00,0x20, +0xff,0xf7,0x7c,0xfd,0x00,0x28,0x82,0xd0,0xf3,0xe7,0x01,0x20,0xff,0xf7,0x76,0xfd, +0x00,0x28,0x3f,0xf4,0x7c,0xaf,0x99,0xe7,0x00,0x20,0xff,0xf7,0x6f,0xfd,0x00,0x28, +0x3f,0xf4,0x69,0xaf,0x00,0x20,0x81,0xe7,0xff,0xf7,0x68,0xfd,0x00,0x28,0x3f,0xf4, +0x62,0xaf,0xf7,0xe7,0x01,0x20,0xff,0xf7,0x61,0xfd,0x00,0x28,0x3f,0xf4,0x67,0xaf, +0xbe,0xe7,0x01,0x20,0xff,0xf7,0x5a,0xfd,0x00,0x28,0x3f,0xf4,0x54,0xaf,0x6c,0xe7, +0x00,0x00,0x01,0x40,0xa0,0x00,0x20,0x42,0x00,0xed,0x00,0xe0,0xa0,0x00,0x5a,0x69, +0x00,0x48,0x00,0x40,0x00,0x44,0x00,0x40,0x58,0x80,0x08,0x42,0x20,0x80,0x08,0x42, +0xc0,0x00,0x5a,0x69,0x02,0x4b,0x18,0x68,0xc0,0xf3,0x05,0x20,0x70,0x47,0x00,0xbf, +0x00,0x00,0x01,0x40,0x70,0xb5,0x1e,0x4e,0x1e,0x4a,0x33,0x68,0x1e,0x4d,0x1f,0x4c, +0x4f,0xf0,0x80,0x71,0x91,0x60,0x9b,0x6d,0x00,0x20,0x98,0x47,0x33,0x68,0x28,0x60, +0x9b,0x6d,0x01,0x20,0x98,0x47,0x68,0x60,0xff,0xf7,0xd8,0xfd,0x28,0x73,0xff,0xf7, +0xe1,0xff,0x63,0x68,0x68,0x73,0x03,0xf4,0xe0,0x23,0xab,0x60,0x00,0x20,0xff,0xf7, +0xef,0xfe,0x33,0x68,0x02,0x21,0x5b,0x6d,0x05,0x46,0x00,0x20,0x98,0x47,0x33,0x68, +0x01,0x20,0x5b,0x6d,0x02,0x21,0x98,0x47,0x46,0xf6,0x5a,0x13,0x23,0x60,0x63,0x68, +0x23,0xf4,0xe0,0x23,0x43,0xf4,0x80,0x23,0x00,0x22,0x63,0x60,0x22,0x60,0x08,0x4b, +0x1d,0xb1,0x40,0xf6,0xce,0x22,0x5a,0x60,0x70,0xbd,0x06,0x4a,0x5a,0x60,0x70,0xbd, +0x6c,0x08,0x00,0x02,0x00,0xed,0x00,0xe0,0x80,0x01,0x00,0x20,0x00,0x04,0x01,0x40, +0x50,0x01,0x00,0x20,0x00,0xad,0xde,0x00,0x19,0x4b,0xdb,0x69,0xda,0x07,0x70,0xb5, +0x1d,0xd4,0x17,0x4c,0xe3,0x69,0x9b,0x07,0x00,0xd4,0x70,0xbd,0x15,0x4d,0x16,0x49, +0x2b,0x68,0x4f,0xf4,0x00,0x10,0x1b,0x69,0x98,0x47,0x23,0x6a,0x0b,0x2b,0x19,0xd0, +0x12,0x4b,0x10,0x4a,0x1b,0x68,0x12,0x68,0x9b,0x6c,0x14,0x69,0x98,0x47,0x10,0x49, +0x23,0x46,0x01,0x44,0xbd,0xe8,0x70,0x40,0x4f,0xf4,0x01,0x10,0x18,0x47,0x0b,0x4b, +0x08,0x4a,0x1b,0x68,0x12,0x68,0x5b,0x68,0x14,0x69,0x98,0x47,0x41,0x1e,0x00,0x20, +0xa0,0x47,0xd6,0xe7,0x2b,0x68,0x06,0x49,0x1b,0x69,0x06,0x48,0x98,0x47,0xdf,0xe7, +0x50,0x01,0x00,0x20,0x6c,0x08,0x00,0x02,0xff,0x0f,0x20,0x00,0x68,0x08,0x00,0x02, +0xff,0x3f,0x20,0x00,0x00,0x20,0x20,0x00,0x14,0x4b,0x70,0xb5,0x14,0x4c,0x1b,0x68, +0x22,0x68,0x5b,0x68,0x15,0x69,0x98,0x47,0x41,0x1e,0x00,0x20,0xa8,0x47,0x23,0x68, +0x10,0x49,0x1b,0x69,0x4f,0xf4,0x00,0x10,0x98,0x47,0x0f,0x4b,0x1b,0x6a,0x0b,0x2b, +0x0e,0xd0,0x0a,0x4b,0x0a,0x4a,0x1b,0x68,0x12,0x68,0x9b,0x6c,0x14,0x69,0x98,0x47, +0x0a,0x49,0x23,0x46,0x01,0x44,0xbd,0xe8,0x70,0x40,0x4f,0xf4,0x01,0x10,0x18,0x47, +0x23,0x68,0x06,0x49,0x1b,0x69,0x06,0x48,0x98,0x47,0xea,0xe7,0x68,0x08,0x00,0x02, +0x6c,0x08,0x00,0x02,0xff,0x0f,0x20,0x00,0x50,0x01,0x00,0x20,0xff,0x3f,0x20,0x00, +0x00,0x20,0x20,0x00,0x2d,0xe9,0xf0,0x41,0xff,0xf7,0xc6,0xff,0x2d,0x49,0x4b,0x69, +0x2c,0x4a,0xdb,0x06,0xfb,0xd5,0x53,0x69,0x43,0xf0,0x01,0x03,0x53,0x61,0xd4,0x68, +0x15,0x69,0xb4,0xf5,0x00,0x1f,0x03,0xd2,0x2b,0x19,0xb3,0xf5,0x00,0x1f,0x2d,0xd8, +0x25,0x4b,0x1b,0x68,0x21,0x46,0x2a,0x46,0x9b,0x6a,0x4f,0xf0,0x20,0x20,0x98,0x47, +0x07,0x46,0x20,0x4c,0x21,0x4e,0x63,0x69,0x1f,0x4d,0x31,0x68,0x2a,0x68,0x23,0xf0, +0x11,0x03,0x63,0x61,0x4b,0x68,0xd2,0xf8,0x14,0x80,0x98,0x47,0x41,0x1e,0x00,0x20, +0xc0,0x47,0x33,0x68,0x2a,0x68,0x9b,0x6c,0x55,0x69,0x98,0x47,0x18,0x49,0x01,0x44, +0x4f,0xf4,0x00,0x10,0xa8,0x47,0x27,0xb1,0x40,0xf6,0xce,0x23,0x63,0x60,0xbd,0xe8, +0xf0,0x81,0x4d,0xf6,0xad,0x63,0x63,0x60,0xbd,0xe8,0xf0,0x81,0xdf,0xf8,0x38,0x80, +0xd8,0xf8,0x00,0x30,0xc4,0xf5,0x00,0x17,0x3a,0x46,0x9b,0x6a,0x21,0x46,0x4f,0xf0, +0x20,0x20,0x98,0x47,0xd8,0xf8,0x00,0x30,0x06,0x46,0xc4,0xf1,0x20,0x20,0xea,0x1b, +0x9b,0x6a,0x00,0xf5,0x00,0x10,0x4f,0xf4,0x00,0x11,0x98,0x47,0x30,0x40,0xc7,0xb2, +0xbf,0xe7,0x00,0xbf,0x50,0x01,0x00,0x20,0x6c,0x08,0x00,0x02,0x68,0x08,0x00,0x02, +0xff,0xff,0x1f,0x00,0x2d,0xe9,0xf0,0x4f,0x4f,0x4c,0x26,0x69,0xe7,0x68,0x83,0xb0, +0x00,0x2e,0x59,0xd0,0x4f,0xf0,0x00,0x09,0xca,0x46,0xcd,0xf8,0x00,0x90,0xb6,0xf5, +0x80,0x5f,0x93,0xbf,0xb0,0x46,0xa6,0xf5,0x80,0x56,0x4f,0xf4,0x80,0x58,0x00,0x26, +0xff,0xf7,0x4a,0xff,0x02,0xe0,0xa3,0x69,0xdb,0x06,0x02,0xd4,0x63,0x69,0xda,0x06, +0xf9,0xd5,0x65,0x69,0x15,0xf0,0x10,0x05,0x41,0xd0,0x63,0x69,0x43,0xf0,0x01,0x03, +0x63,0x61,0x4f,0xf0,0x20,0x2a,0x01,0x25,0x3c,0x4b,0x9f,0x42,0x08,0xeb,0x07,0x09, +0x3b,0x4b,0x02,0xd8,0xb9,0xf5,0x00,0x1f,0x4c,0xd8,0x1b,0x68,0x39,0x46,0x42,0x46, +0x9b,0x6a,0x50,0x46,0x98,0x47,0x4f,0x46,0x81,0x46,0x00,0x2d,0x39,0xd0,0x63,0x69, +0x23,0xf0,0x11,0x03,0x63,0x61,0xdf,0xf8,0xcc,0x80,0x31,0x4d,0xd8,0xf8,0x00,0x20, +0x2b,0x68,0x52,0x68,0xd3,0xf8,0x14,0xb0,0x90,0x47,0x41,0x1e,0x00,0x20,0xd8,0x47, +0xd8,0xf8,0x00,0x30,0x2a,0x68,0x9b,0x6c,0x55,0x69,0x98,0x47,0x27,0x49,0x01,0x44, +0x4f,0xf4,0x00,0x10,0xa8,0x47,0xb9,0xf1,0x00,0x0f,0x3e,0xd0,0x00,0x2e,0xae,0xd1, +0x21,0x4b,0x40,0xf6,0xce,0x22,0x5a,0x60,0x03,0xb0,0xbd,0xe8,0xf0,0x8f,0xa3,0x69, +0x13,0xf0,0x10,0x03,0x08,0xd0,0xa3,0x69,0xdf,0xf8,0x7c,0xa0,0x43,0xf0,0x01,0x03, +0xa3,0x61,0x01,0x23,0x00,0x93,0xb7,0xe7,0x00,0x9a,0x00,0x2a,0xcb,0xd0,0x1d,0x46, +0xb2,0xe7,0x00,0x9b,0x00,0x2b,0xc6,0xd0,0xa3,0x69,0x00,0x95,0x23,0xf0,0x11,0x03, +0xa3,0x61,0xc0,0xe7,0x1a,0x68,0x01,0x93,0xc7,0xf5,0x00,0x1b,0xd2,0xf8,0x28,0xc0, +0x39,0x46,0x5a,0x46,0x50,0x46,0xe0,0x47,0x01,0x9b,0x19,0x68,0x07,0x46,0xd1,0xf8, +0x28,0xc0,0xcb,0xeb,0x08,0x02,0x0a,0xeb,0x0b,0x00,0x4f,0xf4,0x00,0x11,0xe0,0x47, +0x38,0x40,0x4f,0x46,0x5f,0xfa,0x80,0xf9,0x9f,0xe7,0x03,0x4b,0x4d,0xf6,0xad,0x62, +0x5a,0x60,0x03,0xb0,0xbd,0xe8,0xf0,0x8f,0x50,0x01,0x00,0x20,0xff,0xff,0x1f,0x00, +0x6c,0x08,0x00,0x02,0x68,0x08,0x00,0x02,0x00,0x30,0x00,0x20,0x2d,0xe9,0xf0,0x41, +0x1b,0x4c,0x1c,0x4d,0x1c,0x4f,0x29,0x68,0x3a,0x68,0x46,0xf6,0x5a,0x18,0xc4,0xf8, +0x00,0x80,0x63,0x68,0x23,0xf4,0xe0,0x23,0x00,0x26,0x43,0xf4,0x80,0x33,0x63,0x60, +0x26,0x60,0x53,0x6d,0x30,0x46,0x98,0x47,0x3b,0x68,0x69,0x68,0x5b,0x6d,0x01,0x20, +0x98,0x47,0x68,0x7b,0xff,0xf7,0x1c,0xfd,0x07,0x46,0x28,0x7b,0xff,0xf7,0xf4,0xfb, +0xc4,0xf8,0x00,0x80,0x63,0x68,0xaa,0x68,0x0c,0x49,0x23,0xf4,0xe0,0x23,0x13,0x43, +0x63,0x60,0x26,0x60,0x0a,0x4b,0x8e,0x60,0x28,0xb1,0x27,0xb1,0x40,0xf6,0xce,0x22, +0x5a,0x60,0xbd,0xe8,0xf0,0x81,0x4d,0xf6,0xad,0x62,0x5a,0x60,0xbd,0xe8,0xf0,0x81, +0x00,0x04,0x01,0x40,0x80,0x01,0x00,0x20,0x6c,0x08,0x00,0x02,0x00,0xed,0x00,0xe0, +0x50,0x01,0x00,0x20,0x5b,0x4b,0x5c,0x4c,0x1b,0x68,0x5c,0x4e,0x1b,0x68,0x80,0xb5, +0x98,0x47,0xff,0xf7,0xb7,0xfb,0x27,0x46,0x23,0x68,0x20,0x2b,0x00,0xf2,0x99,0x80, +0x01,0xa2,0x52,0xf8,0x23,0xf0,0x00,0xbf,0x99,0x10,0x00,0x01,0x89,0x11,0x00,0x01, +0x65,0x11,0x00,0x01,0xd3,0x11,0x00,0x01,0x57,0x11,0x00,0x01,0xd3,0x11,0x00,0x01, +0xd3,0x11,0x00,0x01,0xd3,0x11,0x00,0x01,0x49,0x11,0x00,0x01,0xd3,0x11,0x00,0x01, +0xd3,0x11,0x00,0x01,0xd3,0x11,0x00,0x01,0xd3,0x11,0x00,0x01,0xd3,0x11,0x00,0x01, +0xd3,0x11,0x00,0x01,0xd3,0x11,0x00,0x01,0x3b,0x11,0x00,0x01,0xd3,0x11,0x00,0x01, +0xd3,0x11,0x00,0x01,0xd3,0x11,0x00,0x01,0xd3,0x11,0x00,0x01,0xd3,0x11,0x00,0x01, +0xd3,0x11,0x00,0x01,0xd3,0x11,0x00,0x01,0xd3,0x11,0x00,0x01,0xd3,0x11,0x00,0x01, +0xd3,0x11,0x00,0x01,0xd3,0x11,0x00,0x01,0xd3,0x11,0x00,0x01,0xd3,0x11,0x00,0x01, +0xd3,0x11,0x00,0x01,0xd3,0x11,0x00,0x01,0x2d,0x11,0x00,0x01,0x01,0x23,0x63,0x60, +0xff,0xf7,0xb8,0xfe,0x00,0x23,0x23,0x60,0xae,0xe7,0x01,0x23,0x63,0x60,0xff,0xf7, +0x5d,0xff,0x00,0x23,0x23,0x60,0xa7,0xe7,0x01,0x23,0x63,0x60,0xff,0xf7,0x82,0xfd, +0x00,0x23,0x23,0x60,0xa0,0xe7,0x01,0x23,0x63,0x60,0xff,0xf7,0x3b,0xfe,0x00,0x23, +0x23,0x60,0x99,0xe7,0x01,0x23,0x63,0x60,0xff,0xf7,0xfe,0xfd,0x05,0x25,0x33,0x68, +0xe0,0x68,0x5b,0x6a,0x98,0x47,0x01,0x3d,0x00,0x28,0x2e,0xd1,0x00,0x2d,0xf6,0xd1, +0x4d,0xf6,0xad,0x63,0x63,0x60,0x0d,0xe0,0x01,0x23,0x63,0x60,0xff,0xf7,0xac,0xfd, +0x05,0x25,0x33,0x68,0x1b,0x6a,0x98,0x47,0x01,0x3d,0x20,0xbb,0x00,0x2d,0xf8,0xd1, +0x17,0x4b,0x63,0x60,0x17,0x4d,0x32,0x68,0x2b,0x68,0xd2,0xf8,0x14,0x80,0x5b,0x68, +0x98,0x47,0x41,0x1e,0x00,0x20,0xc0,0x47,0x2b,0x68,0x32,0x68,0x9b,0x6c,0x55,0x69, +0x98,0x47,0x11,0x49,0x01,0x44,0x4f,0xf4,0x00,0x10,0xa8,0x47,0x00,0x23,0x23,0x60, +0x62,0xe7,0x40,0xf6,0xad,0x33,0x63,0x60,0x5e,0xe7,0x00,0x2d,0xd0,0xd0,0x40,0xf6, +0xce,0x23,0x7b,0x60,0xde,0xe7,0x00,0x2d,0xda,0xd0,0x40,0xf6,0xce,0x23,0x63,0x60, +0xd8,0xe7,0x00,0xbf,0x64,0x08,0x00,0x02,0x50,0x01,0x00,0x20,0x6c,0x08,0x00,0x02, +0xad,0xde,0xad,0xde,0x68,0x08,0x00,0x02,0xff,0xff,0x1f,0x00,0xfe,0xe7,0x00,0xbf, +0xfd,0x01,0x00,0x01,0x85,0x04,0x00,0x01,0xf8,0xb5,0x00,0xbf,0xf8,0xbc,0x08,0xbc, +0x9e,0x46,0x70,0x47,0xf8,0xb5,0x00,0xbf,0xd5,0x01,0x00,0x01,0xf8,0xbc,0x08,0xbc, +0x9e,0x46,0x70,0x47,0x43,0x00,0x00,0x00,0x08,0x20,0x00,0x20,0xf8,0xef,0xff,0x7f, +0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0xf4,0x22,0x00,0x20,0x5c,0x23,0x00,0x20,0xc4,0x23,0x00,0x20,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, +0x34,0x12,0x00,0x01,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,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,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0x33,0xcd,0xab, +0x34,0x12,0x6d,0xe6,0xec,0xde,0x05,0x00,0x0b,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x08,0x20,0x00,0x20, diff --git a/contrib/loaders/flash/msp432/startup_msp432e4.c b/contrib/loaders/flash/msp432/startup_msp432e4.c new file mode 100644 index 0000000..8adce83 --- /dev/null +++ b/contrib/loaders/flash/msp432/startup_msp432e4.c @@ -0,0 +1,122 @@ +/****************************************************************************** +* +* Copyright (C) 2017-2018 Texas Instruments Incorporated - http://www.ti.com/ +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the +* distribution. +* +* Neither the name of Texas Instruments Incorporated nor the names of +* its contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +******************************************************************************/ + +#include <stdint.h> + +/* Entry point for the application. */ +extern int main(); + +/* Reserve space for the system stack. */ +extern uint32_t __stack_top; + +typedef void(*pFunc)(void); + +/* Interrupt handler prototypes */ +void default_handler(void); +void reset_handler(void); + +/* + * The vector table. Note that the proper constructs must be placed on this to + * ensure that it ends up at physical address 0x0000.0000 or at the start of + * the program if located at a start address other than 0. + */ +void (* const intr_vectors[])(void) __attribute__((section(".intvecs"))) = { + (pFunc)&__stack_top, /* The initial stack pointer */ + reset_handler, /* The reset handler */ + default_handler, /* The NMI handler */ + default_handler, /* The hard fault handler */ + default_handler, /* The MPU fault handler */ + default_handler, /* The bus fault handler */ + default_handler, /* The usage fault handler */ + 0, /* Reserved */ + 0, /* Reserved */ + 0, /* Reserved */ + 0, /* Reserved */ + default_handler, /* SVCall handler */ + default_handler, /* Debug monitor handler */ + 0, /* Reserved */ + default_handler, /* The PendSV handler */ + default_handler /* The SysTick handler */ +}; + +/* + * The following are constructs created by the linker, indicating where the + * the "data" and "bss" segments reside in memory. The initializers for the + * for the "data" segment resides immediately following the "text" segment. + */ +extern uint32_t __bss_start__; +extern uint32_t __bss_end__; + +/* + * This is the code that gets called when the processor first starts execution + * following a reset event. Only the absolutely necessary set is performed, + * after which the application supplied entry() routine is called. Any fancy + * actions (such as making decisions based on the reset cause register, and + * resetting the bits in that register) are left solely in the hands of the + * application. + */ +__attribute__((section(".reset"))) __attribute__((naked)) +void reset_handler(void) +{ + /* Set stack pointer */ + __asm(" MOVW.W r0, #0x1700\n" + " MOVT.W r0, #0x2000\n" + " mov sp, r0\n"); + + /* Zero fill the bss segment. */ + __asm(" ldr r0, =__bss_start__\n" + " ldr r1, =__bss_end__\n" + " mov r2, #0\n" + " .thumb_func\n" + "zero_loop:\n" + " cmp r0, r1\n" + " it lt\n" + " strlt r2, [r0], #4\n" + " blt zero_loop"); + + /* Call the application's entry point. */ + main(); +} + +/* + * This is the code that gets called when the processor receives an unexpected + * interrupt. This simply enters an infinite loop, preserving the system state + * for examination by a debugger. + */ +void default_handler(void) +{ + /* Enter an infinite loop. */ + while (1) + ; +} diff --git a/contrib/loaders/flash/msp432/startup_msp432p4.c b/contrib/loaders/flash/msp432/startup_msp432p4.c new file mode 100644 index 0000000..ed7ea10 --- /dev/null +++ b/contrib/loaders/flash/msp432/startup_msp432p4.c @@ -0,0 +1,122 @@ +/****************************************************************************** +* +* Copyright (C) 2012-2018 Texas Instruments Incorporated - http://www.ti.com/ +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the +* distribution. +* +* Neither the name of Texas Instruments Incorporated nor the names of +* its contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +******************************************************************************/ + +#include <stdint.h> + +/* Entry point for the application. */ +extern int main(); + +/* Reserve space for the system stack. */ +extern uint32_t __stack_top; + +typedef void(*pFunc)(void); + +/* Interrupt handler prototypes */ +void default_handler(void); +void reset_handler(void); + +/* + * The vector table. Note that the proper constructs must be placed on this to + * ensure that it ends up at physical address 0x0000.0000 or at the start of + * the program if located at a start address other than 0. + */ +void (* const intr_vectors[])(void) __attribute__((section(".intvecs"))) = { + (pFunc)&__stack_top, /* The initial stack pointer */ + reset_handler, /* The reset handler */ + default_handler, /* The NMI handler */ + default_handler, /* The hard fault handler */ + default_handler, /* The MPU fault handler */ + default_handler, /* The bus fault handler */ + default_handler, /* The usage fault handler */ + 0, /* Reserved */ + 0, /* Reserved */ + 0, /* Reserved */ + 0, /* Reserved */ + default_handler, /* SVCall handler */ + default_handler, /* Debug monitor handler */ + 0, /* Reserved */ + default_handler, /* The PendSV handler */ + default_handler /* The SysTick handler */ +}; + +/* + * The following are constructs created by the linker, indicating where the + * the "data" and "bss" segments reside in memory. The initializers for the + * for the "data" segment resides immediately following the "text" segment. + */ +extern uint32_t __bss_start__; +extern uint32_t __bss_end__; + +/* + * This is the code that gets called when the processor first starts execution + * following a reset event. Only the absolutely necessary set is performed, + * after which the application supplied entry() routine is called. Any fancy + * actions (such as making decisions based on the reset cause register, and + * resetting the bits in that register) are left solely in the hands of the + * application. + */ +__attribute__((section(".reset"))) __attribute__((naked)) +void reset_handler(void) +{ + /* Set stack pointer */ + __asm(" MOVW.W r0, #0x1700\n" + " MOVT.W r0, #0x0100\n" + " mov sp, r0\n"); + + /* Zero fill the bss segment. */ + __asm(" ldr r0, =__bss_start__\n" + " ldr r1, =__bss_end__\n" + " mov r2, #0\n" + " .thumb_func\n" + "zero_loop:\n" + " cmp r0, r1\n" + " it lt\n" + " strlt r2, [r0], #4\n" + " blt zero_loop"); + + /* Call the application's entry point. */ + main(); +} + +/* + * This is the code that gets called when the processor receives an unexpected + * interrupt. This simply enters an infinite loop, preserving the system state + * for examination by a debugger. + */ +void default_handler(void) +{ + /* Enter an infinite loop. */ + while (1) + ; +} diff --git a/contrib/remote_bitbang/remote_bitbang_sysfsgpio.c b/contrib/remote_bitbang/remote_bitbang_sysfsgpio.c index 6641307..5c717ce 100644 --- a/contrib/remote_bitbang/remote_bitbang_sysfsgpio.c +++ b/contrib/remote_bitbang/remote_bitbang_sysfsgpio.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * ***************************************************************************/ /* diff --git a/doc/manual/jtag/drivers/remote_bitbang.txt b/doc/manual/jtag/drivers/remote_bitbang.txt index 5a80047..f394d73 100644 --- a/doc/manual/jtag/drivers/remote_bitbang.txt +++ b/doc/manual/jtag/drivers/remote_bitbang.txt @@ -28,7 +28,7 @@ An additional function, quit, is added to the remote_bitbang interface to indicate there will be no more requests and the connection with the remote driver should be closed. -These five functions are encoded in ascii by assigning a single character to +These five functions are encoded in ASCII by assigning a single character to each possible request. The assignments are: B - Blink on @@ -48,6 +48,6 @@ each possible request. The assignments are: t - Reset 1 0 u - Reset 1 1 -The read response is encoded in ascii as either digit 0 or 1. +The read response is encoded in ASCII as either digit 0 or 1. */ diff --git a/doc/manual/primer/autotools.txt b/doc/manual/primer/autotools.txt index 9d9aada..3471eac 100644 --- a/doc/manual/primer/autotools.txt +++ b/doc/manual/primer/autotools.txt @@ -123,7 +123,7 @@ implement new checks. The <code>make distcheck</code> command produces an archive of the project deliverables (using <code>make dist</code>) and verifies its -integrity for distribution by attemptng to use the package in the same +integrity for distribution by attempting to use the package in the same manner as a user. These checks includes the following steps: diff --git a/doc/manual/primer/commands.txt b/doc/manual/primer/commands.txt index 5f89d50..a626f56 100644 --- a/doc/manual/primer/commands.txt +++ b/doc/manual/primer/commands.txt @@ -30,7 +30,7 @@ called (with the appropriate parameters), the @c CALL_COMMAND_HANDLER macro to pass any e as parameters to the following helper function: The subsequent blocks of code are a normal C function that can do -anything, so only complex commands deserve should use comamnd helper +anything, so only complex commands deserve should use command helper functions. In this respect, this example uses one to demonstrate how -- not when -- they should be used. diff --git a/doc/manual/primer/docs.txt b/doc/manual/primer/docs.txt index 504da79..b1c0531 100644 --- a/doc/manual/primer/docs.txt +++ b/doc/manual/primer/docs.txt @@ -19,7 +19,7 @@ OpenOCD presently produces several kinds of documentation: - See @subpage primerlatex and @ref stylelatex. - The Manual: - Focuses on developing the OpenOCD software. - - Details the architecutre, driver interfaces, and processes. + - Details the architecture, driver interfaces, and processes. - Provides "full" coverage of C source code (work-in-progress). - Written using Doxygen C language conventions (i.e. in comments). - Created with 'make doxygen'. diff --git a/doc/manual/primer/tcl.txt b/doc/manual/primer/tcl.txt index 9be4a05..868a75b 100644 --- a/doc/manual/primer/tcl.txt +++ b/doc/manual/primer/tcl.txt @@ -125,7 +125,7 @@ There is some tricky things going on. =============== First, there is a "for" loop - at level 0 -{level 0 means: out side of a proc/function} +{level 0 means: outside of a procedure/function} This means it is evaluated when the file is parsed. @@ -151,9 +151,9 @@ The FOR command: 5) Goto Step 2. As show, each of these items are in {curly-braces}. This means they -are passed as they are - KEY-POINT: un evaluated to the FOR +are passed as they are - KEY-POINT: unevaluated to the FOR command. Think of it like escaping the backticks in Bash so that the -"under-lying" command can evaluate the contents. In this case, the FOR +"underlying" command can evaluate the contents. In this case, the FOR COMMAND. == END: SIDEBAR: About The FOR command == @@ -167,9 +167,9 @@ Format is like "sprintf". Because of the [brackets], it becomes what you think. But here's how: First - the line is parsed - for {braces}. In this case, there are -none. The, the parser looks for [brackets] and finds them. The, +none. Then, the parser looks for [brackets] and finds them. The parser then evaluates the contents of the [brackets], and replaces -them. It is alot this bash statement. +them. It is similar to this bash statement. EXPORT vn=`date` @@ -179,7 +179,7 @@ LINE 2 & 3 In line 1, we dynamically created a variable name. Here, we are assigning it a value. Lastly Line 3 we force the variable to be -global, not "local" the the "for command body" +global, not "local" within the "for command body" =============== The PROCS @@ -194,7 +194,7 @@ The (1) NAME of the function, a (2) LIST of parameters, and a (3) BODY Again, this is at "level 0" so it is a global function. (Yes, TCL supports local functions, you put them inside of a function} -You'll see in some cases, I nest [brackets] alot and in others I'm +You'll see in some cases, I nest [brackets] a lot and in others I'm lazy or wanted it to be more clear... it is a matter of choice. =============== @@ -224,7 +224,7 @@ All memory regions must have 2 things: RWX - the access ability. WIDTH - the accessible width. - ie: Some regions of memory are not 'word' + i.e.: Some regions of memory are not 'word' accessible. The function "address_info" - given an address should @@ -287,7 +287,7 @@ Notice this IF COMMAND - (not statement) is like this: error [format string...] } -The "IF" command expects either 2 params, or 4 params. +The "IF" command expects either 2 or 4 parameters. === Sidebar: About "commands" === @@ -317,7 +317,7 @@ You give CATCH 1 or 2 parameters. The 2nd (optional) is where to put the error message. CATCH returns 0 on success, 1 for failure. - The "![catch command]" is self explaintory. + The "![catch command]" is self explanatory. The 3rd parameter to IF must be exactly "else" or "elseif" [I lied @@ -341,7 +341,7 @@ exists. {the function: "proc_exists" does this} And - if it does - I call the function. -In "C" it is alot like using: 'sprintf()' to construct a function name +In "C" it is a lot like using: 'sprintf()' to construct a function name string, then using "dlopen()" and "dlsym()" to look it up - and get a function pointer - and calling the function pointer. @@ -380,7 +380,7 @@ Some assumptions: The "CHIP" file has defined some variables in a proper form. -ie: AT91C_BASE_US0 - for usart0, +i.e.: AT91C_BASE_US0 - for usart0, AT91C_BASE_US1 - for usart1 ... And so on ... @@ -394,7 +394,7 @@ looks like this: In this case, I'm trying to figure out what USARTs exist. Step 1 - is to determine if the NAME has been defined. -ie: Does AT91C_BASE_USx - where X is some number exist? +i.e.: Does AT91C_BASE_USx - where X is some number exist? The "info exists VARNAME" tells you if the variable exists. Then - inside the IF statement... There is another loop. This loop is the diff --git a/doc/manual/release.txt b/doc/manual/release.txt index 83f668f..44de446 100644 --- a/doc/manual/release.txt +++ b/doc/manual/release.txt @@ -36,7 +36,7 @@ several important advantages compared to using the source repository were produced as part of creating the archive. -# Because they have been formally released by the project, users don't need to try a random work-in-process revision. Releasing - involves spending some time specifically on quality improvments, + involves spending some time specifically on quality improvements, including bugfixing source code and documentation. -# They provide developers with the flexibility needed to address larger issues, which sometimes involves temporary breakage. @@ -149,7 +149,7 @@ specific git revisions: 0.3.0-rc1-dev-00015-gf37c9b8-dirty -indicates a development tree based on git revison f37c9b8 +indicates a development tree based on git revision f37c9b8 (a truncated version of a SHA1 hash) with some non-git patches applied (the <em>dirty</em> tag). This information can be useful when tracking down bugs. @@ -385,7 +385,7 @@ git tag -m "The openocd-${PACKAGE_VERSION} release." "${PACKAGE_TAG}" - Last updates for the release, including the release tag (you will need to "git push --tags"). - Updates opening the merge window - - At this point, it's OK for commiters to start pushing changes + - At this point, it's OK for committers to start pushing changes which have been held off until the next release. (Any bugfixes to this release will be against a bug-fix release branch starting from the commit you tagged as this release, not mainline.) @@ -423,7 +423,7 @@ tools/release.sh --type=micro branch Both of these variations make automatic commits and tags in your repository, so you should be sure to run it on a cloned copy before -proceding with a live release. +proceeding with a live release. @subsection releasescriptopts Release Script Options diff --git a/doc/manual/scripting.txt b/doc/manual/scripting.txt index 783541c..f8764e2 100644 --- a/doc/manual/scripting.txt +++ b/doc/manual/scripting.txt @@ -43,7 +43,7 @@ Default implementation of procedures in tcl/procedures.tcl. functions constitute the tcl api. flash_banks is such a low level tcl proc. "flash banks" is an example of a command that has human readable output. The human - readable output is expected to change inbetween versions + readable output is expected to change in between versions of OpenOCD. The output from flash_banks may not be in the preferred form for the client. The client then has two choices a) parse the output from flash_banks diff --git a/doc/manual/server.txt b/doc/manual/server.txt index 3c2fbd0..50fcac7 100644 --- a/doc/manual/server.txt +++ b/doc/manual/server.txt @@ -29,7 +29,7 @@ write new code and creates a support nightmare. In many ways, people had talked about the need for some type of high-level interface to OpenOCD, because they only had two choices: - the ability to script: via an external program the actions of OpenOCD. -- the ablity to write a complex internal commands: native 'commands' +- the ability to write a complex internal commands: native 'commands' inside of OpenOCD was complicated. Fundamentally, the basic problem with both of those would be solved @@ -68,7 +68,7 @@ interfaces well with TCL. From there, the developers wanted to create an external front-end that would be @a very usable and that that @a any language could utilize, -allowing simple front-ends to be (a) cross-platform (b) languag +allowing simple front-ends to be (a) cross-platform (b) language agnostic, and (c) easy to develop and use. Simple ASCII protocols are easy. For example, HTTP, FTP (control), and @@ -76,7 +76,7 @@ SMTP are all text-based. All of these examples are widely and well-known, and they do not require high-speed or high-volume. They also support a high degree of interoperability with multiple systems. They are not human-centric protocols; more correctly, they are rigid, -terse, simple ASCII protocols that are emensely parsable by a script. +terse, simple ASCII protocols that are easily parsable by a script. Thus, the TCL server -- a 'machine' type socket interface -- was added with the hope was it would output simple "name-value" pair type @@ -95,25 +95,25 @@ and do things with it! A lot has been said about various "widigit-foo-gui-library is so wonderful". Please refer back to the domino and spider web problem of dependencies. Sure, you may well know the WhatEver-GUI library, but -most others will not (including the next contributer to OpenOCD). +most others will not (including the next contributor to OpenOCD). How do we solve that problem? For example, Cygwin can be painful, Cygwin GUI packages want X11 to be present, crossing the barrier between MinGW and Cygwin is painful, let alone getting the GUI front end to work on MacOS, and -Linux, yuck yuck yuck. Painful. very very painful. +Linux, yuck yuck yuck. Painful, very very painful. What works easier and is less work is what is already present in every platform? The answer: A web browser. In other words, OpenOCD could serve out embedded web pages via "localhost" to your browser. Long before OpenOCD had a TCL command line, Zylin AS built their ZY1000 -devince with a built-in HTTP server. Later, they were willing to both +device with a built-in HTTP server. Later, they were willing to both contribute and integrate most of that work into the main tree. @subsection serverdocsother Other Options Considered -What if a web browser is not acceptable ie: You want to write your own +What if a web browser is not acceptable i.e.: You want to write your own front gadget in Eclipse, or KDevelop, or PerlTK, Ruby, or what ever the latest and greatest Script De Jour is. @@ -134,7 +134,7 @@ taking over OpenOCD. His concern is and was: how do you debug something written in 2 different languages? A "SWIG" front-end is unlikely to help that situation. -@subsection serverdoccombined Combined: Socket & WebServer Benifits +@subsection serverdoccombined Combined: Socket & WebServer Benefits Seriously think about this question: What script language (or compiled language) today cannot talk directly to a socket? Every thing in the @@ -146,23 +146,23 @@ and serve it out via the embedded web server, could it - or something like it talk to the built in TCL server? Yes, absolutely! We are on to something here. -@subsection serverdocplatforms Platform Permuntations +@subsection serverdocplatforms Platform Permutations Look at some permutations where OpenOCD can run; these "just work" if the Socket Approach is used. -- Linux/Cygwin/MinGw/MacOSx/FreeBSD development Host Locally +- Linux/Cygwin/MinGW/MacOSX/FreeBSD development Host Locally - OpenOCD with some dongle on that host -- Linux/Cygwin/MingW/MacOS/FreeBSD development host -- DONGLE: tcpip based ARM-Linux perhaps at91rm9200 or ep93xx.c, running openocd. +- Linux/Cygwin/MinGW/MacOS/FreeBSD development host +- DONGLE: TCP/IP based ARM-Linux perhaps at91rm9200 or ep93xx.c, running openocd. -- Windows cygwin/X desktop environment. +- Windows Cygwin/X desktop environment. - Linux development host (via remote X11) -- Dongle: "eb93xx.c" based linux board +- Dongle: "eb93xx.c" based Linux board @subsection serverdocfuture Development Scale Out @@ -214,8 +214,8 @@ love or attention. Perhaps it will after you read and understand this. One reason might be, this adds one more host side requirement to make use of the feature. In other words, one could write a Python/TK front-end, but it is only useable if you have Python/TK installed. -Maybe this can be done via Ecllipse, but not all developers use Ecplise. -Many devlopers use Emacs (possibly with GUD mode) or vim and will not +Maybe this can be done via Eclipse, but not all developers use Eclipse. +Many developers use Emacs (possibly with GUD mode) or vim and will not accept such an interface. The next developer reading this might be using Insight (GDB-TK) - and somebody else - DDD.. @@ -260,7 +260,7 @@ OS) is another example. One could create a simple: <b>Click here to display memory</b> or maybe <b>click here to display the UART REGISTER BLOCK</b>; click again and see -each register explained in exquisit detail. +each register explained in exquisite detail. For an STM32, one could create a simple HTML page, with simple substitution text that the simple web server use to substitute the @@ -269,7 +269,7 @@ memory. We end up with an HTML page that could list the contents of every peripheral register on the target platform. That also is transportable, regardless of the OpenOCD host -platform: Linux/X86, Linux/ARM, FreeBSD, Cygwin, MingW, or MacOSX. +platform: Linux/X86, Linux/ARM, FreeBSD, Cygwin, MinGW, or MacOSX. You could even port OpenOCD to an Android system and use it as a bit-banging JTAG Adapter serving web pages. diff --git a/doc/manual/style.txt b/doc/manual/style.txt index 0bfae35..e654be9 100644 --- a/doc/manual/style.txt +++ b/doc/manual/style.txt @@ -112,7 +112,7 @@ pthreads require modest and predictable stack usage. @section stylefunc Functions -- static inline functions should be prefered over macros: +- static inline functions should be preferred over macros: @code /** do NOT define macro-like functions like this... */ #define CUBE(x) ((x) * (x) * (x)) @@ -201,7 +201,7 @@ The following guidelines apply to all Doxygen comment blocks: -# @c struct_name::member_name should be used to reference structure fields in the documentation (e.g. @c flash_driver::name). -# URLS get converted to markup automatically, without any extra effort. - -# new pages can be linked into the heirarchy by using the @c \@subpage + -# new pages can be linked into the hierarchy by using the @c \@subpage command somewhere the page(s) under which they should be linked: -# use @c \@ref in other contexts to create links to pages and sections. -# Use good Doxygen mark-up: @@ -233,7 +233,7 @@ documentation as part of standalone text files: - Doxygen creates such pages for files automatically, but no content will appear on them for those that only contain manual pages. - The \@file block should provide useful meta-documentation to assist - techincal writers; typically, a list of the pages that it contains. + technical writers; typically, a list of the pages that it contains. - For example, the @ref styleguide exists in @c doc/manual/style.txt, which contains a reference back to itself. -# The \@file and \@page commands should begin on the same line as @@ -261,7 +261,7 @@ The User's Guide is there to provide two basic kinds of information. It is a guide for how and why to use each feature or mechanism of OpenOCD. It is also the reference manual for all commands and options involved in using them, including interface, flash, target, and other drivers. -At this time, it is the only user-targetted documentation; everything +At this time, it is the only documentation for end users; everything else is addressing OpenOCD developers. There are two key audiences for the User's Guide, both developer based. diff --git a/doc/manual/target/mips.txt b/doc/manual/target/mips.txt index 32c40b9..5121d12 100644 --- a/doc/manual/target/mips.txt +++ b/doc/manual/target/mips.txt @@ -46,14 +46,14 @@ This value is defined only when a processor access is pending. Processor will do the action for us : it can for example read internal state (register values), and send us back the information via EJTAG memory (dmseg), or it can take some data from dmseg and write it into the registers or RAM. -Every time when it sees address (i.e. when this address is the part of the opcode it is executing, wether it is instruction or data fetch) -that falls into dmseg, processor stalls. That acutally meand that CPU stops it's pipeline and it is waitning for dongle to take some action. +Every time when it sees address (i.e. when this address is the part of the opcode it is executing, whether it is instruction or data fetch) +that falls into dmseg, processor stalls. That actually means that CPU stops it's pipeline and it is waiting for dongle to take some action. CPU is now either waiting for dongle to take some data from dmseg (if we requested for CPU do give us internal state, for example), or it will wait for some data from dongle (if it needs following instruction because it did previous, or if the operand address of the currently executed opcode falls somewhere (anywhere) in dmseg (0xff..ff20000 - 0xff..ff2fffff)). -Bit PNnW describes character of CPU access to EJTAG memory (the memry where dongle puts/takes data) - CPU can either READ for it (PNnW == 0) or +Bit PNnW describes character of CPU access to EJTAG memory (the memory where dongle puts/takes data) - CPU can either READ for it (PNnW == 0) or WRITE to it (PNnW == 1). By reading PNnW bit OpenOCD will know if it has to send (PNnW == 0) or to take (PNnW == 1) data (from dmseg, via dongle). @@ -79,7 +79,7 @@ OpenOCD can figure out which action has to be taken by reading PrAcc bit. Once action from dongle has been done, i.e. after the data is taken/put, OpenOCD can signal to CPU to proceed with executing the instruction. This can be the next instruction (if previous was finished before pending), or the same instruction - if for example CPU was waiting on dongle -to give it an operand, because it saw in the instruction opcode that operand address is somewhere in dmseg. That prowoked the CPU to stall (it tried operand fetch to dmseg and stopped), +to give it an operand, because it saw in the instruction opcode that operand address is somewhere in dmseg. That provoked the CPU to stall (it tried operand fetch to dmseg and stopped), and PNnW bit is 0 (CPU does read from dmseg), and PrAcc is 1 (CPU is pending on dmseg access). @subsection spracc SPrAcc @@ -155,16 +155,16 @@ static const uint32_t code[] = { We have to pass this code to CPU via dongle via dmseg. -After debug exception CPU will find itself stalling at the begining of the dmseg. It waits for the first instruction from dongle. +After debug exception CPU will find itself stalling at the beginning of the dmseg. It waits for the first instruction from dongle. This is MIPS32_MTC0(15,31,0), so CPU saves C0 and continues to addr 0xFF20 0001, which falls also to dmseg, so it stalls. Dongle proceeds giving to CPU one by one instruction in this manner. However, things are not so simple. If you take a look at the program, you will see that some instructions take operands. If it has to take -operand from the address in dmseg, CPU will stall witing for the dongle to do the action of passing the operand and signal this by putting PrAcc to 0. -If this operand is somewhere in RAM, CPU will not stall (it stalls only on dmseg), but it will just take it and proceed to nex instruction. But since PC for next instruction +operand from the address in dmseg, CPU will stall waiting for the dongle to do the action of passing the operand and signal this by putting PrAcc to 0. +If this operand is somewhere in RAM, CPU will not stall (it stalls only on dmseg), but it will just take it and proceed to next instruction. But since PC for next instruction points to dmseg, it will stall, so that dongle can pass next instruction. -Some instuctions are jumps (if these are jumps in dmseg addr, CPU will jump and then stall. If this is jump to some address in RAM, CPU will jump and just proceed - +Some instructions are jumps (if these are jumps in dmseg addr, CPU will jump and then stall. If this is jump to some address in RAM, CPU will jump and just proceed - will not stall on addresses in RAM). To have information about CPU is currently (does it stalls wanting on operand or it jumped somewhere waiting for next instruction), @@ -213,10 +213,10 @@ else @endcode i.e. if CPU is stalling on addresses in dmseg that are reserved for input parameters, we can conclude that it actually tried to take (read) -parametar from there, and saw that address of param falls in dmseg, so it stopped. Obviously, now dongle have to give to it operand. +parameter from there, and saw that address of parameter falls in dmseg, so it stopped. Obviously, now dongle have to give to it operand. Similarly, mips32_pracc_exec_write() describes CPU writes into EJTAG memory (dmseg). -Obvioulsy, code is RO, and CPU can change only parameters : +Obviously, code is RO, and CPU can change only parameters : @code mips_ejtag_set_instr(ctx->ejtag_info, EJTAG_INST_DATA); @@ -331,10 +331,10 @@ uint32_t handler_code[] = { }; @endcode -In the begining and the end of the handler we have fuction prologue (save the regs that will be clobbered) and epilogue (restore regs), +In the beginning and the end of the handler we have function prologue (save the regs that will be clobbered) and epilogue (restore regs), and in the very end, after all the xfer have been done, we do jump to the MIPS32_PRACC_TEXT address, i.e. Debug Exception Vector location. We will use this fact (that we came back to MIPS32_PRACC_TEXT) to verify later if all the handler is executed (because when in RAM, -processor do not stall - it executes all instructions untill one of them do not demand access to dmseg (if one of it's opernads is there)). +processor do not stall - it executes all instructions until one of them do not demand access to dmseg (if one of it's operands is there)). This handler is put into the RAM and executed from there, and not instruction by instruction, like in previous simple write (mips_m4k_write_memory()) and read (mips_m4k_read_memory()) functions. @@ -347,12 +347,12 @@ MIPS32_LW(9,0,8) /* start addr in t1 */ and there it will stall - because it will see that one of the operands have to be fetched from dmseg (EJTAG memory, in this case FASTDATA memory segment). -This handler is loaded in the RAM, ath the reserved location "work_area". This work_area is configured in OpenOCD configuration script and should be selected +This handler is loaded in the RAM, at the reserved location "work_area". This work_area is configured in OpenOCD configuration script and should be selected in that way that it is not clobbered (overwritten) by data we want to write-in using FASTDATA. What is executed instruction by instruction which is passed by dongle (via EJATG memory) is small jump code, which jumps at the handler in RAM. CPU stalls on dmseg when receiving these jmp_code instructions, but once it jumps in RAM, CPU do not stall anymore and executes bunch of handler instructions. -Untill it comes to the first instruction which has an operand in FASTDATA area. There it stalls and waits on action from probe. +Until it comes to the first instruction which has an operand in FASTDATA area. There it stalls and waits on action from probe. It happens actually when CPU comes to this loop : @code @@ -393,15 +393,15 @@ for (i = 0; i < count; i++) } @endcode -Each time when OpenOCD fills data to CPU (via dongle, via dmseg), CPU takes it and proceeds in executing the endler. However, since handler is in a assembly loop, +Each time when OpenOCD fills data to CPU (via dongle, via dmseg), CPU takes it and proceeds in executing the handler. However, since handler is in a assembly loop, CPU comes to next instruction which also fetches data from FASTDATA area. So it stalls. Then OpenOCD fills the data again, from it's (OpenOCD's) loop. And this game continues untill all the data has been filled. -After the last data has beend given to CPU it sees that it reached the end address, so it proceeds with next instruction. However, rhis instruction do not point into dmseg, so +After the last data has been given to CPU it sees that it reached the end address, so it proceeds with next instruction. However, this instruction do not point into dmseg, so CPU executes bunch of handler instructions (all prologue) and in the end jumps to MIPS32_PRACC_TEXT address. -On it's side, OpenOCD checks in CPU has jumped back to MIPS32_PRACC_TEXT, which is the confirmation that it correclty executed all the rest of the handler in RAM, -and that is not stuck somewhere in the RAM, or stalling on some acces in dmseg - that would be an error : +On it's side, OpenOCD checks in CPU has jumped back to MIPS32_PRACC_TEXT, which is the confirmation that it correctly executed all the rest of the handler in RAM, +and that is not stuck somewhere in the RAM, or stalling on some access in dmseg - that would be an error : @code address = 0; @@ -462,7 +462,7 @@ Download flow (probe -> target block transfer) : Note: A failure may have a recoverable (and even expected) cause like slow target execution of the load loop. Other failures may be due to unexpected more troublesome causes like an exception while in debug mode or a target hang on a bad target memory access. -Shifted out SPrAcc bit inform us that there was CPU access pendingand that it can be complete. +Shifted out SPrAcc bit inform us that there was CPU access pending and that it can be complete. Basically, we should do following procedure : @@ -497,7 +497,7 @@ by checking SPrAcc that we shifted out. If some FASTDATA write fails, OpenOCD will continue with it's loop (on the host side), but CPU will rest pending (on the target side) waiting for correct FASTDATA write. -Since OpenOCD goes ahead, it will eventually finish it's loop, and proceede to check if CPU took all the data. But since CPU did not took all the data, +Since OpenOCD goes ahead, it will eventually finish it's loop, and proceed to check if CPU took all the data. But since CPU did not took all the data, it is still turns in handler's loop in RAM, stalling on Fastdata area so this check : @code @@ -513,24 +513,24 @@ if (address != MIPS32_PRACC_TEXT) fails, and that gives us enough information of the failure. -In this case, we can lower the JTAG frquency and try again, bacuse most probable reason of this failure is that we tried FASTDATA upload before CPU arrived to rise PrAcc (i.e. before it was pending on access). +In this case, we can lower the JTAG frequency and try again, because most probable reason of this failure is that we tried FASTDATA upload before CPU arrived to rise PrAcc (i.e. before it was pending on access). However, the reasons for failure might be numerous : reset, exceptions which can occur in debug mode, bus hangs, etc. If lowering the JTAG freq does not work either, we can fall back to more robust solution with patch posted below. To summarize, FASTDATA communication goes as following : --# CPU jumps to Debug Exception Vector Location 0xFF200200 in dmseg and it stalls, pending and waiting for EJTAG to give it first debug instruction and signall it by putting PrAcc to "0" +-# CPU jumps to Debug Exception Vector Location 0xFF200200 in dmseg and it stalls, pending and waiting for EJTAG to give it first debug instruction and signal it by putting PrAcc to "0" -# When PrAcc goes to "0" CPU execute one opcode sent by EJTAG via DATA reg. Then it pends on next access, waiting for PrAcc to be put to "0" again -# Following this game, OpenOCD first loads handler code in RAM, and then sends the jmp_code - instruction by instruction via DATA reg, which redirects CPU to handler previously set up in RAM --# Once in RAM CPU does not pend on any instruction, but it executes all handler instructions untill first "fetch" to Fastdata area - then it stops and pends. +-# Once in RAM CPU does not pend on any instruction, but it executes all handler instructions until first "fetch" to Fastdata area - then it stops and pends. -# So - when it comes to any instruction (opcode) in this handler in RAM which reads (or writes) to Fastdata area (0xF..F20.0000 to 0xF..F20.000F), CPU stops (i.e. stalls access). I.e. it stops on this lw opcode and waits to FASTDATA TAP command from the probe. -# CPU continues only if OpenOCD shifted in SPrAcc "0" (and if the PrAcc was "1"). It shifts-out "1" to tell us that it was OK (processor was stalled, so it can complete the access), and that it continued execution of the handler in RAM. -# If PrAcc was not "1" CPU will not continue (go to next instruction), but will shift-out "0" and keep stalling on the same instruction of my handler in RAM. --# When Fastdata loop is finished, CPU executes all following hadler instructions in RAM (prologue). --# In the end of my handler in RAM, I jumps back to begining of Debug Exception Vector Location 0xFF200200 in dmseg. +-# When Fastdata loop is finished, CPU executes all following handler instructions in RAM (prologue). +-# In the end of my handler in RAM, I jumps back to beginning of Debug Exception Vector Location 0xFF200200 in dmseg. -# When it jumps back to 0xFF200200 in dmseg processor stops and pends, waiting for OpenOCD to send it instruction via DATA reg and signal it by putting PrAcc to "0". */ diff --git a/doc/manual/target/notarm.txt b/doc/manual/target/notarm.txt index 5d5be78..6de2c36 100644 --- a/doc/manual/target/notarm.txt +++ b/doc/manual/target/notarm.txt @@ -59,7 +59,7 @@ of the total OpenOCD system. @section targetnotarmppc PowerPC -there exists open source implementations of powerpc +there exists open source implementations of PowerPC target manipulation, but there hasn't been a lot of activity in the mailing list. diff --git a/doc/openocd.texi b/doc/openocd.texi index 3944572..3932db3 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -531,6 +531,12 @@ debuggers to ARM Cortex based targets @url{http://www.keil.com/support/man/docs/ @item @b{Keil ULINK v1} @* Link: @url{http://www.keil.com/ulink1/} + +@item @b{TI XDS110 Debug Probe} +@* The XDS110 is included as the embedded debug probe on many Texas Instruments +LaunchPad evaluation boards. +@* Link: @url{http://processors.wiki.ti.com/index.php/XDS110} +@* Link: @url{http://processors.wiki.ti.com/index.php/XDS_Emulation_Software_Package#XDS110_Support_Utilities} @end itemize @section IBM PC Parallel Printer Port Based @@ -4081,6 +4087,18 @@ or set a new value @var{value}. Select AP @var{num}, defaulting to 0. @end deffn +@deffn Command {$dap_name dpreg} reg [value] +Displays the content of DP register at address @var{reg}, or set it to a new +value @var{value}. + +In case of SWD, @var{reg} is a value in packed format +@math{dpbanksel << 4 | addr} and assumes values 0, 4, 8 ... 0xfc. +In case of JTAG it only assumes values 0, 4, 8 and 0xc. + +@emph{Note:} Consider using @command{poll off} to avoid any disturbing +background activity by OpenOCD while you are operating at such low-level. +@end deffn + @deffn Command {$dap_name baseaddr} [num] Displays debug base address from MEM-AP @var{num}, defaulting to the currently selected AP. @@ -4423,7 +4441,7 @@ The value should normally correspond to a static mapping for the @item @code{-rtos} @var{rtos_type} -- enable rtos support for target, @var{rtos_type} can be one of @option{auto}, @option{eCos}, @option{ThreadX}, @option{FreeRTOS}, @option{linux}, @option{ChibiOS}, -@option{embKernel}, @option{mqx}, @option{uCOS-III} +@option{embKernel}, @option{mqx}, @option{uCOS-III}, @option{nuttx} @xref{gdbrtossupport,,RTOS Support}. @item @code{-defer-examine} -- skip target examination at initial JTAG chain @@ -5569,7 +5587,32 @@ flash erase_sector 0 0 127 # It will perform a mass erase on BlueNRG-2 @end example Triggering a mass erase is also useful when users want to disable readout protection. +@end deffn + +@deffn {Flash Driver} cc26xx +All versions of the SimpleLink CC13xx and CC26xx microcontrollers from Texas +Instruments include internal flash. The cc26xx flash driver supports both the +CC13xx and CC26xx family of devices. The driver automatically recognizes the +specific version's flash parameters and autoconfigures itself. Flash bank 0 +starts at address 0. +@example +flash bank $_FLASHNAME cc26xx 0 0 0 0 $_TARGETNAME +@end example +@end deffn + +@deffn {Flash Driver} cc3220sf +The CC3220SF version of the SimpleLink CC32xx microcontrollers from Texas +Instruments includes 1MB of internal flash. The cc3220sf flash driver only +supports the internal flash. The serial flash on SimpleLink boards is +programmed via the bootloader over a UART connection. Security features of +the CC3220SF may erase the internal flash during power on reset. Refer to +documentation at @url{www.ti.com/cc3220sf} for details on security features +and programming the serial flash. + +@example +flash bank $_FLASHNAME cc3220sf 0 0 0 0 $_TARGETNAME +@end example @end deffn @deffn {Flash Driver} efm32 @@ -5969,6 +6012,41 @@ if @{ [info exists IMEMORY] && [string equal $IMEMORY true] @} @{ @end example @end deffn +@deffn {Flash Driver} msp432 +All versions of the SimpleLink MSP432 microcontrollers from Texas +Instruments include internal flash. The msp432 flash driver automatically +recognizes the specific version's flash parameters and autoconfigures itself. +Main program flash (starting at address 0) is flash bank 0. Information flash +region on MSP432P4 versions (starting at address 0x200000) is flash bank 1. + +@example +flash bank $_FLASHNAME msp432 0 0 0 0 $_TARGETNAME +@end example + +@deffn Command {msp432 mass_erase} [main|all] +Performs a complete erase of flash. By default, @command{mass_erase} will erase +only the main program flash. + +On MSP432P4 versions, using @command{mass_erase all} will erase both the +main program and information flash regions. To also erase the BSL in information +flash, the user must first use the @command{bsl} command. +@end deffn + +@deffn Command {msp432 bsl} [unlock|lock] +On MSP432P4 versions, @command{bsl} unlocks and locks the bootstrap loader (BSL) +region in information flash so that flash commands can erase or write the BSL. +Leave the BSL locked to prevent accidentally corrupting the bootstrap loader. + +To erase and program the BSL: +@example +msp432 bsl unlock +flash erase_address 0x202000 0x2000 +flash write_image bsl.bin 0x202000 +msp432 bsl lock +@end example +@end deffn +@end deffn + @deffn {Flash Driver} niietcm4 This drivers handles the integrated NOR flash on NIIET Cortex-M4 based controllers. Flash size and sector layout are auto-configured by the driver. @@ -6122,6 +6200,68 @@ The @var{num} parameter is a value shown by @command{flash banks}. @end deffn @end deffn +@deffn {Flash Driver} psoc5lp +All members of the PSoC 5LP microcontroller family from Cypress +include internal program flash and use ARM Cortex-M3 cores. +The driver probes for a number of these chips and autoconfigures itself, +apart from the base address. + +@example +flash bank $_FLASHNAME psoc5lp 0x00000000 0 0 0 $_TARGETNAME +@end example + +@b{Note:} PSoC 5LP chips can be configured to have ECC enabled or disabled. +@quotation Attention +If flash operations are performed in ECC-disabled mode, they will also affect +the ECC flash region. Erasing a 16k flash sector in the 0x00000000 area will +then also erase the corresponding 2k data bytes in the 0x48000000 area. +Writing to the ECC data bytes in ECC-disabled mode is not implemented. +@end quotation + +Commands defined in the @var{psoc5lp} driver: + +@deffn Command {psoc5lp mass_erase} +Erases all flash data and ECC/configuration bytes, all flash protection rows, +and all row latches in all flash arrays on the device. +@end deffn +@end deffn + +@deffn {Flash Driver} psoc5lp_eeprom +All members of the PSoC 5LP microcontroller family from Cypress +include internal EEPROM and use ARM Cortex-M3 cores. +The driver probes for a number of these chips and autoconfigures itself, +apart from the base address. + +@example +flash bank $_CHIPNAME.eeprom psoc5lp_eeprom 0x40008000 0 0 0 $_TARGETNAME +@end example +@end deffn + +@deffn {Flash Driver} psoc5lp_nvl +All members of the PSoC 5LP microcontroller family from Cypress +include internal Nonvolatile Latches and use ARM Cortex-M3 cores. +The driver probes for a number of these chips and autoconfigures itself. + +@example +flash bank $_CHIPNAME.nvl psoc5lp_nvl 0 0 0 0 $_TARGETNAME +@end example + +PSoC 5LP chips have multiple NV Latches: + +@itemize +@item Device Configuration NV Latch - 4 bytes +@item Write Once (WO) NV Latch - 4 bytes +@end itemize + +@b{Note:} This driver only implements the Device Configuration NVL. + +The @var{psoc5lp} driver reads the ECC mode from Device Configuration NVL. +@quotation Attention +Switching ECC mode via write to Device Configuration NVL will require a reset +after successful write. +@end quotation +@end deffn + @deffn {Flash Driver} psoc6 Supports PSoC6 (CY8C6xxx) family of Cypress microcontrollers. PSoC6 is a dual-core device with CM0+ and CM4 cores. Both cores share @@ -7262,6 +7402,19 @@ Useful in connection with script files Close the OpenOCD server, disconnecting all clients (GDB, telnet, other). If option @option{error} is used, OpenOCD will return a non-zero exit code to the parent process. + +Like any TCL commands, also @command{shutdown} can be redefined, e.g.: +@example +# redefine shutdown +rename shutdown original_shutdown +proc shutdown @{@} @{ + puts "This is my implementation of shutdown" + # my own stuff before exit OpenOCD + original_shutdown +@} +@end example +If user types CTRL-C or kills OpenOCD, either the command @command{shutdown} +or its replacement will be automatically executed before OpenOCD exits. @end deffn @anchor{debuglevel} @@ -8086,6 +8239,30 @@ interacting with remote files or displaying console messages in the debugger. @end deffn +@deffn Command {arm semihosting_resexit} [@option{enable}|@option{disable}] +@cindex ARM semihosting +Enable resumable SEMIHOSTING_SYS_EXIT. + +When SEMIHOSTING_SYS_EXIT is called outside a debug session, +things are simple, the openocd process calls exit() and passes +the value returned by the target. + +When SEMIHOSTING_SYS_EXIT is called during a debug session, +by default execution returns to the debugger, leaving the +debugger in a HALT state, similar to the state entered when +encountering a break. + +In some use cases, it is useful to have SEMIHOSTING_SYS_EXIT +return normally, as any semihosting call, and do not break +to the debugger. +The standard allows this to happen, but the condition +to trigger it is a bit obscure ("by performing an RDI_Execute +request or equivalent"). + +To make the SEMIHOSTING_SYS_EXIT call return normally, enable +this option (default: disabled). +@end deffn + @section ARMv4 and ARMv5 Architecture @cindex ARMv4 @cindex ARMv5 @@ -8623,8 +8800,8 @@ Enable or disable trace output for all ITM stimulus ports. @deffn Command {cortex_m maskisr} (@option{auto}|@option{on}|@option{off}) Control masking (disabling) interrupts during target step/resume. -The @option{auto} option handles interrupts during stepping a way they get -served but don't disturb the program flow. The step command first allows +The @option{auto} option handles interrupts during stepping in a way that they +get served but don't disturb the program flow. The step command first allows pending interrupt handlers to execute, then disables interrupts and steps over the next instruction where the core was halted. After the step interrupts are enabled again. If the interrupt handlers don't complete within 500ms, @@ -8794,6 +8971,95 @@ Display all registers in @emph{group}. "timer" or any new group created with addreg command. @end deffn +@section RISC-V Architecture + +@uref{http://riscv.org/, RISC-V} is a free and open ISA. OpenOCD supports JTAG +debug of RV32 and RV64 cores in heterogeneous multicore systems of up to 32 +harts. (It's possible to increase this limit to 1024 by changing +RISCV_MAX_HARTS in riscv.h.) OpenOCD primarily supports 0.13 of the RISC-V +Debug Specification, but there is also support for legacy targets that +implement version 0.11. + +@subsection RISC-V Terminology + +A @emph{hart} is a hardware thread. A hart may share resources (eg. FPU) with +another hart, or may be a separate core. RISC-V treats those the same, and +OpenOCD exposes each hart as a separate core. + +@subsection RISC-V Debug Configuration Commands + +@deffn Command {riscv expose_csrs} n0[-m0][,n1[-m1]]... +Configure a list of inclusive ranges for CSRs to expose in addition to the +standard ones. This must be executed before `init`. + +By default OpenOCD attempts to expose only CSRs that are mentioned in a spec, +and then only if the corresponding extension appears to be implemented. This +command can be used if OpenOCD gets this wrong, or a target implements custom +CSRs. +@end deffn + +@deffn Command {riscv expose_csrs} n0[-m0][,n1[-m1]]... +The RISC-V Debug Specification allows targets to expose custom registers +through abstract commands. (See Section 3.5.1.1 in that document.) This command +configures a list of inclusive ranges of those registers to expose. Number 0 +indicates the first custom register, whose abstract command number is 0xc000. +This command must be executed before `init`. +@end deffn + +@deffn Command {riscv set_command_timeout_sec} [seconds] +Set the wall-clock timeout (in seconds) for individual commands. The default +should work fine for all but the slowest targets (eg. simulators). +@end deffn + +@deffn Command {riscv set_reset_timeout_sec} [seconds] +Set the maximum time to wait for a hart to come out of reset after reset is +deasserted. +@end deffn + +@deffn Command {riscv set_scratch_ram} none|[address] +Set the address of 16 bytes of scratch RAM the debugger can use, or 'none'. +This is used to access 64-bit floating point registers on 32-bit targets. +@end deffn + +@deffn Command {riscv set_prefer_sba} on|off +When on, prefer to use System Bus Access to access memory. When off, prefer to +use the Program Buffer to access memory. +@end deffn + +@subsection RISC-V Authentication Commands + +The following commands can be used to authenticate to a RISC-V system. Eg. a +trivial challenge-response protocol could be implemented as follows in a +configuration file, immediately following @command{init}: +@example +set challenge [ocd_riscv authdata_read] +riscv authdata_write [expr $challenge + 1] +@end example + +@deffn Command {riscv authdata_read} +Return the 32-bit value read from authdata. Note that to get read value back in +a TCL script, it needs to be invoked as @command{ocd_riscv authdata_read}. +@end deffn + +@deffn Command {riscv authdata_write} value +Write the 32-bit value to authdata. +@end deffn + +@subsection RISC-V DMI Commands + +The following commands allow direct access to the Debug Module Interface, which +can be used to interact with custom debug features. + +@deffn Command {riscv dmi_read} +Perform a 32-bit DMI read at address, returning the value. Note that to get +read value back in a TCL script, it needs to be invoked as @command{ocd_riscv +dmi_read}. +@end deffn + +@deffn Command {riscv dmi_write} address value +Perform a 32-bit DMI write of value at address. +@end deffn + @anchor{softwaredebugmessagesandtracing} @section Software Debug Messages and Tracing @cindex Linux-ARM DCC support @@ -9551,6 +9817,7 @@ Currently supported rtos's include: @item @option{embKernel} @item @option{mqx} @item @option{uCOS-III} +@item @option{nuttx} @end itemize @quotation Note @@ -9586,6 +9853,8 @@ Rtos::sListSuspended, Rtos::sMaxPriorities, Rtos::sCurrentTaskCount. _mqx_kernel_data, MQX_init_struct. @item uC/OS-III symbols OSRunning, OSTCBCurPtr, OSTaskDbgListPtr, OSTaskQty +@item nuttx symbols +g_readytorun, g_tasklisttable @end table For most RTOS supported the above symbols will be exported by default. However for diff --git a/src/flash/nor/Makefile.am b/src/flash/nor/Makefile.am index 7121412..9a58239 100644 --- a/src/flash/nor/Makefile.am +++ b/src/flash/nor/Makefile.am @@ -19,6 +19,8 @@ NOR_DRIVERS = \ %D%/atsamv.c \ %D%/avrf.c \ %D%/bluenrg-x.c \ + %D%/cc3220sf.c \ + %D%/cc26xx.c \ %D%/cfi.c \ %D%/dsp5680xx_flash.c \ %D%/efm32.c \ @@ -35,6 +37,7 @@ NOR_DRIVERS = \ %D%/lpc2900.c \ %D%/lpcspifi.c \ %D%/mdr.c \ + %D%/msp432.c \ %D%/mrvlqspi.c \ %D%/niietcm4.c \ %D%/non_cfi.c \ @@ -43,6 +46,7 @@ NOR_DRIVERS = \ %D%/ocl.c \ %D%/pic32mx.c \ %D%/psoc4.c \ + %D%/psoc5lp.c \ %D%/psoc6.c \ %D%/sim3x.c \ %D%/spi.c \ @@ -64,9 +68,12 @@ NOR_DRIVERS = \ NORHEADERS = \ %D%/core.h \ + %D%/cc3220sf.h \ + %D%/cc26xx.h \ %D%/cfi.h \ %D%/driver.h \ %D%/imp.h \ %D%/non_cfi.h \ %D%/ocl.h \ - %D%/spi.h + %D%/spi.h \ + %D%/msp432.h diff --git a/src/flash/nor/at91sam4.c b/src/flash/nor/at91sam4.c index 0475216..c5b31e9 100644 --- a/src/flash/nor/at91sam4.c +++ b/src/flash/nor/at91sam4.c @@ -682,6 +682,40 @@ static const struct sam4_chip_details all_sam4_details[] = { }, }, }, + /*at91sam4sa16c - TFBGA100/VFBGA100/LQFP100*/ + { + .chipid_cidr = 0x28a70ce0, + .name = "at91sam4sa16c", + .total_flash_size = 1024 * 1024, + .total_sram_size = 160 * 1024, + .n_gpnvms = 2, + .n_banks = 1, + +/* .bank[0] = { */ + { + { + .probed = 0, + .pChip = NULL, + .pBank = NULL, + .bank_number = 0, + .base_address = FLASH_BANK_BASE_S, + .controller_address = 0x400e0a00, + .flash_wait_states = 5, + .present = 1, + .size_bytes = 1024 * 1024, + .nsectors = 128, + .sector_size = 8192, + .page_size = 512, + }, +/* .bank[1] = {*/ + { + .present = 0, + .probed = 0, + .bank_number = 1, + + }, + }, + }, /*atsam4s16b - LQFP64/QFN64/WLCSP64*/ { .chipid_cidr = 0x289C0CE0, @@ -1261,50 +1295,6 @@ static const struct sam4_chip_details all_sam4_details[] = { }, }, - /*at91sam4sa16c*/ - { - .chipid_cidr = 0x28a70ce0, - .name = "at91sam4sa16c", - .total_flash_size = 1024 * 1024, - .total_sram_size = 160 * 1024, - .n_gpnvms = 3, - .n_banks = 2, - -/* .bank[0] = { */ - { - { - .probed = 0, - .pChip = NULL, - .pBank = NULL, - .bank_number = 0, - .base_address = FLASH_BANK0_BASE_SD, - .controller_address = 0x400e0a00, - .flash_wait_states = 5, - .present = 1, - .size_bytes = 512 * 1024, - .nsectors = 64, - .sector_size = 8192, - .page_size = 512, - }, - -/* .bank[1] = { */ - { - .probed = 0, - .pChip = NULL, - .pBank = NULL, - .bank_number = 1, - .base_address = FLASH_BANK1_BASE_1024K_SD, - .controller_address = 0x400e0c00, - .flash_wait_states = 5, - .present = 1, - .size_bytes = 512 * 1024, - .nsectors = 64, - .sector_size = 8192, - .page_size = 512, - }, - }, - }, - /* atsamg53n19 */ { .chipid_cidr = 0x247e0ae0, @@ -2554,6 +2544,8 @@ static int sam4_GetDetails(struct sam4_bank_private *pPrivate) pPrivate->pChip->cfg.CHIPID_CIDR); sam4_explain_chipid_cidr(pPrivate->pChip); return ERROR_FAIL; + } else { + LOG_INFO("SAM4 Found chip %s, CIDR 0x%08x", pDetails->name, pDetails->chipid_cidr); } /* DANGER: THERE ARE DRAGONS HERE */ @@ -2624,6 +2616,7 @@ static int _sam4_probe(struct flash_bank *bank, int noise) for (x = 0; x < SAM4_MAX_FLASH_BANKS; x++) { if (bank->base == pPrivate->pChip->details.bank[x].base_address) { bank->size = pPrivate->pChip->details.bank[x].size_bytes; + LOG_INFO("SAM4 Set flash bank to %08X - %08X, idx %d", bank->base, bank->base + bank->size, x); break; } } diff --git a/src/flash/nor/at91samd.c b/src/flash/nor/at91samd.c index 8553ee8..017d144 100644 --- a/src/flash/nor/at91samd.c +++ b/src/flash/nor/at91samd.c @@ -115,15 +115,16 @@ static const struct samd_part samd10_parts[] = { /* Known SAMD11 parts */ static const struct samd_part samd11_parts[] = { - { 0x0, "SAMD11D14AMU", 16, 4 }, + { 0x0, "SAMD11D14AM", 16, 4 }, { 0x1, "SAMD11D13AMU", 8, 4 }, { 0x2, "SAMD11D12AMU", 4, 4 }, - { 0x3, "SAMD11D14ASU", 16, 4 }, + { 0x3, "SAMD11D14ASS", 16, 4 }, { 0x4, "SAMD11D13ASU", 8, 4 }, { 0x5, "SAMD11D12ASU", 4, 4 }, { 0x6, "SAMD11C14A", 16, 4 }, { 0x7, "SAMD11C13A", 8, 4 }, { 0x8, "SAMD11C12A", 4, 4 }, + { 0x9, "SAMD11D14AU", 16, 4 }, }; /* Known SAMD20 parts. See Table 12-8 in 42129F–SAM–10/2013 */ diff --git a/src/flash/nor/cc26xx.c b/src/flash/nor/cc26xx.c new file mode 100644 index 0000000..e6e9e59 --- /dev/null +++ b/src/flash/nor/cc26xx.c @@ -0,0 +1,567 @@ +/*************************************************************************** + * Copyright (C) 2017 by Texas Instruments, Inc. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "imp.h" +#include "cc26xx.h" +#include <helper/binarybuffer.h> +#include <helper/time_support.h> +#include <target/algorithm.h> +#include <target/armv7m.h> +#include <target/image.h> + +#define FLASH_TIMEOUT 8000 + +struct cc26xx_bank { + const char *family_name; + uint32_t icepick_id; + uint32_t user_id; + uint32_t device_type; + uint32_t sector_length; + bool probed; + struct working_area *working_area; + struct armv7m_algorithm armv7m_info; + const uint8_t *algo_code; + uint32_t algo_size; + uint32_t algo_working_size; + uint32_t buffer_addr[2]; + uint32_t params_addr[2]; +}; + +static int cc26xx_auto_probe(struct flash_bank *bank); + +static uint32_t cc26xx_device_type(uint32_t icepick_id, uint32_t user_id) +{ + uint32_t device_type = 0; + + switch (icepick_id & ICEPICK_ID_MASK) { + case CC26X0_ICEPICK_ID: + device_type = CC26X0_TYPE; + break; + case CC26X1_ICEPICK_ID: + device_type = CC26X1_TYPE; + break; + case CC13X0_ICEPICK_ID: + device_type = CC13X0_TYPE; + break; + case CC13X2_CC26X2_ICEPICK_ID: + default: + if ((user_id & USER_ID_CC13_MASK) != 0) + device_type = CC13X2_TYPE; + else + device_type = CC26X2_TYPE; + break; + } + + return device_type; +} + +static uint32_t cc26xx_sector_length(uint32_t icepick_id) +{ + uint32_t sector_length; + + switch (icepick_id & ICEPICK_ID_MASK) { + case CC26X0_ICEPICK_ID: + case CC26X1_ICEPICK_ID: + case CC13X0_ICEPICK_ID: + /* Chameleon family device */ + sector_length = CC26X0_SECTOR_LENGTH; + break; + case CC13X2_CC26X2_ICEPICK_ID: + default: + /* Agama family device */ + sector_length = CC26X2_SECTOR_LENGTH; + break; + } + + return sector_length; +} + +static int cc26xx_wait_algo_done(struct flash_bank *bank, uint32_t params_addr) +{ + struct target *target = bank->target; + struct cc26xx_bank *cc26xx_bank = bank->driver_priv; + + uint32_t status_addr = params_addr + CC26XX_STATUS_OFFSET; + uint32_t status = CC26XX_BUFFER_FULL; + long long start_ms; + long long elapsed_ms; + + int retval = ERROR_OK; + + start_ms = timeval_ms(); + while (CC26XX_BUFFER_FULL == status) { + retval = target_read_u32(target, status_addr, &status); + if (ERROR_OK != retval) + return retval; + + elapsed_ms = timeval_ms() - start_ms; + if (elapsed_ms > 500) + keep_alive(); + if (elapsed_ms > FLASH_TIMEOUT) + break; + }; + + if (CC26XX_BUFFER_EMPTY != status) { + LOG_ERROR("%s: Flash operation failed", cc26xx_bank->family_name); + return ERROR_FAIL; + } + + return ERROR_OK; +} + +static int cc26xx_init(struct flash_bank *bank) +{ + struct target *target = bank->target; + struct cc26xx_bank *cc26xx_bank = bank->driver_priv; + + int retval; + + /* Make sure we've probed the flash to get the device and size */ + retval = cc26xx_auto_probe(bank); + if (ERROR_OK != retval) + return retval; + + /* Check for working area to use for flash helper algorithm */ + if (NULL != cc26xx_bank->working_area) + target_free_working_area(target, cc26xx_bank->working_area); + retval = target_alloc_working_area(target, cc26xx_bank->algo_working_size, + &cc26xx_bank->working_area); + if (ERROR_OK != retval) + return retval; + + /* Confirm the defined working address is the area we need to use */ + if (CC26XX_ALGO_BASE_ADDRESS != cc26xx_bank->working_area->address) + return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; + + /* Write flash helper algorithm into target memory */ + retval = target_write_buffer(target, CC26XX_ALGO_BASE_ADDRESS, + cc26xx_bank->algo_size, cc26xx_bank->algo_code); + if (ERROR_OK != retval) { + LOG_ERROR("%s: Failed to load flash helper algorithm", + cc26xx_bank->family_name); + target_free_working_area(target, cc26xx_bank->working_area); + return retval; + } + + /* Initialize the ARMv7 specific info to run the algorithm */ + cc26xx_bank->armv7m_info.common_magic = ARMV7M_COMMON_MAGIC; + cc26xx_bank->armv7m_info.core_mode = ARM_MODE_THREAD; + + /* Begin executing the flash helper algorithm */ + retval = target_start_algorithm(target, 0, NULL, 0, NULL, + CC26XX_ALGO_BASE_ADDRESS, 0, &cc26xx_bank->armv7m_info); + if (ERROR_OK != retval) { + LOG_ERROR("%s: Failed to start flash helper algorithm", + cc26xx_bank->family_name); + target_free_working_area(target, cc26xx_bank->working_area); + return retval; + } + + /* + * At this point, the algorithm is running on the target and + * ready to receive commands and data to flash the target + */ + + return retval; +} + +static int cc26xx_quit(struct flash_bank *bank) +{ + struct target *target = bank->target; + struct cc26xx_bank *cc26xx_bank = bank->driver_priv; + + int retval; + + /* Regardless of the algo's status, attempt to halt the target */ + (void)target_halt(target); + + /* Now confirm target halted and clean up from flash helper algorithm */ + retval = target_wait_algorithm(target, 0, NULL, 0, NULL, 0, FLASH_TIMEOUT, + &cc26xx_bank->armv7m_info); + + target_free_working_area(target, cc26xx_bank->working_area); + cc26xx_bank->working_area = NULL; + + return retval; +} + +static int cc26xx_mass_erase(struct flash_bank *bank) +{ + struct target *target = bank->target; + struct cc26xx_bank *cc26xx_bank = bank->driver_priv; + struct cc26xx_algo_params algo_params; + + int retval; + + if (TARGET_HALTED != target->state) { + LOG_ERROR("Target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + + retval = cc26xx_init(bank); + if (ERROR_OK != retval) + return retval; + + /* Initialize algorithm parameters */ + buf_set_u32(algo_params.address, 0, 32, 0); + buf_set_u32(algo_params.length, 0, 32, 4); + buf_set_u32(algo_params.command, 0, 32, CC26XX_CMD_ERASE_ALL); + buf_set_u32(algo_params.status, 0, 32, CC26XX_BUFFER_FULL); + + /* Issue flash helper algorithm parameters for mass erase */ + retval = target_write_buffer(target, cc26xx_bank->params_addr[0], + sizeof(algo_params), (uint8_t *)&algo_params); + + /* Wait for command to complete */ + if (ERROR_OK == retval) + retval = cc26xx_wait_algo_done(bank, cc26xx_bank->params_addr[0]); + + /* Regardless of errors, try to close down algo */ + (void)cc26xx_quit(bank); + + return retval; +} + +FLASH_BANK_COMMAND_HANDLER(cc26xx_flash_bank_command) +{ + struct cc26xx_bank *cc26xx_bank; + + if (CMD_ARGC < 6) + return ERROR_COMMAND_SYNTAX_ERROR; + + cc26xx_bank = malloc(sizeof(struct cc26xx_bank)); + if (NULL == cc26xx_bank) + return ERROR_FAIL; + + /* Initialize private flash information */ + memset((void *)cc26xx_bank, 0x00, sizeof(struct cc26xx_bank)); + cc26xx_bank->family_name = "cc26xx"; + cc26xx_bank->device_type = CC26XX_NO_TYPE; + cc26xx_bank->sector_length = 0x1000; + + /* Finish initialization of bank */ + bank->driver_priv = cc26xx_bank; + bank->next = NULL; + + return ERROR_OK; +} + +static int cc26xx_erase(struct flash_bank *bank, int first, int last) +{ + struct target *target = bank->target; + struct cc26xx_bank *cc26xx_bank = bank->driver_priv; + struct cc26xx_algo_params algo_params; + + uint32_t address; + uint32_t length; + int retval; + + if (TARGET_HALTED != target->state) { + LOG_ERROR("Target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + + /* Do a mass erase if user requested all sectors of flash */ + if ((first == 0) && (last == (bank->num_sectors - 1))) { + /* Request mass erase of flash */ + return cc26xx_mass_erase(bank); + } + + address = first * cc26xx_bank->sector_length; + length = (last - first + 1) * cc26xx_bank->sector_length; + + retval = cc26xx_init(bank); + if (ERROR_OK != retval) + return retval; + + /* Set up algorithm parameters for erase command */ + buf_set_u32(algo_params.address, 0, 32, address); + buf_set_u32(algo_params.length, 0, 32, length); + buf_set_u32(algo_params.command, 0, 32, CC26XX_CMD_ERASE_SECTORS); + buf_set_u32(algo_params.status, 0, 32, CC26XX_BUFFER_FULL); + + /* Issue flash helper algorithm parameters for erase */ + retval = target_write_buffer(target, cc26xx_bank->params_addr[0], + sizeof(algo_params), (uint8_t *)&algo_params); + + /* If no error, wait for erase to finish */ + if (ERROR_OK == retval) + retval = cc26xx_wait_algo_done(bank, cc26xx_bank->params_addr[0]); + + /* Regardless of errors, try to close down algo */ + (void)cc26xx_quit(bank); + + return retval; +} + +static int cc26xx_protect(struct flash_bank *bank, int set, int first, + int last) +{ + return ERROR_OK; +} + +static int cc26xx_write(struct flash_bank *bank, const uint8_t *buffer, + uint32_t offset, uint32_t count) +{ + struct target *target = bank->target; + struct cc26xx_bank *cc26xx_bank = bank->driver_priv; + struct cc26xx_algo_params algo_params[2]; + uint32_t size = 0; + long long start_ms; + long long elapsed_ms; + uint32_t address; + + uint32_t index; + int retval; + + if (TARGET_HALTED != target->state) { + LOG_ERROR("Target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + + retval = cc26xx_init(bank); + if (ERROR_OK != retval) + return retval; + + /* Initialize algorithm parameters to default values */ + buf_set_u32(algo_params[0].command, 0, 32, CC26XX_CMD_PROGRAM); + buf_set_u32(algo_params[1].command, 0, 32, CC26XX_CMD_PROGRAM); + + /* Write requested data, ping-ponging between two buffers */ + index = 0; + start_ms = timeval_ms(); + address = bank->base + offset; + while (count > 0) { + + if (count > cc26xx_bank->sector_length) + size = cc26xx_bank->sector_length; + else + size = count; + + /* Put next block of data to flash into buffer */ + retval = target_write_buffer(target, cc26xx_bank->buffer_addr[index], + size, buffer); + if (ERROR_OK != retval) { + LOG_ERROR("Unable to write data to target memory"); + break; + } + + /* Update algo parameters for next block */ + buf_set_u32(algo_params[index].address, 0, 32, address); + buf_set_u32(algo_params[index].length, 0, 32, size); + buf_set_u32(algo_params[index].status, 0, 32, CC26XX_BUFFER_FULL); + + /* Issue flash helper algorithm parameters for block write */ + retval = target_write_buffer(target, cc26xx_bank->params_addr[index], + sizeof(algo_params[index]), (uint8_t *)&algo_params[index]); + if (ERROR_OK != retval) + break; + + /* Wait for next ping pong buffer to be ready */ + index ^= 1; + retval = cc26xx_wait_algo_done(bank, cc26xx_bank->params_addr[index]); + if (ERROR_OK != retval) + break; + + count -= size; + buffer += size; + address += size; + + elapsed_ms = timeval_ms() - start_ms; + if (elapsed_ms > 500) + keep_alive(); + } + + /* If no error yet, wait for last buffer to finish */ + if (ERROR_OK == retval) { + index ^= 1; + retval = cc26xx_wait_algo_done(bank, cc26xx_bank->params_addr[index]); + } + + /* Regardless of errors, try to close down algo */ + (void)cc26xx_quit(bank); + + return retval; +} + +static int cc26xx_probe(struct flash_bank *bank) +{ + struct target *target = bank->target; + struct cc26xx_bank *cc26xx_bank = bank->driver_priv; + + uint32_t sector_length; + uint32_t value; + int num_sectors; + int max_sectors; + + int retval; + + retval = target_read_u32(target, FCFG1_ICEPICK_ID, &value); + if (ERROR_OK != retval) + return retval; + cc26xx_bank->icepick_id = value; + + retval = target_read_u32(target, FCFG1_USER_ID, &value); + if (ERROR_OK != retval) + return retval; + cc26xx_bank->user_id = value; + + cc26xx_bank->device_type = cc26xx_device_type(cc26xx_bank->icepick_id, + cc26xx_bank->user_id); + + sector_length = cc26xx_sector_length(cc26xx_bank->icepick_id); + + /* Set up appropriate flash helper algorithm */ + switch (cc26xx_bank->icepick_id & ICEPICK_ID_MASK) { + case CC26X0_ICEPICK_ID: + case CC26X1_ICEPICK_ID: + case CC13X0_ICEPICK_ID: + /* Chameleon family device */ + cc26xx_bank->algo_code = cc26x0_algo; + cc26xx_bank->algo_size = sizeof(cc26x0_algo); + cc26xx_bank->algo_working_size = CC26X0_WORKING_SIZE; + cc26xx_bank->buffer_addr[0] = CC26X0_ALGO_BUFFER_0; + cc26xx_bank->buffer_addr[1] = CC26X0_ALGO_BUFFER_1; + cc26xx_bank->params_addr[0] = CC26X0_ALGO_PARAMS_0; + cc26xx_bank->params_addr[1] = CC26X0_ALGO_PARAMS_1; + max_sectors = CC26X0_MAX_SECTORS; + break; + case CC13X2_CC26X2_ICEPICK_ID: + default: + /* Agama family device */ + cc26xx_bank->algo_code = cc26x2_algo; + cc26xx_bank->algo_size = sizeof(cc26x2_algo); + cc26xx_bank->algo_working_size = CC26X2_WORKING_SIZE; + cc26xx_bank->buffer_addr[0] = CC26X2_ALGO_BUFFER_0; + cc26xx_bank->buffer_addr[1] = CC26X2_ALGO_BUFFER_1; + cc26xx_bank->params_addr[0] = CC26X2_ALGO_PARAMS_0; + cc26xx_bank->params_addr[1] = CC26X2_ALGO_PARAMS_1; + max_sectors = CC26X2_MAX_SECTORS; + break; + } + + retval = target_read_u32(target, CC26XX_FLASH_SIZE_INFO, &value); + if (ERROR_OK != retval) + return retval; + num_sectors = value & 0xff; + if (num_sectors > max_sectors) + num_sectors = max_sectors; + + bank->sectors = malloc(sizeof(struct flash_sector) * num_sectors); + if (NULL == bank->sectors) + return ERROR_FAIL; + + bank->base = CC26XX_FLASH_BASE_ADDR; + bank->num_sectors = num_sectors; + bank->size = num_sectors * sector_length; + bank->write_start_alignment = 0; + bank->write_end_alignment = 0; + cc26xx_bank->sector_length = sector_length; + + for (int i = 0; i < num_sectors; i++) { + bank->sectors[i].offset = i * sector_length; + bank->sectors[i].size = sector_length; + bank->sectors[i].is_erased = -1; + bank->sectors[i].is_protected = 0; + } + + /* We've successfully determined the stats on the flash bank */ + cc26xx_bank->probed = true; + + /* If we fall through to here, then all went well */ + + return ERROR_OK; +} + +static int cc26xx_auto_probe(struct flash_bank *bank) +{ + struct cc26xx_bank *cc26xx_bank = bank->driver_priv; + + int retval = ERROR_OK; + + if (bank->bank_number != 0) { + /* Invalid bank number somehow */ + return ERROR_FAIL; + } + + if (!cc26xx_bank->probed) + retval = cc26xx_probe(bank); + + return retval; +} + +static int cc26xx_protect_check(struct flash_bank *bank) +{ + return ERROR_OK; +} + +static int cc26xx_info(struct flash_bank *bank, char *buf, int buf_size) +{ + struct cc26xx_bank *cc26xx_bank = bank->driver_priv; + int printed = 0; + const char *device; + + switch (cc26xx_bank->device_type) { + case CC26X0_TYPE: + device = "CC26x0"; + break; + case CC26X1_TYPE: + device = "CC26x1"; + break; + case CC13X0_TYPE: + device = "CC13x0"; + break; + case CC13X2_TYPE: + device = "CC13x2"; + break; + case CC26X2_TYPE: + device = "CC26x2"; + break; + case CC26XX_NO_TYPE: + default: + device = "Unrecognized"; + break; + } + + printed = snprintf(buf, buf_size, + "%s device: ICEPick ID 0x%08x, USER ID 0x%08x\n", + device, cc26xx_bank->icepick_id, cc26xx_bank->user_id); + + if (printed >= buf_size) + return ERROR_BUF_TOO_SMALL; + + return ERROR_OK; +} + +struct flash_driver cc26xx_flash = { + .name = "cc26xx", + .flash_bank_command = cc26xx_flash_bank_command, + .erase = cc26xx_erase, + .protect = cc26xx_protect, + .write = cc26xx_write, + .read = default_flash_read, + .probe = cc26xx_probe, + .auto_probe = cc26xx_auto_probe, + .erase_check = default_flash_blank_check, + .protect_check = cc26xx_protect_check, + .info = cc26xx_info, + .free_driver_priv = default_flash_free_driver_priv, +}; diff --git a/src/flash/nor/cc26xx.h b/src/flash/nor/cc26xx.h new file mode 100644 index 0000000..51a09f1 --- /dev/null +++ b/src/flash/nor/cc26xx.h @@ -0,0 +1,101 @@ +/*************************************************************************** + * Copyright (C) 2017 by Texas Instruments, Inc. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ + +#ifndef OPENOCD_FLASH_NOR_CC26XX_H +#define OPENOCD_FLASH_NOR_CC26XX_H + +/* Addresses of FCFG1 registers to access ICEPick Device ID and User ID */ +#define FCFG1_ICEPICK_ID 0x50001318 +#define FCFG1_USER_ID 0x50001294 + +/* ICEPick device ID mask and values */ +#define ICEPICK_ID_MASK 0x0fffffff +#define ICEPICK_REV_MASK 0xf0000000 +#define CC26X0_ICEPICK_ID 0x0b99a02f +#define CC26X1_ICEPICK_ID 0x0b9bd02f +#define CC13X0_ICEPICK_ID 0x0b9be02f +#define CC13X2_CC26X2_ICEPICK_ID 0x0bb4102f + +/* User ID mask for Agama CC13x2 vs CC26x2 */ +#define USER_ID_CC13_MASK 0x00800000 + +/* Common CC26xx/CC13xx flash and memory parameters */ +#define CC26XX_FLASH_BASE_ADDR 0x00000000 +#define CC26XX_FLASH_SIZE_INFO 0x4003002c +#define CC26XX_SRAM_SIZE_INFO 0x40082250 +#define CC26XX_ALGO_BASE_ADDRESS 0x20000000 + +/* Chameleon CC26x0/CC13x0 specific parameters */ +#define CC26X0_MAX_SECTORS 32 +#define CC26X0_SECTOR_LENGTH 0x1000 +#define CC26X0_ALGO_BUFFER_0 0x20001c00 +#define CC26X0_ALGO_BUFFER_1 0x20002c00 +#define CC26X0_ALGO_PARAMS_0 0x20001bd8 +#define CC26X0_ALGO_PARAMS_1 0x20001bec +#define CC26X0_WORKING_SIZE (CC26X0_ALGO_BUFFER_1 + CC26X0_SECTOR_LENGTH - \ + CC26XX_ALGO_BASE_ADDRESS) + +/* Agama CC26x2/CC13x2 specific parameters */ +#define CC26X2_MAX_SECTORS 128 +#define CC26X2_SECTOR_LENGTH 0x2000 +#define CC26X2_ALGO_BUFFER_0 0x20002000 +#define CC26X2_ALGO_BUFFER_1 0x20004000 +#define CC26X2_ALGO_PARAMS_0 0x20001fd8 +#define CC26X2_ALGO_PARAMS_1 0x20001fec +#define CC26X2_WORKING_SIZE (CC26X2_ALGO_BUFFER_1 + CC26X2_SECTOR_LENGTH - \ + CC26XX_ALGO_BASE_ADDRESS) + +/* CC26xx flash helper algorithm buffer flags */ +#define CC26XX_BUFFER_EMPTY 0x00000000 +#define CC26XX_BUFFER_FULL 0xffffffff + +/* CC26XX flash helper algorithm commands */ +#define CC26XX_CMD_NO_ACTION 0 +#define CC26XX_CMD_ERASE_ALL 1 +#define CC26XX_CMD_PROGRAM 2 +#define CC26XX_CMD_ERASE_AND_PROGRAM 3 +#define CC26XX_CMD_ERASE_AND_PROGRAM_WITH_RETAIN 4 +#define CC26XX_CMD_ERASE_SECTORS 5 + +/* CC26xx and CC13xx device types */ +#define CC26XX_NO_TYPE 0 /* Device type not determined yet */ +#define CC26X0_TYPE 1 /* CC26x0 Chameleon device */ +#define CC26X1_TYPE 2 /* CC26x1 Chameleon device */ +#define CC26X2_TYPE 3 /* CC26x2 Agama device */ +#define CC13X0_TYPE 4 /* CC13x0 Chameleon device */ +#define CC13X2_TYPE 5 /* CC13x2 Agama device */ + +/* Flash helper algorithm parameter block struct */ +#define CC26XX_STATUS_OFFSET 0x0c +struct cc26xx_algo_params { + uint8_t address[4]; + uint8_t length[4]; + uint8_t command[4]; + uint8_t status[4]; +}; + +/* Flash helper algorithm for CC26x0 Chameleon targets */ +const uint8_t cc26x0_algo[] = { +#include "../../../contrib/loaders/flash/cc26xx/cc26x0_algo.inc" +}; + +/* Flash helper algorithm for CC26x2 Agama targets */ +const uint8_t cc26x2_algo[] = { +#include "../../../contrib/loaders/flash/cc26xx/cc26x2_algo.inc" +}; + +#endif /* OPENOCD_FLASH_NOR_CC26XX_H */ diff --git a/src/flash/nor/cc3220sf.c b/src/flash/nor/cc3220sf.c new file mode 100644 index 0000000..af45743 --- /dev/null +++ b/src/flash/nor/cc3220sf.c @@ -0,0 +1,529 @@ +/*************************************************************************** + * Copyright (C) 2017 by Texas Instruments, Inc. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "imp.h" +#include "cc3220sf.h" +#include <helper/time_support.h> +#include <target/algorithm.h> +#include <target/armv7m.h> + +#define FLASH_TIMEOUT 5000 + +struct cc3220sf_bank { + bool probed; + struct armv7m_algorithm armv7m_info; +}; + +static int cc3220sf_mass_erase(struct flash_bank *bank) +{ + struct target *target = bank->target; + bool done; + long long start_ms; + long long elapsed_ms; + uint32_t value; + + int retval = ERROR_OK; + + if (TARGET_HALTED != target->state) { + LOG_ERROR("Target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + + /* Set starting address to erase to zero */ + retval = target_write_u32(target, FMA_REGISTER_ADDR, 0); + if (ERROR_OK != retval) + return retval; + + /* Write the MERASE bit of the FMC register */ + retval = target_write_u32(target, FMC_REGISTER_ADDR, FMC_MERASE_VALUE); + if (ERROR_OK != retval) + return retval; + + /* Poll the MERASE bit until the mass erase is complete */ + done = false; + start_ms = timeval_ms(); + while (!done) { + retval = target_read_u32(target, FMC_REGISTER_ADDR, &value); + if (ERROR_OK != retval) + return retval; + + if ((value & FMC_MERASE_BIT) == 0) { + /* Bit clears when mass erase is finished */ + done = true; + } else { + elapsed_ms = timeval_ms() - start_ms; + if (elapsed_ms > 500) + keep_alive(); + if (elapsed_ms > FLASH_TIMEOUT) + break; + } + } + + if (!done) { + /* Mass erase timed out waiting for confirmation */ + return ERROR_FAIL; + } + + return retval; +} + +FLASH_BANK_COMMAND_HANDLER(cc3220sf_flash_bank_command) +{ + struct cc3220sf_bank *cc3220sf_bank; + + if (CMD_ARGC < 6) + return ERROR_COMMAND_SYNTAX_ERROR; + + cc3220sf_bank = malloc(sizeof(struct cc3220sf_bank)); + if (NULL == cc3220sf_bank) + return ERROR_FAIL; + + /* Initialize private flash information */ + cc3220sf_bank->probed = false; + + /* Finish initialization of flash bank */ + bank->driver_priv = cc3220sf_bank; + bank->next = NULL; + + return ERROR_OK; +} + +static int cc3220sf_erase(struct flash_bank *bank, int first, int last) +{ + struct target *target = bank->target; + bool done; + long long start_ms; + long long elapsed_ms; + uint32_t address; + uint32_t value; + + int retval = ERROR_OK; + + if (TARGET_HALTED != target->state) { + LOG_ERROR("Target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + + /* Do a mass erase if user requested all sectors of flash */ + if ((first == 0) && (last == (bank->num_sectors - 1))) { + /* Request mass erase of flash */ + return cc3220sf_mass_erase(bank); + } + + /* Erase requested sectors one by one */ + for (int i = first; i <= last; i++) { + + /* Determine address of sector to erase */ + address = FLASH_BASE_ADDR + i * FLASH_SECTOR_SIZE; + + /* Set starting address to erase */ + retval = target_write_u32(target, FMA_REGISTER_ADDR, address); + if (ERROR_OK != retval) + return retval; + + /* Write the ERASE bit of the FMC register */ + retval = target_write_u32(target, FMC_REGISTER_ADDR, FMC_ERASE_VALUE); + if (ERROR_OK != retval) + return retval; + + /* Poll the ERASE bit until the erase is complete */ + done = false; + start_ms = timeval_ms(); + while (!done) { + retval = target_read_u32(target, FMC_REGISTER_ADDR, &value); + if (ERROR_OK != retval) + return retval; + + if ((value & FMC_ERASE_BIT) == 0) { + /* Bit clears when mass erase is finished */ + done = true; + } else { + elapsed_ms = timeval_ms() - start_ms; + if (elapsed_ms > 500) + keep_alive(); + if (elapsed_ms > FLASH_TIMEOUT) + break; + } + } + + if (!done) { + /* Sector erase timed out waiting for confirmation */ + return ERROR_FAIL; + } + } + + return retval; +} + +static int cc3220sf_protect(struct flash_bank *bank, int set, int first, + int last) +{ + return ERROR_OK; +} + +static int cc3220sf_write(struct flash_bank *bank, const uint8_t *buffer, + uint32_t offset, uint32_t count) +{ + struct target *target = bank->target; + struct cc3220sf_bank *cc3220sf_bank = bank->driver_priv; + struct working_area *algo_working_area; + struct working_area *buffer_working_area; + struct reg_param reg_params[3]; + uint32_t algo_base_address; + uint32_t algo_buffer_address; + uint32_t algo_buffer_size; + uint32_t address; + uint32_t remaining; + uint32_t words; + uint32_t result; + + int retval = ERROR_OK; + + if (TARGET_HALTED != target->state) { + LOG_ERROR("Target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + + /* Obtain working area to use for flash helper algorithm */ + retval = target_alloc_working_area(target, sizeof(cc3220sf_algo), + &algo_working_area); + if (ERROR_OK != retval) + return retval; + + /* Obtain working area to use for flash buffer */ + retval = target_alloc_working_area(target, + target_get_working_area_avail(target), &buffer_working_area); + if (ERROR_OK != retval) { + target_free_working_area(target, algo_working_area); + return retval; + } + + algo_base_address = algo_working_area->address; + algo_buffer_address = buffer_working_area->address; + algo_buffer_size = buffer_working_area->size; + + /* Make sure buffer size is a multiple of 32 word (0x80 byte) chunks */ + /* (algo runs more efficiently if it operates on 32 words at a time) */ + if (algo_buffer_size > 0x80) + algo_buffer_size &= ~0x7f; + + /* Write flash helper algorithm into target memory */ + retval = target_write_buffer(target, algo_base_address, + sizeof(cc3220sf_algo), cc3220sf_algo); + if (ERROR_OK != retval) { + target_free_working_area(target, algo_working_area); + target_free_working_area(target, buffer_working_area); + return retval; + } + + /* Initialize the ARMv7m specific info to run the algorithm */ + cc3220sf_bank->armv7m_info.common_magic = ARMV7M_COMMON_MAGIC; + cc3220sf_bank->armv7m_info.core_mode = ARM_MODE_THREAD; + + /* Initialize register params for flash helper algorithm */ + init_reg_param(®_params[0], "r0", 32, PARAM_OUT); + init_reg_param(®_params[1], "r1", 32, PARAM_OUT); + init_reg_param(®_params[2], "r2", 32, PARAM_IN_OUT); + + /* Prepare to write to flash */ + address = FLASH_BASE_ADDR + offset; + remaining = count; + + /* The flash hardware can only write complete words to flash. If + * an unaligned address is passed in, we must do a read-modify-write + * on a word with enough bytes to align the rest of the buffer. And + * if less than a whole word remains at the end, we must also do a + * read-modify-write on a final word to finish up. + */ + + /* Do one word write to align address on 32-bit boundary if needed */ + if (0 != (address & 0x3)) { + uint8_t head[4]; + + /* Get starting offset for data to write (will be 1 to 3) */ + uint32_t head_offset = address & 0x03; + + /* Get the aligned address to write this first word to */ + uint32_t head_address = address & 0xfffffffc; + + /* Retrieve what is already in flash at the head address */ + retval = target_read_buffer(target, head_address, sizeof(head), head); + + if (ERROR_OK == retval) { + /* Substitute in the new data to write */ + while ((remaining > 0) && (head_offset < 4)) { + head[head_offset] = *buffer; + head_offset++; + address++; + buffer++; + remaining--; + } + } + + if (ERROR_OK == retval) { + /* Helper parameters are passed in registers R0-R2 */ + /* Set start of data buffer, address to write to, and word count */ + buf_set_u32(reg_params[0].value, 0, 32, algo_buffer_address); + buf_set_u32(reg_params[1].value, 0, 32, head_address); + buf_set_u32(reg_params[2].value, 0, 32, 1); + + /* Write head value into buffer to flash */ + retval = target_write_buffer(target, algo_buffer_address, + sizeof(head), head); + } + + if (ERROR_OK == retval) { + /* Execute the flash helper algorithm */ + retval = target_run_algorithm(target, 0, NULL, 3, reg_params, + algo_base_address, 0, FLASH_TIMEOUT, + &cc3220sf_bank->armv7m_info); + if (ERROR_OK != retval) + LOG_ERROR("cc3220sf: Flash algorithm failed to run"); + + /* Check that the head value was written to flash */ + result = buf_get_u32(reg_params[2].value, 0, 32); + if (0 != result) { + retval = ERROR_FAIL; + LOG_ERROR("cc3220sf: Flash operation failed"); + } + } + } + + /* Check if there's data at end of buffer that isn't a full word */ + uint32_t tail_count = remaining & 0x03; + /* Adjust remaining so it is a multiple of whole words */ + remaining -= tail_count; + + while ((ERROR_OK == retval) && (remaining > 0)) { + /* Set start of data buffer and address to write to */ + buf_set_u32(reg_params[0].value, 0, 32, algo_buffer_address); + buf_set_u32(reg_params[1].value, 0, 32, address); + + /* Download data to write into memory buffer */ + if (remaining >= algo_buffer_size) { + /* Fill up buffer with data to flash */ + retval = target_write_buffer(target, algo_buffer_address, + algo_buffer_size, buffer); + if (ERROR_OK != retval) + break; + + /* Count to write is in 32-bit words */ + words = algo_buffer_size / 4; + + /* Bump variables to next data */ + address += algo_buffer_size; + buffer += algo_buffer_size; + remaining -= algo_buffer_size; + } else { + /* Fill buffer with what's left of the data */ + retval = target_write_buffer(target, algo_buffer_address, + remaining, buffer); + if (ERROR_OK != retval) + break; + + /* Calculate the final word count to write */ + words = remaining / 4; + if (0 != (remaining % 4)) + words++; + + /* Bump variables to any final data */ + address += remaining; + buffer += remaining; + remaining = 0; + } + + /* Set number of words to write */ + buf_set_u32(reg_params[2].value, 0, 32, words); + + /* Execute the flash helper algorithm */ + retval = target_run_algorithm(target, 0, NULL, 3, reg_params, + algo_base_address, 0, FLASH_TIMEOUT, + &cc3220sf_bank->armv7m_info); + if (ERROR_OK != retval) { + LOG_ERROR("cc3220sf: Flash algorithm failed to run"); + break; + } + + /* Check that all words were written to flash */ + result = buf_get_u32(reg_params[2].value, 0, 32); + if (0 != result) { + retval = ERROR_FAIL; + LOG_ERROR("cc3220sf: Flash operation failed"); + break; + } + } + + /* Do one word write for any final bytes less than a full word */ + if ((ERROR_OK == retval) && (0 != tail_count)) { + uint8_t tail[4]; + + /* Set starting byte offset for data to write */ + uint32_t tail_offset = 0; + + /* Retrieve what is already in flash at the tail address */ + retval = target_read_buffer(target, address, sizeof(tail), tail); + + if (ERROR_OK == retval) { + /* Substitute in the new data to write */ + while (tail_count > 0) { + tail[tail_offset] = *buffer; + tail_offset++; + buffer++; + tail_count--; + } + } + + if (ERROR_OK == retval) { + /* Set start of data buffer, address to write to, and word count */ + buf_set_u32(reg_params[0].value, 0, 32, algo_buffer_address); + buf_set_u32(reg_params[1].value, 0, 32, address); + buf_set_u32(reg_params[2].value, 0, 32, 1); + + /* Write tail value into buffer to flash */ + retval = target_write_buffer(target, algo_buffer_address, + sizeof(tail), tail); + } + + if (ERROR_OK == retval) { + /* Execute the flash helper algorithm */ + retval = target_run_algorithm(target, 0, NULL, 3, reg_params, + algo_base_address, 0, FLASH_TIMEOUT, + &cc3220sf_bank->armv7m_info); + if (ERROR_OK != retval) + LOG_ERROR("cc3220sf: Flash algorithm failed to run"); + + /* Check that the tail was written to flash */ + result = buf_get_u32(reg_params[2].value, 0, 32); + if (0 != result) { + retval = ERROR_FAIL; + LOG_ERROR("cc3220sf: Flash operation failed"); + } + } + } + + /* Free resources */ + destroy_reg_param(®_params[0]); + destroy_reg_param(®_params[1]); + destroy_reg_param(®_params[2]); + target_free_working_area(target, algo_working_area); + target_free_working_area(target, buffer_working_area); + + return retval; +} + +static int cc3220sf_probe(struct flash_bank *bank) +{ + struct cc3220sf_bank *cc3220sf_bank = bank->driver_priv; + + uint32_t base; + uint32_t size; + int num_sectors; + int bank_id; + + bank_id = bank->bank_number; + + if (0 == bank_id) { + base = FLASH_BASE_ADDR; + size = FLASH_NUM_SECTORS * FLASH_SECTOR_SIZE; + num_sectors = FLASH_NUM_SECTORS; + } else { + /* Invalid bank number somehow */ + return ERROR_FAIL; + } + + if (NULL != bank->sectors) { + free(bank->sectors); + bank->sectors = NULL; + } + + bank->sectors = malloc(sizeof(struct flash_sector) * num_sectors); + if (NULL == bank->sectors) + return ERROR_FAIL; + + bank->base = base; + bank->size = size; + bank->write_start_alignment = 0; + bank->write_end_alignment = 0; + bank->num_sectors = num_sectors; + + for (int i = 0; i < num_sectors; i++) { + bank->sectors[i].offset = i * FLASH_SECTOR_SIZE; + bank->sectors[i].size = FLASH_SECTOR_SIZE; + bank->sectors[i].is_erased = -1; + bank->sectors[i].is_protected = 0; + } + + /* We've successfully recorded the stats on this flash bank */ + cc3220sf_bank->probed = true; + + /* If we fall through to here, then all went well */ + + return ERROR_OK; +} + +static int cc3220sf_auto_probe(struct flash_bank *bank) +{ + struct cc3220sf_bank *cc3220sf_bank = bank->driver_priv; + + int retval = ERROR_OK; + + if (0 != bank->bank_number) { + /* Invalid bank number somehow */ + return ERROR_FAIL; + } + + if (!cc3220sf_bank->probed) + retval = cc3220sf_probe(bank); + + return retval; +} + +static int cc3220sf_protect_check(struct flash_bank *bank) +{ + return ERROR_OK; +} + +static int cc3220sf_info(struct flash_bank *bank, char *buf, int buf_size) +{ + int printed; + + printed = snprintf(buf, buf_size, "CC3220SF with 1MB internal flash\n"); + + if (printed >= buf_size) + return ERROR_BUF_TOO_SMALL; + + return ERROR_OK; +} + +struct flash_driver cc3220sf_flash = { + .name = "cc3220sf", + .flash_bank_command = cc3220sf_flash_bank_command, + .erase = cc3220sf_erase, + .protect = cc3220sf_protect, + .write = cc3220sf_write, + .read = default_flash_read, + .probe = cc3220sf_probe, + .auto_probe = cc3220sf_auto_probe, + .erase_check = default_flash_blank_check, + .protect_check = cc3220sf_protect_check, + .info = cc3220sf_info, + .free_driver_priv = default_flash_free_driver_priv, +}; diff --git a/src/flash/nor/cc3220sf.h b/src/flash/nor/cc3220sf.h new file mode 100644 index 0000000..36c17be --- /dev/null +++ b/src/flash/nor/cc3220sf.h @@ -0,0 +1,45 @@ +/*************************************************************************** + * Copyright (C) 2017 by Texas Instruments, Inc. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ + +#ifndef OPENOCD_FLASH_NOR_CC3220SF_H +#define OPENOCD_FLASH_NOR_CC3220SF_H + +/* CC3220SF device types */ +#define CC3220_NO_TYPE 0 /* Device type not determined yet */ +#define CC3220_OTHER 1 /* CC3220 variant without flash */ +#define CC3220SF 2 /* CC3220SF variant with flash */ + +/* Flash parameters */ +#define FLASH_BASE_ADDR 0x01000000 +#define FLASH_SECTOR_SIZE 2048 +#define FLASH_NUM_SECTORS 512 + +/* CC2200SF flash registers */ +#define FMA_REGISTER_ADDR 0x400FD000 +#define FMC_REGISTER_ADDR 0x400FD008 +#define FMC_DEFAULT_VALUE 0xA4420000 +#define FMC_ERASE_BIT 0x00000002 +#define FMC_MERASE_BIT 0x00000004 +#define FMC_ERASE_VALUE (FMC_DEFAULT_VALUE | FMC_ERASE_BIT) +#define FMC_MERASE_VALUE (FMC_DEFAULT_VALUE | FMC_MERASE_BIT) + +/* Flash helper algorithm for CC3220SF */ +const uint8_t cc3220sf_algo[] = { +#include "../../../contrib/loaders/flash/cc3220sf/cc3220sf.inc" +}; + +#endif /* OPENOCD_FLASH_NOR_CC3220SF_H */ diff --git a/src/flash/nor/core.c b/src/flash/nor/core.c index f05c68b..4941281 100644 --- a/src/flash/nor/core.c +++ b/src/flash/nor/core.c @@ -188,9 +188,17 @@ void flash_free_all_banks(void) else LOG_WARNING("Flash driver of %s does not support free_driver_priv()", bank->name); + /* For 'virtual' flash driver bank->sectors and bank->prot_blocks pointers are copied from + * master flash_bank structure. They point to memory locations allocated by master flash driver + * so master driver is responsible for releasing them. + * Avoid UB caused by double-free memory corruption if flash bank is 'virtual'. */ + + if (strcmp(bank->driver->name, "virtual") != 0) { + free(bank->sectors); + free(bank->prot_blocks); + } + free(bank->name); - free(bank->sectors); - free(bank->prot_blocks); free(bank); bank = next; } diff --git a/src/flash/nor/drivers.c b/src/flash/nor/drivers.c index 3d6dab2..2b3146d 100644 --- a/src/flash/nor/drivers.c +++ b/src/flash/nor/drivers.c @@ -32,6 +32,8 @@ extern struct flash_driver ath79_flash; extern struct flash_driver atsamv_flash; extern struct flash_driver avr_flash; extern struct flash_driver bluenrgx_flash; +extern struct flash_driver cc3220sf_flash; +extern struct flash_driver cc26xx_flash; extern struct flash_driver cfi_flash; extern struct flash_driver dsp5680xx_flash; extern struct flash_driver efm32_flash; @@ -49,6 +51,7 @@ extern struct flash_driver lpc2900_flash; extern struct flash_driver lpcspifi_flash; extern struct flash_driver mdr_flash; extern struct flash_driver mrvlqspi_flash; +extern struct flash_driver msp432_flash; extern struct flash_driver niietcm4_flash; extern struct flash_driver nrf5_flash; extern struct flash_driver nrf51_flash; @@ -56,6 +59,9 @@ extern struct flash_driver numicro_flash; extern struct flash_driver ocl_flash; extern struct flash_driver pic32mx_flash; extern struct flash_driver psoc4_flash; +extern struct flash_driver psoc5lp_flash; +extern struct flash_driver psoc5lp_eeprom_flash; +extern struct flash_driver psoc5lp_nvl_flash; extern struct flash_driver psoc6_flash; extern struct flash_driver sim3x_flash; extern struct flash_driver stellaris_flash; @@ -91,6 +97,8 @@ static struct flash_driver *flash_drivers[] = { &atsamv_flash, &avr_flash, &bluenrgx_flash, + &cc3220sf_flash, + &cc26xx_flash, &cfi_flash, &dsp5680xx_flash, &efm32_flash, @@ -108,6 +116,7 @@ static struct flash_driver *flash_drivers[] = { &lpcspifi_flash, &mdr_flash, &mrvlqspi_flash, + &msp432_flash, &niietcm4_flash, &nrf5_flash, &nrf51_flash, @@ -115,6 +124,9 @@ static struct flash_driver *flash_drivers[] = { &ocl_flash, &pic32mx_flash, &psoc4_flash, + &psoc5lp_flash, + &psoc5lp_eeprom_flash, + &psoc5lp_nvl_flash, &psoc6_flash, &sim3x_flash, &stellaris_flash, diff --git a/src/flash/nor/fespi.c b/src/flash/nor/fespi.c index 6df0d38..6667d36 100644 --- a/src/flash/nor/fespi.c +++ b/src/flash/nor/fespi.c @@ -1179,5 +1179,6 @@ struct flash_driver fespi_flash = { .auto_probe = fespi_auto_probe, .erase_check = default_flash_blank_check, .protect_check = fespi_protect_check, - .info = get_fespi_info + .info = get_fespi_info, + .free_driver_priv = default_flash_free_driver_priv }; diff --git a/src/flash/nor/kinetis.c b/src/flash/nor/kinetis.c index 4d665d3..86fad72 100644 --- a/src/flash/nor/kinetis.c +++ b/src/flash/nor/kinetis.c @@ -937,7 +937,7 @@ static int kinetis_create_missing_banks(struct kinetis_chip *k_chip) unsigned num_blocks; struct kinetis_flash_bank *k_bank; struct flash_bank *bank; - char base_name[80], name[80], num[4]; + char base_name[69], name[80], num[4]; char *class, *p; num_blocks = k_chip->num_pflash_blocks + k_chip->num_nvm_blocks; @@ -948,7 +948,8 @@ static int kinetis_create_missing_banks(struct kinetis_chip *k_chip) bank = k_chip->banks[0].bank; if (bank && bank->name) { - strncpy(base_name, bank->name, sizeof(base_name)); + strncpy(base_name, bank->name, sizeof(base_name) - 1); + base_name[sizeof(base_name) - 1] = '\0'; p = strstr(base_name, ".pflash"); if (p) { *p = '\0'; @@ -960,7 +961,8 @@ static int kinetis_create_missing_banks(struct kinetis_chip *k_chip) } } } else { - strncpy(base_name, target_name(k_chip->target), sizeof(base_name)); + strncpy(base_name, target_name(k_chip->target), sizeof(base_name) - 1); + base_name[sizeof(base_name) - 1] = '\0'; p = strstr(base_name, ".cpu"); if (p) *p = '\0'; @@ -2012,7 +2014,7 @@ static int kinetis_probe_chip(struct kinetis_chip *k_chip) unsigned cpu_mhz = 120; unsigned idx; bool use_nvm_marking = false; - char flash_marking[11], nvm_marking[2]; + char flash_marking[12], nvm_marking[2]; char name[40]; k_chip->probed = false; diff --git a/src/flash/nor/msp432.c b/src/flash/nor/msp432.c new file mode 100644 index 0000000..5caa052 --- /dev/null +++ b/src/flash/nor/msp432.c @@ -0,0 +1,1103 @@ +/*************************************************************************** + * Copyright (C) 2018 by Texas Instruments, Inc. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "imp.h" +#include "msp432.h" +#include <helper/binarybuffer.h> +#include <helper/time_support.h> +#include <target/algorithm.h> +#include <target/armv7m.h> +#include <target/image.h> + +/* MSP432P4 hardware registers */ +#define P4_FLASH_MAIN_SIZE_REG 0xE0043020 +#define P4_FLASH_INFO_SIZE_REG 0xE0043024 +#define P4_DEVICE_ID_REG 0x0020100C +#define P4_HARDWARE_REV_REG 0x00201010 + +/* MSP432E4 hardware registers */ +#define E4_DID0_REG 0x400FE000 +#define E4_DID1_REG 0x400FE004 + +#define FLASH_TIMEOUT 8000 + +#define SUPPORT_MESSAGE \ + "Your pre-production MSP432P401x silicon is not fully supported\n" \ + "You can find more information at www.ti.com/product/MSP432P401R" + +struct msp432_bank { + uint32_t device_id; + uint32_t hardware_rev; + int family_type; + int device_type; + uint32_t sector_length; + bool probed[2]; + bool unlock_bsl; + struct working_area *working_area; + struct armv7m_algorithm armv7m_info; +}; + +static int msp432_auto_probe(struct flash_bank *bank); + +static int msp432_device_type(uint32_t family_type, uint32_t device_id, + uint32_t hardware_rev) +{ + int device_type = MSP432_NO_TYPE; + + if (MSP432E4 == family_type) { + /* MSP432E4 device family */ + + if (device_id == 0x180C0002) { + if (hardware_rev == 0x102DC06E) { + /* The 01Y variant */ + device_type = MSP432E401Y; + } else if (hardware_rev == 0x1032E076) { + /* The 11Y variant */ + device_type = MSP432E411Y; + } else { + /* Reasonable guess that this is a new variant */ + device_type = MSP432E4X_GUESS; + } + } else { + /* Wild guess that this is an MSP432E4 */ + device_type = MSP432E4X_GUESS; + } + } else { + /* MSP432P4 device family */ + + /* Examine the device ID and hardware revision to get the device type */ + switch (device_id) { + case 0xA000: + case 0xA001: + case 0xA002: + case 0xA003: + case 0xA004: + case 0xA005: + /* Device is definitely MSP432P401x, check hardware revision */ + if (hardware_rev == 0x41 || hardware_rev == 0x42) { + /* Rev A or B of the silicon has been deprecated */ + device_type = MSP432P401X_DEPR; + } else if (hardware_rev >= 0x43 && hardware_rev <= 0x49) { + /* Current and future revisions of the MSP432P401x device */ + device_type = MSP432P401X; + } else { + /* Unknown or unanticipated hardware revision */ + device_type = MSP432P401X_GUESS; + } + break; + case 0xA010: + case 0xA012: + case 0xA016: + case 0xA019: + case 0xA01F: + case 0xA020: + case 0xA022: + case 0xA026: + case 0xA029: + case 0xA02F: + /* Device is definitely MSP432P411x, check hardware revision */ + if (hardware_rev >= 0x41 && hardware_rev <= 0x49) { + /* Current and future revisions of the MSP432P411x device */ + device_type = MSP432P411X; + } else { + /* Unknown or unanticipated hardware revision */ + device_type = MSP432P411X_GUESS; + } + break; + case 0xFFFF: + /* Device is very early silicon that has been deprecated */ + device_type = MSP432P401X_DEPR; + break; + default: + if (device_id < 0xA010) { + /* Wild guess that this is an MSP432P401x */ + device_type = MSP432P401X_GUESS; + } else { + /* Reasonable guess that this is a new variant */ + device_type = MSP432P411X_GUESS; + } + break; + } + } + + return device_type; +} + +static const char *msp432_return_text(uint32_t return_code) +{ + switch (return_code) { + case FLASH_BUSY: + return "FLASH_BUSY"; + case FLASH_SUCCESS: + return "FLASH_SUCCESS"; + case FLASH_ERROR: + return "FLASH_ERROR"; + case FLASH_TIMEOUT_ERROR: + return "FLASH_TIMEOUT_ERROR"; + case FLASH_VERIFY_ERROR: + return "FLASH_VERIFY_WRONG"; + case FLASH_WRONG_COMMAND: + return "FLASH_WRONG_COMMAND"; + case FLASH_POWER_ERROR: + return "FLASH_POWER_ERROR"; + default: + return "UNDEFINED_RETURN_CODE"; + } +} + +static void msp432_init_params(struct msp432_algo_params *algo_params) +{ + buf_set_u32(algo_params->flash_command, 0, 32, FLASH_NO_COMMAND); + buf_set_u32(algo_params->return_code, 0, 32, 0); + buf_set_u32(algo_params->_reserved0, 0, 32, 0); + buf_set_u32(algo_params->address, 0, 32, 0); + buf_set_u32(algo_params->length, 0, 32, 0); + buf_set_u32(algo_params->buffer1_status, 0, 32, BUFFER_INACTIVE); + buf_set_u32(algo_params->buffer2_status, 0, 32, BUFFER_INACTIVE); + buf_set_u32(algo_params->erase_param, 0, 32, FLASH_ERASE_MAIN); + buf_set_u32(algo_params->unlock_bsl, 0, 32, FLASH_LOCK_BSL); +} + +static int msp432_exec_cmd(struct target *target, struct msp432_algo_params + *algo_params, uint32_t command) +{ + int retval; + + /* Make sure the given params do not include the command */ + buf_set_u32(algo_params->flash_command, 0, 32, FLASH_NO_COMMAND); + buf_set_u32(algo_params->return_code, 0, 32, 0); + buf_set_u32(algo_params->buffer1_status, 0, 32, BUFFER_INACTIVE); + buf_set_u32(algo_params->buffer2_status, 0, 32, BUFFER_INACTIVE); + + /* Write out parameters to target memory */ + retval = target_write_buffer(target, ALGO_PARAMS_BASE_ADDR, + sizeof(struct msp432_algo_params), (uint8_t *)algo_params); + if (ERROR_OK != retval) + return retval; + + /* Write out command to target memory */ + retval = target_write_buffer(target, ALGO_FLASH_COMMAND_ADDR, + sizeof(command), (uint8_t *)&command); + + return retval; +} + +static int msp432_wait_return_code(struct target *target) +{ + uint32_t return_code = 0; + long long start_ms; + long long elapsed_ms; + + int retval = ERROR_OK; + + start_ms = timeval_ms(); + while ((0 == return_code) || (FLASH_BUSY == return_code)) { + retval = target_read_buffer(target, ALGO_RETURN_CODE_ADDR, + sizeof(return_code), (uint8_t *)&return_code); + if (ERROR_OK != retval) + return retval; + + elapsed_ms = timeval_ms() - start_ms; + if (elapsed_ms > 500) + keep_alive(); + if (elapsed_ms > FLASH_TIMEOUT) + break; + }; + + if (FLASH_SUCCESS != return_code) { + LOG_ERROR("msp432: Flash operation failed: %s", + msp432_return_text(return_code)); + return ERROR_FAIL; + } + + return ERROR_OK; +} + +static int msp432_wait_inactive(struct target *target, uint32_t buffer) +{ + uint32_t status_code = BUFFER_ACTIVE; + uint32_t status_addr; + long long start_ms; + long long elapsed_ms; + + int retval; + + switch (buffer) { + case 1: /* Buffer 1 */ + status_addr = ALGO_BUFFER1_STATUS_ADDR; + break; + case 2: /* Buffer 2 */ + status_addr = ALGO_BUFFER2_STATUS_ADDR; + break; + default: + return ERROR_FAIL; + } + + start_ms = timeval_ms(); + while (BUFFER_INACTIVE != status_code) { + retval = target_read_buffer(target, status_addr, sizeof(status_code), + (uint8_t *)&status_code); + if (ERROR_OK != retval) + return retval; + + elapsed_ms = timeval_ms() - start_ms; + if (elapsed_ms > 500) + keep_alive(); + if (elapsed_ms > FLASH_TIMEOUT) + break; + }; + + if (BUFFER_INACTIVE != status_code) { + LOG_ERROR( + "msp432: Flash operation failed: buffer not written to flash"); + return ERROR_FAIL; + } + + return ERROR_OK; +} + +static int msp432_init(struct flash_bank *bank) +{ + struct target *target = bank->target; + struct msp432_bank *msp432_bank = bank->driver_priv; + struct msp432_algo_params algo_params; + struct reg_param reg_params[1]; + + const uint8_t *loader_code; + uint32_t loader_size; + uint32_t algo_entry_addr; + int retval; + + /* Make sure we've probed the flash to get the device and size */ + retval = msp432_auto_probe(bank); + if (ERROR_OK != retval) + return retval; + + /* Choose appropriate flash helper algorithm */ + switch (msp432_bank->device_type) { + case MSP432P401X: + case MSP432P401X_DEPR: + case MSP432P401X_GUESS: + default: + loader_code = msp432p401x_algo; + loader_size = sizeof(msp432p401x_algo); + algo_entry_addr = P4_ALGO_ENTRY_ADDR; + break; + case MSP432P411X: + case MSP432P411X_GUESS: + loader_code = msp432p411x_algo; + loader_size = sizeof(msp432p411x_algo); + algo_entry_addr = P4_ALGO_ENTRY_ADDR; + break; + case MSP432E401Y: + case MSP432E411Y: + case MSP432E4X_GUESS: + loader_code = msp432e4x_algo; + loader_size = sizeof(msp432e4x_algo); + algo_entry_addr = E4_ALGO_ENTRY_ADDR; + break; + } + + /* Issue warnings if this is a device we may not be able to flash */ + if (MSP432P401X_GUESS == msp432_bank->device_type || + MSP432P411X_GUESS == msp432_bank->device_type) { + /* Explicit device type check failed. Report this. */ + LOG_WARNING( + "msp432: Unrecognized MSP432P4 Device ID and Hardware " + "Rev (%04X, %02X)", msp432_bank->device_id, + msp432_bank->hardware_rev); + } else if (MSP432P401X_DEPR == msp432_bank->device_type) { + LOG_WARNING( + "msp432: MSP432P401x pre-production device (deprecated " + "silicon)\n" SUPPORT_MESSAGE); + } else if (MSP432E4X_GUESS == msp432_bank->device_type) { + /* Explicit device type check failed. Report this. */ + LOG_WARNING( + "msp432: Unrecognized MSP432E4 DID0 and DID1 values " + "(%08X, %08X)", msp432_bank->device_id, + msp432_bank->hardware_rev); + } + + /* Check for working area to use for flash helper algorithm */ + if (NULL != msp432_bank->working_area) + target_free_working_area(target, msp432_bank->working_area); + retval = target_alloc_working_area(target, ALGO_WORKING_SIZE, + &msp432_bank->working_area); + if (ERROR_OK != retval) + return retval; + + /* Confirm the defined working address is the area we need to use */ + if (ALGO_BASE_ADDR != msp432_bank->working_area->address) + return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; + + /* Write flash helper algorithm into target memory */ + retval = target_write_buffer(target, ALGO_BASE_ADDR, loader_size, + loader_code); + if (ERROR_OK != retval) + return retval; + + /* Initialize the ARMv7 specific info to run the algorithm */ + msp432_bank->armv7m_info.common_magic = ARMV7M_COMMON_MAGIC; + msp432_bank->armv7m_info.core_mode = ARM_MODE_THREAD; + + /* Initialize algorithm parameters to default values */ + msp432_init_params(&algo_params); + + /* Write out parameters to target memory */ + retval = target_write_buffer(target, ALGO_PARAMS_BASE_ADDR, + sizeof(algo_params), (uint8_t *)&algo_params); + if (ERROR_OK != retval) + return retval; + + /* Initialize stack pointer for flash helper algorithm */ + init_reg_param(®_params[0], "sp", 32, PARAM_OUT); + buf_set_u32(reg_params[0].value, 0, 32, ALGO_STACK_POINTER_ADDR); + + /* Begin executing the flash helper algorithm */ + retval = target_start_algorithm(target, 0, 0, 1, reg_params, + algo_entry_addr, 0, &msp432_bank->armv7m_info); + destroy_reg_param(®_params[0]); + if (ERROR_OK != retval) { + LOG_ERROR("msp432: Failed to start flash helper algorithm"); + return retval; + } + + /* + * At this point, the algorithm is running on the target and + * ready to receive commands and data to flash the target + */ + + /* Issue the init command to the flash helper algorithm */ + retval = msp432_exec_cmd(target, &algo_params, FLASH_INIT); + if (ERROR_OK != retval) + return retval; + + retval = msp432_wait_return_code(target); + + return retval; +} + +static int msp432_quit(struct flash_bank *bank) +{ + struct target *target = bank->target; + struct msp432_bank *msp432_bank = bank->driver_priv; + struct msp432_algo_params algo_params; + + int retval; + + /* Initialize algorithm parameters to default values */ + msp432_init_params(&algo_params); + + /* Issue the exit command to the flash helper algorithm */ + retval = msp432_exec_cmd(target, &algo_params, FLASH_EXIT); + if (ERROR_OK != retval) + return retval; + + (void)msp432_wait_return_code(target); + + /* Regardless of the return code, attempt to halt the target */ + (void)target_halt(target); + + /* Now confirm target halted and clean up from flash helper algorithm */ + retval = target_wait_algorithm(target, 0, NULL, 0, NULL, 0, FLASH_TIMEOUT, + &msp432_bank->armv7m_info); + + target_free_working_area(target, msp432_bank->working_area); + msp432_bank->working_area = NULL; + + return retval; +} + +static int msp432_mass_erase(struct flash_bank *bank, bool all) +{ + struct target *target = bank->target; + struct msp432_bank *msp432_bank = bank->driver_priv; + struct msp432_algo_params algo_params; + + int retval; + + if (TARGET_HALTED != target->state) { + LOG_ERROR("Target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + + retval = msp432_init(bank); + if (ERROR_OK != retval) + return retval; + + /* Initialize algorithm parameters to default values */ + msp432_init_params(&algo_params); + if (all) { + buf_set_u32(algo_params.erase_param, 0, 32, + FLASH_ERASE_MAIN | FLASH_ERASE_INFO); + if (msp432_bank->unlock_bsl) + buf_set_u32(algo_params.unlock_bsl, 0, 32, FLASH_UNLOCK_BSL); + } + + /* Issue the mass erase command to the flash helper algorithm */ + retval = msp432_exec_cmd(target, &algo_params, FLASH_MASS_ERASE); + if (ERROR_OK != retval) { + (void)msp432_quit(bank); + return retval; + } + + retval = msp432_wait_return_code(target); + if (ERROR_OK != retval) { + (void)msp432_quit(bank); + return retval; + } + + retval = msp432_quit(bank); + if (ERROR_OK != retval) + return retval; + + return retval; +} + +COMMAND_HANDLER(msp432_mass_erase_command) +{ + struct flash_bank *bank; + struct msp432_bank *msp432_bank; + bool all; + int retval; + + if (0 == CMD_ARGC) { + all = false; + } else if (1 == CMD_ARGC) { + /* Check argument for how much to erase */ + if (0 == strcmp(CMD_ARGV[0], "main")) + all = false; + else if (0 == strcmp(CMD_ARGV[0], "all")) + all = true; + else + return ERROR_COMMAND_SYNTAX_ERROR; + } else { + return ERROR_COMMAND_SYNTAX_ERROR; + } + + retval = get_flash_bank_by_num(0, &bank); + if (ERROR_OK != retval) + return retval; + + msp432_bank = bank->driver_priv; + + if (MSP432E4 == msp432_bank->family_type) { + /* MSP432E4 does not have main vs info regions, ignore "all" */ + all = false; + } + + retval = msp432_mass_erase(bank, all); + if (ERROR_OK != retval) + return retval; + + if (MSP432E4 == msp432_bank->family_type) { + /* MSP432E4 does not have main vs info regions */ + LOG_INFO("msp432: Mass erase of flash is complete"); + } else { + LOG_INFO("msp432: Mass erase of %s is complete", + all ? "main + info flash" : "main flash"); + } + + return ERROR_OK; +} + +COMMAND_HANDLER(msp432_bsl_command) +{ + struct flash_bank *bank; + struct msp432_bank *msp432_bank; + int retval; + + if (1 < CMD_ARGC) + return ERROR_COMMAND_SYNTAX_ERROR; + + retval = get_flash_bank_by_num(0, &bank); + if (ERROR_OK != retval) + return retval; + + msp432_bank = bank->driver_priv; + + if (MSP432E4 == msp432_bank->family_type) { + LOG_WARNING("msp432: MSP432E4 does not have a BSL region"); + return ERROR_OK; + } + + if (1 == CMD_ARGC) { + if (0 == strcmp(CMD_ARGV[0], "lock")) + msp432_bank->unlock_bsl = false; + else if (0 == strcmp(CMD_ARGV[0], "unlock")) + msp432_bank->unlock_bsl = true; + else + return ERROR_COMMAND_SYNTAX_ERROR; + } + + LOG_INFO("msp432: BSL flash region is currently %slocked", + msp432_bank->unlock_bsl ? "un" : ""); + + return ERROR_OK; +} + +FLASH_BANK_COMMAND_HANDLER(msp432_flash_bank_command) +{ + struct msp432_bank *msp432_bank; + + if (CMD_ARGC < 6) + return ERROR_COMMAND_SYNTAX_ERROR; + + msp432_bank = malloc(sizeof(struct msp432_bank)); + if (NULL == msp432_bank) + return ERROR_FAIL; + + /* Initialize private flash information */ + msp432_bank->device_id = 0; + msp432_bank->hardware_rev = 0; + msp432_bank->family_type = MSP432_NO_FAMILY; + msp432_bank->device_type = MSP432_NO_TYPE; + msp432_bank->sector_length = 0x1000; + msp432_bank->probed[0] = false; + msp432_bank->probed[1] = false; + msp432_bank->unlock_bsl = false; + msp432_bank->working_area = NULL; + + /* Finish initialization of bank 0 (main flash) */ + bank->driver_priv = msp432_bank; + bank->next = NULL; + + return ERROR_OK; +} + +static int msp432_erase(struct flash_bank *bank, int first, int last) +{ + struct target *target = bank->target; + struct msp432_bank *msp432_bank = bank->driver_priv; + struct msp432_algo_params algo_params; + + int retval; + + if (TARGET_HALTED != target->state) { + LOG_ERROR("Target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + + /* Do a mass erase if user requested all sectors of main flash */ + if ((0 == bank->bank_number) && (first == 0) && + (last == (bank->num_sectors - 1))) { + /* Request mass erase of main flash */ + return msp432_mass_erase(bank, false); + } + + retval = msp432_init(bank); + if (ERROR_OK != retval) + return retval; + + /* Initialize algorithm parameters to default values */ + msp432_init_params(&algo_params); + + /* Adjust params if this is the info bank */ + if (1 == bank->bank_number) { + buf_set_u32(algo_params.erase_param, 0, 32, FLASH_ERASE_INFO); + /* And flag if BSL is unlocked */ + if (msp432_bank->unlock_bsl) + buf_set_u32(algo_params.unlock_bsl, 0, 32, FLASH_UNLOCK_BSL); + } + + /* Erase requested sectors one by one */ + for (int i = first; i <= last; i++) { + + /* Skip TVL (read-only) sector of the info bank */ + if (1 == bank->bank_number && 1 == i) + continue; + + /* Skip BSL sectors of info bank if locked */ + if (1 == bank->bank_number && (2 == i || 3 == i) && + !msp432_bank->unlock_bsl) + continue; + + /* Convert sector number to starting address of sector */ + buf_set_u32(algo_params.address, 0, 32, bank->base + + (i * msp432_bank->sector_length)); + + /* Issue the sector erase command to the flash helper algorithm */ + retval = msp432_exec_cmd(target, &algo_params, FLASH_SECTOR_ERASE); + if (ERROR_OK != retval) { + (void)msp432_quit(bank); + return retval; + } + + retval = msp432_wait_return_code(target); + if (ERROR_OK != retval) { + (void)msp432_quit(bank); + return retval; + } + } + + retval = msp432_quit(bank); + if (ERROR_OK != retval) + return retval; + + return retval; +} + +static int msp432_protect(struct flash_bank *bank, int set, int first, + int last) +{ + return ERROR_OK; +} + +static int msp432_write(struct flash_bank *bank, const uint8_t *buffer, + uint32_t offset, uint32_t count) +{ + struct target *target = bank->target; + struct msp432_bank *msp432_bank = bank->driver_priv; + struct msp432_algo_params algo_params; + uint32_t size; + uint32_t data_ready = BUFFER_DATA_READY; + long long start_ms; + long long elapsed_ms; + + int retval; + + if (TARGET_HALTED != target->state) { + LOG_ERROR("Target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + + /* + * Block attempts to write to read-only sectors of flash + * The TVL region in sector 1 of the info flash is always read-only + * The BSL region in sectors 2 and 3 of the info flash may be unlocked + * The helper algorithm will hang on attempts to write to TVL + */ + if (1 == bank->bank_number) { + /* Set read-only start to TVL sector */ + uint32_t start = 0x1000; + /* Set read-only end after BSL region if locked */ + uint32_t end = (msp432_bank->unlock_bsl) ? 0x2000 : 0x4000; + /* Check if request includes anything in read-only sectors */ + if ((offset + count - 1) < start || offset >= end) { + /* The request includes no bytes in read-only sectors */ + /* Fall out and process the request normally */ + } else { + /* Send a request for anything before read-only sectors */ + if (offset < start) { + uint32_t start_count = MIN(start - offset, count); + retval = msp432_write(bank, buffer, offset, start_count); + if (ERROR_OK != retval) + return retval; + } + /* Send a request for anything after read-only sectors */ + if ((offset + count - 1) >= end) { + uint32_t skip = end - offset; + count -= skip; + offset += skip; + buffer += skip; + return msp432_write(bank, buffer, offset, count); + } else { + /* Request is entirely in read-only sectors */ + return ERROR_OK; + } + } + } + + retval = msp432_init(bank); + if (ERROR_OK != retval) + return retval; + + /* Initialize algorithm parameters to default values */ + msp432_init_params(&algo_params); + + /* Set up parameters for requested flash write operation */ + buf_set_u32(algo_params.address, 0, 32, bank->base + offset); + buf_set_u32(algo_params.length, 0, 32, count); + + /* Check if this is the info bank */ + if (1 == bank->bank_number) { + /* And flag if BSL is unlocked */ + if (msp432_bank->unlock_bsl) + buf_set_u32(algo_params.unlock_bsl, 0, 32, FLASH_UNLOCK_BSL); + } + + /* Set up flash helper algorithm to continuous flash mode */ + retval = msp432_exec_cmd(target, &algo_params, FLASH_CONTINUOUS); + if (ERROR_OK != retval) { + (void)msp432_quit(bank); + return retval; + } + + /* Write requested data, one buffer at a time */ + start_ms = timeval_ms(); + while (count > 0) { + + if (count > ALGO_BUFFER_SIZE) + size = ALGO_BUFFER_SIZE; + else + size = count; + + /* Put next block of data to flash into buffer */ + retval = target_write_buffer(target, ALGO_BUFFER1_ADDR, size, buffer); + if (ERROR_OK != retval) { + LOG_ERROR("Unable to write data to target memory"); + (void)msp432_quit(bank); + return ERROR_FLASH_OPERATION_FAILED; + } + + /* Signal the flash helper algorithm that data is ready to flash */ + retval = target_write_buffer(target, ALGO_BUFFER1_STATUS_ADDR, + sizeof(data_ready), (uint8_t *)&data_ready); + if (ERROR_OK != retval) { + (void)msp432_quit(bank); + return ERROR_FLASH_OPERATION_FAILED; + } + + retval = msp432_wait_inactive(target, 1); + if (ERROR_OK != retval) { + (void)msp432_quit(bank); + return retval; + } + + count -= size; + buffer += size; + + elapsed_ms = timeval_ms() - start_ms; + if (elapsed_ms > 500) + keep_alive(); + } + + /* Confirm that the flash helper algorithm is finished */ + retval = msp432_wait_return_code(target); + if (ERROR_OK != retval) { + (void)msp432_quit(bank); + return retval; + } + + retval = msp432_quit(bank); + if (ERROR_OK != retval) + return retval; + + return retval; +} + +static int msp432_probe(struct flash_bank *bank) +{ + struct target *target = bank->target; + struct msp432_bank *msp432_bank = bank->driver_priv; + + char *name; + + uint32_t device_id; + uint32_t hardware_rev; + + uint32_t base; + uint32_t sector_length; + uint32_t size; + int num_sectors; + int bank_id; + + int retval; + + bank_id = bank->bank_number; + + /* Read the flash size register to determine this is a P4 or not */ + /* MSP432P4s will return the size of flash. MSP432E4s will return zero */ + retval = target_read_u32(target, P4_FLASH_MAIN_SIZE_REG, &size); + if (ERROR_OK != retval) + return retval; + + if (0 == size) { + /* This is likely an MSP432E4 */ + msp432_bank->family_type = MSP432E4; + + retval = target_read_u32(target, E4_DID0_REG, &device_id); + if (ERROR_OK != retval) + return retval; + + msp432_bank->device_id = device_id; + + retval = target_read_u32(target, E4_DID1_REG, &hardware_rev); + if (ERROR_OK != retval) + return retval; + + msp432_bank->hardware_rev = hardware_rev; + } else { + /* This is likely an MSP432P4 */ + msp432_bank->family_type = MSP432P4; + + retval = target_read_u32(target, P4_DEVICE_ID_REG, &device_id); + if (ERROR_OK != retval) + return retval; + + msp432_bank->device_id = device_id & 0xFFFF; + + retval = target_read_u32(target, P4_HARDWARE_REV_REG, &hardware_rev); + if (ERROR_OK != retval) + return retval; + + msp432_bank->hardware_rev = hardware_rev & 0xFF; + } + + msp432_bank->device_type = msp432_device_type(msp432_bank->family_type, + msp432_bank->device_id, msp432_bank->hardware_rev); + + /* If not already allocated, create the info bank for MSP432P4 */ + /* We could not determine it was needed until device was probed */ + if (MSP432P4 == msp432_bank->family_type) { + /* If we've been given bank 1, then this was already done */ + if (0 == bank_id) { + /* And only allocate it if it doesn't exist yet */ + if (NULL == bank->next) { + struct flash_bank *info_bank; + info_bank = malloc(sizeof(struct flash_bank)); + if (NULL == info_bank) + return ERROR_FAIL; + + name = malloc(strlen(bank->name)+1); + if (NULL == name) { + free(info_bank); + return ERROR_FAIL; + } + strcpy(name, bank->name); + + /* Initialize bank 1 (info region) */ + info_bank->name = name; + info_bank->target = bank->target; + info_bank->driver = bank->driver; + info_bank->driver_priv = bank->driver_priv; + info_bank->bank_number = 1; + info_bank->base = 0x00200000; + info_bank->size = 0; + info_bank->chip_width = 0; + info_bank->bus_width = 0; + info_bank->erased_value = 0xff; + info_bank->default_padded_value = 0xff; + info_bank->write_start_alignment = 0; + info_bank->write_end_alignment = 0; + info_bank->minimal_write_gap = FLASH_WRITE_GAP_SECTOR; + info_bank->num_sectors = 0; + info_bank->sectors = NULL; + info_bank->num_prot_blocks = 0; + info_bank->prot_blocks = NULL; + info_bank->next = NULL; + + /* Enable the new bank */ + bank->next = info_bank; + } + } + } + + if (MSP432P4 == msp432_bank->family_type) { + /* Set up MSP432P4 specific flash parameters */ + if (0 == bank_id) { + retval = target_read_u32(target, P4_FLASH_MAIN_SIZE_REG, &size); + if (ERROR_OK != retval) + return retval; + + base = P4_FLASH_MAIN_BASE; + sector_length = P4_SECTOR_LENGTH; + num_sectors = size / sector_length; + } else if (1 == bank_id) { + if (msp432_bank->device_type == MSP432P411X || + msp432_bank->device_type == MSP432P411X_GUESS) { + /* MSP432P411x has an info size register, use that for size */ + retval = target_read_u32(target, P4_FLASH_INFO_SIZE_REG, &size); + if (ERROR_OK != retval) + return retval; + } else { + /* All other MSP432P401x devices have fixed info region size */ + size = 0x4000; /* 16 KB info region */ + } + base = P4_FLASH_INFO_BASE; + sector_length = P4_SECTOR_LENGTH; + num_sectors = size / sector_length; + } else { + /* Invalid bank number somehow */ + return ERROR_FAIL; + } + } else { + /* Set up MSP432E4 specific flash parameters */ + base = E4_FLASH_BASE; + size = E4_FLASH_SIZE; + sector_length = E4_SECTOR_LENGTH; + num_sectors = size / sector_length; + } + + if (NULL != bank->sectors) { + free(bank->sectors); + bank->sectors = NULL; + } + + bank->sectors = malloc(sizeof(struct flash_sector) * num_sectors); + if (NULL == bank->sectors) + return ERROR_FAIL; + + bank->base = base; + bank->size = size; + bank->write_start_alignment = 0; + bank->write_end_alignment = 0; + bank->num_sectors = num_sectors; + msp432_bank->sector_length = sector_length; + + for (int i = 0; i < num_sectors; i++) { + bank->sectors[i].offset = i * sector_length; + bank->sectors[i].size = sector_length; + bank->sectors[i].is_erased = -1; + bank->sectors[i].is_protected = 0; + } + + /* We've successfully determined the stats on this flash bank */ + msp432_bank->probed[bank_id] = true; + + /* If we fall through to here, then all went well */ + + return ERROR_OK; +} + +static int msp432_auto_probe(struct flash_bank *bank) +{ + struct msp432_bank *msp432_bank = bank->driver_priv; + + int retval = ERROR_OK; + + if (bank->bank_number < 0 || bank->bank_number > 1) { + /* Invalid bank number somehow */ + return ERROR_FAIL; + } + + if (!msp432_bank->probed[bank->bank_number]) + retval = msp432_probe(bank); + + return retval; +} + +static int msp432_protect_check(struct flash_bank *bank) +{ + return ERROR_OK; +} + +static int msp432_info(struct flash_bank *bank, char *buf, int buf_size) +{ + struct msp432_bank *msp432_bank = bank->driver_priv; + int printed = 0; + + switch (msp432_bank->device_type) { + case MSP432P401X_DEPR: + if (0xFFFF == msp432_bank->device_id) { + /* Very early pre-production silicon currently deprecated */ + printed = snprintf(buf, buf_size, + "MSP432P401x pre-production device (deprecated silicon)\n" + SUPPORT_MESSAGE); + } else { + /* Revision A or B silicon, also deprecated */ + printed = snprintf(buf, buf_size, + "MSP432P401x Device Rev %c (deprecated silicon)\n" + SUPPORT_MESSAGE, (char)msp432_bank->hardware_rev); + } + break; + case MSP432P401X: + printed = snprintf(buf, buf_size, + "MSP432P401x Device Rev %c\n", + (char)msp432_bank->hardware_rev); + break; + case MSP432P411X: + printed = snprintf(buf, buf_size, + "MSP432P411x Device Rev %c\n", + (char)msp432_bank->hardware_rev); + break; + case MSP432E401Y: + printed = snprintf(buf, buf_size, "MSP432E401Y Device\n"); + break; + case MSP432E411Y: + printed = snprintf(buf, buf_size, "MSP432E411Y Device\n"); + break; + case MSP432E4X_GUESS: + printed = snprintf(buf, buf_size, + "Unrecognized MSP432E4 DID0 and DID1 IDs (%08X, %08X)", + msp432_bank->device_id, msp432_bank->hardware_rev); + break; + case MSP432P401X_GUESS: + case MSP432P411X_GUESS: + default: + printed = snprintf(buf, buf_size, + "Unrecognized MSP432P4 Device ID and Hardware Rev (%04X, %02X)", + msp432_bank->device_id, msp432_bank->hardware_rev); + break; + } + + buf_size -= printed; + + if (0 > buf_size) + return ERROR_BUF_TOO_SMALL; + + return ERROR_OK; +} + +static void msp432_flash_free_driver_priv(struct flash_bank *bank) +{ + /* A single private struct is shared between main and info banks */ + /* Only free it on the call for main bank (#0) */ + if ((0 == bank->bank_number) && (NULL != bank->driver_priv)) + free(bank->driver_priv); + /* Forget about the private struct on both main and info banks */ + bank->driver_priv = NULL; +} + +static const struct command_registration msp432_exec_command_handlers[] = { + { + .name = "mass_erase", + .handler = msp432_mass_erase_command, + .mode = COMMAND_EXEC, + .help = "Erase entire flash memory on device.", + .usage = "['main' | 'all']", + }, + { + .name = "bsl", + .handler = msp432_bsl_command, + .mode = COMMAND_EXEC, + .help = "Allow BSL to be erased or written by flash commands.", + .usage = "['unlock' | 'lock']", + }, + COMMAND_REGISTRATION_DONE +}; + +static const struct command_registration msp432_command_handlers[] = { + { + .name = "msp432", + .mode = COMMAND_EXEC, + .help = "MSP432 flash command group", + .usage = "", + .chain = msp432_exec_command_handlers, + }, + COMMAND_REGISTRATION_DONE +}; + +struct flash_driver msp432_flash = { + .name = "msp432", + .commands = msp432_command_handlers, + .flash_bank_command = msp432_flash_bank_command, + .erase = msp432_erase, + .protect = msp432_protect, + .write = msp432_write, + .read = default_flash_read, + .probe = msp432_probe, + .auto_probe = msp432_auto_probe, + .erase_check = default_flash_blank_check, + .protect_check = msp432_protect_check, + .info = msp432_info, + .free_driver_priv = msp432_flash_free_driver_priv, +}; diff --git a/src/flash/nor/msp432.h b/src/flash/nor/msp432.h new file mode 100644 index 0000000..ffefa8f --- /dev/null +++ b/src/flash/nor/msp432.h @@ -0,0 +1,127 @@ +/*************************************************************************** + * Copyright (C) 2018 by Texas Instruments, Inc. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ + +#ifndef OPENOCD_FLASH_NOR_MSP432_H +#define OPENOCD_FLASH_NOR_MSP432_H + +/* MSP432 family types */ +#define MSP432_NO_FAMILY 0 /* Family type not determined yet */ +#define MSP432E4 1 /* MSP432E4 family of devices */ +#define MSP432P4 2 /* MSP432P4 family of devices */ + +/* MSP432 device types */ +#define MSP432_NO_TYPE 0 /* Device type not determined yet */ +#define MSP432P401X_DEPR 1 /* Early MSP432P401x offerings, now deprecated */ +#define MSP432P401X 2 /* MSP432P401x device, revision C or higher */ +#define MSP432P411X 3 /* MSP432P411x device, revision A or higher */ +#define MSP432P401X_GUESS 4 /* Assuming it's an MSP432P401x device */ +#define MSP432P411X_GUESS 5 /* Assuming it's an MSP432P411x device */ +#define MSP432E401Y 6 /* MSP432E401Y device */ +#define MSP432E411Y 7 /* MSP432E401Y device */ +#define MSP432E4X_GUESS 8 /* Assuming it's an MSP432E4x device */ + +/* MSP432P4 flash parameters */ +#define P4_FLASH_MAIN_BASE 0x00000000 +#define P4_FLASH_INFO_BASE 0x00200000 +#define P4_SECTOR_LENGTH 0x1000 +#define P4_ALGO_ENTRY_ADDR 0x01000110 + +/* MSP432E4 flash paramters */ +#define E4_FLASH_BASE 0x00000000 +#define E4_FLASH_SIZE 0x100000 +#define E4_SECTOR_LENGTH 0x4000 +#define E4_ALGO_ENTRY_ADDR 0x20000110 + +/* Flash helper algorithm key addresses */ +#define ALGO_BASE_ADDR 0x20000000 +#define ALGO_BUFFER1_ADDR 0x20002000 +#define ALGO_BUFFER2_ADDR 0x20003000 +#define ALGO_PARAMS_BASE_ADDR 0x20000150 +#define ALGO_FLASH_COMMAND_ADDR 0x20000150 +#define ALGO_RETURN_CODE_ADDR 0x20000154 +#define ALGO_FLASH_DEST_ADDR 0x2000015c +#define ALGO_FLASH_LENGTH_ADDR 0x20000160 +#define ALGO_BUFFER1_STATUS_ADDR 0x20000164 +#define ALGO_BUFFER2_STATUS_ADDR 0x20000168 +#define ALGO_ERASE_PARAM_ADDR 0x2000016c +#define ALGO_UNLOCK_BSL_ADDR 0x20000170 +#define ALGO_STACK_POINTER_ADDR 0x20002000 + +/* Flash helper algorithm key sizes */ +#define ALGO_BUFFER_SIZE 0x1000 +#define ALGO_WORKING_SIZE (ALGO_BUFFER2_ADDR + 0x1000 - ALGO_BASE_ADDR) + +/* Flash helper algorithm flash commands */ +#define FLASH_NO_COMMAND 0 +#define FLASH_MASS_ERASE 1 +#define FLASH_SECTOR_ERASE 2 +#define FLASH_PROGRAM 4 +#define FLASH_INIT 8 +#define FLASH_EXIT 16 +#define FLASH_CONTINUOUS 32 + +/* Flash helper algorithm return codes */ +#define FLASH_BUSY 0x00000001 +#define FLASH_SUCCESS 0x00000ACE +#define FLASH_ERROR 0x0000DEAD +#define FLASH_TIMEOUT_ERROR 0xDEAD0000 +#define FLASH_VERIFY_ERROR 0xDEADDEAD +#define FLASH_WRONG_COMMAND 0x00000BAD +#define FLASH_POWER_ERROR 0x00DEAD00 + +/* Flash helper algorithm buffer status values */ +#define BUFFER_INACTIVE 0x00 +#define BUFFER_ACTIVE 0x01 +#define BUFFER_DATA_READY 0x10 + +/* Flash helper algorithm erase parameters */ +#define FLASH_ERASE_MAIN 0x01 +#define FLASH_ERASE_INFO 0x02 + +/* Flash helper algorithm lock/unlock BSL options */ +#define FLASH_LOCK_BSL 0x00 +#define FLASH_UNLOCK_BSL 0x0b + +/* Flash helper algorithm parameter block struct */ +struct msp432_algo_params { + uint8_t flash_command[4]; + uint8_t return_code[4]; + uint8_t _reserved0[4]; + uint8_t address[4]; + uint8_t length[4]; + uint8_t buffer1_status[4]; + uint8_t buffer2_status[4]; + uint8_t erase_param[4]; + uint8_t unlock_bsl[4]; +}; + +/* Flash helper algorithm for MSP432P401x targets */ +const uint8_t msp432p401x_algo[] = { +#include "../../../contrib/loaders/flash/msp432/msp432p401x_algo.inc" +}; + +/* Flash helper algorithm for MSP432P411x targets */ +const uint8_t msp432p411x_algo[] = { +#include "../../../contrib/loaders/flash/msp432/msp432p411x_algo.inc" +}; + +/* Flash helper algorithm for MSP432E4x targets */ +const uint8_t msp432e4x_algo[] = { +#include "../../../contrib/loaders/flash/msp432/msp432e4x_algo.inc" +}; + +#endif /* OPENOCD_FLASH_NOR_MSP432_H */ diff --git a/src/flash/nor/nrf5.c b/src/flash/nor/nrf5.c index 31dd5aa..16459c7 100644 --- a/src/flash/nor/nrf5.c +++ b/src/flash/nor/nrf5.c @@ -108,6 +108,7 @@ enum nrf5_nvmc_config_bits { struct nrf5_info { uint32_t code_page_size; + uint32_t refcount; struct { bool probed; @@ -204,6 +205,7 @@ static const struct nrf5_device_spec nrf5_known_devices_table[] = { /* nRF52832 Devices */ NRF5_DEVICE_DEF(0x00C7, "52832", "QFAA", "B0", 512), + NRF5_DEVICE_DEF(0x0139, "52832", "QFAA", "E0", 512), }; static int nrf5_bank_is_probed(struct flash_bank *bank) @@ -531,7 +533,6 @@ static int nrf5_probe(struct flash_bank *bank) bank->sectors[0].size = bank->size; bank->sectors[0].offset = 0; - /* mark as unknown */ bank->sectors[0].is_erased = 0; bank->sectors[0].is_protected = 0; @@ -553,17 +554,6 @@ static int nrf5_auto_probe(struct flash_bank *bank) return nrf5_probe(bank); } -static struct flash_sector *nrf5_find_sector_by_address(struct flash_bank *bank, uint32_t address) -{ - struct nrf5_info *chip = bank->driver_priv; - - for (int i = 0; i < bank->num_sectors; i++) - if (bank->sectors[i].offset <= address && - address < (bank->sectors[i].offset + chip->code_page_size)) - return &bank->sectors[i]; - return NULL; -} - static int nrf5_erase_all(struct nrf5_info *chip) { LOG_DEBUG("Erasing all non-volatile memory"); @@ -615,9 +605,6 @@ static int nrf5_erase_page(struct flash_bank *bank, sector->offset); } - if (res == ERROR_OK) - sector->is_erased = 1; - return res; } @@ -743,48 +730,22 @@ static int nrf5_write_pages(struct flash_bank *bank, uint32_t start, uint32_t en { int res = ERROR_FAIL; struct nrf5_info *chip = bank->driver_priv; - struct flash_sector *sector; - uint32_t offset; assert(start % chip->code_page_size == 0); assert(end % chip->code_page_size == 0); - /* Erase all sectors */ - for (offset = start; offset < end; offset += chip->code_page_size) { - sector = nrf5_find_sector_by_address(bank, offset); - if (!sector) { - LOG_ERROR("Invalid sector @ 0x%08"PRIx32, offset); - return ERROR_FLASH_SECTOR_INVALID; - } - - if (sector->is_protected) { - LOG_ERROR("Can't erase protected sector @ 0x%08"PRIx32, offset); - goto error; - } - - if (sector->is_erased != 1) { /* 1 = erased, 0= not erased, -1 = unknown */ - res = nrf5_erase_page(bank, chip, sector); - if (res != ERROR_OK) { - LOG_ERROR("Failed to erase sector @ 0x%08"PRIx32, sector->offset); - goto error; - } - } - sector->is_erased = 0; - } - res = nrf5_nvmc_write_enable(chip); if (res != ERROR_OK) goto error; res = nrf5_ll_flash_write(chip, start, buffer, (end - start)); if (res != ERROR_OK) - goto set_read_only; + goto error; return nrf5_nvmc_read_only(chip); -set_read_only: - nrf5_nvmc_read_only(chip); error: + nrf5_nvmc_read_only(chip); LOG_ERROR("Failed to write to nrf5 flash"); return res; } @@ -876,11 +837,9 @@ static int nrf5_uicr_flash_write(struct flash_bank *bank, if (res != ERROR_OK) return res; - if (sector->is_erased != 1) { - res = nrf5_erase_page(bank, chip, sector); - if (res != ERROR_OK) - return res; - } + res = nrf5_erase_page(bank, chip, sector); + if (res != ERROR_OK) + return res; res = nrf5_nvmc_write_enable(chip); if (res != ERROR_OK) @@ -911,6 +870,18 @@ static int nrf5_write(struct flash_bank *bank, const uint8_t *buffer, return chip->bank[bank->bank_number].write(bank, chip, buffer, offset, count); } +static void nrf5_free_driver_priv(struct flash_bank *bank) +{ + struct nrf5_info *chip = bank->driver_priv; + if (chip == NULL) + return; + + chip->refcount--; + if (chip->refcount == 0) { + free(chip); + bank->driver_priv = NULL; + } +} FLASH_BANK_COMMAND_HANDLER(nrf5_flash_bank_command) { @@ -946,6 +917,7 @@ FLASH_BANK_COMMAND_HANDLER(nrf5_flash_bank_command) break; } + chip->refcount++; chip->bank[bank->bank_number].probed = false; bank->driver_priv = chip; @@ -992,9 +964,6 @@ COMMAND_HANDLER(nrf5_handle_mass_erase_command) return res; } - for (int i = 0; i < bank->num_sectors; i++) - bank->sectors[i].is_erased = 1; - res = nrf5_protect_check(bank); if (res != ERROR_OK) { LOG_ERROR("Failed to check chip's write protection"); @@ -1005,8 +974,6 @@ COMMAND_HANDLER(nrf5_handle_mass_erase_command) if (res != ERROR_OK) return res; - bank->sectors[0].is_erased = 1; - return ERROR_OK; } @@ -1175,6 +1142,7 @@ struct flash_driver nrf5_flash = { .auto_probe = nrf5_auto_probe, .erase_check = default_flash_blank_check, .protect_check = nrf5_protect_check, + .free_driver_priv = nrf5_free_driver_priv, }; /* We need to retain the flash-driver name as well as the commands @@ -1192,4 +1160,5 @@ struct flash_driver nrf51_flash = { .auto_probe = nrf5_auto_probe, .erase_check = default_flash_blank_check, .protect_check = nrf5_protect_check, + .free_driver_priv = nrf5_free_driver_priv, }; diff --git a/src/flash/nor/psoc5lp.c b/src/flash/nor/psoc5lp.c new file mode 100644 index 0000000..b88abbb --- /dev/null +++ b/src/flash/nor/psoc5lp.c @@ -0,0 +1,1586 @@ +/* + * PSoC 5LP flash driver + * + * Copyright (c) 2016 Andreas Färber + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "imp.h" +#include <helper/time_support.h> +#include <target/armv7m.h> + +#define PM_ACT_CFG0 0x400043A0 +#define PM_ACT_CFG12 0x400043AC +#define SPC_CPU_DATA 0x40004720 +#define SPC_SR 0x40004722 +#define PRT1_PC2 0x4000500A +#define PHUB_CH0_BASIC_CFG 0x40007010 +#define PHUB_CH0_ACTION 0x40007014 +#define PHUB_CH0_BASIC_STATUS 0x40007018 +#define PHUB_CH1_BASIC_CFG 0x40007020 +#define PHUB_CH1_ACTION 0x40007024 +#define PHUB_CH1_BASIC_STATUS 0x40007028 +#define PHUB_CFGMEM0_CFG0 0x40007600 +#define PHUB_CFGMEM0_CFG1 0x40007604 +#define PHUB_CFGMEM1_CFG0 0x40007608 +#define PHUB_CFGMEM1_CFG1 0x4000760C +#define PHUB_TDMEM0_ORIG_TD0 0x40007800 +#define PHUB_TDMEM0_ORIG_TD1 0x40007804 +#define PHUB_TDMEM1_ORIG_TD0 0x40007808 +#define PHUB_TDMEM1_ORIG_TD1 0x4000780C +#define PANTHER_DEVICE_ID 0x4008001C + +/* NVL is not actually mapped to the Cortex-M address space + * As we need a base addess different from other banks in the device + * we use the address of NVL programming data in Cypress images */ +#define NVL_META_BASE 0x90000000 + +#define PM_ACT_CFG12_EN_EE (1 << 4) + +#define SPC_KEY1 0xB6 +#define SPC_KEY2 0xD3 + +#define SPC_LOAD_BYTE 0x00 +#define SPC_LOAD_MULTI_BYTE 0x01 +#define SPC_LOAD_ROW 0x02 +#define SPC_READ_BYTE 0x03 +#define SPC_READ_MULTI_BYTE 0x04 +#define SPC_WRITE_ROW 0x05 +#define SPC_WRITE_USER_NVL 0x06 +#define SPC_PRG_ROW 0x07 +#define SPC_ERASE_SECTOR 0x08 +#define SPC_ERASE_ALL 0x09 +#define SPC_READ_HIDDEN_ROW 0x0A +#define SPC_PROGRAM_PROTECT_ROW 0x0B +#define SPC_GET_CHECKSUM 0x0C +#define SPC_GET_TEMP 0x0E +#define SPC_READ_VOLATILE_BYTE 0x10 + +#define SPC_ARRAY_ALL 0x3F +#define SPC_ARRAY_EEPROM 0x40 +#define SPC_ARRAY_NVL_USER 0x80 +#define SPC_ARRAY_NVL_WO 0xF8 + +#define SPC_ROW_PROTECTION 0 + +#define SPC_OPCODE_LEN 3 + +#define SPC_SR_DATA_READY (1 << 0) +#define SPC_SR_IDLE (1 << 1) + +#define PM_ACT_CFG0_EN_CLK_SPC (1 << 3) + +#define PHUB_CHx_BASIC_CFG_EN (1 << 0) +#define PHUB_CHx_BASIC_CFG_WORK_SEP (1 << 5) + +#define PHUB_CHx_ACTION_CPU_REQ (1 << 0) + +#define PHUB_CFGMEMx_CFG0 (1 << 7) + +#define PHUB_TDMEMx_ORIG_TD0_NEXT_TD_PTR_LAST (0xff << 16) +#define PHUB_TDMEMx_ORIG_TD0_INC_SRC_ADDR (1 << 24) + +#define NVL_3_ECCEN (1 << 3) + +#define ROW_SIZE 256 +#define ROW_ECC_SIZE 32 +#define ROWS_PER_SECTOR 64 +#define SECTOR_SIZE (ROWS_PER_SECTOR * ROW_SIZE) +#define ROWS_PER_BLOCK 256 +#define BLOCK_SIZE (ROWS_PER_BLOCK * ROW_SIZE) +#define SECTORS_PER_BLOCK (BLOCK_SIZE / SECTOR_SIZE) +#define EEPROM_ROW_SIZE 16 +#define EEPROM_SECTOR_SIZE (ROWS_PER_SECTOR * EEPROM_ROW_SIZE) +#define EEPROM_BLOCK_SIZE (ROWS_PER_BLOCK * EEPROM_ROW_SIZE) + +#define PART_NUMBER_LEN (17 + 1) + +struct psoc5lp_device { + uint32_t id; + unsigned fam; + unsigned speed_mhz; + unsigned flash_kb; + unsigned eeprom_kb; +}; + +/* + * Device information collected from datasheets. + * Different temperature ranges (C/I/Q/A) may share IDs, not differing otherwise. + */ +static const struct psoc5lp_device psoc5lp_devices[] = { + /* CY8C58LP Family Datasheet */ + { .id = 0x2E11F069, .fam = 8, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 }, + { .id = 0x2E120069, .fam = 8, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 }, + { .id = 0x2E123069, .fam = 8, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 }, + { .id = 0x2E124069, .fam = 8, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 }, + { .id = 0x2E126069, .fam = 8, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 }, + { .id = 0x2E127069, .fam = 8, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 }, + { .id = 0x2E117069, .fam = 8, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 }, + { .id = 0x2E118069, .fam = 8, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 }, + { .id = 0x2E119069, .fam = 8, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 }, + { .id = 0x2E11C069, .fam = 8, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 }, + { .id = 0x2E114069, .fam = 8, .speed_mhz = 67, .flash_kb = 64, .eeprom_kb = 2 }, + { .id = 0x2E115069, .fam = 8, .speed_mhz = 67, .flash_kb = 64, .eeprom_kb = 2 }, + { .id = 0x2E116069, .fam = 8, .speed_mhz = 67, .flash_kb = 64, .eeprom_kb = 2 }, + { .id = 0x2E160069, .fam = 8, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 }, + /* '' */ + { .id = 0x2E161069, .fam = 8, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 }, + /* '' */ + { .id = 0x2E1D2069, .fam = 8, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 }, + { .id = 0x2E1D6069, .fam = 8, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 }, + + /* CY8C56LP Family Datasheet */ + { .id = 0x2E10A069, .fam = 6, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 }, + { .id = 0x2E10D069, .fam = 6, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 }, + { .id = 0x2E10E069, .fam = 6, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 }, + { .id = 0x2E106069, .fam = 6, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 }, + { .id = 0x2E108069, .fam = 6, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 }, + { .id = 0x2E109069, .fam = 6, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 }, + { .id = 0x2E101069, .fam = 6, .speed_mhz = 67, .flash_kb = 64, .eeprom_kb = 2 }, + { .id = 0x2E104069, .fam = 6, .speed_mhz = 67, .flash_kb = 64, .eeprom_kb = 2 }, + /* '' */ + { .id = 0x2E105069, .fam = 6, .speed_mhz = 67, .flash_kb = 64, .eeprom_kb = 2 }, + { .id = 0x2E128069, .fam = 6, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 }, + /* '' */ + { .id = 0x2E122069, .fam = 6, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 }, + { .id = 0x2E129069, .fam = 6, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 }, + { .id = 0x2E163069, .fam = 6, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 }, + { .id = 0x2E156069, .fam = 6, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 }, + { .id = 0x2E1D3069, .fam = 6, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 }, + + /* CY8C54LP Family Datasheet */ + { .id = 0x2E11A069, .fam = 4, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 }, + { .id = 0x2E16A069, .fam = 4, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 }, + { .id = 0x2E12A069, .fam = 4, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 }, + { .id = 0x2E103069, .fam = 4, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 }, + { .id = 0x2E16C069, .fam = 4, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 }, + { .id = 0x2E102069, .fam = 4, .speed_mhz = 67, .flash_kb = 64, .eeprom_kb = 2 }, + { .id = 0x2E148069, .fam = 4, .speed_mhz = 67, .flash_kb = 64, .eeprom_kb = 2 }, + { .id = 0x2E155069, .fam = 4, .speed_mhz = 67, .flash_kb = 64, .eeprom_kb = 2 }, + { .id = 0x2E16B069, .fam = 4, .speed_mhz = 67, .flash_kb = 64, .eeprom_kb = 2 }, + { .id = 0x2E12B069, .fam = 4, .speed_mhz = 67, .flash_kb = 32, .eeprom_kb = 2 }, + { .id = 0x2E168069, .fam = 4, .speed_mhz = 67, .flash_kb = 32, .eeprom_kb = 2 }, + { .id = 0x2E178069, .fam = 4, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 }, + { .id = 0x2E15D069, .fam = 4, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 }, + { .id = 0x2E1D4069, .fam = 4, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 }, + + /* CY8C52LP Family Datasheet */ + { .id = 0x2E11E069, .fam = 2, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 }, + { .id = 0x2E12F069, .fam = 2, .speed_mhz = 67, .flash_kb = 256, .eeprom_kb = 2 }, + { .id = 0x2E133069, .fam = 2, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 }, + { .id = 0x2E159069, .fam = 2, .speed_mhz = 67, .flash_kb = 128, .eeprom_kb = 2 }, + { .id = 0x2E11D069, .fam = 2, .speed_mhz = 67, .flash_kb = 64, .eeprom_kb = 2 }, + { .id = 0x2E121069, .fam = 2, .speed_mhz = 67, .flash_kb = 64, .eeprom_kb = 2 }, + { .id = 0x2E184069, .fam = 2, .speed_mhz = 67, .flash_kb = 64, .eeprom_kb = 2 }, + { .id = 0x2E196069, .fam = 2, .speed_mhz = 67, .flash_kb = 64, .eeprom_kb = 2 }, + { .id = 0x2E132069, .fam = 2, .speed_mhz = 67, .flash_kb = 32, .eeprom_kb = 2 }, + { .id = 0x2E138069, .fam = 2, .speed_mhz = 67, .flash_kb = 32, .eeprom_kb = 2 }, + { .id = 0x2E13A069, .fam = 2, .speed_mhz = 67, .flash_kb = 32, .eeprom_kb = 2 }, + { .id = 0x2E152069, .fam = 2, .speed_mhz = 67, .flash_kb = 32, .eeprom_kb = 2 }, + { .id = 0x2E15F069, .fam = 2, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 }, + { .id = 0x2E15A069, .fam = 2, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 }, + { .id = 0x2E1D5069, .fam = 2, .speed_mhz = 80, .flash_kb = 256, .eeprom_kb = 2 }, +}; + +static void psoc5lp_get_part_number(const struct psoc5lp_device *dev, char *str) +{ + strcpy(str, "CY8Cabcdefg-LPxxx"); + + str[4] = '5'; + str[5] = '0' + dev->fam; + + switch (dev->speed_mhz) { + case 67: + str[6] = '6'; + break; + case 80: + str[6] = '8'; + break; + default: + str[6] = '?'; + } + + switch (dev->flash_kb) { + case 32: + str[7] = '5'; + break; + case 64: + str[7] = '6'; + break; + case 128: + str[7] = '7'; + break; + case 256: + str[7] = '8'; + break; + default: + str[7] = '?'; + } + + /* Package does not matter. */ + str[8] = 'x'; + str[9] = 'x'; + + /* Temperate range cannot uniquely be identified. */ + str[10] = 'x'; +} + +static int psoc5lp_get_device_id(struct target *target, uint32_t *id) +{ + int retval; + + retval = target_read_u32(target, PANTHER_DEVICE_ID, id); /* dummy read */ + if (retval != ERROR_OK) + return retval; + retval = target_read_u32(target, PANTHER_DEVICE_ID, id); + return retval; +} + +static int psoc5lp_find_device(struct target *target, + const struct psoc5lp_device **device) +{ + uint32_t device_id; + unsigned i; + int retval; + + *device = NULL; + + retval = psoc5lp_get_device_id(target, &device_id); + if (retval != ERROR_OK) + return retval; + LOG_DEBUG("PANTHER_DEVICE_ID = 0x%08" PRIX32, device_id); + + for (i = 0; i < ARRAY_SIZE(psoc5lp_devices); i++) { + if (psoc5lp_devices[i].id == device_id) { + *device = &psoc5lp_devices[i]; + return ERROR_OK; + } + } + + LOG_ERROR("Device 0x%08" PRIX32 " not supported", device_id); + return ERROR_FLASH_OPER_UNSUPPORTED; +} + +static int psoc5lp_spc_enable_clock(struct target *target) +{ + int retval; + uint8_t pm_act_cfg0; + + retval = target_read_u8(target, PM_ACT_CFG0, &pm_act_cfg0); + if (retval != ERROR_OK) { + LOG_ERROR("Cannot read PM_ACT_CFG0"); + return retval; + } + + if (pm_act_cfg0 & PM_ACT_CFG0_EN_CLK_SPC) + return ERROR_OK; /* clock already enabled */ + + retval = target_write_u8(target, PM_ACT_CFG0, pm_act_cfg0 | PM_ACT_CFG0_EN_CLK_SPC); + if (retval != ERROR_OK) + LOG_ERROR("Cannot enable SPC clock"); + + return retval; +} + +static int psoc5lp_spc_write_opcode(struct target *target, uint8_t opcode) +{ + int retval; + + retval = target_write_u8(target, SPC_CPU_DATA, SPC_KEY1); + if (retval != ERROR_OK) + return retval; + retval = target_write_u8(target, SPC_CPU_DATA, SPC_KEY2 + opcode); + if (retval != ERROR_OK) + return retval; + retval = target_write_u8(target, SPC_CPU_DATA, opcode); + return retval; +} + +static void psoc5lp_spc_write_opcode_buffer(struct target *target, + uint8_t *buf, uint8_t opcode) +{ + buf[0] = SPC_KEY1; + buf[1] = SPC_KEY2 + opcode; + buf[2] = opcode; +} + +static int psoc5lp_spc_busy_wait_data(struct target *target) +{ + int64_t endtime; + uint8_t sr; + int retval; + + retval = target_read_u8(target, SPC_SR, &sr); /* dummy read */ + if (retval != ERROR_OK) + return retval; + + endtime = timeval_ms() + 1000; /* 1 second timeout */ + do { + alive_sleep(1); + retval = target_read_u8(target, SPC_SR, &sr); + if (retval != ERROR_OK) + return retval; + if (sr == SPC_SR_DATA_READY) + return ERROR_OK; + } while (timeval_ms() < endtime); + + return ERROR_FLASH_OPERATION_FAILED; +} + +static int psoc5lp_spc_busy_wait_idle(struct target *target) +{ + int64_t endtime; + uint8_t sr; + int retval; + + retval = target_read_u8(target, SPC_SR, &sr); /* dummy read */ + if (retval != ERROR_OK) + return retval; + + endtime = timeval_ms() + 1000; /* 1 second timeout */ + do { + alive_sleep(1); + retval = target_read_u8(target, SPC_SR, &sr); + if (retval != ERROR_OK) + return retval; + if (sr == SPC_SR_IDLE) + return ERROR_OK; + } while (timeval_ms() < endtime); + + return ERROR_FLASH_OPERATION_FAILED; +} + +static int psoc5lp_spc_load_byte(struct target *target, + uint8_t array_id, uint8_t offset, uint8_t value) +{ + int retval; + + retval = psoc5lp_spc_write_opcode(target, SPC_LOAD_BYTE); + if (retval != ERROR_OK) + return retval; + retval = target_write_u8(target, SPC_CPU_DATA, array_id); + if (retval != ERROR_OK) + return retval; + retval = target_write_u8(target, SPC_CPU_DATA, offset); + if (retval != ERROR_OK) + return retval; + retval = target_write_u8(target, SPC_CPU_DATA, value); + if (retval != ERROR_OK) + return retval; + + retval = psoc5lp_spc_busy_wait_idle(target); + if (retval != ERROR_OK) + return retval; + + return ERROR_OK; +} + +static int psoc5lp_spc_load_row(struct target *target, + uint8_t array_id, const uint8_t *data, unsigned row_size) +{ + unsigned i; + int retval; + + retval = psoc5lp_spc_write_opcode(target, SPC_LOAD_ROW); + if (retval != ERROR_OK) + return retval; + retval = target_write_u8(target, SPC_CPU_DATA, array_id); + if (retval != ERROR_OK) + return retval; + + for (i = 0; i < row_size; i++) { + retval = target_write_u8(target, SPC_CPU_DATA, data[i]); + if (retval != ERROR_OK) + return retval; + } + + retval = psoc5lp_spc_busy_wait_idle(target); + if (retval != ERROR_OK) + return retval; + + return ERROR_OK; +} + +static int psoc5lp_spc_read_byte(struct target *target, + uint8_t array_id, uint8_t offset, uint8_t *data) +{ + int retval; + + retval = psoc5lp_spc_write_opcode(target, SPC_READ_BYTE); + if (retval != ERROR_OK) + return retval; + retval = target_write_u8(target, SPC_CPU_DATA, array_id); + if (retval != ERROR_OK) + return retval; + retval = target_write_u8(target, SPC_CPU_DATA, offset); + if (retval != ERROR_OK) + return retval; + + retval = psoc5lp_spc_busy_wait_data(target); + if (retval != ERROR_OK) + return retval; + + retval = target_read_u8(target, SPC_CPU_DATA, data); + if (retval != ERROR_OK) + return retval; + + retval = psoc5lp_spc_busy_wait_idle(target); + if (retval != ERROR_OK) + return retval; + + return ERROR_OK; +} + +static int psoc5lp_spc_write_row(struct target *target, + uint8_t array_id, uint16_t row_id, const uint8_t *temp) +{ + int retval; + + retval = psoc5lp_spc_write_opcode(target, SPC_WRITE_ROW); + if (retval != ERROR_OK) + return retval; + retval = target_write_u8(target, SPC_CPU_DATA, array_id); + if (retval != ERROR_OK) + return retval; + retval = target_write_u8(target, SPC_CPU_DATA, row_id >> 8); + if (retval != ERROR_OK) + return retval; + retval = target_write_u8(target, SPC_CPU_DATA, row_id & 0xff); + if (retval != ERROR_OK) + return retval; + retval = target_write_u8(target, SPC_CPU_DATA, temp[0]); + if (retval != ERROR_OK) + return retval; + retval = target_write_u8(target, SPC_CPU_DATA, temp[1]); + if (retval != ERROR_OK) + return retval; + + retval = psoc5lp_spc_busy_wait_idle(target); + if (retval != ERROR_OK) + return retval; + + return ERROR_OK; +} + +static int psoc5lp_spc_write_user_nvl(struct target *target, + uint8_t array_id) +{ + int retval; + + retval = psoc5lp_spc_write_opcode(target, SPC_WRITE_USER_NVL); + if (retval != ERROR_OK) + return retval; + retval = target_write_u8(target, SPC_CPU_DATA, array_id); + if (retval != ERROR_OK) + return retval; + + retval = psoc5lp_spc_busy_wait_idle(target); + if (retval != ERROR_OK) + return retval; + + return ERROR_OK; +} + +static int psoc5lp_spc_erase_sector(struct target *target, + uint8_t array_id, uint8_t row_id) +{ + int retval; + + retval = psoc5lp_spc_write_opcode(target, SPC_ERASE_SECTOR); + if (retval != ERROR_OK) + return retval; + retval = target_write_u8(target, SPC_CPU_DATA, array_id); + if (retval != ERROR_OK) + return retval; + retval = target_write_u8(target, SPC_CPU_DATA, row_id); + if (retval != ERROR_OK) + return retval; + + retval = psoc5lp_spc_busy_wait_idle(target); + if (retval != ERROR_OK) + return retval; + + return ERROR_OK; +} + +static int psoc5lp_spc_erase_all(struct target *target) +{ + int retval; + + retval = psoc5lp_spc_write_opcode(target, SPC_ERASE_ALL); + if (retval != ERROR_OK) + return retval; + + retval = psoc5lp_spc_busy_wait_idle(target); + if (retval != ERROR_OK) + return retval; + + return ERROR_OK; +} + +static int psoc5lp_spc_read_hidden_row(struct target *target, + uint8_t array_id, uint8_t row_id, uint8_t *data) +{ + int i, retval; + + retval = psoc5lp_spc_write_opcode(target, SPC_READ_HIDDEN_ROW); + if (retval != ERROR_OK) + return retval; + retval = target_write_u8(target, SPC_CPU_DATA, array_id); + if (retval != ERROR_OK) + return retval; + retval = target_write_u8(target, SPC_CPU_DATA, row_id); + if (retval != ERROR_OK) + return retval; + + retval = psoc5lp_spc_busy_wait_data(target); + if (retval != ERROR_OK) + return retval; + + for (i = 0; i < ROW_SIZE; i++) { + retval = target_read_u8(target, SPC_CPU_DATA, &data[i]); + if (retval != ERROR_OK) + return retval; + } + + retval = psoc5lp_spc_busy_wait_idle(target); + if (retval != ERROR_OK) + return retval; + + return ERROR_OK; +} + +static int psoc5lp_spc_get_temp(struct target *target, uint8_t samples, + uint8_t *data) +{ + int retval; + + retval = psoc5lp_spc_write_opcode(target, SPC_GET_TEMP); + if (retval != ERROR_OK) + return retval; + retval = target_write_u8(target, SPC_CPU_DATA, samples); + if (retval != ERROR_OK) + return retval; + + retval = psoc5lp_spc_busy_wait_data(target); + if (retval != ERROR_OK) + return retval; + + retval = target_read_u8(target, SPC_CPU_DATA, &data[0]); + if (retval != ERROR_OK) + return retval; + retval = target_read_u8(target, SPC_CPU_DATA, &data[1]); + if (retval != ERROR_OK) + return retval; + + retval = psoc5lp_spc_busy_wait_idle(target); + if (retval != ERROR_OK) + return retval; + + return ERROR_OK; +} + +static int psoc5lp_spc_read_volatile_byte(struct target *target, + uint8_t array_id, uint8_t offset, uint8_t *data) +{ + int retval; + + retval = psoc5lp_spc_write_opcode(target, SPC_READ_VOLATILE_BYTE); + if (retval != ERROR_OK) + return retval; + retval = target_write_u8(target, SPC_CPU_DATA, array_id); + if (retval != ERROR_OK) + return retval; + retval = target_write_u8(target, SPC_CPU_DATA, offset); + if (retval != ERROR_OK) + return retval; + + retval = psoc5lp_spc_busy_wait_data(target); + if (retval != ERROR_OK) + return retval; + + retval = target_read_u8(target, SPC_CPU_DATA, data); + if (retval != ERROR_OK) + return retval; + + retval = psoc5lp_spc_busy_wait_idle(target); + if (retval != ERROR_OK) + return retval; + + return ERROR_OK; +} + +/* + * NV Latch + */ + +struct psoc5lp_nvl_flash_bank { + bool probed; + const struct psoc5lp_device *device; +}; + +static int psoc5lp_nvl_read(struct flash_bank *bank, + uint8_t *buffer, uint32_t offset, uint32_t count) +{ + int retval; + + retval = psoc5lp_spc_enable_clock(bank->target); + if (retval != ERROR_OK) + return retval; + + while (count > 0) { + retval = psoc5lp_spc_read_byte(bank->target, + SPC_ARRAY_NVL_USER, offset, buffer); + if (retval != ERROR_OK) + return retval; + buffer++; + offset++; + count--; + } + + return ERROR_OK; +} + +static int psoc5lp_nvl_erase(struct flash_bank *bank, int first, int last) +{ + LOG_WARNING("There is no erase operation for NV Latches"); + return ERROR_FLASH_OPER_UNSUPPORTED; +} + +static int psoc5lp_nvl_erase_check(struct flash_bank *bank) +{ + int i; + + for (i = 0; i < bank->num_sectors; i++) + bank->sectors[i].is_erased = 0; + + return ERROR_OK; +} + +static int psoc5lp_nvl_write(struct flash_bank *bank, + const uint8_t *buffer, uint32_t offset, uint32_t byte_count) +{ + struct target *target = bank->target; + uint8_t *current_data, val; + bool write_required = false, pullup_needed = false, ecc_changed = false; + uint32_t i; + int retval; + + if (offset != 0 || byte_count != bank->size) { + LOG_ERROR("NVL can only be written in whole"); + return ERROR_FLASH_OPER_UNSUPPORTED; + } + + current_data = calloc(1, bank->size); + if (!current_data) + return ERROR_FAIL; + retval = psoc5lp_nvl_read(bank, current_data, offset, byte_count); + if (retval != ERROR_OK) { + free(current_data); + return retval; + } + for (i = offset; i < byte_count; i++) { + if (current_data[i] != buffer[i]) { + write_required = true; + break; + } + } + if (((buffer[2] & 0x80) == 0x80) && ((current_data[0] & 0x0C) != 0x08)) + pullup_needed = true; + if (((buffer[3] ^ current_data[3]) & 0x08) == 0x08) + ecc_changed = true; + free(current_data); + + if (!write_required) { + LOG_INFO("Unchanged, skipping NVL write"); + return ERROR_OK; + } + if (pullup_needed) { + retval = target_read_u8(target, PRT1_PC2, &val); + if (retval != ERROR_OK) + return retval; + val &= 0xF0; + val |= 0x05; + retval = target_write_u8(target, PRT1_PC2, val); + if (retval != ERROR_OK) + return retval; + } + + for (i = offset; i < byte_count; i++) { + retval = psoc5lp_spc_load_byte(target, + SPC_ARRAY_NVL_USER, i, buffer[i]); + if (retval != ERROR_OK) + return retval; + + retval = psoc5lp_spc_read_volatile_byte(target, + SPC_ARRAY_NVL_USER, i, &val); + if (retval != ERROR_OK) + return retval; + if (val != buffer[i]) { + LOG_ERROR("Failed to load NVL byte %" PRIu32 ": " + "expected 0x%02" PRIx8 ", read 0x%02" PRIx8, + i, buffer[i], val); + return ERROR_FLASH_OPERATION_FAILED; + } + } + + retval = psoc5lp_spc_write_user_nvl(target, SPC_ARRAY_NVL_USER); + if (retval != ERROR_OK) + return retval; + + if (ecc_changed) { + retval = target_call_reset_callbacks(target, RESET_INIT); + if (retval != ERROR_OK) + LOG_WARNING("Reset failed after enabling or disabling ECC"); + } + + return ERROR_OK; +} + +static int psoc5lp_nvl_protect_check(struct flash_bank *bank) +{ + int i; + + for (i = 0; i < bank->num_sectors; i++) + bank->sectors[i].is_protected = -1; + + return ERROR_OK; +} + +static int psoc5lp_nvl_get_info_command(struct flash_bank *bank, + char *buf, int buf_size) +{ + struct psoc5lp_nvl_flash_bank *psoc_nvl_bank = bank->driver_priv; + char part_number[PART_NUMBER_LEN]; + + psoc5lp_get_part_number(psoc_nvl_bank->device, part_number); + + snprintf(buf, buf_size, "%s", part_number); + + return ERROR_OK; +} + +static int psoc5lp_nvl_probe(struct flash_bank *bank) +{ + struct psoc5lp_nvl_flash_bank *psoc_nvl_bank = bank->driver_priv; + int retval; + + if (psoc_nvl_bank->probed) + return ERROR_OK; + + if (bank->target->state != TARGET_HALTED) { + LOG_ERROR("Target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + + retval = psoc5lp_find_device(bank->target, &psoc_nvl_bank->device); + if (retval != ERROR_OK) + return retval; + + bank->base = NVL_META_BASE; + bank->size = 4; + bank->num_sectors = 1; + bank->sectors = calloc(bank->num_sectors, + sizeof(struct flash_sector)); + bank->sectors[0].offset = 0; + bank->sectors[0].size = 4; + bank->sectors[0].is_erased = -1; + bank->sectors[0].is_protected = -1; + + psoc_nvl_bank->probed = true; + + return ERROR_OK; +} + +static int psoc5lp_nvl_auto_probe(struct flash_bank *bank) +{ + struct psoc5lp_nvl_flash_bank *psoc_nvl_bank = bank->driver_priv; + + if (psoc_nvl_bank->probed) + return ERROR_OK; + + return psoc5lp_nvl_probe(bank); +} + +FLASH_BANK_COMMAND_HANDLER(psoc5lp_nvl_flash_bank_command) +{ + struct psoc5lp_nvl_flash_bank *psoc_nvl_bank; + + psoc_nvl_bank = malloc(sizeof(struct psoc5lp_nvl_flash_bank)); + if (!psoc_nvl_bank) + return ERROR_FLASH_OPERATION_FAILED; + + psoc_nvl_bank->probed = false; + + bank->driver_priv = psoc_nvl_bank; + + return ERROR_OK; +} + +static const struct command_registration psoc5lp_nvl_exec_command_handlers[] = { + COMMAND_REGISTRATION_DONE +}; + +static const struct command_registration psoc5lp_nvl_command_handlers[] = { + { + .name = "psoc5lp_nvl", + .mode = COMMAND_ANY, + .help = "PSoC 5LP NV Latch command group", + .usage = "", + .chain = psoc5lp_nvl_exec_command_handlers, + }, + COMMAND_REGISTRATION_DONE +}; + +struct flash_driver psoc5lp_nvl_flash = { + .name = "psoc5lp_nvl", + .commands = psoc5lp_nvl_command_handlers, + .flash_bank_command = psoc5lp_nvl_flash_bank_command, + .info = psoc5lp_nvl_get_info_command, + .probe = psoc5lp_nvl_probe, + .auto_probe = psoc5lp_nvl_auto_probe, + .protect_check = psoc5lp_nvl_protect_check, + .read = psoc5lp_nvl_read, + .erase = psoc5lp_nvl_erase, + .erase_check = psoc5lp_nvl_erase_check, + .write = psoc5lp_nvl_write, + .free_driver_priv = default_flash_free_driver_priv, +}; + +/* + * EEPROM + */ + +struct psoc5lp_eeprom_flash_bank { + bool probed; + const struct psoc5lp_device *device; +}; + +static int psoc5lp_eeprom_erase(struct flash_bank *bank, int first, int last) +{ + int i, retval; + + for (i = first; i <= last; i++) { + retval = psoc5lp_spc_erase_sector(bank->target, + SPC_ARRAY_EEPROM, i); + if (retval != ERROR_OK) + return retval; + } + + return ERROR_OK; +} + +static int psoc5lp_eeprom_write(struct flash_bank *bank, + const uint8_t *buffer, uint32_t offset, uint32_t byte_count) +{ + struct target *target = bank->target; + uint8_t temp[2]; + unsigned row; + int retval; + + if (offset % EEPROM_ROW_SIZE != 0) { + LOG_ERROR("Writes must be row-aligned, got offset 0x%08" PRIx32, + offset); + return ERROR_FLASH_DST_BREAKS_ALIGNMENT; + } + + retval = psoc5lp_spc_get_temp(target, 3, temp); + if (retval != ERROR_OK) { + LOG_ERROR("Unable to read Die temperature"); + return retval; + } + LOG_DEBUG("Get_Temp: sign 0x%02" PRIx8 ", magnitude 0x%02" PRIx8, + temp[0], temp[1]); + + for (row = offset / EEPROM_ROW_SIZE; byte_count >= EEPROM_ROW_SIZE; row++) { + retval = psoc5lp_spc_load_row(target, SPC_ARRAY_EEPROM, + buffer, EEPROM_ROW_SIZE); + if (retval != ERROR_OK) + return retval; + + retval = psoc5lp_spc_write_row(target, SPC_ARRAY_EEPROM, + row, temp); + if (retval != ERROR_OK) + return retval; + + buffer += EEPROM_ROW_SIZE; + byte_count -= EEPROM_ROW_SIZE; + offset += EEPROM_ROW_SIZE; + } + if (byte_count > 0) { + uint8_t buf[EEPROM_ROW_SIZE]; + + memcpy(buf, buffer, byte_count); + memset(buf + byte_count, bank->default_padded_value, + EEPROM_ROW_SIZE - byte_count); + + LOG_DEBUG("Padding %d bytes", EEPROM_ROW_SIZE - byte_count); + retval = psoc5lp_spc_load_row(target, SPC_ARRAY_EEPROM, + buf, EEPROM_ROW_SIZE); + if (retval != ERROR_OK) + return retval; + + retval = psoc5lp_spc_write_row(target, SPC_ARRAY_EEPROM, + row, temp); + if (retval != ERROR_OK) + return retval; + } + + return ERROR_OK; +} + +static int psoc5lp_eeprom_protect_check(struct flash_bank *bank) +{ + int i; + + for (i = 0; i < bank->num_sectors; i++) + bank->sectors[i].is_protected = -1; + + return ERROR_OK; +} + +static int psoc5lp_eeprom_get_info_command(struct flash_bank *bank, char *buf, int buf_size) +{ + struct psoc5lp_eeprom_flash_bank *psoc_eeprom_bank = bank->driver_priv; + char part_number[PART_NUMBER_LEN]; + + psoc5lp_get_part_number(psoc_eeprom_bank->device, part_number); + + snprintf(buf, buf_size, "%s", part_number); + + return ERROR_OK; +} + +static int psoc5lp_eeprom_probe(struct flash_bank *bank) +{ + struct psoc5lp_eeprom_flash_bank *psoc_eeprom_bank = bank->driver_priv; + uint32_t flash_addr = bank->base; + uint32_t val; + int i, retval; + + if (psoc_eeprom_bank->probed) + return ERROR_OK; + + if (bank->target->state != TARGET_HALTED) { + LOG_ERROR("Target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + + retval = psoc5lp_find_device(bank->target, &psoc_eeprom_bank->device); + if (retval != ERROR_OK) + return retval; + + retval = target_read_u32(bank->target, PM_ACT_CFG12, &val); + if (retval != ERROR_OK) + return retval; + if (!(val & PM_ACT_CFG12_EN_EE)) { + val |= PM_ACT_CFG12_EN_EE; + retval = target_write_u32(bank->target, PM_ACT_CFG12, val); + if (retval != ERROR_OK) + return retval; + } + + bank->size = psoc_eeprom_bank->device->eeprom_kb * 1024; + bank->num_sectors = DIV_ROUND_UP(bank->size, EEPROM_SECTOR_SIZE); + bank->sectors = calloc(bank->num_sectors, + sizeof(struct flash_sector)); + for (i = 0; i < bank->num_sectors; i++) { + bank->sectors[i].size = EEPROM_SECTOR_SIZE; + bank->sectors[i].offset = flash_addr - bank->base; + bank->sectors[i].is_erased = -1; + bank->sectors[i].is_protected = -1; + + flash_addr += bank->sectors[i].size; + } + + bank->default_padded_value = bank->erased_value = 0x00; + + psoc_eeprom_bank->probed = true; + + return ERROR_OK; +} + +static int psoc5lp_eeprom_auto_probe(struct flash_bank *bank) +{ + struct psoc5lp_eeprom_flash_bank *psoc_eeprom_bank = bank->driver_priv; + + if (psoc_eeprom_bank->probed) + return ERROR_OK; + + return psoc5lp_eeprom_probe(bank); +} + +FLASH_BANK_COMMAND_HANDLER(psoc5lp_eeprom_flash_bank_command) +{ + struct psoc5lp_eeprom_flash_bank *psoc_eeprom_bank; + + psoc_eeprom_bank = malloc(sizeof(struct psoc5lp_eeprom_flash_bank)); + if (!psoc_eeprom_bank) + return ERROR_FLASH_OPERATION_FAILED; + + psoc_eeprom_bank->probed = false; + psoc_eeprom_bank->device = NULL; + + bank->driver_priv = psoc_eeprom_bank; + + return ERROR_OK; +} + +static const struct command_registration psoc5lp_eeprom_exec_command_handlers[] = { + COMMAND_REGISTRATION_DONE +}; + +static const struct command_registration psoc5lp_eeprom_command_handlers[] = { + { + .name = "psoc5lp_eeprom", + .mode = COMMAND_ANY, + .help = "PSoC 5LP EEPROM command group", + .usage = "", + .chain = psoc5lp_eeprom_exec_command_handlers, + }, + COMMAND_REGISTRATION_DONE +}; + +struct flash_driver psoc5lp_eeprom_flash = { + .name = "psoc5lp_eeprom", + .commands = psoc5lp_eeprom_command_handlers, + .flash_bank_command = psoc5lp_eeprom_flash_bank_command, + .info = psoc5lp_eeprom_get_info_command, + .probe = psoc5lp_eeprom_probe, + .auto_probe = psoc5lp_eeprom_auto_probe, + .protect_check = psoc5lp_eeprom_protect_check, + .read = default_flash_read, + .erase = psoc5lp_eeprom_erase, + .erase_check = default_flash_blank_check, + .write = psoc5lp_eeprom_write, + .free_driver_priv = default_flash_free_driver_priv, +}; + +/* + * Program Flash + */ + +struct psoc5lp_flash_bank { + bool probed; + const struct psoc5lp_device *device; + bool ecc_enabled; + /* If ecc is disabled, num_sectors counts both std and ecc sectors. + * If ecc is enabled, num_sectors indicates just the number of std sectors. + * However ecc sector descriptors bank->sector[num_sectors..2*num_sectors-1] + * are used for driver private flash operations */ +}; + +static int psoc5lp_erase(struct flash_bank *bank, int first, int last) +{ + struct psoc5lp_flash_bank *psoc_bank = bank->driver_priv; + int i, retval; + + if (!psoc_bank->ecc_enabled) { + /* Silently avoid erasing sectors twice */ + if (last >= first + bank->num_sectors / 2) { + LOG_DEBUG("Skipping duplicate erase of sectors %d to %d", + first + bank->num_sectors / 2, last); + last = first + (bank->num_sectors / 2) - 1; + } + /* Check for any remaining ECC sectors */ + if (last >= bank->num_sectors / 2) { + LOG_WARNING("Skipping erase of ECC region sectors %d to %d", + bank->num_sectors / 2, last); + last = (bank->num_sectors / 2) - 1; + } + } + + for (i = first; i <= last; i++) { + retval = psoc5lp_spc_erase_sector(bank->target, + i / SECTORS_PER_BLOCK, i % SECTORS_PER_BLOCK); + if (retval != ERROR_OK) + return retval; + } + + return ERROR_OK; +} + +/* Derived from core.c:default_flash_blank_check() */ +static int psoc5lp_erase_check(struct flash_bank *bank) +{ + struct psoc5lp_flash_bank *psoc_bank = bank->driver_priv; + struct target *target = bank->target; + int i, retval; + + if (target->state != TARGET_HALTED) { + LOG_ERROR("Target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + + int num_sectors = bank->num_sectors; + if (psoc_bank->ecc_enabled) + num_sectors *= 2; /* count both std and ecc sector always */ + + struct target_memory_check_block *block_array; + block_array = malloc(num_sectors * sizeof(struct target_memory_check_block)); + if (block_array == NULL) + return ERROR_FAIL; + + for (i = 0; i < num_sectors; i++) { + block_array[i].address = bank->base + bank->sectors[i].offset; + block_array[i].size = bank->sectors[i].size; + block_array[i].result = UINT32_MAX; /* erase state unknown */ + } + + bool fast_check = true; + for (i = 0; i < num_sectors; ) { + retval = armv7m_blank_check_memory(target, + block_array + i, num_sectors - i, + bank->erased_value); + if (retval < 1) { + /* Run slow fallback if the first run gives no result + * otherwise use possibly incomplete results */ + if (i == 0) + fast_check = false; + break; + } + i += retval; /* add number of blocks done this round */ + } + + if (fast_check) { + if (psoc_bank->ecc_enabled) { + for (i = 0; i < bank->num_sectors; i++) + bank->sectors[i].is_erased = + (block_array[i].result != 1) + ? block_array[i].result + : block_array[i + bank->num_sectors].result; + /* if std sector is erased, use status of ecc sector */ + } else { + for (i = 0; i < num_sectors; i++) + bank->sectors[i].is_erased = block_array[i].result; + } + retval = ERROR_OK; + } else { + LOG_ERROR("Can't run erase check - add working memory"); + retval = ERROR_FAIL; + } + free(block_array); + + return retval; +} + +static int psoc5lp_write(struct flash_bank *bank, const uint8_t *buffer, + uint32_t offset, uint32_t byte_count) +{ + struct psoc5lp_flash_bank *psoc_bank = bank->driver_priv; + struct target *target = bank->target; + struct working_area *code_area, *even_row_area, *odd_row_area; + uint32_t row_size; + uint8_t temp[2], buf[12], ecc_bytes[ROW_ECC_SIZE]; + unsigned array_id, row; + int i, retval; + + if (offset + byte_count > bank->size) { + LOG_ERROR("Writing to ECC not supported"); + return ERROR_FLASH_DST_OUT_OF_BANK; + } + + if (offset % ROW_SIZE != 0) { + LOG_ERROR("Writes must be row-aligned, got offset 0x%08" PRIx32, + offset); + return ERROR_FLASH_DST_BREAKS_ALIGNMENT; + } + + row_size = ROW_SIZE; + if (!psoc_bank->ecc_enabled) { + row_size += ROW_ECC_SIZE; + memset(ecc_bytes, bank->default_padded_value, ROW_ECC_SIZE); + } + + retval = psoc5lp_spc_get_temp(target, 3, temp); + if (retval != ERROR_OK) { + LOG_ERROR("Unable to read Die temperature"); + return retval; + } + LOG_DEBUG("Get_Temp: sign 0x%02" PRIx8 ", magnitude 0x%02" PRIx8, + temp[0], temp[1]); + + assert(target_get_working_area_avail(target) == target->working_area_size); + retval = target_alloc_working_area(target, + target_get_working_area_avail(target) / 2, &code_area); + if (retval != ERROR_OK) { + LOG_ERROR("Could not allocate working area for program SRAM"); + return retval; + } + assert(code_area->address < 0x20000000); + + retval = target_alloc_working_area(target, + SPC_OPCODE_LEN + 1 + row_size + 3 + SPC_OPCODE_LEN + 6, + &even_row_area); + if (retval != ERROR_OK) { + LOG_ERROR("Could not allocate working area for even row"); + goto err_alloc_even; + } + assert(even_row_area->address >= 0x20000000); + + retval = target_alloc_working_area(target, even_row_area->size, + &odd_row_area); + if (retval != ERROR_OK) { + LOG_ERROR("Could not allocate working area for odd row"); + goto err_alloc_odd; + } + assert(odd_row_area->address >= 0x20000000); + + for (array_id = offset / BLOCK_SIZE; byte_count > 0; array_id++) { + for (row = (offset / ROW_SIZE) % ROWS_PER_BLOCK; + row < ROWS_PER_BLOCK && byte_count > 0; row++) { + bool even_row = (row % 2 == 0); + struct working_area *data_area = even_row ? even_row_area : odd_row_area; + unsigned len = MIN(ROW_SIZE, byte_count); + + LOG_DEBUG("Writing load command for array %u row %u at 0x%08" TARGET_PRIxADDR, + array_id, row, data_area->address); + + psoc5lp_spc_write_opcode_buffer(target, buf, SPC_LOAD_ROW); + buf[SPC_OPCODE_LEN] = array_id; + retval = target_write_buffer(target, data_area->address, 4, buf); + if (retval != ERROR_OK) + goto err_write; + + retval = target_write_buffer(target, + data_area->address + SPC_OPCODE_LEN + 1, + len, buffer); + if (retval != ERROR_OK) + goto err_write; + buffer += len; + byte_count -= len; + offset += len; + + if (len < ROW_SIZE) { + uint8_t padding[ROW_SIZE]; + + memset(padding, bank->default_padded_value, ROW_SIZE); + + LOG_DEBUG("Padding %d bytes", ROW_SIZE - len); + retval = target_write_buffer(target, + data_area->address + SPC_OPCODE_LEN + 1 + len, + ROW_SIZE - len, padding); + if (retval != ERROR_OK) + goto err_write; + } + + if (!psoc_bank->ecc_enabled) { + retval = target_write_buffer(target, + data_area->address + SPC_OPCODE_LEN + 1 + ROW_SIZE, + sizeof(ecc_bytes), ecc_bytes); + if (retval != ERROR_OK) + goto err_write; + } + + for (i = 0; i < 3; i++) + buf[i] = 0x00; /* 3 NOPs for short delay */ + psoc5lp_spc_write_opcode_buffer(target, buf + 3, SPC_PRG_ROW); + buf[3 + SPC_OPCODE_LEN] = array_id; + buf[3 + SPC_OPCODE_LEN + 1] = row >> 8; + buf[3 + SPC_OPCODE_LEN + 2] = row & 0xff; + memcpy(buf + 3 + SPC_OPCODE_LEN + 3, temp, 2); + buf[3 + SPC_OPCODE_LEN + 5] = 0x00; /* padding */ + retval = target_write_buffer(target, + data_area->address + SPC_OPCODE_LEN + 1 + row_size, + 12, buf); + if (retval != ERROR_OK) + goto err_write; + + retval = target_write_u32(target, + even_row ? PHUB_CH0_BASIC_STATUS : PHUB_CH1_BASIC_STATUS, + (even_row ? 0 : 1) << 8); + if (retval != ERROR_OK) + goto err_dma; + + retval = target_write_u32(target, + even_row ? PHUB_CH0_BASIC_CFG : PHUB_CH1_BASIC_CFG, + PHUB_CHx_BASIC_CFG_WORK_SEP | PHUB_CHx_BASIC_CFG_EN); + if (retval != ERROR_OK) + goto err_dma; + + retval = target_write_u32(target, + even_row ? PHUB_CFGMEM0_CFG0 : PHUB_CFGMEM1_CFG0, + PHUB_CFGMEMx_CFG0); + if (retval != ERROR_OK) + goto err_dma; + + retval = target_write_u32(target, + even_row ? PHUB_CFGMEM0_CFG1 : PHUB_CFGMEM1_CFG1, + ((SPC_CPU_DATA >> 16) << 16) | (data_area->address >> 16)); + if (retval != ERROR_OK) + goto err_dma; + + retval = target_write_u32(target, + even_row ? PHUB_TDMEM0_ORIG_TD0 : PHUB_TDMEM1_ORIG_TD0, + PHUB_TDMEMx_ORIG_TD0_INC_SRC_ADDR | + PHUB_TDMEMx_ORIG_TD0_NEXT_TD_PTR_LAST | + ((SPC_OPCODE_LEN + 1 + row_size + 3 + SPC_OPCODE_LEN + 5) & 0xfff)); + if (retval != ERROR_OK) + goto err_dma; + + retval = target_write_u32(target, + even_row ? PHUB_TDMEM0_ORIG_TD1 : PHUB_TDMEM1_ORIG_TD1, + ((SPC_CPU_DATA & 0xffff) << 16) | (data_area->address & 0xffff)); + if (retval != ERROR_OK) + goto err_dma; + + retval = psoc5lp_spc_busy_wait_idle(target); + if (retval != ERROR_OK) + goto err_idle; + + retval = target_write_u32(target, + even_row ? PHUB_CH0_ACTION : PHUB_CH1_ACTION, + PHUB_CHx_ACTION_CPU_REQ); + if (retval != ERROR_OK) + goto err_dma_action; + } + } + + retval = psoc5lp_spc_busy_wait_idle(target); + +err_dma_action: +err_idle: +err_dma: +err_write: + target_free_working_area(target, odd_row_area); +err_alloc_odd: + target_free_working_area(target, even_row_area); +err_alloc_even: + target_free_working_area(target, code_area); + + return retval; +} + +static int psoc5lp_protect_check(struct flash_bank *bank) +{ + struct psoc5lp_flash_bank *psoc_bank = bank->driver_priv; + uint8_t row_data[ROW_SIZE]; + const unsigned protection_bytes_per_sector = ROWS_PER_SECTOR * 2 / 8; + unsigned i, j, k, num_sectors; + int retval; + + if (bank->target->state != TARGET_HALTED) { + LOG_ERROR("Target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + + for (i = 0; i < DIV_ROUND_UP(bank->size, BLOCK_SIZE); i++) { + retval = psoc5lp_spc_read_hidden_row(bank->target, i, + SPC_ROW_PROTECTION, row_data); + if (retval != ERROR_OK) + return retval; + + /* Last flash array may have less rows, but in practice full sectors. */ + if (i == bank->size / BLOCK_SIZE) + num_sectors = (bank->size % BLOCK_SIZE) / SECTOR_SIZE; + else + num_sectors = SECTORS_PER_BLOCK; + + for (j = 0; j < num_sectors; j++) { + int sector_nr = i * SECTORS_PER_BLOCK + j; + struct flash_sector *sector = &bank->sectors[sector_nr]; + struct flash_sector *ecc_sector; + + if (psoc_bank->ecc_enabled) + ecc_sector = &bank->sectors[bank->num_sectors + sector_nr]; + else + ecc_sector = &bank->sectors[bank->num_sectors / 2 + sector_nr]; + + sector->is_protected = ecc_sector->is_protected = 0; + for (k = protection_bytes_per_sector * j; + k < protection_bytes_per_sector * (j + 1); k++) { + assert(k < protection_bytes_per_sector * SECTORS_PER_BLOCK); + LOG_DEBUG("row[%u][%02u] = 0x%02" PRIx8, i, k, row_data[k]); + if (row_data[k] != 0x00) { + sector->is_protected = ecc_sector->is_protected = 1; + break; + } + } + } + } + + return ERROR_OK; +} + +static int psoc5lp_get_info_command(struct flash_bank *bank, char *buf, int buf_size) +{ + struct psoc5lp_flash_bank *psoc_bank = bank->driver_priv; + char part_number[PART_NUMBER_LEN]; + const char *ecc; + + psoc5lp_get_part_number(psoc_bank->device, part_number); + ecc = psoc_bank->ecc_enabled ? "ECC enabled" : "ECC disabled"; + + snprintf(buf, buf_size, "%s %s", part_number, ecc); + + return ERROR_OK; +} + +static int psoc5lp_probe(struct flash_bank *bank) +{ + struct target *target = bank->target; + struct psoc5lp_flash_bank *psoc_bank = bank->driver_priv; + uint32_t flash_addr = bank->base; + uint8_t nvl[4], temp[2]; + int i, retval; + + if (target->state != TARGET_HALTED) { + LOG_ERROR("Target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + + if (!psoc_bank->device) { + retval = psoc5lp_find_device(target, &psoc_bank->device); + if (retval != ERROR_OK) + return retval; + + bank->size = psoc_bank->device->flash_kb * 1024; + } + + bank->num_sectors = DIV_ROUND_UP(bank->size, SECTOR_SIZE); + + if (!psoc_bank->probed) { + retval = psoc5lp_spc_enable_clock(target); + if (retval != ERROR_OK) + return retval; + + /* First values read are inaccurate, so do it once now. */ + retval = psoc5lp_spc_get_temp(target, 3, temp); + if (retval != ERROR_OK) { + LOG_ERROR("Unable to read Die temperature"); + return retval; + } + + bank->sectors = calloc(bank->num_sectors * 2, + sizeof(struct flash_sector)); + for (i = 0; i < bank->num_sectors; i++) { + bank->sectors[i].size = SECTOR_SIZE; + bank->sectors[i].offset = flash_addr - bank->base; + bank->sectors[i].is_erased = -1; + bank->sectors[i].is_protected = -1; + + flash_addr += bank->sectors[i].size; + } + flash_addr = 0x48000000; + for (i = bank->num_sectors; i < bank->num_sectors * 2; i++) { + bank->sectors[i].size = ROWS_PER_SECTOR * ROW_ECC_SIZE; + bank->sectors[i].offset = flash_addr - bank->base; + bank->sectors[i].is_erased = -1; + bank->sectors[i].is_protected = -1; + + flash_addr += bank->sectors[i].size; + } + + bank->default_padded_value = bank->erased_value = 0x00; + + psoc_bank->probed = true; + } + + retval = psoc5lp_spc_read_byte(target, SPC_ARRAY_NVL_USER, 3, &nvl[3]); + if (retval != ERROR_OK) + return retval; + LOG_DEBUG("NVL[%d] = 0x%02" PRIx8, 3, nvl[3]); + psoc_bank->ecc_enabled = nvl[3] & NVL_3_ECCEN; + + if (!psoc_bank->ecc_enabled) + bank->num_sectors *= 2; + + return ERROR_OK; +} + +static int psoc5lp_auto_probe(struct flash_bank *bank) +{ + return psoc5lp_probe(bank); +} + +COMMAND_HANDLER(psoc5lp_handle_mass_erase_command) +{ + struct flash_bank *bank; + int retval; + + if (CMD_ARGC < 1) + return ERROR_COMMAND_SYNTAX_ERROR; + + retval = CALL_COMMAND_HANDLER(flash_command_get_bank, 0, &bank); + if (retval != ERROR_OK) + return retval; + + retval = psoc5lp_spc_erase_all(bank->target); + if (retval == ERROR_OK) + command_print(CMD_CTX, "PSoC 5LP erase succeeded"); + else + command_print(CMD_CTX, "PSoC 5LP erase failed"); + + return retval; +} + +FLASH_BANK_COMMAND_HANDLER(psoc5lp_flash_bank_command) +{ + struct psoc5lp_flash_bank *psoc_bank; + + psoc_bank = malloc(sizeof(struct psoc5lp_flash_bank)); + if (!psoc_bank) + return ERROR_FLASH_OPERATION_FAILED; + + psoc_bank->probed = false; + psoc_bank->device = NULL; + + bank->driver_priv = psoc_bank; + + return ERROR_OK; +} + +static const struct command_registration psoc5lp_exec_command_handlers[] = { + { + .name = "mass_erase", + .handler = psoc5lp_handle_mass_erase_command, + .mode = COMMAND_EXEC, + .usage = "bank_id", + .help = "Erase all flash data and ECC/configuration bytes, " + "all flash protection rows, " + "and all row latches in all flash arrays on the device.", + }, + COMMAND_REGISTRATION_DONE +}; + +static const struct command_registration psoc5lp_command_handlers[] = { + { + .name = "psoc5lp", + .mode = COMMAND_ANY, + .help = "PSoC 5LP flash command group", + .usage = "", + .chain = psoc5lp_exec_command_handlers, + }, + COMMAND_REGISTRATION_DONE +}; + +struct flash_driver psoc5lp_flash = { + .name = "psoc5lp", + .commands = psoc5lp_command_handlers, + .flash_bank_command = psoc5lp_flash_bank_command, + .info = psoc5lp_get_info_command, + .probe = psoc5lp_probe, + .auto_probe = psoc5lp_auto_probe, + .protect_check = psoc5lp_protect_check, + .read = default_flash_read, + .erase = psoc5lp_erase, + .erase_check = psoc5lp_erase_check, + .write = psoc5lp_write, + .free_driver_priv = default_flash_free_driver_priv, +}; diff --git a/src/flash/nor/spi.c b/src/flash/nor/spi.c index b255edb..6ac253d 100644 --- a/src/flash/nor/spi.c +++ b/src/flash/nor/spi.c @@ -54,6 +54,7 @@ const struct flash_device flash_devices[] = { FLASH_ID("sp s25fl164k", 0xd8, 0xc7, 0x00174001, 0x100, 0x10000, 0x800000), FLASH_ID("sp s25fl128", 0xd8, 0xc7, 0x00182001, 0x100, 0x10000, 0x1000000), FLASH_ID("sp s25fl256", 0xd8, 0xc7, 0x00190201, 0x100, 0x10000, 0x2000000), + FLASH_ID("cy s25fl256", 0xd8, 0xc7, 0x00196001, 0x100, 0x10000, 0x2000000), FLASH_ID("atmel 25f512", 0x52, 0xc7, 0x0065001f, 0x80, 0x8000, 0x10000), FLASH_ID("atmel 25f1024", 0x52, 0x62, 0x0060001f, 0x100, 0x8000, 0x20000), FLASH_ID("atmel 25f2048", 0x52, 0x62, 0x0063001f, 0x100, 0x10000, 0x40000), diff --git a/src/flash/nor/stm32f1x.c b/src/flash/nor/stm32f1x.c index 015988a..faada9a 100644 --- a/src/flash/nor/stm32f1x.c +++ b/src/flash/nor/stm32f1x.c @@ -585,8 +585,10 @@ static int stm32x_write_block(struct flash_bank *bank, const uint8_t *buffer, retval = target_write_buffer(target, write_algorithm->address, sizeof(stm32x_flash_write_code), stm32x_flash_write_code); - if (retval != ERROR_OK) + if (retval != ERROR_OK) { + target_free_working_area(target, write_algorithm); return retval; + } /* memory buffer */ while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) { diff --git a/src/flash/nor/stm32f2x.c b/src/flash/nor/stm32f2x.c index 8013e58..413d04d 100644 --- a/src/flash/nor/stm32f2x.c +++ b/src/flash/nor/stm32f2x.c @@ -252,6 +252,8 @@ static int stm32x_wait_status_busy(struct flash_bank *bank, int timeout) /* Clear but report errors */ if (status & FLASH_ERROR) { + if (retval == ERROR_OK) + retval = ERROR_FAIL; /* If this operation fails, we ignore it and report the original * retval */ @@ -597,8 +599,10 @@ static int stm32x_write_block(struct flash_bank *bank, const uint8_t *buffer, retval = target_write_buffer(target, write_algorithm->address, sizeof(stm32x_flash_write_code), stm32x_flash_write_code); - if (retval != ERROR_OK) + if (retval != ERROR_OK) { + target_free_working_area(target, write_algorithm); return retval; + } /* memory buffer */ while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) { diff --git a/src/flash/nor/stm32h7x.c b/src/flash/nor/stm32h7x.c index 009eb9b..fcfcf91 100644 --- a/src/flash/nor/stm32h7x.c +++ b/src/flash/nor/stm32h7x.c @@ -64,7 +64,7 @@ #define FLASH_WRPERR (1 << 17) /* Write protection error */ #define FLASH_PGSERR (1 << 18) /* Programming sequence error */ #define FLASH_STRBERR (1 << 19) /* Strobe error */ -#define FLASH_INCERR (1 << 21) /* Increment error */ +#define FLASH_INCERR (1 << 21) /* Inconsistency error */ #define FLASH_OPERR (1 << 22) /* Operation error */ #define FLASH_RDPERR (1 << 23) /* Read Protection error */ #define FLASH_RDSERR (1 << 24) /* Secure Protection error */ @@ -220,6 +220,8 @@ static int stm32x_wait_status_busy(struct flash_bank *bank, int timeout) /* Clear error + EOP flags but report errors */ if (status & FLASH_ERROR) { + if (retval == ERROR_OK) + retval = ERROR_FAIL; /* If this operation fails, we ignore it and report the original retval */ target_write_u32(target, stm32x_get_flash_reg(bank, FLASH_CCR), status); } @@ -495,7 +497,7 @@ static int stm32x_erase(struct flash_bank *bank, int first, int last) retval = stm32x_wait_status_busy(bank, FLASH_ERASE_TIMEOUT); if (retval != ERROR_OK) { - LOG_ERROR("erase time-out error sector %d", i); + LOG_ERROR("erase time-out or operation error sector %d", i); return retval; } bank->sectors[i].is_erased = 1; @@ -581,8 +583,10 @@ static int stm32x_write_block(struct flash_bank *bank, const uint8_t *buffer, retval = target_write_buffer(target, write_algorithm->address, sizeof(stm32x_flash_write_code), stm32x_flash_write_code); - if (retval != ERROR_OK) + if (retval != ERROR_OK) { + target_free_working_area(target, write_algorithm); return retval; + } /* memory buffer */ while (target_alloc_working_area_try(target, buffer_size, &source) != ERROR_OK) { diff --git a/src/flash/nor/stm32l4x.c b/src/flash/nor/stm32l4x.c index e47313c..4fb7e03 100644 --- a/src/flash/nor/stm32l4x.c +++ b/src/flash/nor/stm32l4x.c @@ -187,6 +187,8 @@ static int stm32l4_wait_status_busy(struct flash_bank *bank, int timeout) /* Clear but report errors */ if (status & FLASH_ERROR) { + if (retval == ERROR_OK) + retval = ERROR_FAIL; /* If this operation fails, we ignore it and report the original * retval */ @@ -474,8 +476,10 @@ static int stm32l4_write_block(struct flash_bank *bank, const uint8_t *buffer, retval = target_write_buffer(target, write_algorithm->address, sizeof(stm32l4_flash_write_code), stm32l4_flash_write_code); - if (retval != ERROR_OK) + if (retval != ERROR_OK) { + target_free_working_area(target, write_algorithm); return retval; + } /* memory buffer */ while (target_alloc_working_area_try(target, buffer_size, &source) != diff --git a/src/flash/nor/stm32lx.c b/src/flash/nor/stm32lx.c index c68d7c2..3251df3 100644 --- a/src/flash/nor/stm32lx.c +++ b/src/flash/nor/stm32lx.c @@ -146,7 +146,7 @@ static const struct stm32lx_rev stm32_425_revs[] = { { 0x1000, "A" }, { 0x2000, "B" }, { 0x2008, "Y" }, }; static const struct stm32lx_rev stm32_427_revs[] = { - { 0x1000, "A" }, { 0x1018, "Y" }, { 0x1038, "X" }, + { 0x1000, "A" }, { 0x1018, "Y" }, { 0x1038, "X" }, { 0x10f8, "V" }, }; static const struct stm32lx_rev stm32_429_revs[] = { { 0x1000, "A" }, { 0x1018, "Z" }, diff --git a/src/flash/nor/tcl.c b/src/flash/nor/tcl.c index 34681db..95ca819 100644 --- a/src/flash/nor/tcl.c +++ b/src/flash/nor/tcl.c @@ -288,24 +288,6 @@ COMMAND_HANDLER(handle_flash_erase_address_command) return retval; } -static int flash_check_sector_parameters(struct command_context *cmd_ctx, - uint32_t first, uint32_t last, uint32_t num_sectors) -{ - if (!(first <= last)) { - command_print(cmd_ctx, "ERROR: " - "first sector must be <= last sector"); - return ERROR_FAIL; - } - - if (!(last <= (num_sectors - 1))) { - command_print(cmd_ctx, "ERROR: last sector must be <= %" PRIu32, - num_sectors - 1); - return ERROR_FAIL; - } - - return ERROR_OK; -} - COMMAND_HANDLER(handle_flash_erase_command) { if (CMD_ARGC != 3) @@ -327,9 +309,18 @@ COMMAND_HANDLER(handle_flash_erase_command) else COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], last); - retval = flash_check_sector_parameters(CMD_CTX, first, last, p->num_sectors); - if (retval != ERROR_OK) - return retval; + if (!(first <= last)) { + command_print(CMD_CTX, "ERROR: " + "first sector must be <= last"); + return ERROR_FAIL; + } + + if (!(last <= (uint32_t)(p->num_sectors - 1))) { + command_print(CMD_CTX, "ERROR: " + "last sector must be <= %" PRIu32, + p->num_sectors - 1); + return ERROR_FAIL; + } struct duration bench; duration_start(&bench); @@ -375,15 +366,28 @@ COMMAND_HANDLER(handle_flash_protect_command) bool set; COMMAND_PARSE_ON_OFF(CMD_ARGV[3], set); - retval = flash_check_sector_parameters(CMD_CTX, first, last, num_blocks); - if (retval != ERROR_OK) - return retval; + if (!(first <= last)) { + command_print(CMD_CTX, "ERROR: " + "first %s must be <= last", + (p->num_prot_blocks) ? "block" : "sector"); + return ERROR_FAIL; + } + + if (!(last <= (uint32_t)(num_blocks - 1))) { + command_print(CMD_CTX, "ERROR: " + "last %s must be <= %" PRIu32, + (p->num_prot_blocks) ? "block" : "sector", + num_blocks - 1); + return ERROR_FAIL; + } retval = flash_driver_protect(p, set, first, last); if (retval == ERROR_OK) { - command_print(CMD_CTX, "%s protection for sectors %" PRIu32 + command_print(CMD_CTX, "%s protection for %s %" PRIu32 " through %" PRIu32 " on flash bank %d", - (set) ? "set" : "cleared", first, last, p->bank_number); + (set) ? "set" : "cleared", + (p->num_prot_blocks) ? "blocks" : "sectors", + first, last, p->bank_number); } return retval; @@ -502,7 +506,7 @@ COMMAND_HANDLER(handle_flash_fill_command) if (count == 0) return ERROR_OK; - if (address + count >= bank->base + bank->size) { + if (address + count * wordsize > bank->base + bank->size) { LOG_ERROR("Cannot cross flash bank borders"); return ERROR_FAIL; } diff --git a/src/flash/nor/tms470.c b/src/flash/nor/tms470.c index 102bf1b..2435e79 100644 --- a/src/flash/nor/tms470.c +++ b/src/flash/nor/tms470.c @@ -151,6 +151,7 @@ static int tms470_read_part_info(struct flash_bank *bank) if (bank->sectors) { free(bank->sectors); bank->sectors = NULL; + bank->num_sectors = 0; } /* @@ -754,9 +755,6 @@ static int tms470_erase_sector(struct flash_bank *bank, int sector) target_write_u32(target, 0xFFFFFFDC, glbctrl); LOG_DEBUG("set glbctrl = 0x%08" PRIx32 "", glbctrl); - if (result == ERROR_OK) - bank->sectors[sector].is_erased = 1; - return result; } @@ -1044,27 +1042,17 @@ static int tms470_erase_check(struct flash_bank *bank) * an attempt to reduce the JTAG overhead. */ for (sector = 0; sector < bank->num_sectors; sector++) { - if (bank->sectors[sector].is_erased != 1) { - uint32_t i, addr = bank->base + bank->sectors[sector].offset; - - LOG_INFO("checking flash bank %d sector %d", tms470_info->ordinal, sector); - - target_read_buffer(target, addr, bank->sectors[sector].size, buffer); - - bank->sectors[sector].is_erased = 1; - for (i = 0; i < bank->sectors[sector].size; i++) { - if (buffer[i] != 0xff) { - LOG_WARNING("tms470 bank %d, sector %d, not erased.", - tms470_info->ordinal, - sector); - LOG_WARNING( - "at location 0x%08" PRIx32 ": flash data is 0x%02x.", - addr + i, - buffer[i]); - - bank->sectors[sector].is_erased = 0; - break; - } + uint32_t i, addr = bank->base + bank->sectors[sector].offset; + + LOG_INFO("checking flash bank %d sector %d", tms470_info->ordinal, sector); + + target_read_buffer(target, addr, bank->sectors[sector].size, buffer); + + bank->sectors[sector].is_erased = 1; + for (i = 0; i < bank->sectors[sector].size; i++) { + if (buffer[i] != 0xff) { + bank->sectors[sector].is_erased = 0; + break; } } if (bank->sectors[sector].is_erased != 1) { diff --git a/src/flash/nor/virtual.c b/src/flash/nor/virtual.c index d5d688b..15c4bff 100644 --- a/src/flash/nor/virtual.c +++ b/src/flash/nor/virtual.c @@ -46,8 +46,13 @@ static void virtual_update_bank_info(struct flash_bank *bank) bank->bus_width = master_bank->bus_width; bank->erased_value = master_bank->erased_value; bank->default_padded_value = master_bank->default_padded_value; + bank->write_start_alignment = master_bank->write_start_alignment; + bank->write_end_alignment = master_bank->write_end_alignment; + bank->minimal_write_gap = master_bank->minimal_write_gap; bank->num_sectors = master_bank->num_sectors; bank->sectors = master_bank->sectors; + bank->num_prot_blocks = master_bank->num_prot_blocks; + bank->prot_blocks = master_bank->prot_blocks; } FLASH_BANK_COMMAND_HANDLER(virtual_flash_bank_command) diff --git a/src/jtag/aice/aice_usb.c b/src/jtag/aice/aice_usb.c index 50468f3..d77b26b 100644 --- a/src/jtag/aice/aice_usb.c +++ b/src/jtag/aice/aice_usb.c @@ -2289,37 +2289,39 @@ get_delay: static int aice_usb_set_clock(int set_clock) { - if (aice_write_ctrl(AICE_WRITE_CTRL_TCK_CONTROL, - AICE_TCK_CONTROL_TCK_SCAN) != ERROR_OK) - return ERROR_FAIL; + if (set_clock & AICE_TCK_CONTROL_TCK_SCAN) { + if (aice_write_ctrl(AICE_WRITE_CTRL_TCK_CONTROL, + AICE_TCK_CONTROL_TCK_SCAN) != ERROR_OK) + return ERROR_FAIL; - /* Read out TCK_SCAN clock value */ - uint32_t scan_clock; - if (aice_read_ctrl(AICE_READ_CTRL_GET_ICE_STATE, &scan_clock) != ERROR_OK) - return ERROR_FAIL; + /* Read out TCK_SCAN clock value */ + uint32_t scan_clock; + if (aice_read_ctrl(AICE_READ_CTRL_GET_ICE_STATE, &scan_clock) != ERROR_OK) + return ERROR_FAIL; - scan_clock &= 0x0F; + scan_clock &= 0x0F; - uint32_t scan_base_freq; - if (scan_clock & 0x8) - scan_base_freq = 48000; /* 48 MHz */ - else - scan_base_freq = 30000; /* 30 MHz */ + uint32_t scan_base_freq; + if (scan_clock & 0x8) + scan_base_freq = 48000; /* 48 MHz */ + else + scan_base_freq = 30000; /* 30 MHz */ - uint32_t set_base_freq; - if (set_clock & 0x8) - set_base_freq = 48000; - else - set_base_freq = 30000; + uint32_t set_base_freq; + if (set_clock & 0x8) + set_base_freq = 48000; + else + set_base_freq = 30000; - uint32_t set_freq; - uint32_t scan_freq; - set_freq = set_base_freq >> (set_clock & 0x7); - scan_freq = scan_base_freq >> (scan_clock & 0x7); + uint32_t set_freq; + uint32_t scan_freq; + set_freq = set_base_freq >> (set_clock & 0x7); + scan_freq = scan_base_freq >> (scan_clock & 0x7); - if (scan_freq < set_freq) { - LOG_ERROR("User specifies higher jtag clock than TCK_SCAN clock"); - return ERROR_FAIL; + if (scan_freq < set_freq) { + LOG_ERROR("User specifies higher jtag clock than TCK_SCAN clock"); + return ERROR_FAIL; + } } if (aice_write_ctrl(AICE_WRITE_CTRL_TCK_CONTROL, set_clock) != ERROR_OK) diff --git a/src/jtag/aice/aice_usb.h b/src/jtag/aice/aice_usb.h index 2911ae5..15cc1f6 100644 --- a/src/jtag/aice/aice_usb.h +++ b/src/jtag/aice/aice_usb.h @@ -71,6 +71,7 @@ /* Constants for AICE command WRITE_CTRL:TCK_CONTROL */ #define AICE_TCK_CONTROL_TCK3048 0x08 +#define AICE_TCK_CONTROL_TCK_SCAN 0x10 /* Constants for AICE command WRITE_CTRL:JTAG_PIN_CONTROL */ #define AICE_JTAG_PIN_CONTROL_SRST 0x01 diff --git a/src/jtag/core.c b/src/jtag/core.c index 5d9b810..f90ae99 100644 --- a/src/jtag/core.c +++ b/src/jtag/core.c @@ -1843,7 +1843,7 @@ void adapter_deassert_reset(void) LOG_ERROR("transport is not selected"); } -int adapter_config_trace(bool enabled, enum tpio_pin_protocol pin_protocol, +int adapter_config_trace(bool enabled, enum tpiu_pin_protocol pin_protocol, uint32_t port_size, unsigned int *trace_freq) { if (jtag->config_trace) diff --git a/src/jtag/drivers/Makefile.am b/src/jtag/drivers/Makefile.am index b3b4d21..ccef018 100644 --- a/src/jtag/drivers/Makefile.am +++ b/src/jtag/drivers/Makefile.am @@ -156,10 +156,12 @@ endif if IMX_GPIO DRIVERFILES += %D%/imx_gpio.c endif - if KITPROG DRIVERFILES += %D%/kitprog.c endif +if XDS110 +DRIVERFILES += %D%/xds110.c +endif DRIVERHEADERS = \ %D%/bitbang.h \ diff --git a/src/jtag/drivers/cmsis_dap_usb.c b/src/jtag/drivers/cmsis_dap_usb.c index b8181d6..4ee4836 100644 --- a/src/jtag/drivers/cmsis_dap_usb.c +++ b/src/jtag/drivers/cmsis_dap_usb.c @@ -729,6 +729,20 @@ static void cmsis_dap_swd_read_reg(uint8_t cmd, uint32_t *value, uint32_t ap_del cmsis_dap_swd_queue_cmd(cmd, value, 0); } +static int cmsis_dap_get_serial_info(void) +{ + uint8_t *data; + + int retval = cmsis_dap_cmd_DAP_Info(INFO_ID_SERNUM, &data); + if (retval != ERROR_OK) + return retval; + + if (data[0]) /* strlen */ + LOG_INFO("CMSIS-DAP: Serial# = %s", &data[1]); + + return ERROR_OK; +} + static int cmsis_dap_get_version_info(void) { uint8_t *data; @@ -802,8 +816,7 @@ static int cmsis_dap_swd_switch_seq(enum swd_special_seq seq) /* When we are reconnecting, DAP_Connect needs to be rerun, at * least on Keil ULINK-ME */ - retval = cmsis_dap_cmd_DAP_Connect(seq == LINE_RESET || seq == JTAG_TO_SWD ? - CONNECT_SWD : CONNECT_JTAG); + retval = cmsis_dap_cmd_DAP_Connect(CONNECT_SWD); if (retval != ERROR_OK) return retval; } @@ -842,17 +855,6 @@ static int cmsis_dap_swd_open(void) { int retval; - if (cmsis_dap_handle == NULL) { - /* SWD init */ - retval = cmsis_dap_usb_open(); - if (retval != ERROR_OK) - return retval; - - retval = cmsis_dap_get_caps_info(); - if (retval != ERROR_OK) - return retval; - } - if (!(cmsis_dap_handle->caps & INFO_CAPS_SWD)) { LOG_ERROR("CMSIS-DAP: SWD not supported"); return ERROR_JTAG_DEVICE_ERROR; @@ -873,6 +875,22 @@ static int cmsis_dap_init(void) int retval; uint8_t *data; + retval = cmsis_dap_usb_open(); + if (retval != ERROR_OK) + return retval; + + retval = cmsis_dap_get_caps_info(); + if (retval != ERROR_OK) + return retval; + + retval = cmsis_dap_get_version_info(); + if (retval != ERROR_OK) + return retval; + + retval = cmsis_dap_get_serial_info(); + if (retval != ERROR_OK) + return retval; + if (swd_mode) { retval = cmsis_dap_swd_open(); if (retval != ERROR_OK) @@ -880,16 +898,6 @@ static int cmsis_dap_init(void) } if (cmsis_dap_handle == NULL) { - - /* JTAG init */ - retval = cmsis_dap_usb_open(); - if (retval != ERROR_OK) - return retval; - - retval = cmsis_dap_get_caps_info(); - if (retval != ERROR_OK) - return retval; - /* Connect in JTAG mode */ if (!(cmsis_dap_handle->caps & INFO_CAPS_JTAG)) { LOG_ERROR("CMSIS-DAP: JTAG not supported"); @@ -903,10 +911,6 @@ static int cmsis_dap_init(void) LOG_INFO("CMSIS-DAP: Interface Initialised (JTAG)"); } - retval = cmsis_dap_get_version_info(); - if (retval != ERROR_OK) - return retval; - /* INFO_ID_PKT_SZ - short */ retval = cmsis_dap_cmd_DAP_Info(INFO_ID_PKT_SZ, &data); if (retval != ERROR_OK) @@ -1458,6 +1462,12 @@ static void cmsis_dap_execute_stableclocks(struct jtag_command *cmd) cmsis_dap_stableclocks(cmd->cmd.runtest->num_cycles); } +static void cmsis_dap_execute_tms(struct jtag_command *cmd) +{ + DEBUG_JTAG_IO("TMS: %d bits", cmd->cmd.tms->num_bits); + cmsis_dap_cmd_DAP_SWJ_Sequence(cmd->cmd.tms->num_bits, cmd->cmd.tms->bits); +} + /* TODO: Is there need to call cmsis_dap_flush() for the JTAG_PATHMOVE, * JTAG_RUNTEST, JTAG_STABLECLOCKS? */ static void cmsis_dap_execute_command(struct jtag_command *cmd) @@ -1488,6 +1498,8 @@ static void cmsis_dap_execute_command(struct jtag_command *cmd) cmsis_dap_execute_stableclocks(cmd); break; case JTAG_TMS: + cmsis_dap_execute_tms(cmd); + break; default: LOG_ERROR("BUG: unknown JTAG command type 0x%X encountered", cmd->type); exit(-1); @@ -1650,6 +1662,7 @@ static const char * const cmsis_dap_transport[] = { "swd", "jtag", NULL }; struct jtag_interface cmsis_dap_interface = { .name = "cmsis-dap", + .supported = DEBUG_CAP_TMS_SEQ, .commands = cmsis_dap_command_handlers, .swd = &cmsis_dap_swd_driver, .transports = cmsis_dap_transport, diff --git a/src/jtag/drivers/jlink.c b/src/jtag/drivers/jlink.c index 132ef06..e74965e 100644 --- a/src/jtag/drivers/jlink.c +++ b/src/jtag/drivers/jlink.c @@ -1263,7 +1263,7 @@ static bool check_trace_freq(struct jaylink_swo_speed speed, return false; } -static int config_trace(bool enabled, enum tpio_pin_protocol pin_protocol, +static int config_trace(bool enabled, enum tpiu_pin_protocol pin_protocol, uint32_t port_size, unsigned int *trace_freq) { int ret; @@ -1275,7 +1275,7 @@ static int config_trace(bool enabled, enum tpio_pin_protocol pin_protocol, return ERROR_FAIL; } - if (pin_protocol != ASYNC_UART) { + if (pin_protocol != TPIU_PIN_PROTOCOL_ASYNC_UART) { LOG_ERROR("Selected pin protocol is not supported."); return ERROR_FAIL; } diff --git a/src/jtag/drivers/jtag_vpi.c b/src/jtag/drivers/jtag_vpi.c index 1b0fcba..1a42b3a 100644 --- a/src/jtag/drivers/jtag_vpi.c +++ b/src/jtag/drivers/jtag_vpi.c @@ -204,23 +204,20 @@ static int jtag_vpi_queue_tdi_xfer(uint8_t *bits, int nb_bits, int tap_shift) static int jtag_vpi_queue_tdi(uint8_t *bits, int nb_bits, int tap_shift) { int nb_xfer = DIV_ROUND_UP(nb_bits, XFERT_MAX_SIZE * 8); - uint8_t *xmit_buffer = bits; - int xmit_nb_bits = nb_bits; - int i = 0; int retval; while (nb_xfer) { - if (nb_xfer == 1) { - retval = jtag_vpi_queue_tdi_xfer(&xmit_buffer[i], xmit_nb_bits, tap_shift); + retval = jtag_vpi_queue_tdi_xfer(bits, nb_bits, tap_shift); if (retval != ERROR_OK) return retval; } else { - retval = jtag_vpi_queue_tdi_xfer(&xmit_buffer[i], XFERT_MAX_SIZE * 8, NO_TAP_SHIFT); + retval = jtag_vpi_queue_tdi_xfer(bits, XFERT_MAX_SIZE * 8, NO_TAP_SHIFT); if (retval != ERROR_OK) return retval; - xmit_nb_bits -= XFERT_MAX_SIZE * 8; - i += XFERT_MAX_SIZE; + nb_bits -= XFERT_MAX_SIZE * 8; + if (bits) + bits += XFERT_MAX_SIZE; } nb_xfer--; @@ -318,7 +315,7 @@ static int jtag_vpi_runtest(int cycles, tap_state_t state) if (retval != ERROR_OK) return retval; - retval = jtag_vpi_queue_tdi(NULL, cycles, NO_TAP_SHIFT); + retval = jtag_vpi_queue_tdi(NULL, cycles, TAP_SHIFT); if (retval != ERROR_OK) return retval; diff --git a/src/jtag/drivers/kitprog.c b/src/jtag/drivers/kitprog.c index 522eb17..e3ad84d 100644 --- a/src/jtag/drivers/kitprog.c +++ b/src/jtag/drivers/kitprog.c @@ -888,13 +888,11 @@ COMMAND_HANDLER(kitprog_handle_acquire_psoc_command) COMMAND_HANDLER(kitprog_handle_serial_command) { if (CMD_ARGC == 1) { - size_t len = strlen(CMD_ARGV[0]); - kitprog_serial = calloc(len + 1, sizeof(char)); + kitprog_serial = strdup(CMD_ARGV[0]); if (kitprog_serial == NULL) { LOG_ERROR("Failed to allocate memory for the serial number"); return ERROR_FAIL; } - strncpy(kitprog_serial, CMD_ARGV[0], len + 1); } else { LOG_ERROR("expected exactly one argument to kitprog_serial <serial-number>"); return ERROR_FAIL; diff --git a/src/jtag/drivers/stlink_usb.c b/src/jtag/drivers/stlink_usb.c index 99f96b9..d9ca53e 100644 --- a/src/jtag/drivers/stlink_usb.c +++ b/src/jtag/drivers/stlink_usb.c @@ -2194,12 +2194,13 @@ error_open: return ERROR_FAIL; } -int stlink_config_trace(void *handle, bool enabled, enum tpio_pin_protocol pin_protocol, +int stlink_config_trace(void *handle, bool enabled, enum tpiu_pin_protocol pin_protocol, uint32_t port_size, unsigned int *trace_freq) { struct stlink_usb_handle_s *h = handle; - if (enabled && (h->jtag_api < 2 || pin_protocol != ASYNC_UART)) { + if (enabled && (h->jtag_api < 2 || + pin_protocol != TPIU_PIN_PROTOCOL_ASYNC_UART)) { LOG_ERROR("The attached ST-LINK version doesn't support this trace mode"); return ERROR_FAIL; } diff --git a/src/jtag/drivers/sysfsgpio.c b/src/jtag/drivers/sysfsgpio.c index 5a4651d..5535c71 100644 --- a/src/jtag/drivers/sysfsgpio.c +++ b/src/jtag/drivers/sysfsgpio.c @@ -58,11 +58,11 @@ /* * Helper func to determine if gpio number valid * - * Assume here that there will be less than 1000 gpios on a system + * Assume here that there will be less than 10000 gpios on a system */ static int is_gpio_valid(int gpio) { - return gpio >= 0 && gpio < 1000; + return gpio >= 0 && gpio < 10000; } /* @@ -89,7 +89,7 @@ static int open_write_close(const char *name, const char *valstr) */ static void unexport_sysfs_gpio(int gpio) { - char gpiostr[4]; + char gpiostr[5]; if (!is_gpio_valid(gpio)) return; @@ -113,7 +113,7 @@ static void unexport_sysfs_gpio(int gpio) static int setup_sysfs_gpio(int gpio, int is_output, int init_high) { char buf[40]; - char gpiostr[4]; + char gpiostr[5]; int ret; if (!is_gpio_valid(gpio)) diff --git a/src/jtag/drivers/usb_blaster/usb_blaster.c b/src/jtag/drivers/usb_blaster/usb_blaster.c index df9f2a1..8ccf871 100644 --- a/src/jtag/drivers/usb_blaster/usb_blaster.c +++ b/src/jtag/drivers/usb_blaster/usb_blaster.c @@ -445,6 +445,7 @@ static void ublast_queue_bytes(uint8_t *bytes, int nb_bytes) * ublast_tms_seq - write a TMS sequence transition to JTAG * @bits: TMS bits to be written (bit0, bit1 .. bitN) * @nb_bits: number of TMS bits (between 1 and 8) + * @skip: number of TMS bits to skip at the beginning of the series * * Write a serie of TMS transitions, where each transition consists in : * - writing out TCK=0, TMS=<new_state>, TDI=<???> @@ -452,12 +453,12 @@ static void ublast_queue_bytes(uint8_t *bytes, int nb_bytes) * The function ensures that at the end of the sequence, the clock (TCK) is put * low. */ -static void ublast_tms_seq(const uint8_t *bits, int nb_bits) +static void ublast_tms_seq(const uint8_t *bits, int nb_bits, int skip) { int i; DEBUG_JTAG_IO("(bits=%02x..., nb_bits=%d)", bits[0], nb_bits); - for (i = 0; i < nb_bits; i++) + for (i = skip; i < nb_bits; i++) ublast_clock_tms((bits[i / 8] >> (i % 8)) & 0x01); ublast_idle_clock(); } @@ -469,7 +470,7 @@ static void ublast_tms_seq(const uint8_t *bits, int nb_bits) static void ublast_tms(struct tms_command *cmd) { DEBUG_JTAG_IO("(num_bits=%d)", cmd->num_bits); - ublast_tms_seq(cmd->bits, cmd->num_bits); + ublast_tms_seq(cmd->bits, cmd->num_bits, 0); } /** @@ -501,11 +502,12 @@ static void ublast_path_move(struct pathmove_command *cmd) /** * ublast_state_move - move JTAG state to the target state * @state: the target state + * @skip: number of bits to skip at the beginning of the path * * Input the correct TMS sequence to the JTAG TAP so that we end up in the * target state. This assumes the current state (tap_get_state()) is correct. */ -static void ublast_state_move(tap_state_t state) +static void ublast_state_move(tap_state_t state, int skip) { uint8_t tms_scan; int tms_len; @@ -516,7 +518,7 @@ static void ublast_state_move(tap_state_t state) return; tms_scan = tap_get_tms_path(tap_get_state(), state); tms_len = tap_get_tms_path_len(tap_get_state(), state); - ublast_tms_seq(&tms_scan, tms_len); + ublast_tms_seq(&tms_scan, tms_len, skip); tap_set_state(state); } @@ -688,9 +690,9 @@ static void ublast_runtest(int cycles, tap_state_t state) { DEBUG_JTAG_IO("%s(cycles=%i, end_state=%d)", __func__, cycles, state); - ublast_state_move(TAP_IDLE); + ublast_state_move(TAP_IDLE, 0); ublast_queue_tdi(NULL, cycles, SCAN_OUT); - ublast_state_move(state); + ublast_state_move(state, 0); } static void ublast_stableclocks(int cycles) @@ -720,9 +722,9 @@ static int ublast_scan(struct scan_command *cmd) scan_bits = jtag_build_buffer(cmd, &buf); if (cmd->ir_scan) - ublast_state_move(TAP_IRSHIFT); + ublast_state_move(TAP_IRSHIFT, 0); else - ublast_state_move(TAP_DRSHIFT); + ublast_state_move(TAP_DRSHIFT, 0); log_buf = hexdump(buf, DIV_ROUND_UP(scan_bits, 8)); DEBUG_JTAG_IO("%s(scan=%s, type=%s, bits=%d, buf=[%s], end_state=%d)", __func__, @@ -733,20 +735,15 @@ static int ublast_scan(struct scan_command *cmd) ublast_queue_tdi(buf, scan_bits, type); - /* - * As our JTAG is in an unstable state (IREXIT1 or DREXIT1), move it - * forward to a stable IRPAUSE or DRPAUSE. - */ - ublast_clock_tms(0); - if (cmd->ir_scan) - tap_set_state(TAP_IRPAUSE); - else - tap_set_state(TAP_DRPAUSE); - ret = jtag_read_buffer(buf, cmd); if (buf) free(buf); - ublast_state_move(cmd->end_state); + /* + * ublast_queue_tdi sends the last bit with TMS=1. We are therefore + * already in Exit1-DR/IR and have to skip the first step on our way + * to end_state. + */ + ublast_state_move(cmd->end_state, 1); return ret; } @@ -776,7 +773,7 @@ static void ublast_initial_wipeout(void) /* * Put JTAG in RESET state (five 1 on TMS) */ - ublast_tms_seq(&tms_reset, 5); + ublast_tms_seq(&tms_reset, 5, 0); tap_set_state(TAP_RESET); } @@ -805,7 +802,7 @@ static int ublast_execute_queue(void) ublast_stableclocks(cmd->cmd.stableclocks->num_cycles); break; case JTAG_TLR_RESET: - ublast_state_move(cmd->cmd.statemove->end_state); + ublast_state_move(cmd->cmd.statemove->end_state, 0); break; case JTAG_PATHMOVE: ublast_path_move(cmd->cmd.pathmove); diff --git a/src/jtag/drivers/xds110.c b/src/jtag/drivers/xds110.c new file mode 100644 index 0000000..b97eef2 --- /dev/null +++ b/src/jtag/drivers/xds110.c @@ -0,0 +1,1973 @@ +/*************************************************************************** + * Copyright (C) 2017 by Texas Instruments, Inc. * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <transport/transport.h> +#include <jtag/swd.h> +#include <jtag/interface.h> +#include <jtag/commands.h> +#include <jtag/tcl.h> +#include <libusb.h> + +/* XDS110 USB serial number length */ +#define XDS110_SERIAL_LEN 8 + +/* Firmware version that introduced OpenOCD support via block accesses */ +#define OCD_FIRMWARE_VERSION 0x02030011 +#define OCD_FIRMWARE_UPGRADE \ + "XDS110: upgrade to version 2.3.0.11+ for improved support" + +/*************************************************************************** + * USB Connection Buffer Definitions * + ***************************************************************************/ + +/* Max USB packet size for up to USB 3.0 */ +#define MAX_PACKET 1024 + +/* + * Maximum data payload that can be handled in a single call + * Limitation is the size of the buffers in the XDS110 firmware + */ +#define MAX_DATA_BLOCK 4096 + +#ifndef USB_PAYLOAD_SIZE +/* Largest data block plus parameters */ +#define USB_PAYLOAD_SIZE (MAX_DATA_BLOCK + 60) +#endif +#define MAX_RESULT_QUEUE (MAX_DATA_BLOCK / 4) + +/*************************************************************************** + * USB Connection Endpoints * + ***************************************************************************/ + +/* Bulk endpoints used by the XDS110 debug interface */ +#define INTERFACE_DEBUG (2) +#define ENDPOINT_DEBUG_IN (3 | LIBUSB_ENDPOINT_IN) +#define ENDPOINT_DEBUG_OUT (2 | LIBUSB_ENDPOINT_OUT) + +/*************************************************************************** + * XDS110 Firmware API Definitions * + ***************************************************************************/ + +/* + * Default values controlling how the host communicates commands + * with XDS110 firmware (automatic retry count and wait timeout) + */ +#define DEFAULT_ATTEMPTS (1) +#define DEFAULT_TIMEOUT (4000) + +/* XDS110 API error codes */ +#define SC_ERR_NONE 0 +#define SC_ERR_XDS110_FAIL -261 +#define SC_ERR_SWD_WAIT -613 +#define SC_ERR_SWD_FAULT -614 +#define SC_ERR_SWD_PROTOCOL -615 +#define SC_ERR_SWD_PARITY -616 +#define SC_ERR_SWD_DEVICE_ID -617 + +/* TCK frequency limits */ +#define XDS110_MIN_TCK_SPEED 100 /* kHz */ +#define XDS110_MAX_TCK_SPEED 2500 /* kHz */ +#define XDS110_TCK_PULSE_INCREMENT 66.0 + +/* Scan mode on connect */ +#define MODE_JTAG 1 + +/* XDS110 API JTAG state definitions */ +#define XDS_JTAG_STATE_RESET 1 +#define XDS_JTAG_STATE_IDLE 2 +#define XDS_JTAG_STATE_SHIFT_DR 3 +#define XDS_JTAG_STATE_SHIFT_IR 4 +#define XDS_JTAG_STATE_PAUSE_DR 5 +#define XDS_JTAG_STATE_PAUSE_IR 6 +#define XDS_JTAG_STATE_EXIT1_DR 8 +#define XDS_JTAG_STATE_EXIT1_IR 9 +#define XDS_JTAG_STATE_EXIT2_DR 10 +#define XDS_JTAG_STATE_EXIT2_IR 11 +#define XDS_JTAG_STATE_SELECT_DR 12 +#define XDS_JTAG_STATE_SELECT_IR 13 +#define XDS_JTAG_STATE_UPDATE_DR 14 +#define XDS_JTAG_STATE_UPDATE_IR 15 +#define XDS_JTAG_STATE_CAPTURE_DR 16 +#define XDS_JTAG_STATE_CAPTURE_IR 17 + +/* XDS110 API JTAG transit definitions */ +#define XDS_JTAG_TRANSIT_QUICKEST 1 +#define XDS_JTAG_TRANSIT_VIA_CAPTURE 2 +#define XDS_JTAG_TRANSIT_VIA_IDLE 3 + +/* DAP register definitions as used by XDS110 APIs */ + +#define DAP_AP 0 /* DAP AP register type */ +#define DAP_DP 1 /* DAP DP register type */ + +#define DAP_DP_IDCODE 0x0 /* DAP DP IDCODE register (read only) */ +#define DAP_DP_ABORT 0x0 /* DAP DP ABORT register (write only) */ +#define DAP_DP_STAT 0x4 /* DAP DP STAT register (for read only) */ +#define DAP_DP_CTRL 0x4 /* DAP DP CTRL register (for write only) */ +#define DAP_DP_ADDR 0x8 /* DAP DP SELECT register (legacy name) */ +#define DAP_DP_RESEND 0x8 /* DAP DP RESEND register (read only) */ +#define DAP_DP_SELECT 0x8 /* DAP DP SELECT register (write only) */ +#define DAP_DP_RDBUFF 0xc /* DAP DP RDBUFF Read Buffer register */ + +#define DAP_AP_CSW 0x00 /* DAP AP Control Status Word */ +#define DAP_AP_TAR 0x04 /* DAP AP Transfer Address */ +#define DAP_AP_DRW 0x0C /* DAP AP Data Read/Write */ +#define DAP_AP_BD0 0x10 /* DAP AP Banked Data 0 */ +#define DAP_AP_BD1 0x14 /* DAP AP Banked Data 1 */ +#define DAP_AP_BD2 0x18 /* DAP AP Banked Data 2 */ +#define DAP_AP_BD3 0x1C /* DAP AP Banked Data 3 */ +#define DAP_AP_RTBL 0xF8 /* DAP AP Debug ROM Table */ +#define DAP_AP_IDR 0xFC /* DAP AP Identification Register */ + +/* Command packet definitions */ + +#define XDS_OUT_LEN 1 /* command (byte) */ +#define XDS_IN_LEN 4 /* error code (int) */ + +/* XDS API Commands */ +#define XDS_CONNECT 0x01 /* Connect JTAG connection */ +#define XDS_DISCONNECT 0x02 /* Disconnect JTAG connection */ +#define XDS_VERSION 0x03 /* Get firmware version and hardware ID */ +#define XDS_SET_TCK 0x04 /* Set TCK delay (to set TCK frequency) */ +#define XDS_SET_TRST 0x05 /* Assert or deassert nTRST signal */ +#define XDS_CYCLE_TCK 0x07 /* Toggle TCK for a number of cycles */ +#define XDS_GOTO_STATE 0x09 /* Go to requested JTAG state */ +#define XDS_JTAG_SCAN 0x0c /* Send and receive JTAG scan */ +#define XDS_SET_SRST 0x0e /* Assert or deassert nSRST signal */ +#define CMAPI_CONNECT 0x0f /* CMAPI connect */ +#define CMAPI_DISCONNECT 0x10 /* CMAPI disconnect */ +#define CMAPI_ACQUIRE 0x11 /* CMAPI acquire */ +#define CMAPI_RELEASE 0x12 /* CMAPI release */ +#define CMAPI_REG_READ 0x15 /* CMAPI DAP register read */ +#define CMAPI_REG_WRITE 0x16 /* CMAPI DAP register write */ +#define SWD_CONNECT 0x17 /* Switch from JTAG to SWD connection */ +#define SWD_DISCONNECT 0x18 /* Switch from SWD to JTAG connection */ +#define CJTAG_CONNECT 0x2b /* Switch from JTAG to cJTAG connection */ +#define CJTAG_DISCONNECT 0x2c /* Switch from cJTAG to JTAG connection */ +#define OCD_DAP_REQUEST 0x3a /* Handle block of DAP requests */ +#define OCD_SCAN_REQUEST 0x3b /* Handle block of JTAG scan requests */ +#define OCD_PATHMOVE 0x3c /* Handle PATHMOVE to navigate JTAG states */ + +#define CMD_IR_SCAN 1 +#define CMD_DR_SCAN 2 +#define CMD_RUNTEST 3 +#define CMD_STABLECLOCKS 4 + +/* Array to convert from OpenOCD tap_state_t to XDS JTAG state */ +const uint32_t xds_jtag_state[] = { + XDS_JTAG_STATE_EXIT2_DR, /* TAP_DREXIT2 = 0x0 */ + XDS_JTAG_STATE_EXIT1_DR, /* TAP_DREXIT1 = 0x1 */ + XDS_JTAG_STATE_SHIFT_DR, /* TAP_DRSHIFT = 0x2 */ + XDS_JTAG_STATE_PAUSE_DR, /* TAP_DRPAUSE = 0x3 */ + XDS_JTAG_STATE_SELECT_IR, /* TAP_IRSELECT = 0x4 */ + XDS_JTAG_STATE_UPDATE_DR, /* TAP_DRUPDATE = 0x5 */ + XDS_JTAG_STATE_CAPTURE_DR, /* TAP_DRCAPTURE = 0x6 */ + XDS_JTAG_STATE_SELECT_DR, /* TAP_DRSELECT = 0x7 */ + XDS_JTAG_STATE_EXIT2_IR, /* TAP_IREXIT2 = 0x8 */ + XDS_JTAG_STATE_EXIT1_IR, /* TAP_IREXIT1 = 0x9 */ + XDS_JTAG_STATE_SHIFT_IR, /* TAP_IRSHIFT = 0xa */ + XDS_JTAG_STATE_PAUSE_IR, /* TAP_IRPAUSE = 0xb */ + XDS_JTAG_STATE_IDLE, /* TAP_IDLE = 0xc */ + XDS_JTAG_STATE_UPDATE_IR, /* TAP_IRUPDATE = 0xd */ + XDS_JTAG_STATE_CAPTURE_IR, /* TAP_IRCAPTURE = 0xe */ + XDS_JTAG_STATE_RESET, /* TAP_RESET = 0xf */ +}; + +struct scan_result { + bool first; + uint8_t *buffer; + uint32_t num_bits; +}; + +struct xds110_info { + /* USB connection handles and data buffers */ + libusb_context *ctx; + libusb_device_handle *dev; + unsigned char read_payload[USB_PAYLOAD_SIZE]; + unsigned char write_packet[3]; + unsigned char write_payload[USB_PAYLOAD_SIZE]; + /* Status flags */ + bool is_connected; + bool is_cmapi_connected; + bool is_cmapi_acquired; + bool is_swd_mode; + bool is_ap_dirty; + /* DAP register caches */ + uint32_t select; + uint32_t rdbuff; + bool use_rdbuff; + /* TCK speed and delay count*/ + uint32_t speed; + uint32_t delay_count; + /* XDS110 serial number */ + char serial[XDS110_SERIAL_LEN + 1]; + /* XDS110 firmware and hardware version */ + uint32_t firmware; + uint16_t hardware; + /* Transaction queues */ + unsigned char txn_requests[MAX_DATA_BLOCK]; + uint32_t *txn_dap_results[MAX_DATA_BLOCK / 4]; + struct scan_result txn_scan_results[MAX_DATA_BLOCK / 4]; + uint32_t txn_request_size; + uint32_t txn_result_size; + uint32_t txn_result_count; +}; + +static struct xds110_info xds110 = { + .ctx = NULL, + .dev = NULL, + .is_connected = false, + .is_cmapi_connected = false, + .is_cmapi_acquired = false, + .is_swd_mode = false, + .is_ap_dirty = false, + .speed = XDS110_MAX_TCK_SPEED, + .delay_count = 0, + .serial = {0}, + .firmware = 0, + .hardware = 0, + .txn_request_size = 0, + .txn_result_size = 0, + .txn_result_count = 0 +}; + +static inline void xds110_set_u32(uint8_t *buffer, uint32_t value) +{ + buffer[3] = (value >> 24) & 0xff; + buffer[2] = (value >> 16) & 0xff; + buffer[1] = (value >> 8) & 0xff; + buffer[0] = (value >> 0) & 0xff; +} + +static inline void xds110_set_u16(uint8_t *buffer, uint16_t value) +{ + buffer[1] = (value >> 8) & 0xff; + buffer[0] = (value >> 0) & 0xff; +} + +static inline uint32_t xds110_get_u32(uint8_t *buffer) +{ + uint32_t value = (((uint32_t)buffer[3]) << 24) | + (((uint32_t)buffer[2]) << 16) | + (((uint32_t)buffer[1]) << 8) | + (((uint32_t)buffer[0]) << 0); + return value; +} + +static inline uint16_t xds110_get_u16(uint8_t *buffer) +{ + uint16_t value = (((uint32_t)buffer[1]) << 8) | + (((uint32_t)buffer[0]) << 0); + return value; +} + +/*************************************************************************** + * usb connection routines * + * * + * The following functions handle connecting, reading, and writing to * + * the XDS110 over USB using the libusb library. * + ***************************************************************************/ + +static bool usb_connect(void) +{ + libusb_context *ctx = NULL; + libusb_device **list = NULL; + libusb_device_handle *dev = NULL; + + struct libusb_device_descriptor desc; + + uint16_t vid = 0x0451; + uint16_t pid = 0xbef3; + ssize_t count = 0; + ssize_t i = 0; + int result = 0; + bool found = false; + + /* Initialize libusb context */ + result = libusb_init(&ctx); + + if (0 == result) { + /* Get list of USB devices attached to system */ + count = libusb_get_device_list(ctx, &list); + if (count <= 0) { + result = -1; + list = NULL; + } + } + + if (0 == result) { + /* Scan through list of devices for any XDS110s */ + for (i = 0; i < count; i++) { + /* Check for device VID/PID match */ + libusb_get_device_descriptor(list[i], &desc); + if (desc.idVendor == vid && desc.idProduct == pid) { + result = libusb_open(list[i], &dev); + if (0 == result) { + const int MAX_DATA = 256; + unsigned char data[MAX_DATA + 1]; + *data = '\0'; + + /* May be the requested device if serial number matches */ + if (0 == xds110.serial[0]) { + /* No serial number given; match first XDS110 found */ + found = true; + break; + } else { + /* Get the device's serial number string */ + result = libusb_get_string_descriptor_ascii(dev, + desc.iSerialNumber, data, MAX_DATA); + if (0 < result && + 0 == strcmp((char *)data, (char *)xds110.serial)) { + found = true; + break; + } + } + + /* If we fall though to here, we don't want this device */ + libusb_close(dev); + dev = NULL; + } + } + } + } + + /* + * We can fall through the for() loop with two possible exit conditions: + * 1) found the right XDS110, and that device is open + * 2) didn't find the XDS110, and no devices are currently open + */ + + if (NULL != list) { + /* Free the device list, we're done with it */ + libusb_free_device_list(list, 1); + } + + if (found) { + /* Save the context and device handles */ + xds110.ctx = ctx; + xds110.dev = dev; + + /* Set libusb to auto detach kernel */ + (void)libusb_set_auto_detach_kernel_driver(dev, 1); + + /* Claim the debug interface on the XDS110 */ + result = libusb_claim_interface(dev, INTERFACE_DEBUG); + } else { + /* Couldn't find an XDS110, flag the error */ + result = -1; + } + + /* On an error, clean up what we can */ + if (0 != result) { + if (NULL != dev) { + /* Release the debug and data interface on the XDS110 */ + (void)libusb_release_interface(dev, INTERFACE_DEBUG); + libusb_close(dev); + } + if (NULL != ctx) + libusb_exit(ctx); + xds110.ctx = NULL; + xds110.dev = NULL; + } + + /* Log the results */ + if (0 == result) + LOG_INFO("XDS110: connected"); + else + LOG_ERROR("XDS110: failed to connect"); + + return (0 == result) ? true : false; +} + +static void usb_disconnect(void) +{ + if (NULL != xds110.dev) { + /* Release the debug and data interface on the XDS110 */ + (void)libusb_release_interface(xds110.dev, INTERFACE_DEBUG); + libusb_close(xds110.dev); + xds110.dev = NULL; + } + if (NULL != xds110.ctx) { + libusb_exit(xds110.ctx); + xds110.ctx = NULL; + } + + LOG_INFO("XDS110: disconnected"); +} + +static bool usb_read(unsigned char *buffer, int size, int *bytes_read, + int timeout) +{ + int result; + + if (NULL == xds110.dev || NULL == buffer || NULL == bytes_read) + return false; + + /* Force a non-zero timeout to prevent blocking */ + if (0 == timeout) + timeout = DEFAULT_TIMEOUT; + + result = libusb_bulk_transfer(xds110.dev, ENDPOINT_DEBUG_IN, buffer, size, + bytes_read, timeout); + + return (0 == result) ? true : false; +} + +static bool usb_write(unsigned char *buffer, int size, int *written) +{ + int bytes_written = 0; + int result = LIBUSB_SUCCESS; + int retries = 0; + + if (NULL == xds110.dev || NULL == buffer) + return false; + + result = libusb_bulk_transfer(xds110.dev, ENDPOINT_DEBUG_OUT, buffer, + size, &bytes_written, 0); + + while (LIBUSB_ERROR_PIPE == result && retries < 3) { + /* Try clearing the pipe stall and retry transfer */ + libusb_clear_halt(xds110.dev, ENDPOINT_DEBUG_OUT); + result = libusb_bulk_transfer(xds110.dev, ENDPOINT_DEBUG_OUT, buffer, + size, &bytes_written, 0); + retries++; + } + + if (NULL != written) + *written = bytes_written; + + return (0 == result && size == bytes_written) ? true : false; +} + +static bool usb_get_response(uint32_t *total_bytes_read, uint32_t timeout) +{ + static unsigned char buffer[MAX_PACKET]; + int bytes_read; + uint16_t size; + uint16_t count; + bool success; + + size = 0; + success = true; + while (success) { + success = usb_read(buffer, sizeof(buffer), &bytes_read, timeout); + if (success) { + /* + * Validate that this appears to be a good response packet + * First check it contains enough data for header and error + * code, plus the first character is the start character + */ + if (bytes_read >= 7 && '*' == buffer[0]) { + /* Extract the payload size */ + size = xds110_get_u16(&buffer[1]); + /* Sanity test on payload size */ + if (USB_PAYLOAD_SIZE >= size && 4 <= size) { + /* Check we didn't get more data than expected */ + if ((bytes_read - 3) <= size) { + /* Packet appears to be valid, move on */ + break; + } + } + } + } + /* + * Somehow received an invalid packet, retry till we + * time out or a valid response packet is received + */ + } + + /* Abort now if we didn't receive a valid response */ + if (!success) { + if (NULL != total_bytes_read) + *total_bytes_read = 0; + return false; + } + + /* Build the return payload into xds110.read_payload */ + + /* Copy over payload data from received buffer (skipping header) */ + count = 0; + bytes_read -= 3; + memcpy((void *)&xds110.read_payload[count], (void *)&buffer[3], bytes_read); + count += bytes_read; + /* + * Drop timeout to just 1/2 second. Once the XDS110 starts sending + * a response, the remaining packets should arrive in short order + */ + if (timeout > 500) + timeout = 500; /* ms */ + + /* If there's more data to retrieve, get it now */ + while ((count < size) && success) { + success = usb_read(buffer, sizeof(buffer), &bytes_read, timeout); + if (success) { + if ((count + bytes_read) > size) { + /* Read too much data, not a valid packet, abort */ + success = false; + } else { + /* Copy this data over to xds110.read_payload */ + memcpy((void *)&xds110.read_payload[count], (void *)buffer, + bytes_read); + count += bytes_read; + } + } + } + + if (!success) + count = 0; + if (NULL != total_bytes_read) + *total_bytes_read = count; + + return success; +} + +static bool usb_send_command(uint16_t size) +{ + int written; + bool success = true; + + /* Check the packet length */ + if (size > USB_PAYLOAD_SIZE) + return false; + + /* Place the start character into the packet buffer */ + xds110.write_packet[0] = '*'; + + /* Place the payload size into the packet buffer */ + xds110_set_u16(&xds110.write_packet[1], size); + + /* Adjust size to include header */ + size += 3; + + /* Send the data via the USB connection */ + success = usb_write(xds110.write_packet, (int)size, &written); + + /* Check if the correct number of bytes was written */ + if (written != (int)size) + success = false; + + return success; +} + +/*************************************************************************** + * XDS110 firmware API routines * + * * + * The following functions handle calling into the XDS110 firmware to * + * perform requested debug actions. * + ***************************************************************************/ + +static bool xds_execute(uint32_t out_length, uint32_t in_length, + uint32_t attempts, uint32_t timeout) +{ + bool done = false; + bool success = true; + int error = 0; + uint32_t bytes_read = 0; + + if (NULL == xds110.dev) + return false; + + while (!done && attempts > 0) { + attempts--; + + /* Send command to XDS110 */ + success = usb_send_command(out_length); + + if (success) { + /* Get response from XDS110 */ + success = usb_get_response(&bytes_read, timeout); + } + + if (success) { + /* Check for valid response from XDS code handling */ + if (bytes_read != in_length) { + /* Unexpected amount of data returned */ + success = false; + } else { + /* Extract error code from return packet */ + error = (int)xds110_get_u32(&xds110.read_payload[0]); + done = true; + } + } + } + + if (!success) + error = SC_ERR_XDS110_FAIL; + + if (0 != error) + success = false; + + return success; +} + +static bool xds_connect(void) +{ + bool success; + + xds110.write_payload[0] = XDS_CONNECT; + + success = xds_execute(XDS_OUT_LEN, XDS_IN_LEN, DEFAULT_ATTEMPTS, + DEFAULT_TIMEOUT); + + return success; +} + +static bool xds_disconnect(void) +{ + bool success; + + xds110.write_payload[0] = XDS_DISCONNECT; + + success = xds_execute(XDS_OUT_LEN, XDS_IN_LEN, DEFAULT_ATTEMPTS, + DEFAULT_TIMEOUT); + + return success; +} + +static bool xds_version(uint32_t *firmware_id, uint16_t *hardware_id) +{ + uint8_t *fw_id_pntr = &xds110.read_payload[XDS_IN_LEN + 0]; /* 32-bits */ + uint8_t *hw_id_pntr = &xds110.read_payload[XDS_IN_LEN + 4]; /* 16-bits */ + + bool success; + + xds110.write_payload[0] = XDS_VERSION; + + success = xds_execute(XDS_OUT_LEN, XDS_IN_LEN + 6, DEFAULT_ATTEMPTS, + DEFAULT_TIMEOUT); + + if (success) { + if (NULL != firmware_id) + *firmware_id = xds110_get_u32(fw_id_pntr); + if (NULL != hardware_id) + *hardware_id = xds110_get_u16(hw_id_pntr); + } + + return success; +} + +static bool xds_set_tck_delay(uint32_t delay) +{ + uint8_t *delay_pntr = &xds110.write_payload[XDS_OUT_LEN + 0]; /* 32-bits */ + + bool success; + + xds110.write_payload[0] = XDS_SET_TCK; + + xds110_set_u32(delay_pntr, delay); + + success = xds_execute(XDS_OUT_LEN + 4, XDS_IN_LEN, DEFAULT_ATTEMPTS, + DEFAULT_TIMEOUT); + + return success; +} + +static bool xds_set_trst(uint8_t trst) +{ + uint8_t *trst_pntr = &xds110.write_payload[XDS_OUT_LEN + 0]; /* 8-bits */ + + bool success; + + xds110.write_payload[0] = XDS_SET_TRST; + + *trst_pntr = trst; + + success = xds_execute(XDS_OUT_LEN + 1, XDS_IN_LEN, DEFAULT_ATTEMPTS, + DEFAULT_TIMEOUT); + + return success; +} + +static bool xds_cycle_tck(uint32_t count) +{ + uint8_t *count_pntr = &xds110.write_payload[XDS_OUT_LEN + 0]; /* 32-bits */ + + bool success; + + xds110.write_payload[0] = XDS_CYCLE_TCK; + + xds110_set_u32(count_pntr, count); + + success = xds_execute(XDS_OUT_LEN + 4, XDS_IN_LEN, DEFAULT_ATTEMPTS, + DEFAULT_TIMEOUT); + + return success; +} + +static bool xds_goto_state(uint32_t state) +{ + uint8_t *state_pntr = &xds110.write_payload[XDS_OUT_LEN + 0]; /* 32-bits */ + uint8_t *transit_pntr = &xds110.write_payload[XDS_OUT_LEN+4]; /* 32-bits */ + + bool success; + + xds110.write_payload[0] = XDS_GOTO_STATE; + + xds110_set_u32(state_pntr, state); + xds110_set_u32(transit_pntr, XDS_JTAG_TRANSIT_QUICKEST); + + success = xds_execute(XDS_OUT_LEN+8, XDS_IN_LEN, DEFAULT_ATTEMPTS, + DEFAULT_TIMEOUT); + + return success; +} + +static bool xds_jtag_scan(uint32_t shift_state, uint16_t shift_bits, + uint32_t end_state, uint8_t *data_out, uint8_t *data_in) +{ + uint8_t *bits_pntr = &xds110.write_payload[XDS_OUT_LEN + 0]; /* 16-bits */ + uint8_t *path_pntr = &xds110.write_payload[XDS_OUT_LEN + 2]; /* 8-bits */ + uint8_t *trans1_pntr = &xds110.write_payload[XDS_OUT_LEN + 3]; /* 8-bits */ + uint8_t *end_pntr = &xds110.write_payload[XDS_OUT_LEN + 4]; /* 8-bits */ + uint8_t *trans2_pntr = &xds110.write_payload[XDS_OUT_LEN + 5]; /* 8-bits */ + uint8_t *pre_pntr = &xds110.write_payload[XDS_OUT_LEN + 6]; /* 16-bits */ + uint8_t *pos_pntr = &xds110.write_payload[XDS_OUT_LEN + 8]; /* 16-bits */ + uint8_t *delay_pntr = &xds110.write_payload[XDS_OUT_LEN + 10]; /* 16-bits */ + uint8_t *rep_pntr = &xds110.write_payload[XDS_OUT_LEN + 12]; /* 16-bits */ + uint8_t *out_pntr = &xds110.write_payload[XDS_OUT_LEN + 14]; /* 16-bits */ + uint8_t *in_pntr = &xds110.write_payload[XDS_OUT_LEN + 16]; /* 16-bits */ + uint8_t *data_out_pntr = &xds110.write_payload[XDS_OUT_LEN + 18]; + uint8_t *data_in_pntr = &xds110.read_payload[XDS_IN_LEN+0]; + + uint16_t total_bytes = DIV_ROUND_UP(shift_bits, 8); + + bool success; + + xds110.write_payload[0] = XDS_JTAG_SCAN; + + xds110_set_u16(bits_pntr, shift_bits); /* bits to scan */ + *path_pntr = (uint8_t)(shift_state & 0xff); /* IR vs DR path */ + *trans1_pntr = (uint8_t)XDS_JTAG_TRANSIT_QUICKEST; /* start state route */ + *end_pntr = (uint8_t)(end_state & 0xff); /* JTAG state after scan */ + *trans2_pntr = (uint8_t)XDS_JTAG_TRANSIT_QUICKEST; /* end state route */ + xds110_set_u16(pre_pntr, 0); /* number of preamble bits */ + xds110_set_u16(pos_pntr, 0); /* number of postamble bits */ + xds110_set_u16(delay_pntr, 0); /* number of extra TCKs after scan */ + xds110_set_u16(rep_pntr, 1); /* number of repetitions */ + xds110_set_u16(out_pntr, total_bytes); /* out buffer offset (if repeats) */ + xds110_set_u16(in_pntr, total_bytes); /* in buffer offset (if repeats) */ + + memcpy((void *)data_out_pntr, (void *)data_out, total_bytes); + + success = xds_execute(XDS_OUT_LEN + 18 + total_bytes, + XDS_IN_LEN + total_bytes, DEFAULT_ATTEMPTS, DEFAULT_TIMEOUT); + + if (success) + memcpy((void *)data_in, (void *)data_in_pntr, total_bytes); + + return success; +} + +static bool xds_set_srst(uint8_t srst) +{ + uint8_t *srst_pntr = &xds110.write_payload[XDS_OUT_LEN + 0]; /* 8-bits */ + + bool success; + + xds110.write_payload[0] = XDS_SET_SRST; + + *srst_pntr = srst; + + success = xds_execute(XDS_OUT_LEN + 1, XDS_IN_LEN, DEFAULT_ATTEMPTS, + DEFAULT_TIMEOUT); + + return success; +} + +static bool cmapi_connect(uint32_t *idcode) +{ + uint8_t *idcode_pntr = &xds110.read_payload[XDS_IN_LEN + 0]; /* 32-bits */ + + bool success; + + xds110.write_payload[0] = CMAPI_CONNECT; + + success = xds_execute(XDS_OUT_LEN, XDS_IN_LEN+4, DEFAULT_ATTEMPTS, + DEFAULT_TIMEOUT); + + if (success) { + if (NULL != idcode) + *idcode = xds110_get_u32(idcode_pntr); + } + + return success; +} + +static bool cmapi_disconnect(void) +{ + bool success; + + xds110.write_payload[0] = CMAPI_DISCONNECT; + + success = xds_execute(XDS_OUT_LEN, XDS_IN_LEN, DEFAULT_ATTEMPTS, + DEFAULT_TIMEOUT); + + return success; +} + +static bool cmapi_acquire(void) +{ + bool success; + + xds110.write_payload[0] = CMAPI_ACQUIRE; + + success = xds_execute(XDS_OUT_LEN, XDS_IN_LEN, DEFAULT_ATTEMPTS, + DEFAULT_TIMEOUT); + + return success; +} + +static bool cmapi_release(void) +{ + bool success; + + xds110.write_payload[0] = CMAPI_RELEASE; + + success = xds_execute(XDS_OUT_LEN, XDS_IN_LEN, DEFAULT_ATTEMPTS, + DEFAULT_TIMEOUT); + + return success; +} + +static bool cmapi_read_dap_reg(uint32_t type, uint32_t ap_num, + uint32_t address, uint32_t *value) +{ + uint8_t *type_pntr = &xds110.write_payload[XDS_OUT_LEN + 0]; /* 8-bits */ + uint8_t *ap_num_pntr = &xds110.write_payload[XDS_OUT_LEN + 1]; /* 8-bits */ + uint8_t *address_pntr = &xds110.write_payload[XDS_OUT_LEN + 2]; /* 8-bits */ + uint8_t *value_pntr = &xds110.read_payload[XDS_IN_LEN + 0]; /* 32-bits */ + + bool success; + + xds110.write_payload[0] = CMAPI_REG_READ; + + *type_pntr = (uint8_t)(type & 0xff); + *ap_num_pntr = (uint8_t)(ap_num & 0xff); + *address_pntr = (uint8_t)(address & 0xff); + + success = xds_execute(XDS_OUT_LEN + 3, XDS_IN_LEN + 4, DEFAULT_ATTEMPTS, + DEFAULT_TIMEOUT); + + if (success) { + if (NULL != value) + *value = xds110_get_u32(value_pntr); + } + + return success; +} + +static bool cmapi_write_dap_reg(uint32_t type, uint32_t ap_num, + uint32_t address, uint32_t *value) +{ + uint8_t *type_pntr = &xds110.write_payload[XDS_OUT_LEN + 0]; /* 8-bits */ + uint8_t *ap_num_pntr = &xds110.write_payload[XDS_OUT_LEN + 1]; /* 8-bits */ + uint8_t *address_pntr = &xds110.write_payload[XDS_OUT_LEN + 2]; /* 8-bits */ + uint8_t *value_pntr = &xds110.write_payload[XDS_OUT_LEN + 3]; /* 32-bits */ + + bool success; + + if (NULL == value) + return false; + + xds110.write_payload[0] = CMAPI_REG_WRITE; + + *type_pntr = (uint8_t)(type & 0xff); + *ap_num_pntr = (uint8_t)(ap_num & 0xff); + *address_pntr = (uint8_t)(address & 0xff); + xds110_set_u32(value_pntr, *value); + + success = xds_execute(XDS_OUT_LEN + 7, XDS_IN_LEN, DEFAULT_ATTEMPTS, + DEFAULT_TIMEOUT); + + return success; +} + +static bool swd_connect(void) +{ + bool success; + + xds110.write_payload[0] = SWD_CONNECT; + + success = xds_execute(XDS_OUT_LEN, XDS_IN_LEN, DEFAULT_ATTEMPTS, + DEFAULT_TIMEOUT); + + return success; +} + +static bool swd_disconnect(void) +{ + bool success; + + xds110.write_payload[0] = SWD_DISCONNECT; + + success = xds_execute(XDS_OUT_LEN, XDS_IN_LEN, DEFAULT_ATTEMPTS, + DEFAULT_TIMEOUT); + + return success; +} + +static bool cjtag_connect(uint32_t format) +{ + uint8_t *format_pntr = &xds110.write_payload[XDS_OUT_LEN + 0]; /* 32-bits */ + + bool success; + + xds110.write_payload[0] = CJTAG_CONNECT; + + xds110_set_u32(format_pntr, format); + + success = xds_execute(XDS_OUT_LEN + 4, XDS_IN_LEN, DEFAULT_ATTEMPTS, + DEFAULT_TIMEOUT); + + return success; +} + +static bool cjtag_disconnect(void) +{ + bool success; + + xds110.write_payload[0] = CJTAG_DISCONNECT; + + success = xds_execute(XDS_OUT_LEN, XDS_IN_LEN, DEFAULT_ATTEMPTS, + DEFAULT_TIMEOUT); + + return success; +} + +static bool ocd_dap_request(uint8_t *dap_requests, uint32_t request_size, + uint32_t *dap_results, uint32_t result_count) +{ + uint8_t *request_pntr = &xds110.write_payload[XDS_OUT_LEN + 0]; + uint8_t *result_pntr = &xds110.read_payload[XDS_IN_LEN + 0]; + + bool success; + + if (NULL == dap_requests || NULL == dap_results) + return false; + + xds110.write_payload[0] = OCD_DAP_REQUEST; + + memcpy((void *)request_pntr, (void *)dap_requests, request_size); + + success = xds_execute(XDS_OUT_LEN + request_size, + XDS_IN_LEN + (result_count * 4), DEFAULT_ATTEMPTS, + DEFAULT_TIMEOUT); + + if (success && (result_count > 0)) + memcpy((void *)dap_results, (void *)result_pntr, result_count * 4); + + return success; +} + +static bool ocd_scan_request(uint8_t *scan_requests, uint32_t request_size, + uint8_t *scan_results, uint32_t result_size) +{ + uint8_t *request_pntr = &xds110.write_payload[XDS_OUT_LEN + 0]; + uint8_t *result_pntr = &xds110.read_payload[XDS_IN_LEN + 0]; + + bool success; + + if (NULL == scan_requests || NULL == scan_results) + return false; + + xds110.write_payload[0] = OCD_SCAN_REQUEST; + + memcpy((void *)request_pntr, (void *)scan_requests, request_size); + + success = xds_execute(XDS_OUT_LEN + request_size, + XDS_IN_LEN + result_size, DEFAULT_ATTEMPTS, + DEFAULT_TIMEOUT); + + if (success && (result_size > 0)) + memcpy((void *)scan_results, (void *)result_pntr, result_size); + + return success; +} + +static bool ocd_pathmove(uint32_t num_states, uint8_t *path) +{ + uint8_t *num_pntr = &xds110.write_payload[XDS_OUT_LEN + 0]; /* 32-bits */ + uint8_t *path_pntr = &xds110.write_payload[XDS_OUT_LEN + 4]; + + bool success; + + if (NULL == path) + return false; + + xds110.write_payload[0] = OCD_PATHMOVE; + + xds110_set_u32(num_pntr, num_states); + + memcpy((void *)path_pntr, (void *)path, num_states); + + success = xds_execute(XDS_OUT_LEN + 4 + num_states, XDS_IN_LEN, + DEFAULT_ATTEMPTS, DEFAULT_TIMEOUT); + + return success; +} + +/*************************************************************************** + * swd driver interface * + * * + * The following functions provide SWD support to OpenOCD. * + ***************************************************************************/ + +static int xds110_swd_init(void) +{ + xds110.is_swd_mode = true; + return ERROR_OK; +} + +static int xds110_swd_switch_seq(enum swd_special_seq seq) +{ + uint32_t idcode; + bool success; + + switch (seq) { + case LINE_RESET: + LOG_ERROR("Sequence SWD line reset (%d) not supported", seq); + return ERROR_FAIL; + case JTAG_TO_SWD: + LOG_DEBUG("JTAG-to-SWD"); + xds110.is_swd_mode = false; + xds110.is_cmapi_connected = false; + xds110.is_cmapi_acquired = false; + /* Run sequence to put target in SWD mode */ + success = swd_connect(); + /* Re-iniitialize CMAPI API for DAP access */ + if (success) { + xds110.is_swd_mode = true; + success = cmapi_connect(&idcode); + if (success) { + xds110.is_cmapi_connected = true; + success = cmapi_acquire(); + } + } + break; + case SWD_TO_JTAG: + LOG_DEBUG("SWD-to-JTAG"); + xds110.is_swd_mode = false; + xds110.is_cmapi_connected = false; + xds110.is_cmapi_acquired = false; + /* Run sequence to put target in JTAG mode */ + success = swd_disconnect(); + if (success) { + /* Re-initialize JTAG interface */ + success = cjtag_connect(MODE_JTAG); + } + break; + default: + LOG_ERROR("Sequence %d not supported", seq); + return ERROR_FAIL; + } + + if (success) + return ERROR_OK; + else + return ERROR_FAIL; +} + +static bool xds110_legacy_read_reg(uint8_t cmd, uint32_t *value) +{ + /* Make sure this is a read request */ + bool is_read_request = (0 != (SWD_CMD_RnW & cmd)); + /* Determine whether this is a DP or AP register access */ + uint32_t type = (0 != (SWD_CMD_APnDP & cmd)) ? DAP_AP : DAP_DP; + /* Determine the AP number from cached SELECT value */ + uint32_t ap_num = (xds110.select & 0xff000000) >> 24; + /* Extract register address from command */ + uint32_t address = ((cmd & SWD_CMD_A32) >> 1); + /* Extract bank address from cached SELECT value */ + uint32_t bank = (xds110.select & 0x000000f0); + + uint32_t reg_value = 0; + uint32_t temp_value = 0; + + bool success; + + if (!is_read_request) + return false; + + if (DAP_AP == type) { + /* Add bank address to register address for CMAPI call */ + address |= bank; + } + + if (DAP_DP == type && DAP_DP_RDBUFF == address && xds110.use_rdbuff) { + /* If RDBUFF is cached and this is a DP RDBUFF read, use the cache */ + reg_value = xds110.rdbuff; + success = true; + } else if (DAP_AP == type && DAP_AP_DRW == address && xds110.use_rdbuff) { + /* If RDBUFF is cached and this is an AP DRW read, use the cache, */ + /* but still call into the firmware to get the next read. */ + reg_value = xds110.rdbuff; + success = cmapi_read_dap_reg(type, ap_num, address, &temp_value); + } else { + success = cmapi_read_dap_reg(type, ap_num, address, &temp_value); + if (success) + reg_value = temp_value; + } + + /* Mark that we have consumed or invalidated the RDBUFF cache */ + xds110.use_rdbuff = false; + + /* Handle result of read attempt */ + if (!success) + LOG_ERROR("XDS110: failed to read DAP register"); + else if (NULL != value) + *value = reg_value; + + if (success && DAP_AP == type) { + /* + * On a successful DAP AP read, we actually have the value from RDBUFF, + * the firmware will have run the AP request and made the RDBUFF read + */ + xds110.use_rdbuff = true; + xds110.rdbuff = temp_value; + } + + return success; +} + +static bool xds110_legacy_write_reg(uint8_t cmd, uint32_t value) +{ + /* Make sure this isn't a read request */ + bool is_read_request = (0 != (SWD_CMD_RnW & cmd)); + /* Determine whether this is a DP or AP register access */ + uint32_t type = (0 != (SWD_CMD_APnDP & cmd)) ? DAP_AP : DAP_DP; + /* Determine the AP number from cached SELECT value */ + uint32_t ap_num = (xds110.select & 0xff000000) >> 24; + /* Extract register address from command */ + uint32_t address = ((cmd & SWD_CMD_A32) >> 1); + /* Extract bank address from cached SELECT value */ + uint32_t bank = (xds110.select & 0x000000f0); + + bool success; + + if (is_read_request) + return false; + + /* Invalidate the RDBUFF cache */ + xds110.use_rdbuff = false; + + if (DAP_AP == type) { + /* Add bank address to register address for CMAPI call */ + address |= bank; + /* Any write to an AP register invalidates the firmware's cache */ + xds110.is_ap_dirty = true; + } else if (DAP_DP_SELECT == address) { + /* Any write to the SELECT register invalidates the firmware's cache */ + xds110.is_ap_dirty = true; + } + + success = cmapi_write_dap_reg(type, ap_num, address, &value); + + if (!success) { + LOG_ERROR("XDS110: failed to write DAP register"); + } else { + /* + * If the debugger wrote to SELECT, cache the value + * to use to build the apNum and address values above + */ + if ((DAP_DP == type) && (DAP_DP_SELECT == address)) + xds110.select = value; + } + + return success; +} + +static int xds110_swd_run_queue(void) +{ + static uint32_t dap_results[MAX_RESULT_QUEUE]; + uint8_t cmd; + uint32_t request; + uint32_t result; + uint32_t value; + bool success = true; + + if (0 == xds110.txn_request_size) + return ERROR_OK; + + /* Terminate request queue */ + xds110.txn_requests[xds110.txn_request_size++] = 0; + + if (xds110.firmware >= OCD_FIRMWARE_VERSION) { + /* XDS110 firmware has the API to directly handle the queue */ + success = ocd_dap_request(xds110.txn_requests, + xds110.txn_request_size, dap_results, xds110.txn_result_count); + } else { + /* Legacy firmware needs to handle queue via discrete DAP calls */ + request = 0; + result = 0; + while (xds110.txn_requests[request] != 0) { + cmd = xds110.txn_requests[request++]; + if (0 == (SWD_CMD_RnW & cmd)) { + /* DAP register write command */ + value = (uint32_t)(xds110.txn_requests[request++]) << 0; + value |= (uint32_t)(xds110.txn_requests[request++]) << 8; + value |= (uint32_t)(xds110.txn_requests[request++]) << 16; + value |= (uint32_t)(xds110.txn_requests[request++]) << 24; + if (success) + success = xds110_legacy_write_reg(cmd, value); + } else { + /* DAP register read command */ + value = 0; + if (success) + success = xds110_legacy_read_reg(cmd, &value); + dap_results[result++] = value; + } + } + } + + /* Transfer results into caller's buffers */ + for (result = 0; result < xds110.txn_result_count; result++) + if (0 != xds110.txn_dap_results[result]) + *xds110.txn_dap_results[result] = dap_results[result]; + + xds110.txn_request_size = 0; + xds110.txn_result_size = 0; + xds110.txn_result_count = 0; + + return (success) ? ERROR_OK : ERROR_FAIL; +} + +static void xds110_swd_queue_cmd(uint8_t cmd, uint32_t *value) +{ + /* Check if this is a read or write request */ + bool is_read_request = (0 != (SWD_CMD_RnW & cmd)); + /* Determine whether this is a DP or AP register access */ + uint32_t type = (0 != (SWD_CMD_APnDP & cmd)) ? DAP_AP : DAP_DP; + /* Extract register address from command */ + uint32_t address = ((cmd & SWD_CMD_A32) >> 1); + uint32_t request_size = (is_read_request) ? 1 : 5; + + /* Check if new request would be too large to fit */ + if (((xds110.txn_request_size + request_size + 1) > MAX_DATA_BLOCK) || + ((xds110.txn_result_count + 1) > MAX_RESULT_QUEUE)) + xds110_swd_run_queue(); + + /* Set the START bit in cmd to ensure cmd is not zero */ + /* (a value of zero is used to terminate the buffer) */ + cmd |= SWD_CMD_START; + + /* Add request to queue; queue is built marshalled for XDS110 call */ + if (is_read_request) { + /* Queue read request, save pointer to pass back result */ + xds110.txn_requests[xds110.txn_request_size++] = cmd; + xds110.txn_dap_results[xds110.txn_result_count++] = value; + xds110.txn_result_size += 4; + } else { + /* Check for and prevent sticky overrun detection */ + if (DAP_DP == type && DAP_DP_CTRL == address && + (*value & CORUNDETECT)) { + LOG_DEBUG("XDS110: refusing to enable sticky overrun detection"); + *value &= ~CORUNDETECT; + } + /* Queue write request, add value directly to queue buffer */ + xds110.txn_requests[xds110.txn_request_size++] = cmd; + xds110.txn_requests[xds110.txn_request_size++] = (*value >> 0) & 0xff; + xds110.txn_requests[xds110.txn_request_size++] = (*value >> 8) & 0xff; + xds110.txn_requests[xds110.txn_request_size++] = (*value >> 16) & 0xff; + xds110.txn_requests[xds110.txn_request_size++] = (*value >> 24) & 0xff; + } +} + +static void xds110_swd_read_reg(uint8_t cmd, uint32_t *value, + uint32_t ap_delay_clk) +{ + xds110_swd_queue_cmd(cmd, value); +} +static void xds110_swd_write_reg(uint8_t cmd, uint32_t value, + uint32_t ap_delay_clk) +{ + xds110_swd_queue_cmd(cmd, &value); +} + +/*************************************************************************** + * jtag interface * + * * + * The following functions provide XDS110 interface to OpenOCD. * + ***************************************************************************/ + +static void xds110_show_info(void) +{ + uint32_t firmware = xds110.firmware; + + LOG_INFO("XDS110: firmware version = %d.%d.%d.%d", + (((firmware >> 28) & 0xf) * 10) + ((firmware >> 24) & 0xf), + (((firmware >> 20) & 0xf) * 10) + ((firmware >> 16) & 0xf), + (((firmware >> 12) & 0xf) * 10) + ((firmware >> 8) & 0xf), + (((firmware >> 4) & 0xf) * 10) + ((firmware >> 0) & 0xf)); + LOG_INFO("XDS110: hardware version = 0x%04x", xds110.hardware); + if (0 != xds110.serial[0]) + LOG_INFO("XDS110: serial number = %s)", xds110.serial); + if (xds110.is_swd_mode) { + LOG_INFO("XDS110: connected to target via SWD"); + LOG_INFO("XDS110: SWCLK set to %d kHz", xds110.speed); + } else { + LOG_INFO("XDS110: connected to target via JTAG"); + LOG_INFO("XDS110: TCK set to %d kHz", xds110.speed); + } + + /* Alert user that there's a better firmware to use */ + if (firmware < OCD_FIRMWARE_VERSION) { + LOG_WARNING("XDS110: the firmware is not optimized for OpenOCD"); + LOG_WARNING(OCD_FIRMWARE_UPGRADE); + } +} + +static int xds110_quit(void) +{ + if (xds110.is_cmapi_acquired) { + (void)cmapi_release(); + xds110.is_cmapi_acquired = false; + } + if (xds110.is_cmapi_connected) { + (void)cmapi_disconnect(); + xds110.is_cmapi_connected = false; + } + if (xds110.is_connected) { + if (xds110.is_swd_mode) { + /* Switch out of SWD mode */ + (void)swd_disconnect(); + } else { + /* Switch out of cJTAG mode */ + (void)cjtag_disconnect(); + } + /* Tell firmware we're disconnecting */ + (void)xds_disconnect(); + xds110.is_connected = false; + } + /* Close down the USB connection to the XDS110 debug probe */ + usb_disconnect(); + + return ERROR_OK; +} + +static int xds110_init(void) +{ + bool success; + + /* Establish USB connection to the XDS110 debug probe */ + success = usb_connect(); + + if (success) { + /* Send connect message to XDS110 firmware */ + success = xds_connect(); + if (success) + xds110.is_connected = true; + } + + if (success) { + uint32_t firmware; + uint16_t hardware; + + /* Retrieve version IDs from firmware */ + /* Version numbers are stored in BCD format */ + success = xds_version(&firmware, &hardware); + if (success) { + /* Save the firmware and hardware version */ + xds110.firmware = firmware; + xds110.hardware = hardware; + } + } + + if (success) { + success = xds_set_trst(0); + if (success) + success = xds_cycle_tck(50); + if (success) + success = xds_set_trst(1); + if (success) + success = xds_cycle_tck(50); + } + + if (success) { + if (xds110.is_swd_mode) { + /* Switch to SWD if needed */ + success = swd_connect(); + } else { + success = cjtag_connect(MODE_JTAG); + } + } + + if (success && xds110.is_swd_mode) { + uint32_t idcode; + + /* Connect to CMAPI interface in XDS110 */ + success = cmapi_connect(&idcode); + + /* Acquire exclusive access to CMAPI interface */ + if (success) { + xds110.is_cmapi_connected = true; + success = cmapi_acquire(); + if (success) + xds110.is_cmapi_acquired = true; + } + } + + if (!success) + xds110_quit(); + + if (success) + xds110_show_info(); + + return (success) ? ERROR_OK : ERROR_FAIL; +} + +static void xds110_legacy_scan(uint32_t shift_state, uint32_t total_bits, + uint32_t end_state, uint8_t *data_out, uint8_t *data_in) +{ + (void)xds_jtag_scan(shift_state, total_bits, end_state, data_out, data_in); +} + +static void xds110_legacy_runtest(uint32_t clocks, uint32_t end_state) +{ + xds_goto_state(XDS_JTAG_STATE_IDLE); + xds_cycle_tck(clocks); + xds_goto_state(end_state); +} + +static void xds110_legacy_stableclocks(uint32_t clocks) +{ + xds_cycle_tck(clocks); +} + +static void xds110_flush(void) +{ + uint8_t command; + uint32_t clocks; + uint32_t shift_state; + uint32_t end_state; + uint32_t bits; + uint32_t bytes; + uint32_t request; + uint32_t result; + uint8_t *data_out; + uint8_t data_in[MAX_DATA_BLOCK]; + uint8_t *data_pntr; + + if (0 == xds110.txn_request_size) + return; + + /* Terminate request queue */ + xds110.txn_requests[xds110.txn_request_size++] = 0; + + if (xds110.firmware >= OCD_FIRMWARE_VERSION) { + /* Updated firmware has the API to directly handle the queue */ + (void)ocd_scan_request(xds110.txn_requests, xds110.txn_request_size, + data_in, xds110.txn_result_size); + } else { + /* Legacy firmware needs to handle queue via discrete JTAG calls */ + request = 0; + result = 0; + while (xds110.txn_requests[request] != 0) { + command = xds110.txn_requests[request++]; + switch (command) { + case CMD_IR_SCAN: + case CMD_DR_SCAN: + if (command == CMD_IR_SCAN) + shift_state = XDS_JTAG_STATE_SHIFT_IR; + else + shift_state = XDS_JTAG_STATE_SHIFT_DR; + end_state = (uint32_t)(xds110.txn_requests[request++]); + bits = (uint32_t)(xds110.txn_requests[request++]) << 0; + bits |= (uint32_t)(xds110.txn_requests[request++]) << 8; + data_out = &xds110.txn_requests[request]; + bytes = DIV_ROUND_UP(bits, 8); + xds110_legacy_scan(shift_state, bits, end_state, data_out, + &data_in[result]); + result += bytes; + request += bytes; + break; + case CMD_RUNTEST: + clocks = (uint32_t)(xds110.txn_requests[request++]) << 0; + clocks |= (uint32_t)(xds110.txn_requests[request++]) << 8; + clocks |= (uint32_t)(xds110.txn_requests[request++]) << 16; + clocks |= (uint32_t)(xds110.txn_requests[request++]) << 24; + end_state = (uint32_t)xds110.txn_requests[request++]; + xds110_legacy_runtest(clocks, end_state); + break; + case CMD_STABLECLOCKS: + clocks = (uint32_t)(xds110.txn_requests[request++]) << 0; + clocks |= (uint32_t)(xds110.txn_requests[request++]) << 8; + clocks |= (uint32_t)(xds110.txn_requests[request++]) << 16; + clocks |= (uint32_t)(xds110.txn_requests[request++]) << 24; + xds110_legacy_stableclocks(clocks); + break; + default: + LOG_ERROR("BUG: unknown JTAG command type 0x%x encountered", + command); + exit(-1); + break; + } + } + } + + /* Transfer results into caller's buffers from data_in buffer */ + bits = 0; /* Bit offset into current scan result */ + data_pntr = data_in; + for (result = 0; result < xds110.txn_result_count; result++) { + if (xds110.txn_scan_results[result].first) { + if (bits != 0) { + bytes = DIV_ROUND_UP(bits, 8); + data_pntr += bytes; + } + bits = 0; + } + if (xds110.txn_scan_results[result].buffer != 0) + bit_copy(xds110.txn_scan_results[result].buffer, 0, data_pntr, + bits, xds110.txn_scan_results[result].num_bits); + bits += xds110.txn_scan_results[result].num_bits; + } + + xds110.txn_request_size = 0; + xds110.txn_result_size = 0; + xds110.txn_result_count = 0; +} + +static void xds110_execute_reset(struct jtag_command *cmd) +{ + char trst; + char srst; + + if (cmd->cmd.reset->trst != -1) { + if (cmd->cmd.reset->trst == 0) { + /* Deassert nTRST (active low) */ + trst = 1; + } else { + /* Assert nTRST (active low) */ + trst = 0; + } + (void)xds_set_trst(trst); + } + + if (cmd->cmd.reset->srst != -1) { + if (cmd->cmd.reset->srst == 0) { + /* Deassert nSRST (active low) */ + srst = 1; + } else { + /* Assert nSRST (active low) */ + srst = 0; + } + (void)xds_set_srst(srst); + } +} + +static void xds110_execute_sleep(struct jtag_command *cmd) +{ + jtag_sleep(cmd->cmd.sleep->us); + return; +} + +static void xds110_execute_tlr_reset(struct jtag_command *cmd) +{ + (void)xds_goto_state(XDS_JTAG_STATE_RESET); + + return; +} + +static void xds110_execute_pathmove(struct jtag_command *cmd) +{ + uint32_t i; + uint32_t num_states; + uint8_t *path; + + num_states = (uint32_t)cmd->cmd.pathmove->num_states; + + if (num_states == 0) + return; + + path = (uint8_t *)malloc(num_states * sizeof(uint8_t)); + if (path == 0) { + LOG_ERROR("XDS110: unable to allocate memory"); + return; + } + + /* Convert requested path states into XDS API states */ + for (i = 0; i < num_states; i++) + path[i] = (uint8_t)xds_jtag_state[cmd->cmd.pathmove->path[i]]; + + if (xds110.firmware >= OCD_FIRMWARE_VERSION) { + /* Updated firmware fully supports pathmove */ + (void)ocd_pathmove(num_states, path); + } else { + /* Notify user that legacy firmware simply cannot handle pathmove */ + LOG_ERROR("XDS110: the firmware does not support pathmove command"); + LOG_ERROR(OCD_FIRMWARE_UPGRADE); + /* If pathmove is required, then debug is not possible */ + exit(-1); + } + + free((void *)path); + + return; +} + +static void xds110_queue_scan(struct jtag_command *cmd) +{ + int i; + uint32_t offset; + uint32_t total_fields; + uint32_t total_bits; + uint32_t total_bytes; + uint8_t end_state; + uint8_t *buffer; + + /* Calculate the total number of bits to scan */ + total_bits = 0; + total_fields = 0; + for (i = 0; i < cmd->cmd.scan->num_fields; i++) { + total_fields++; + total_bits += (uint32_t)cmd->cmd.scan->fields[i].num_bits; + } + + if (total_bits == 0) + return; + + total_bytes = DIV_ROUND_UP(total_bits, 8); + + /* Check if new request would be too large to fit */ + if (((xds110.txn_request_size + 1 + total_bytes + sizeof(end_state) + 1) + > MAX_DATA_BLOCK) || ((xds110.txn_result_count + total_fields) > + MAX_RESULT_QUEUE)) + xds110_flush(); + + /* Check if this single request is too large to fit */ + if ((1 + total_bytes + sizeof(end_state) + 1) > MAX_DATA_BLOCK) { + LOG_ERROR("BUG: JTAG scan request is too large to handle (%d bits)", + total_bits); + /* Failing to run this scan mucks up debug on this target */ + exit(-1); + } + + if (cmd->cmd.scan->ir_scan) + xds110.txn_requests[xds110.txn_request_size++] = CMD_IR_SCAN; + else + xds110.txn_requests[xds110.txn_request_size++] = CMD_DR_SCAN; + + end_state = (uint8_t)xds_jtag_state[cmd->cmd.scan->end_state]; + xds110.txn_requests[xds110.txn_request_size++] = end_state; + + xds110.txn_requests[xds110.txn_request_size++] = (total_bits >> 0) & 0xff; + xds110.txn_requests[xds110.txn_request_size++] = (total_bits >> 8) & 0xff; + + /* Build request data by flattening fields into single buffer */ + /* also populate the results array to return the results when run */ + offset = 0; + buffer = &xds110.txn_requests[xds110.txn_request_size]; + /* Clear data out buffer to default value of all zeros */ + memset((void *)buffer, 0x00, total_bytes); + for (i = 0; i < cmd->cmd.scan->num_fields; i++) { + if (cmd->cmd.scan->fields[i].out_value != 0) { + /* Copy over data to scan out into request buffer */ + bit_copy(buffer, offset, cmd->cmd.scan->fields[i].out_value, 0, + cmd->cmd.scan->fields[i].num_bits); + } + offset += cmd->cmd.scan->fields[i].num_bits; + xds110.txn_scan_results[xds110.txn_result_count].first = (i == 0); + xds110.txn_scan_results[xds110.txn_result_count].num_bits = + cmd->cmd.scan->fields[i].num_bits; + xds110.txn_scan_results[xds110.txn_result_count++].buffer = + cmd->cmd.scan->fields[i].in_value; + } + xds110.txn_request_size += total_bytes; + xds110.txn_result_size += total_bytes; + + return; +} + +static void xds110_queue_runtest(struct jtag_command *cmd) +{ + uint32_t clocks = (uint32_t)cmd->cmd.stableclocks->num_cycles; + uint8_t end_state = (uint8_t)xds_jtag_state[cmd->cmd.runtest->end_state]; + + /* Check if new request would be too large to fit */ + if ((xds110.txn_request_size + 1 + sizeof(clocks) + sizeof(end_state) + 1) + > MAX_DATA_BLOCK) + xds110_flush(); + + /* Queue request and cycle count directly to queue buffer */ + xds110.txn_requests[xds110.txn_request_size++] = CMD_RUNTEST; + xds110.txn_requests[xds110.txn_request_size++] = (clocks >> 0) & 0xff; + xds110.txn_requests[xds110.txn_request_size++] = (clocks >> 8) & 0xff; + xds110.txn_requests[xds110.txn_request_size++] = (clocks >> 16) & 0xff; + xds110.txn_requests[xds110.txn_request_size++] = (clocks >> 24) & 0xff; + xds110.txn_requests[xds110.txn_request_size++] = end_state; + + return; +} + +static void xds110_queue_stableclocks(struct jtag_command *cmd) +{ + uint32_t clocks = (uint32_t)cmd->cmd.stableclocks->num_cycles; + + /* Check if new request would be too large to fit */ + if ((xds110.txn_request_size + 1 + sizeof(clocks) + 1) > MAX_DATA_BLOCK) + xds110_flush(); + + /* Queue request and cycle count directly to queue buffer */ + xds110.txn_requests[xds110.txn_request_size++] = CMD_STABLECLOCKS; + xds110.txn_requests[xds110.txn_request_size++] = (clocks >> 0) & 0xff; + xds110.txn_requests[xds110.txn_request_size++] = (clocks >> 8) & 0xff; + xds110.txn_requests[xds110.txn_request_size++] = (clocks >> 16) & 0xff; + xds110.txn_requests[xds110.txn_request_size++] = (clocks >> 24) & 0xff; + + return; +} + +static void xds110_execute_command(struct jtag_command *cmd) +{ + switch (cmd->type) { + case JTAG_RESET: + xds110_flush(); + xds110_execute_reset(cmd); + break; + case JTAG_SLEEP: + xds110_flush(); + xds110_execute_sleep(cmd); + break; + case JTAG_TLR_RESET: + xds110_flush(); + xds110_execute_tlr_reset(cmd); + break; + case JTAG_PATHMOVE: + xds110_flush(); + xds110_execute_pathmove(cmd); + break; + case JTAG_SCAN: + xds110_queue_scan(cmd); + break; + case JTAG_RUNTEST: + xds110_queue_runtest(cmd); + break; + case JTAG_STABLECLOCKS: + xds110_queue_stableclocks(cmd); + break; + case JTAG_TMS: + default: + LOG_ERROR("BUG: unknown JTAG command type 0x%x encountered", + cmd->type); + exit(-1); + } +} + +static int xds110_execute_queue(void) +{ + struct jtag_command *cmd = jtag_command_queue; + + while (cmd != NULL) { + xds110_execute_command(cmd); + cmd = cmd->next; + } + + xds110_flush(); + + return ERROR_OK; +} + +static int xds110_speed(int speed) +{ + bool success; + + if (speed == 0) { + LOG_INFO("XDS110: RTCK not supported"); + return ERROR_JTAG_NOT_IMPLEMENTED; + } + + if (speed > XDS110_MAX_TCK_SPEED) { + LOG_INFO("XDS110: reduce speed request: %dkHz to %dkHz maximum", + speed, XDS110_MAX_TCK_SPEED); + speed = XDS110_MAX_TCK_SPEED; + } + + if (speed < XDS110_MIN_TCK_SPEED) { + LOG_INFO("XDS110: increase speed request: %dkHz to %dkHz minimum", + speed, XDS110_MIN_TCK_SPEED); + speed = XDS110_MIN_TCK_SPEED; + } + + /* The default is the maximum frequency the XDS110 can support */ + uint32_t freq_to_use = XDS110_MAX_TCK_SPEED * 1000; /* Hz */ + uint32_t delay_count = 0; + + if (XDS110_MAX_TCK_SPEED != speed) { + freq_to_use = speed * 1000; /* Hz */ + + /* Calculate the delay count value */ + double one_giga = 1000000000; + /* Get the pulse duration for the maximum frequency supported in ns */ + double max_freq_pulse_duration = one_giga / + (XDS110_MAX_TCK_SPEED * 1000); + + /* Convert frequency to pulse duration */ + double freq_to_pulse_width_in_ns = one_giga / freq_to_use; + + /* + * Start with the pulse duration for the maximum frequency. Keep + * decrementing the time added by each count value till the requested + * frequency pulse is less than the calculated value. + */ + double current_value = max_freq_pulse_duration; + + while (current_value < freq_to_pulse_width_in_ns) { + current_value += XDS110_TCK_PULSE_INCREMENT; + ++delay_count; + } + + /* + * Determine which delay count yields the best match. + * The one obtained above or one less. + */ + if (delay_count) { + double diff_freq_1 = freq_to_use - + (one_giga / (max_freq_pulse_duration + + (XDS110_TCK_PULSE_INCREMENT * delay_count))); + double diff_freq_2 = (one_giga / (max_freq_pulse_duration + + (XDS110_TCK_PULSE_INCREMENT * (delay_count - 1)))) - + freq_to_use; + + /* One less count value yields a better match */ + if (diff_freq_1 > diff_freq_2) + --delay_count; + } + } + + /* Send the delay count to the XDS110 firmware */ + success = xds_set_tck_delay(delay_count); + + if (success) { + xds110.delay_count = delay_count; + xds110.speed = speed; + } + + return (success) ? ERROR_OK : ERROR_FAIL; +} + +static int xds110_speed_div(int speed, int *khz) +{ + *khz = speed; + return ERROR_OK; +} + +static int xds110_khz(int khz, int *jtag_speed) +{ + *jtag_speed = khz; + return ERROR_OK; +} + +static int_least32_t xds110_swd_frequency(int_least32_t hz) +{ + if (hz > 0) + xds110_speed(hz / 1000); + return hz; +} + +COMMAND_HANDLER(xds110_handle_info_command) +{ + xds110_show_info(); + return ERROR_OK; +} + +COMMAND_HANDLER(xds110_handle_serial_command) +{ + wchar_t serial[XDS110_SERIAL_LEN + 1]; + + xds110.serial[0] = 0; + + if (CMD_ARGC == 1) { + size_t len = mbstowcs(0, CMD_ARGV[0], 0); + if (len > XDS110_SERIAL_LEN) { + LOG_ERROR("XDS110: serial number is limited to %d characters", + XDS110_SERIAL_LEN); + return ERROR_FAIL; + } + if ((size_t)-1 == mbstowcs(serial, CMD_ARGV[0], len + 1)) { + LOG_ERROR("XDS110: unable to convert serial number"); + return ERROR_FAIL; + } + + for (uint32_t i = 0; i < len; i++) + xds110.serial[i] = (char)serial[i]; + + xds110.serial[len] = 0; + } else { + LOG_ERROR("XDS110: expected exactly one argument to xds110_serial " + "<serial-number>"); + return ERROR_FAIL; + } + + return ERROR_OK; +} + +static const struct command_registration xds110_subcommand_handlers[] = { + { + .name = "info", + .handler = &xds110_handle_info_command, + .mode = COMMAND_EXEC, + .usage = "", + .help = "show XDS110 info", + }, + COMMAND_REGISTRATION_DONE +}; + +static const struct command_registration xds110_command_handlers[] = { + { + .name = "xds110", + .mode = COMMAND_ANY, + .help = "perform XDS110 management", + .usage = "<cmd>", + .chain = xds110_subcommand_handlers, + }, + { + .name = "xds110_serial", + .handler = &xds110_handle_serial_command, + .mode = COMMAND_CONFIG, + .help = "set the XDS110 probe serial number", + .usage = "serial_string", + }, + COMMAND_REGISTRATION_DONE +}; + +static const struct swd_driver xds110_swd_driver = { + .init = xds110_swd_init, + .frequency = xds110_swd_frequency, + .switch_seq = xds110_swd_switch_seq, + .read_reg = xds110_swd_read_reg, + .write_reg = xds110_swd_write_reg, + .run = xds110_swd_run_queue, +}; + +static const char * const xds110_transport[] = { "swd", "jtag", NULL }; + +struct jtag_interface xds110_interface = { + .name = "xds110", + .commands = xds110_command_handlers, + .swd = &xds110_swd_driver, + .transports = xds110_transport, + + .execute_queue = xds110_execute_queue, + .speed = xds110_speed, + .speed_div = xds110_speed_div, + .khz = xds110_khz, + .init = xds110_init, + .quit = xds110_quit, +}; diff --git a/src/jtag/hla/hla_interface.c b/src/jtag/hla/hla_interface.c index cb9ef39..2abed21 100644 --- a/src/jtag/hla/hla_interface.c +++ b/src/jtag/hla/hla_interface.c @@ -191,7 +191,7 @@ int hl_interface_override_target(const char **targetname) return ERROR_FAIL; } -int hl_interface_config_trace(bool enabled, enum tpio_pin_protocol pin_protocol, +int hl_interface_config_trace(bool enabled, enum tpiu_pin_protocol pin_protocol, uint32_t port_size, unsigned int *trace_freq) { if (hl_if.layout->api->config_trace) diff --git a/src/jtag/hla/hla_layout.h b/src/jtag/hla/hla_layout.h index 40c1321..9f41b59 100644 --- a/src/jtag/hla/hla_layout.h +++ b/src/jtag/hla/hla_layout.h @@ -91,7 +91,7 @@ struct hl_layout_api_s { * its maximum supported rate there * @returns ERROR_OK on success, an error code on failure. */ - int (*config_trace)(void *handle, bool enabled, enum tpio_pin_protocol pin_protocol, + int (*config_trace)(void *handle, bool enabled, enum tpiu_pin_protocol pin_protocol, uint32_t port_size, unsigned int *trace_freq); /** * Poll for new trace data diff --git a/src/jtag/interface.h b/src/jtag/interface.h index cdfc676..e6fa0ca 100644 --- a/src/jtag/interface.h +++ b/src/jtag/interface.h @@ -309,7 +309,7 @@ struct jtag_interface { * its maximum supported rate there * @returns ERROR_OK on success, an error code on failure. */ - int (*config_trace)(bool enabled, enum tpio_pin_protocol pin_protocol, + int (*config_trace)(bool enabled, enum tpiu_pin_protocol pin_protocol, uint32_t port_size, unsigned int *trace_freq); /** @@ -328,7 +328,7 @@ extern const char * const jtag_only[]; void adapter_assert_reset(void); void adapter_deassert_reset(void); -int adapter_config_trace(bool enabled, enum tpio_pin_protocol pin_protocol, +int adapter_config_trace(bool enabled, enum tpiu_pin_protocol pin_protocol, uint32_t port_size, unsigned int *trace_freq); int adapter_poll_trace(uint8_t *buf, size_t *size); diff --git a/src/jtag/interfaces.c b/src/jtag/interfaces.c index ddeadb4..286a73a 100644 --- a/src/jtag/interfaces.c +++ b/src/jtag/interfaces.c @@ -132,6 +132,9 @@ extern struct jtag_interface kitprog_interface; #if BUILD_IMX_GPIO == 1 extern struct jtag_interface imx_gpio_interface; #endif +#if BUILD_XDS110 == 1 +extern struct jtag_interface xds110_interface; +#endif #endif /* standard drivers */ /** @@ -234,6 +237,9 @@ struct jtag_interface *jtag_interfaces[] = { #if BUILD_IMX_GPIO == 1 &imx_gpio_interface, #endif +#if BUILD_XDS110 == 1 + &xds110_interface, +#endif #endif /* standard drivers */ NULL, }; diff --git a/src/jtag/zy1000/zy1000.c b/src/jtag/zy1000/zy1000.c index 67d9907..4e53dd1 100644 --- a/src/jtag/zy1000/zy1000.c +++ b/src/jtag/zy1000/zy1000.c @@ -265,8 +265,8 @@ COMMAND_HANDLER(handle_power_command) bool enable; COMMAND_PARSE_ON_OFF(CMD_ARGV[0], enable); setPower(enable); - /* fall through */ } + /* fall through */ case 0: LOG_INFO("Target power %s", savePower ? "on" : "off"); break; diff --git a/src/rtos/Makefile.am b/src/rtos/Makefile.am index 22f7da5..6f14b42 100644 --- a/src/rtos/Makefile.am +++ b/src/rtos/Makefile.am @@ -16,6 +16,7 @@ noinst_LTLIBRARIES += %D%/librtos.la %D%/mqx.c \ %D%/riscv_debug.c \ %D%/uCOS-III.c \ + %D%/nuttx.c \ %D%/rtos.h \ %D%/rtos_standard_stackings.h \ %D%/rtos_ecos_stackings.h \ @@ -24,6 +25,7 @@ noinst_LTLIBRARIES += %D%/librtos.la %D%/rtos_embkernel_stackings.h \ %D%/rtos_mqx_stackings.h \ %D%/rtos_ucos_iii_stackings.h \ + %D%/nuttx_header.h \ %D%/riscv_debug.h %C%_librtos_la_CFLAGS = $(AM_CFLAGS) diff --git a/src/rtos/nuttx.c b/src/rtos/nuttx.c new file mode 100644 index 0000000..284b968 --- /dev/null +++ b/src/rtos/nuttx.c @@ -0,0 +1,405 @@ +/*************************************************************************** + * Copyright 2016,2017 Sony Video & Sound Products Inc. * + * Masatoshi Tateishi - Masatoshi.Tateishi@jp.sony.com * + * Masayuki Ishikawa - Masayuki.Ishikawa@jp.sony.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <jtag/jtag.h> +#include "target/target.h" +#include "target/target_type.h" +#include "target/armv7m.h" +#include "target/cortex_m.h" +#include "rtos.h" +#include "helper/log.h" +#include "helper/types.h" +#include "server/gdb_server.h" + +#include "nuttx_header.h" + + +int rtos_thread_packet(struct connection *connection, const char *packet, int packet_size); + +#ifdef CONFIG_DISABLE_SIGNALS +#define SIG_QUEUE_NUM 0 +#else +#define SIG_QUEUE_NUM 1 +#endif /* CONFIG_DISABLE_SIGNALS */ + +#ifdef CONFIG_DISABLE_MQUEUE +#define M_QUEUE_NUM 0 +#else +#define M_QUEUE_NUM 2 +#endif /* CONFIG_DISABLE_MQUEUE */ + +#ifdef CONFIG_PAGING +#define PAGING_QUEUE_NUM 1 +#else +#define PAGING_QUEUE_NUM 0 +#endif /* CONFIG_PAGING */ + + +#define TASK_QUEUE_NUM (6 + SIG_QUEUE_NUM + M_QUEUE_NUM + PAGING_QUEUE_NUM) + + +/* see nuttx/sched/os_start.c */ +static char *nuttx_symbol_list[] = { + "g_readytorun", /* 0: must be top of this array */ + "g_tasklisttable", + NULL +}; + +/* see nuttx/include/nuttx/sched.h */ +struct tcb { + uint32_t flink; + uint32_t blink; + uint8_t dat[512]; +}; + +struct { + uint32_t addr; + uint32_t prio; +} g_tasklist[TASK_QUEUE_NUM]; + +static char *task_state_str[] = { + "INVALID", + "PENDING", + "READYTORUN", + "RUNNING", + "INACTIVE", + "WAIT_SEM", +#ifndef CONFIG_DISABLE_SIGNALS + "WAIT_SIG", +#endif /* CONFIG_DISABLE_SIGNALS */ +#ifndef CONFIG_DISABLE_MQUEUE + "WAIT_MQNOTEMPTY", + "WAIT_MQNOTFULL", +#endif /* CONFIG_DISABLE_MQUEUE */ +#ifdef CONFIG_PAGING + "WAIT_PAGEFILL", +#endif /* CONFIG_PAGING */ +}; + +/* see arch/arm/include/armv7-m/irq_cmnvector.h */ +static const struct stack_register_offset nuttx_stack_offsets_cortex_m[] = { + { 0x28, 32 }, /* r0 */ + { 0x2c, 32 }, /* r1 */ + { 0x30, 32 }, /* r2 */ + { 0x34, 32 }, /* r3 */ + { 0x08, 32 }, /* r4 */ + { 0x0c, 32 }, /* r5 */ + { 0x10, 32 }, /* r6 */ + { 0x14, 32 }, /* r7 */ + { 0x18, 32 }, /* r8 */ + { 0x1c, 32 }, /* r9 */ + { 0x20, 32 }, /* r10 */ + { 0x24, 32 }, /* r11 */ + { 0x38, 32 }, /* r12 */ + { 0, 32 }, /* sp */ + { 0x3c, 32 }, /* lr */ + { 0x40, 32 }, /* pc */ + { 0x44, 32 }, /* xPSR */ +}; + + +static const struct rtos_register_stacking nuttx_stacking_cortex_m = { + 0x48, /* stack_registers_size */ + -1, /* stack_growth_direction */ + 17, /* num_output_registers */ + 0, /* stack_alignment */ + nuttx_stack_offsets_cortex_m /* register_offsets */ +}; + +static const struct stack_register_offset nuttx_stack_offsets_cortex_m_fpu[] = { + { 0x6c, 32 }, /* r0 */ + { 0x70, 32 }, /* r1 */ + { 0x74, 32 }, /* r2 */ + { 0x78, 32 }, /* r3 */ + { 0x08, 32 }, /* r4 */ + { 0x0c, 32 }, /* r5 */ + { 0x10, 32 }, /* r6 */ + { 0x14, 32 }, /* r7 */ + { 0x18, 32 }, /* r8 */ + { 0x1c, 32 }, /* r9 */ + { 0x20, 32 }, /* r10 */ + { 0x24, 32 }, /* r11 */ + { 0x7c, 32 }, /* r12 */ + { 0, 32 }, /* sp */ + { 0x80, 32 }, /* lr */ + { 0x84, 32 }, /* pc */ + { 0x88, 32 }, /* xPSR */ +}; + +static const struct rtos_register_stacking nuttx_stacking_cortex_m_fpu = { + 0x8c, /* stack_registers_size */ + -1, /* stack_growth_direction */ + 17, /* num_output_registers */ + 0, /* stack_alignment */ + nuttx_stack_offsets_cortex_m_fpu /* register_offsets */ +}; + +static int pid_offset = PID; +static int state_offset = STATE; +static int name_offset = NAME; +static int xcpreg_offset = XCPREG; +static int name_size = NAME_SIZE; + +static int rcmd_offset(const char *cmd, const char *name) +{ + if (strncmp(cmd, name, strlen(name))) + return -1; + + if (strlen(cmd) <= strlen(name) + 1) + return -1; + + return atoi(cmd + strlen(name)); +} + +static int nuttx_thread_packet(struct connection *connection, + char const *packet, int packet_size) +{ + char cmd[GDB_BUFFER_SIZE / 2] = ""; + + if (!strncmp(packet, "qRcmd", 5)) { + size_t len = unhexify((uint8_t *)cmd, packet + 6, sizeof(cmd)); + int offset; + + if (len <= 0) + goto pass; + + offset = rcmd_offset(cmd, "nuttx.pid_offset"); + + if (offset >= 0) { + LOG_INFO("pid_offset: %d", offset); + pid_offset = offset; + goto retok; + } + + offset = rcmd_offset(cmd, "nuttx.state_offset"); + + if (offset >= 0) { + LOG_INFO("state_offset: %d", offset); + state_offset = offset; + goto retok; + } + + offset = rcmd_offset(cmd, "nuttx.name_offset"); + + if (offset >= 0) { + LOG_INFO("name_offset: %d", offset); + name_offset = offset; + goto retok; + } + + offset = rcmd_offset(cmd, "nuttx.xcpreg_offset"); + + if (offset >= 0) { + LOG_INFO("xcpreg_offset: %d", offset); + xcpreg_offset = offset; + goto retok; + } + + offset = rcmd_offset(cmd, "nuttx.name_size"); + + if (offset >= 0) { + LOG_INFO("name_size: %d", offset); + name_size = offset; + goto retok; + } + } +pass: + return rtos_thread_packet(connection, packet, packet_size); +retok: + gdb_put_packet(connection, "OK", 2); + return ERROR_OK; +} + + +static bool nuttx_detect_rtos(struct target *target) +{ + if ((target->rtos->symbols != NULL) && + (target->rtos->symbols[0].address != 0) && + (target->rtos->symbols[1].address != 0)) { + return true; + } + return false; +} + +static int nuttx_create(struct target *target) +{ + + target->rtos->gdb_thread_packet = nuttx_thread_packet; + LOG_INFO("target type name = %s", target->type->name); + return 0; +} + +static int nuttx_update_threads(struct rtos *rtos) +{ + uint32_t thread_count; + struct tcb tcb; + int ret; + uint32_t head; + uint32_t tcb_addr; + uint32_t i; + uint8_t state; + + if (rtos->symbols == NULL) { + LOG_ERROR("No symbols for NuttX"); + return -3; + } + + /* free previous thread details */ + rtos_free_threadlist(rtos); + + ret = target_read_buffer(rtos->target, rtos->symbols[1].address, + sizeof(g_tasklist), (uint8_t *)&g_tasklist); + if (ret) { + LOG_ERROR("target_read_buffer : ret = %d\n", ret); + return ERROR_FAIL; + } + + thread_count = 0; + + for (i = 0; i < TASK_QUEUE_NUM; i++) { + + if (g_tasklist[i].addr == 0) + continue; + + ret = target_read_u32(rtos->target, g_tasklist[i].addr, + &head); + + if (ret) { + LOG_ERROR("target_read_u32 : ret = %d\n", ret); + return ERROR_FAIL; + } + + /* readytorun head is current thread */ + if (g_tasklist[i].addr == rtos->symbols[0].address) + rtos->current_thread = head; + + + tcb_addr = head; + while (tcb_addr) { + struct thread_detail *thread; + ret = target_read_buffer(rtos->target, tcb_addr, + sizeof(tcb), (uint8_t *)&tcb); + if (ret) { + LOG_ERROR("target_read_buffer : ret = %d\n", + ret); + return ERROR_FAIL; + } + thread_count++; + + rtos->thread_details = realloc(rtos->thread_details, + sizeof(struct thread_detail) * thread_count); + thread = &rtos->thread_details[thread_count - 1]; + thread->threadid = tcb_addr; + thread->exists = true; + + state = tcb.dat[state_offset - 8]; + thread->extra_info_str = NULL; + if (state < sizeof(task_state_str)/sizeof(char *)) { + thread->extra_info_str = malloc(256); + snprintf(thread->extra_info_str, 256, "pid:%d, %s", + tcb.dat[pid_offset - 8] | + tcb.dat[pid_offset - 8 + 1] << 8, + task_state_str[state]); + } + + if (name_offset) { + thread->thread_name_str = malloc(name_size + 1); + snprintf(thread->thread_name_str, name_size, + "%s", (char *)&tcb.dat[name_offset - 8]); + } else { + thread->thread_name_str = malloc(sizeof("None")); + strcpy(thread->thread_name_str, "None"); + } + + tcb_addr = tcb.flink; + } + } + rtos->thread_count = thread_count; + + return 0; +} + + +/* + * thread_id = tcb address; + */ +static int nuttx_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, + char **hex_reg_list) { + int retval; + + *hex_reg_list = NULL; + + /* Check for armv7m with *enabled* FPU, i.e. a Cortex-M4F */ + bool cm4_fpu_enabled = false; + struct armv7m_common *armv7m_target = target_to_armv7m(rtos->target); + if (is_armv7m(armv7m_target)) { + if (armv7m_target->fp_feature == FPv4_SP) { + /* Found ARM v7m target which includes a FPU */ + uint32_t cpacr; + + retval = target_read_u32(rtos->target, FPU_CPACR, &cpacr); + if (retval != ERROR_OK) { + LOG_ERROR("Could not read CPACR register to check FPU state"); + return -1; + } + + /* Check if CP10 and CP11 are set to full access. */ + if (cpacr & 0x00F00000) { + /* Found target with enabled FPU */ + cm4_fpu_enabled = 1; + } + } + } + + const struct rtos_register_stacking *stacking; + if (cm4_fpu_enabled) + stacking = &nuttx_stacking_cortex_m_fpu; + else + stacking = &nuttx_stacking_cortex_m; + + return rtos_generic_stack_read(rtos->target, stacking, + (uint32_t)thread_id + xcpreg_offset, hex_reg_list); +} + +static int nuttx_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[]) +{ + unsigned int i; + + *symbol_list = (symbol_table_elem_t *) calloc(1, + sizeof(symbol_table_elem_t) * ARRAY_SIZE(nuttx_symbol_list)); + + for (i = 0; i < ARRAY_SIZE(nuttx_symbol_list); i++) + (*symbol_list)[i].symbol_name = nuttx_symbol_list[i]; + + return 0; +} + +struct rtos_type nuttx_rtos = { + .name = "nuttx", + .detect_rtos = nuttx_detect_rtos, + .create = nuttx_create, + .update_threads = nuttx_update_threads, + .get_thread_reg_list = nuttx_get_thread_reg_list, + .get_symbol_list_to_lookup = nuttx_get_symbol_list_to_lookup, +}; + diff --git a/src/rtos/nuttx_header.h b/src/rtos/nuttx_header.h new file mode 100644 index 0000000..00b0484 --- /dev/null +++ b/src/rtos/nuttx_header.h @@ -0,0 +1,71 @@ +/*************************************************************************** + * Copyright 2016,2017 Sony Video & Sound Products Inc. * + * Masatoshi Tateishi - Masatoshi.Tateishi@jp.sony.com * + * Masayuki Ishikawa - Masayuki.Ishikawa@jp.sony.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ + +#ifndef OPENOCD_RTOS_NUTTX_HEADER_H +#define OPENOCD_RTOS_NUTTX_HEADER_H + +/* gdb script to update the header file + according to kernel version and build option + before executing function awareness + kernel symbol must be loaded : symbol nuttx + +define awareness + set logging off + set logging file nuttx_header.h + set logging on + + printf "#define PID %p\n",&((struct tcb_s *)(0))->pid + printf "#define XCPREG %p\n",&((struct tcb_s *)(0))->xcp.regs + printf "#define STATE %p\n",&((struct tcb_s *)(0))->task_state + printf "#define NAME %p\n",&((struct tcb_s *)(0))->name + printf "#define NAME_SIZE %d\n",sizeof(((struct tcb_s *)(0))->name) + end + + + OR ~/.gdbinit + + +define hookpost-file + + if &g_readytorun != 0 + eval "monitor nuttx.pid_offset %d", &((struct tcb_s *)(0))->pid + eval "monitor nuttx.xcpreg_offset %d", &((struct tcb_s *)(0))->xcp.regs + eval "monitor nuttx.state_offset %d", &((struct tcb_s *)(0))->task_state + eval "monitor nuttx.name_offset %d", &((struct tcb_s *)(0))->name + eval "monitor nuttx.name_size %d", sizeof(((struct tcb_s *)(0))->name) + end + +end + +*/ + +/* default offset */ +#define PID 0xc +#define XCPREG 0x70 +#define STATE 0x19 +#define NAME 0xb8 +#define NAME_SIZE 32 + +/* defconfig of nuttx */ +/* #define CONFIG_DISABLE_SIGNALS */ +#define CONFIG_DISABLE_MQUEUE +/* #define CONFIG_PAGING */ + + +#endif /* OPENOCD_RTOS_NUTTX_HEADER_H */ diff --git a/src/rtos/riscv_debug.c b/src/rtos/riscv_debug.c index 90caf40..6703008 100644 --- a/src/rtos/riscv_debug.c +++ b/src/rtos/riscv_debug.c @@ -22,11 +22,6 @@ static int riscv_create_rtos(struct target *target) struct riscv_rtos *r = calloc(1, sizeof(*r)); target->rtos->rtos_specific_params = r; -#if 0 - r->target_hartid = 0; - r->target_any_hart = true; - r->target_every_hart = true; -#endif target->rtos->current_threadid = 1; target->rtos->current_thread = 1; @@ -129,6 +124,13 @@ static int riscv_gdb_thread_packet(struct connection *connection, const char *pa return ERROR_OK; } + if (strcmp(packet, "qC") == 0) { + char rep_str[32]; + snprintf(rep_str, 32, "QC%" PRIx64, rtos->current_threadid); + gdb_put_packet(connection, rep_str, strlen(rep_str)); + return ERROR_OK; + } + return GDB_THREAD_PACKET_NOT_CONSUMED; case 'Q': @@ -266,12 +268,6 @@ static int riscv_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, char { LOG_DEBUG("Updating RISC-V register list for hart %d", (int)(thread_id - 1)); -#if 0 - LOG_ERROR(" Not actually updating"); - *hex_reg_list = 0; - return JIM_OK; -#endif - size_t n_regs = 32; size_t xlen = 64; size_t reg_chars = xlen / 8 * 2; diff --git a/src/rtos/rtos.c b/src/rtos/rtos.c index 4f23040..bd9da0d 100644 --- a/src/rtos/rtos.c +++ b/src/rtos/rtos.c @@ -35,6 +35,7 @@ extern struct rtos_type ChibiOS_rtos; extern struct rtos_type embKernel_rtos; extern struct rtos_type mqx_rtos; extern struct rtos_type uCOS_III_rtos; +extern struct rtos_type nuttx_rtos; extern struct rtos_type riscv_rtos; static struct rtos_type *rtos_types[] = { @@ -46,6 +47,7 @@ static struct rtos_type *rtos_types[] = { &embKernel_rtos, &mqx_rtos, &uCOS_III_rtos, + &nuttx_rtos, &riscv_rtos, NULL }; diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c index 81dc32d..58df51a 100644 --- a/src/server/gdb_server.c +++ b/src/server/gdb_server.c @@ -112,6 +112,8 @@ static char *gdb_port_next; static void gdb_log_callback(void *priv, const char *file, unsigned line, const char *function, const char *string); +static void gdb_sig_halted(struct connection *connection); + /* number of gdb connections, mainly to suppress gdb related debugging spam * in helper/log.c when no gdb connections are actually active */ int gdb_actual_connections; @@ -720,7 +722,7 @@ static int gdb_output(struct command_context *context, const char *line) static void gdb_signal_reply(struct target *target, struct connection *connection) { struct gdb_connection *gdb_connection = connection->priv; - char sig_reply[45]; + char sig_reply[65]; char stop_reason[20]; char current_thread[25]; int sig_reply_len; @@ -765,7 +767,7 @@ static void gdb_signal_reply(struct target *target, struct connection *connectio current_thread[0] = '\0'; if (target->rtos != NULL) { struct target *ct; - snprintf(current_thread, sizeof(current_thread), "thread:%016" PRIx64 ";", + snprintf(current_thread, sizeof(current_thread), "thread:%" PRIx64 ";", target->rtos->current_thread); target->rtos->current_threadid = target->rtos->current_thread; target->rtos->gdb_target_for_threadid(connection, target->rtos->current_threadid, &ct); @@ -791,64 +793,64 @@ static void gdb_fileio_reply(struct target *target, struct connection *connectio bool program_exited = false; if (strcmp(target->fileio_info->identifier, "open") == 0) - sprintf(fileio_command, "F%s,%" PRIx32 "/%" PRIx32 ",%" PRIx32 ",%" PRIx32, target->fileio_info->identifier, + sprintf(fileio_command, "F%s,%" PRIx64 "/%" PRIx64 ",%" PRIx64 ",%" PRIx64, target->fileio_info->identifier, target->fileio_info->param_1, target->fileio_info->param_2, target->fileio_info->param_3, target->fileio_info->param_4); else if (strcmp(target->fileio_info->identifier, "close") == 0) - sprintf(fileio_command, "F%s,%" PRIx32, target->fileio_info->identifier, + sprintf(fileio_command, "F%s,%" PRIx64, target->fileio_info->identifier, target->fileio_info->param_1); else if (strcmp(target->fileio_info->identifier, "read") == 0) - sprintf(fileio_command, "F%s,%" PRIx32 ",%" PRIx32 ",%" PRIx32, target->fileio_info->identifier, + sprintf(fileio_command, "F%s,%" PRIx64 ",%" PRIx64 ",%" PRIx64, target->fileio_info->identifier, target->fileio_info->param_1, target->fileio_info->param_2, target->fileio_info->param_3); else if (strcmp(target->fileio_info->identifier, "write") == 0) - sprintf(fileio_command, "F%s,%" PRIx32 ",%" PRIx32 ",%" PRIx32, target->fileio_info->identifier, + sprintf(fileio_command, "F%s,%" PRIx64 ",%" PRIx64 ",%" PRIx64, target->fileio_info->identifier, target->fileio_info->param_1, target->fileio_info->param_2, target->fileio_info->param_3); else if (strcmp(target->fileio_info->identifier, "lseek") == 0) - sprintf(fileio_command, "F%s,%" PRIx32 ",%" PRIx32 ",%" PRIx32, target->fileio_info->identifier, + sprintf(fileio_command, "F%s,%" PRIx64 ",%" PRIx64 ",%" PRIx64, target->fileio_info->identifier, target->fileio_info->param_1, target->fileio_info->param_2, target->fileio_info->param_3); else if (strcmp(target->fileio_info->identifier, "rename") == 0) - sprintf(fileio_command, "F%s,%" PRIx32 "/%" PRIx32 ",%" PRIx32 "/%" PRIx32, target->fileio_info->identifier, + sprintf(fileio_command, "F%s,%" PRIx64 "/%" PRIx64 ",%" PRIx64 "/%" PRIx64, target->fileio_info->identifier, target->fileio_info->param_1, target->fileio_info->param_2, target->fileio_info->param_3, target->fileio_info->param_4); else if (strcmp(target->fileio_info->identifier, "unlink") == 0) - sprintf(fileio_command, "F%s,%" PRIx32 "/%" PRIx32, target->fileio_info->identifier, + sprintf(fileio_command, "F%s,%" PRIx64 "/%" PRIx64, target->fileio_info->identifier, target->fileio_info->param_1, target->fileio_info->param_2); else if (strcmp(target->fileio_info->identifier, "stat") == 0) - sprintf(fileio_command, "F%s,%" PRIx32 "/%" PRIx32 ",%" PRIx32, target->fileio_info->identifier, + sprintf(fileio_command, "F%s,%" PRIx64 "/%" PRIx64 ",%" PRIx64, target->fileio_info->identifier, target->fileio_info->param_1, target->fileio_info->param_2, target->fileio_info->param_3); else if (strcmp(target->fileio_info->identifier, "fstat") == 0) - sprintf(fileio_command, "F%s,%" PRIx32 ",%" PRIx32, target->fileio_info->identifier, + sprintf(fileio_command, "F%s,%" PRIx64 ",%" PRIx64, target->fileio_info->identifier, target->fileio_info->param_1, target->fileio_info->param_2); else if (strcmp(target->fileio_info->identifier, "gettimeofday") == 0) - sprintf(fileio_command, "F%s,%" PRIx32 ",%" PRIx32, target->fileio_info->identifier, + sprintf(fileio_command, "F%s,%" PRIx64 ",%" PRIx64, target->fileio_info->identifier, target->fileio_info->param_1, target->fileio_info->param_2); else if (strcmp(target->fileio_info->identifier, "isatty") == 0) - sprintf(fileio_command, "F%s,%" PRIx32, target->fileio_info->identifier, + sprintf(fileio_command, "F%s,%" PRIx64, target->fileio_info->identifier, target->fileio_info->param_1); else if (strcmp(target->fileio_info->identifier, "system") == 0) - sprintf(fileio_command, "F%s,%" PRIx32 "/%" PRIx32, target->fileio_info->identifier, + sprintf(fileio_command, "F%s,%" PRIx64 "/%" PRIx64, target->fileio_info->identifier, target->fileio_info->param_1, target->fileio_info->param_2); else if (strcmp(target->fileio_info->identifier, "exit") == 0) { /* If target hits exit syscall, report to GDB the program is terminated. * In addition, let target run its own exit syscall handler. */ program_exited = true; - sprintf(fileio_command, "W%02" PRIx32, target->fileio_info->param_1); + sprintf(fileio_command, "W%02" PRIx64, target->fileio_info->param_1); } else { LOG_DEBUG("Unknown syscall: %s", target->fileio_info->identifier); @@ -934,6 +936,7 @@ static int gdb_new_connection(struct connection *connection) target = get_target_from_connection(connection); connection->priv = gdb_connection; + connection->cmd_ctx->current_target = target; /* initialize gdb connection information */ gdb_connection->buf_p = gdb_connection->buffer; @@ -1357,7 +1360,8 @@ static int gdb_set_register_packet(struct connection *connection, int chars = (DIV_ROUND_UP(reg_list[reg_num]->size, 8) * 2); if ((unsigned int)chars != strlen(separator + 1)) { - LOG_ERROR("gdb sent a packet with wrong register size"); + LOG_ERROR("gdb sent %zu bits for a %d-bit register (%s)", + strlen(separator + 1) * 4, chars * 4, reg_list[reg_num]->name); free(bin_buf); return ERROR_SERVER_REMOTE_CLOSED; } @@ -2704,6 +2708,7 @@ static bool gdb_handle_vcont_packet(struct connection *connection, const char *p /* simple case, a continue packet */ if (parse[0] == 'c') { + gdb_running_type = 'c'; LOG_DEBUG("target %s continue", target_name(target)); log_add_callback(gdb_log_callback, connection); retval = target_resume(target, 1, 0, 0, 0); @@ -2730,6 +2735,7 @@ static bool gdb_handle_vcont_packet(struct connection *connection, const char *p /* single-step or step-over-breakpoint */ if (parse[0] == 's') { + gdb_running_type = 's'; bool fake_step = false; if (strncmp(parse, "s:", 2) == 0) { @@ -3016,9 +3022,12 @@ static int gdb_v_packet(struct connection *connection, static int gdb_detach(struct connection *connection) { - target_call_event_callbacks(get_target_from_connection(connection), - TARGET_EVENT_GDB_DETACH); - + /* + * Only reply "OK" to GDB + * it will close the connection and this will trigger a call to + * gdb_connection_closed() that will in turn trigger the event + * TARGET_EVENT_GDB_DETACH + */ return gdb_put_packet(connection, "OK", 2); } @@ -3084,7 +3093,7 @@ static void gdb_log_callback(void *priv, const char *file, unsigned line, gdb_output_con(connection, string); } -void gdb_sig_halted(struct connection *connection) +static void gdb_sig_halted(struct connection *connection) { char sig_reply[4]; snprintf(sig_reply, 4, "T%2.2x", 2); diff --git a/src/server/gdb_server.h b/src/server/gdb_server.h index 1366c76..0c50836 100644 --- a/src/server/gdb_server.h +++ b/src/server/gdb_server.h @@ -47,7 +47,6 @@ static inline struct target *get_target_from_connection(struct connection *conne } void gdb_set_frontend_state_running(struct connection *connection); -void gdb_sig_halted(struct connection *connection); #define ERROR_GDB_BUFFER_TOO_SMALL (-800) #define ERROR_GDB_TIMEOUT (-801) diff --git a/src/server/server.c b/src/server/server.c index 4e80656..f8273d4 100644 --- a/src/server/server.c +++ b/src/server/server.c @@ -46,9 +46,13 @@ static struct service *services; -/* shutdown_openocd == 1: exit the main event loop, and quit the - * debugger; 2: quit with non-zero return code */ -static int shutdown_openocd; +enum shutdown_reason { + CONTINUE_MAIN_LOOP, /* stay in main event loop */ + SHUTDOWN_REQUESTED, /* set by shutdown command; exit the event loop and quit the debugger */ + SHUTDOWN_WITH_ERROR_CODE, /* set by shutdown command; quit with non-zero return code */ + SHUTDOWN_WITH_SIGNAL_CODE /* set by sig_handler; exec shutdown then exit with signal as return code */ +}; +static enum shutdown_reason shutdown_openocd = CONTINUE_MAIN_LOOP; /* store received signal to exit application by killing ourselves */ static int last_signal; @@ -360,6 +364,35 @@ static void remove_connections(struct service *service) } } +int remove_service(const char *name, const char *port) +{ + struct service *tmp; + struct service *prev; + + prev = services; + + for (tmp = services; tmp; prev = tmp, tmp = tmp->next) { + if (!strcmp(tmp->name, name) && !strcmp(tmp->port, port)) { + remove_connections(tmp); + + if (tmp == services) + services = tmp->next; + else + prev->next = tmp->next; + + if (tmp->type != CONNECTION_STDINOUT) + close_socket(tmp->fd); + + free(tmp->priv); + free_service(tmp); + + return ERROR_OK; + } + } + + return ERROR_OK; +} + static int remove_services(void) { struct service *c = services; @@ -413,7 +446,7 @@ int server_loop(struct command_context *command_context) LOG_ERROR("couldn't set SIGPIPE to SIG_IGN"); #endif - while (!shutdown_openocd) { + while (shutdown_openocd == CONTINUE_MAIN_LOOP) { /* monitor sockets for activity */ fd_max = 0; FD_ZERO(&read_fds); @@ -505,7 +538,7 @@ int server_loop(struct command_context *command_context) for (service = services; service; service = service->next) { /* handle new connections on listeners */ if ((service->fd != -1) - && (FD_ISSET(service->fd, &read_fds))) { + && (FD_ISSET(service->fd, &read_fds))) { if (service->max_connections != 0) add_connection(service, command_context); else { @@ -537,7 +570,7 @@ int server_loop(struct command_context *command_context) service->type == CONNECTION_STDINOUT) { /* if connection uses a pipe then * shutdown openocd on error */ - shutdown_openocd = 1; + shutdown_openocd = SHUTDOWN_REQUESTED; } remove_connection(service, c); LOG_INFO("dropped '%s' connection", @@ -555,29 +588,48 @@ int server_loop(struct command_context *command_context) MSG msg; while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { if (msg.message == WM_QUIT) - shutdown_openocd = 1; + shutdown_openocd = SHUTDOWN_WITH_SIGNAL_CODE; } #endif } - return shutdown_openocd != 2 ? ERROR_OK : ERROR_FAIL; + /* when quit for signal or CTRL-C, run (eventually user implemented) "shutdown" */ + if (shutdown_openocd == SHUTDOWN_WITH_SIGNAL_CODE) + command_run_line(command_context, "shutdown"); + + return shutdown_openocd == SHUTDOWN_WITH_ERROR_CODE ? ERROR_FAIL : ERROR_OK; } +void sig_handler(int sig) +{ + /* store only first signal that hits us */ + if (shutdown_openocd == CONTINUE_MAIN_LOOP) { + shutdown_openocd = SHUTDOWN_WITH_SIGNAL_CODE; + last_signal = sig; + LOG_DEBUG("Terminating on Signal %d", sig); + } else + LOG_DEBUG("Ignored extra Signal %d", sig); +} + + #ifdef _WIN32 BOOL WINAPI ControlHandler(DWORD dwCtrlType) { - shutdown_openocd = 1; + shutdown_openocd = SHUTDOWN_WITH_SIGNAL_CODE; return TRUE; } -#endif - -void sig_handler(int sig) +#else +static void sigkey_handler(int sig) { - /* store only first signal that hits us */ - if (!last_signal) - last_signal = sig; - shutdown_openocd = 1; + /* ignore keystroke generated signals if not in foreground process group */ + + if (tcgetpgrp(STDIN_FILENO) > 0) + sig_handler(sig); + else + LOG_DEBUG("Ignored Signal %d", sig); } +#endif + int server_preinit(void) { @@ -600,8 +652,13 @@ int server_preinit(void) SetConsoleCtrlHandler(ControlHandler, TRUE); signal(SIGBREAK, sig_handler); -#endif signal(SIGINT, sig_handler); +#else + signal(SIGHUP, sig_handler); + signal(SIGPIPE, sig_handler); + signal(SIGQUIT, sigkey_handler); + signal(SIGINT, sigkey_handler); +#endif signal(SIGTERM, sig_handler); signal(SIGABRT, sig_handler); @@ -682,11 +739,11 @@ COMMAND_HANDLER(handle_shutdown_command) { LOG_USER("shutdown command invoked"); - shutdown_openocd = 1; + shutdown_openocd = SHUTDOWN_REQUESTED; if (CMD_ARGC == 1) { if (!strcmp(CMD_ARGV[0], "error")) { - shutdown_openocd = 2; + shutdown_openocd = SHUTDOWN_WITH_ERROR_CODE; return ERROR_FAIL; } } @@ -743,7 +800,7 @@ static const struct command_registration server_command_handlers[] = { .mode = COMMAND_ANY, .usage = "[name]", .help = "Specify address by name on which to listen for " - "incoming TCP/IP connections", + "incoming TCP/IP connections", }, COMMAND_REGISTRATION_DONE }; diff --git a/src/server/server.h b/src/server/server.h index d4eae94..96e0b48 100644 --- a/src/server/server.h +++ b/src/server/server.h @@ -78,6 +78,7 @@ int add_service(char *name, const char *port, int max_connections, new_connection_handler_t new_connection_handler, input_handler_t in_handler, connection_closed_handler_t close_handler, void *priv); +int remove_service(const char *name, const char *port); int server_preinit(void); int server_init(struct command_context *cmd_ctx); diff --git a/src/target/Makefile.am b/src/target/Makefile.am index 030015a..b1119e7 100644 --- a/src/target/Makefile.am +++ b/src/target/Makefile.am @@ -4,7 +4,9 @@ else OOCD_TRACE_FILES = endif -%C%_libtarget_la_LIBADD = %D%/openrisc/libopenrisc.la +%C%_libtarget_la_LIBADD = %D%/openrisc/libopenrisc.la \ + %D%/riscv/libriscv.la + STARTUP_TCL_SRCS += %D%/startup.tcl @@ -21,7 +23,6 @@ noinst_LTLIBRARIES += %D%/libtarget.la $(NDS32_SRC) \ $(STM8_SRC) \ $(INTEL_IA32_SRC) \ - $(RISCV_SRC) \ %D%/avrt.c \ %D%/dsp563xx.c \ %D%/dsp563xx_once.c \ @@ -40,6 +41,7 @@ TARGET_CORE_SRC = \ %D%/target.c \ %D%/target_request.c \ %D%/testee.c \ + %D%/semihosting_common.c \ %D%/smp.c ARMV4_5_SRC = \ @@ -136,13 +138,6 @@ INTEL_IA32_SRC = \ %D%/lakemont.c \ %D%/x86_32_common.c -RISCV_SRC = \ - %D%/riscv/riscv-011.c \ - %D%/riscv/riscv-013.c \ - %D%/riscv/riscv.c \ - %D%/riscv/program.c \ - %D%/riscv/batch.c - %C%_libtarget_la_SOURCES += \ %D%/algorithm.h \ %D%/arm.h \ @@ -218,9 +213,11 @@ RISCV_SRC = \ %D%/nds32_v3.h \ %D%/nds32_v3m.h \ %D%/nds32_aice.h \ + %D%/semihosting_common.h \ %D%/stm8.h \ %D%/lakemont.h \ %D%/x86_32_common.h \ %D%/arm_cti.h include %D%/openrisc/Makefile.am +include %D%/riscv/Makefile.am diff --git a/src/target/aarch64.c b/src/target/aarch64.c index cd83502..454de9e 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -28,6 +28,7 @@ #include "target_type.h" #include "armv8_opcodes.h" #include "armv8_cache.h" +#include "arm_semihosting.h" #include <helper/time_support.h> enum restart_mode { @@ -522,6 +523,9 @@ static int aarch64_poll(struct target *target) if (target->smp) update_halt_gdb(target, debug_reason); + if (arm_semihosting(target, &retval) != 0) + return retval; + switch (prev_target_state) { case TARGET_RUNNING: case TARGET_UNKNOWN: @@ -543,6 +547,9 @@ static int aarch64_poll(struct target *target) static int aarch64_halt(struct target *target) { + struct armv8_common *armv8 = target_to_armv8(target); + armv8->last_run_control_op = ARMV8_RUNCONTROL_HALT; + if (target->smp) return aarch64_halt_smp(target, false); @@ -831,6 +838,9 @@ static int aarch64_resume(struct target *target, int current, int retval = 0; uint64_t addr = address; + struct armv8_common *armv8 = target_to_armv8(target); + armv8->last_run_control_op = ARMV8_RUNCONTROL_RESUME; + if (target->state != TARGET_HALTED) return ERROR_TARGET_NOT_HALTED; @@ -1069,6 +1079,8 @@ static int aarch64_step(struct target *target, int current, target_addr_t addres int retval; uint32_t edecr; + armv8->last_run_control_op = ARMV8_RUNCONTROL_STEP; + if (target->state != TARGET_HALTED) { LOG_WARNING("target not halted"); return ERROR_TARGET_NOT_HALTED; @@ -1682,17 +1694,19 @@ static int aarch64_deassert_reset(struct target *target) if (retval != ERROR_OK) return retval; + retval = aarch64_init_debug_access(target); + if (retval != ERROR_OK) + return retval; + if (target->reset_halt) { if (target->state != TARGET_HALTED) { LOG_WARNING("%s: ran after reset and before halt ...", target_name(target)); retval = target_halt(target); - if (retval != ERROR_OK) - return retval; } } - return aarch64_init_debug_access(target); + return retval; } static int aarch64_write_cpu_memory_slow(struct target *target, @@ -2351,6 +2365,7 @@ static int aarch64_init_target(struct command_context *cmd_ctx, struct target *target) { /* examine_first() does a bunch of this */ + arm_semihosting_init(target); return ERROR_OK; } @@ -2590,6 +2605,143 @@ COMMAND_HANDLER(aarch64_mask_interrupts_command) return ERROR_OK; } +static int jim_mcrmrc(Jim_Interp *interp, int argc, Jim_Obj * const *argv) +{ + struct command_context *context; + struct target *target; + struct arm *arm; + int retval; + bool is_mcr = false; + int arg_cnt = 0; + + if (Jim_CompareStringImmediate(interp, argv[0], "mcr")) { + is_mcr = true; + arg_cnt = 7; + } else { + arg_cnt = 6; + } + + context = current_command_context(interp); + assert(context != NULL); + + target = get_current_target(context); + if (target == NULL) { + LOG_ERROR("%s: no current target", __func__); + return JIM_ERR; + } + if (!target_was_examined(target)) { + LOG_ERROR("%s: not yet examined", target_name(target)); + return JIM_ERR; + } + + arm = target_to_arm(target); + if (!is_arm(arm)) { + LOG_ERROR("%s: not an ARM", target_name(target)); + return JIM_ERR; + } + + if (target->state != TARGET_HALTED) + return ERROR_TARGET_NOT_HALTED; + + if (arm->core_state == ARM_STATE_AARCH64) { + LOG_ERROR("%s: not 32-bit arm target", target_name(target)); + return JIM_ERR; + } + + if (argc != arg_cnt) { + LOG_ERROR("%s: wrong number of arguments", __func__); + return JIM_ERR; + } + + int cpnum; + uint32_t op1; + uint32_t op2; + uint32_t CRn; + uint32_t CRm; + uint32_t value; + long l; + + /* NOTE: parameter sequence matches ARM instruction set usage: + * MCR pNUM, op1, rX, CRn, CRm, op2 ; write CP from rX + * MRC pNUM, op1, rX, CRn, CRm, op2 ; read CP into rX + * The "rX" is necessarily omitted; it uses Tcl mechanisms. + */ + retval = Jim_GetLong(interp, argv[1], &l); + if (retval != JIM_OK) + return retval; + if (l & ~0xf) { + LOG_ERROR("%s: %s %d out of range", __func__, + "coprocessor", (int) l); + return JIM_ERR; + } + cpnum = l; + + retval = Jim_GetLong(interp, argv[2], &l); + if (retval != JIM_OK) + return retval; + if (l & ~0x7) { + LOG_ERROR("%s: %s %d out of range", __func__, + "op1", (int) l); + return JIM_ERR; + } + op1 = l; + + retval = Jim_GetLong(interp, argv[3], &l); + if (retval != JIM_OK) + return retval; + if (l & ~0xf) { + LOG_ERROR("%s: %s %d out of range", __func__, + "CRn", (int) l); + return JIM_ERR; + } + CRn = l; + + retval = Jim_GetLong(interp, argv[4], &l); + if (retval != JIM_OK) + return retval; + if (l & ~0xf) { + LOG_ERROR("%s: %s %d out of range", __func__, + "CRm", (int) l); + return JIM_ERR; + } + CRm = l; + + retval = Jim_GetLong(interp, argv[5], &l); + if (retval != JIM_OK) + return retval; + if (l & ~0x7) { + LOG_ERROR("%s: %s %d out of range", __func__, + "op2", (int) l); + return JIM_ERR; + } + op2 = l; + + value = 0; + + if (is_mcr == true) { + retval = Jim_GetLong(interp, argv[6], &l); + if (retval != JIM_OK) + return retval; + value = l; + + /* NOTE: parameters reordered! */ + /* ARMV4_5_MCR(cpnum, op1, 0, CRn, CRm, op2) */ + retval = arm->mcr(target, cpnum, op1, op2, CRn, CRm, value); + if (retval != ERROR_OK) + return JIM_ERR; + } else { + /* NOTE: parameters reordered! */ + /* ARMV4_5_MRC(cpnum, op1, 0, CRn, CRm, op2) */ + retval = arm->mrc(target, cpnum, op1, op2, CRn, CRm, &value); + if (retval != ERROR_OK) + return JIM_ERR; + + Jim_SetResult(interp, Jim_NewIntObj(interp, value)); + } + + return JIM_OK; +} + static const struct command_registration aarch64_exec_command_handlers[] = { { .name = "cache_info", @@ -2625,9 +2777,25 @@ static const struct command_registration aarch64_exec_command_handlers[] = { .help = "mask aarch64 interrupts during single-step", .usage = "['on'|'off']", }, + { + .name = "mcr", + .mode = COMMAND_EXEC, + .jim_handler = jim_mcrmrc, + .help = "write coprocessor register", + .usage = "cpnum op1 CRn CRm op2 value", + }, + { + .name = "mrc", + .mode = COMMAND_EXEC, + .jim_handler = jim_mcrmrc, + .help = "read coprocessor register", + .usage = "cpnum op1 CRn CRm op2", + }, + COMMAND_REGISTRATION_DONE }; + static const struct command_registration aarch64_command_handlers[] = { { .chain = armv8_command_handlers, diff --git a/src/target/adi_v5_swd.c b/src/target/adi_v5_swd.c index 0de272d..b520223 100644 --- a/src/target/adi_v5_swd.c +++ b/src/target/adi_v5_swd.c @@ -276,6 +276,16 @@ static int swd_run(struct adiv5_dap *dap) return swd_run_inner(dap); } +/** Put the SWJ-DP back to JTAG mode */ +static void swd_quit(struct adiv5_dap *dap) +{ + const struct swd_driver *swd = adiv5_dap_swd_driver(dap); + + swd->switch_seq(SWD_TO_JTAG); + /* flush the queue before exit */ + swd->run(); +} + const struct dap_ops swd_dap_ops = { .connect = swd_connect, .queue_dp_read = swd_queue_dp_read, @@ -284,6 +294,7 @@ const struct dap_ops swd_dap_ops = { .queue_ap_write = swd_queue_ap_write, .queue_ap_abort = swd_queue_ap_abort, .run = swd_run, + .quit = swd_quit, }; /* diff --git a/src/target/arm.h b/src/target/arm.h index dd25d53..316ff9a 100644 --- a/src/target/arm.h +++ b/src/target/arm.h @@ -8,6 +8,9 @@ * Copyright (C) 2009 by Øyvind Harboe * oyvind.harboe@zylin.com * + * Copyright (C) 2018 by Liviu Ionescu + * <ilg@livius.net> + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or @@ -28,7 +31,6 @@ #include <helper/command.h> #include "target.h" - /** * @file * Holds the interface to ARM cores. @@ -181,32 +183,11 @@ struct arm { /** Flag reporting armv6m based core. */ bool is_armv6m; - /** Flag reporting whether semihosting is active. */ - bool is_semihosting; - - /** Flag reporting whether semihosting fileio is active. */ - bool is_semihosting_fileio; - - /** Flag reporting whether semihosting fileio operation is active. */ - bool semihosting_hit_fileio; - /** Floating point or VFP version, 0 if disabled. */ int arm_vfp_version; - /** Current semihosting operation. */ - int semihosting_op; - - /** Current semihosting result. */ - int semihosting_result; - - /** Value to be returned by semihosting SYS_ERRNO request. */ - int semihosting_errno; - int (*setup_semihosting)(struct target *target, int enable); - /** Semihosting command line. */ - char *semihosting_cmdline; - /** Backpointer to the target. */ struct target *target; diff --git a/src/target/arm_adi_v5.c b/src/target/arm_adi_v5.c index e2d9b5e..302ea78 100644 --- a/src/target/arm_adi_v5.c +++ b/src/target/arm_adi_v5.c @@ -102,8 +102,10 @@ static int mem_ap_setup_csw(struct adiv5_ap *ap, uint32_t csw) if (csw != ap->csw_value) { /* LOG_DEBUG("DAP: Set CSW %x",csw); */ int retval = dap_queue_ap_write(ap, MEM_AP_REG_CSW, csw); - if (retval != ERROR_OK) + if (retval != ERROR_OK) { + ap->csw_value = 0; return retval; + } ap->csw_value = csw; } return ERROR_OK; @@ -114,8 +116,10 @@ static int mem_ap_setup_tar(struct adiv5_ap *ap, uint32_t tar) if (!ap->tar_valid || tar != ap->tar_value) { /* LOG_DEBUG("DAP: Set TAR %x",tar); */ int retval = dap_queue_ap_write(ap, MEM_AP_REG_TAR, tar); - if (retval != ERROR_OK) + if (retval != ERROR_OK) { + ap->tar_valid = false; return retval; + } ap->tar_value = tar; ap->tar_valid = true; } @@ -152,6 +156,8 @@ static uint32_t mem_ap_get_tar_increment(struct adiv5_ap *ap) return 2; case CSW_32BIT: return 4; + default: + return 0; } case CSW_ADDRINC_PACKED: return 4; @@ -1610,13 +1616,12 @@ COMMAND_HANDLER(dap_memaccess_command) COMMAND_HANDLER(dap_apsel_command) { struct adiv5_dap *dap = adiv5_get_dap(CMD_DATA); - uint32_t apsel, apid; - int retval; + uint32_t apsel; switch (CMD_ARGC) { case 0: - apsel = dap->apsel; - break; + command_print(CMD_CTX, "%" PRIi32, dap->apsel); + return ERROR_OK; case 1: COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], apsel); /* AP address is in bits 31:24 of DP_SELECT */ @@ -1628,18 +1633,7 @@ COMMAND_HANDLER(dap_apsel_command) } dap->apsel = apsel; - - retval = dap_queue_ap_read(dap_ap(dap, apsel), AP_REG_IDR, &apid); - if (retval != ERROR_OK) - return retval; - retval = dap_run(dap); - if (retval != ERROR_OK) - return retval; - - command_print(CMD_CTX, "ap %" PRIi32 " selected, identification register 0x%8.8" PRIx32, - apsel, apid); - - return retval; + return ERROR_OK; } COMMAND_HANDLER(dap_apcsw_command) @@ -1720,6 +1714,7 @@ COMMAND_HANDLER(dap_apreg_command) { struct adiv5_dap *dap = adiv5_get_dap(CMD_DATA); uint32_t apsel, reg, value; + struct adiv5_ap *ap; int retval; if (CMD_ARGC < 2 || CMD_ARGC > 3) @@ -1729,6 +1724,7 @@ COMMAND_HANDLER(dap_apreg_command) /* AP address is in bits 31:24 of DP_SELECT */ if (apsel >= 256) return ERROR_COMMAND_SYNTAX_ERROR; + ap = dap_ap(dap, apsel); COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], reg); if (reg >= 256 || (reg & 3)) @@ -1736,9 +1732,21 @@ COMMAND_HANDLER(dap_apreg_command) if (CMD_ARGC == 3) { COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], value); - retval = dap_queue_ap_write(dap_ap(dap, apsel), reg, value); + switch (reg) { + case MEM_AP_REG_CSW: + ap->csw_default = 0; /* invalid, force write */ + retval = mem_ap_setup_csw(ap, value); + break; + case MEM_AP_REG_TAR: + ap->tar_valid = false; /* invalid, force write */ + retval = mem_ap_setup_tar(ap, value); + break; + default: + retval = dap_queue_ap_write(ap, reg, value); + break; + } } else { - retval = dap_queue_ap_read(dap_ap(dap, apsel), reg, &value); + retval = dap_queue_ap_read(ap, reg, &value); } if (retval == ERROR_OK) retval = dap_run(dap); @@ -1752,6 +1760,37 @@ COMMAND_HANDLER(dap_apreg_command) return retval; } +COMMAND_HANDLER(dap_dpreg_command) +{ + struct adiv5_dap *dap = adiv5_get_dap(CMD_DATA); + uint32_t reg, value; + int retval; + + if (CMD_ARGC < 1 || CMD_ARGC > 2) + return ERROR_COMMAND_SYNTAX_ERROR; + + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], reg); + if (reg >= 256 || (reg & 3)) + return ERROR_COMMAND_SYNTAX_ERROR; + + if (CMD_ARGC == 2) { + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value); + retval = dap_queue_dp_write(dap, reg, value); + } else { + retval = dap_queue_dp_read(dap, reg, &value); + } + if (retval == ERROR_OK) + retval = dap_run(dap); + + if (retval != ERROR_OK) + return retval; + + if (CMD_ARGC == 1) + command_print(CMD_CTX, "0x%08" PRIx32, value); + + return retval; +} + COMMAND_HANDLER(dap_ti_be_32_quirks_command) { struct adiv5_dap *dap = adiv5_get_dap(CMD_DATA); @@ -1787,7 +1826,7 @@ const struct command_registration dap_instance_commands[] = { { .name = "apsel", .handler = dap_apsel_command, - .mode = COMMAND_EXEC, + .mode = COMMAND_ANY, .help = "Set the currently selected AP (default 0) " "and display the result", .usage = "[ap_num]", @@ -1795,7 +1834,7 @@ const struct command_registration dap_instance_commands[] = { { .name = "apcsw", .handler = dap_apcsw_command, - .mode = COMMAND_EXEC, + .mode = COMMAND_ANY, .help = "Set CSW default bits", .usage = "[value [mask]]", }, @@ -1817,6 +1856,14 @@ const struct command_registration dap_instance_commands[] = { .usage = "ap_num reg [value]", }, { + .name = "dpreg", + .handler = dap_dpreg_command, + .mode = COMMAND_EXEC, + .help = "read/write a register from DP " + "(reg is byte address (bank << 4 | reg) of a word register, like 0 4 8...)", + .usage = "reg [value]", + }, + { .name = "baseaddr", .handler = dap_baseaddr_command, .mode = COMMAND_EXEC, diff --git a/src/target/arm_adi_v5.h b/src/target/arm_adi_v5.h index 22c3166..883ac8b 100644 --- a/src/target/arm_adi_v5.h +++ b/src/target/arm_adi_v5.h @@ -286,6 +286,9 @@ struct dap_ops { /** Executes all queued DAP operations but doesn't check * sticky error conditions */ int (*sync)(struct adiv5_dap *dap); + + /** Optional; called at OpenOCD exit */ + void (*quit)(struct adiv5_dap *dap); }; /* diff --git a/src/target/arm_dap.c b/src/target/arm_dap.c index 8c08180..3be4d71 100644 --- a/src/target/arm_dap.c +++ b/src/target/arm_dap.c @@ -132,8 +132,13 @@ static int dap_init_all(void) int dap_cleanup_all(void) { struct arm_dap_object *obj, *tmp; + struct adiv5_dap *dap; list_for_each_entry_safe(obj, tmp, &all_dap, lh) { + dap = &obj->dap; + if (dap->ops && dap->ops->quit) + dap->ops->quit(dap); + free(obj->name); free(obj); } diff --git a/src/target/arm_disassembler.c b/src/target/arm_disassembler.c index 8e783d3..8eb8194 100644 --- a/src/target/arm_disassembler.c +++ b/src/target/arm_disassembler.c @@ -118,15 +118,78 @@ static int evaluate_pld(uint32_t opcode, uint32_t address, struct arm_instruction *instruction) { /* PLD */ - if ((opcode & 0x0d70f000) == 0x0550f000) { + if ((opcode & 0x0d30f000) == 0x0510f000) { + uint8_t Rn; + uint8_t U; + unsigned offset; + instruction->type = ARM_PLD; + Rn = (opcode & 0xf0000) >> 16; + U = (opcode & 0x00800000) >> 23; + if (Rn == 0xf) { + /* literal */ + offset = opcode & 0x0fff; + snprintf(instruction->text, 128, + "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tPLD %s%d", + address, opcode, U ? "" : "-", offset); + } else { + uint8_t I, R; - snprintf(instruction->text, - 128, - "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tPLD ...TODO...", - address, - opcode); + I = (opcode & 0x02000000) >> 25; + R = (opcode & 0x00400000) >> 22; + + if (I) { + /* register PLD{W} [<Rn>,+/-<Rm>{, <shift>}] */ + offset = (opcode & 0x0F80) >> 7; + uint8_t Rm; + Rm = opcode & 0xf; + + if (offset == 0) { + /* No shift */ + snprintf(instruction->text, 128, + "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tPLD%s [r%d, %sr%d]", + address, opcode, R ? "" : "W", Rn, U ? "" : "-", Rm); + + } else { + uint8_t shift; + shift = (opcode & 0x60) >> 5; + if (shift == 0x0) { + /* LSL */ + snprintf(instruction->text, 128, + "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tPLD%s [r%d, %sr%d, LSL #0x%x)", + address, opcode, R ? "" : "W", Rn, U ? "" : "-", Rm, offset); + } else if (shift == 0x1) { + /* LSR */ + snprintf(instruction->text, 128, + "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tPLD%s [r%d, %sr%d, LSR #0x%x)", + address, opcode, R ? "" : "W", Rn, U ? "" : "-", Rm, offset); + } else if (shift == 0x2) { + /* ASR */ + snprintf(instruction->text, 128, + "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tPLD%s [r%d, %sr%d, ASR #0x%x)", + address, opcode, R ? "" : "W", Rn, U ? "" : "-", Rm, offset); + } else if (shift == 0x3) { + /* ROR */ + snprintf(instruction->text, 128, + "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tPLD%s [r%d, %sr%d, ROR #0x%x)", + address, opcode, R ? "" : "W", Rn, U ? "" : "-", Rm, offset); + } + } + } else { + /* immediate PLD{W} [<Rn>, #+/-<imm12>] */ + offset = opcode & 0x0fff; + if (offset == 0) { + snprintf(instruction->text, 128, + "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tPLD%s [r%d]", + address, opcode, R ? "" : "W", Rn); + } else { + snprintf(instruction->text, 128, + "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tPLD%s [r%d, #%s%d]", + address, opcode, R ? "" : "W", Rn, U ? "" : "-", offset); + } + } + } return ERROR_OK; } /* DSB */ @@ -1549,7 +1612,7 @@ static int evaluate_misc_instr(uint32_t opcode, } /* SMLAW < y> */ - if (((opcode & 0x00600000) == 0x00100000) && (x == 0)) { + if (((opcode & 0x00600000) == 0x00200000) && (x == 0)) { uint8_t Rd, Rm, Rs, Rn; instruction->type = ARM_SMLAWy; Rd = (opcode & 0xf0000) >> 16; @@ -1571,7 +1634,7 @@ static int evaluate_misc_instr(uint32_t opcode, } /* SMUL < x><y> */ - if ((opcode & 0x00600000) == 0x00300000) { + if ((opcode & 0x00600000) == 0x00600000) { uint8_t Rd, Rm, Rs; instruction->type = ARM_SMULxy; Rd = (opcode & 0xf0000) >> 16; @@ -1592,7 +1655,7 @@ static int evaluate_misc_instr(uint32_t opcode, } /* SMULW < y> */ - if (((opcode & 0x00600000) == 0x00100000) && (x == 1)) { + if (((opcode & 0x00600000) == 0x00200000) && (x == 1)) { uint8_t Rd, Rm, Rs; instruction->type = ARM_SMULWy; Rd = (opcode & 0xf0000) >> 16; diff --git a/src/target/arm_semihosting.c b/src/target/arm_semihosting.c index f31f901..9117a74 100644 --- a/src/target/arm_semihosting.c +++ b/src/target/arm_semihosting.c @@ -8,6 +8,9 @@ * Copyright (C) 2016 by Square, Inc. * * Steven Stallion <stallion@squareup.com> * * * + * Copyright (C) 2018 by Liviu Ionescu * + * <ilg@livius.net> * + * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * @@ -43,6 +46,7 @@ #include "arm7_9_common.h" #include "armv7m.h" #include "armv7a.h" +#include "armv8.h" #include "cortex_m.h" #include "register.h" #include "arm_opcodes.h" @@ -52,25 +56,35 @@ #include <helper/log.h> #include <sys/stat.h> -static const int open_modeflags[12] = { - O_RDONLY, - O_RDONLY | O_BINARY, - O_RDWR, - O_RDWR | O_BINARY, - O_WRONLY | O_CREAT | O_TRUNC, - O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, - O_RDWR | O_CREAT | O_TRUNC, - O_RDWR | O_CREAT | O_TRUNC | O_BINARY, - O_WRONLY | O_CREAT | O_APPEND, - O_WRONLY | O_CREAT | O_APPEND | O_BINARY, - O_RDWR | O_CREAT | O_APPEND, - O_RDWR | O_CREAT | O_APPEND | O_BINARY -}; +static int arm_semihosting_resume(struct target *target, int *retval) +{ + if (is_armv8(target_to_armv8(target))) { + struct armv8_common *armv8 = target_to_armv8(target); + if (armv8->last_run_control_op == ARMV8_RUNCONTROL_RESUME) { + *retval = target_resume(target, 1, 0, 0, 0); + if (*retval != ERROR_OK) { + LOG_ERROR("Failed to resume target"); + return 0; + } + } else if (armv8->last_run_control_op == ARMV8_RUNCONTROL_STEP) + target->debug_reason = DBG_REASON_SINGLESTEP; + } else { + *retval = target_resume(target, 1, 0, 0, 0); + if (*retval != ERROR_OK) { + LOG_ERROR("Failed to resume target"); + return 0; + } + } + return 1; +} static int post_result(struct target *target) { struct arm *arm = target_to_arm(target); + if (!target->semihosting) + return ERROR_FAIL; + /* REVISIT this looks wrong ... ARM11 and Cortex-A8 * should work this way at least sometimes. */ @@ -79,7 +93,7 @@ static int post_result(struct target *target) uint32_t spsr; /* return value in R0 */ - buf_set_u32(arm->core_cache->reg_list[0].value, 0, 32, arm->semihosting_result); + buf_set_u32(arm->core_cache->reg_list[0].value, 0, 32, target->semihosting->result); arm->core_cache->reg_list[0].dirty = 1; /* LR --> PC */ @@ -100,528 +114,28 @@ static int post_result(struct target *target) if (spsr & 0x20) arm->core_state = ARM_STATE_THUMB; + } else if (is_armv8(target_to_armv8(target))) { + if (arm->core_state == ARM_STATE_AARCH64) { + /* return value in R0 */ + buf_set_u64(arm->core_cache->reg_list[0].value, 0, 64, target->semihosting->result); + arm->core_cache->reg_list[0].dirty = 1; + + uint64_t pc = buf_get_u64(arm->core_cache->reg_list[32].value, 0, 64); + buf_set_u64(arm->pc->value, 0, 64, pc + 4); + arm->pc->dirty = 1; + } } else { /* resume execution, this will be pc+2 to skip over the * bkpt instruction */ /* return result in R0 */ - buf_set_u32(arm->core_cache->reg_list[0].value, 0, 32, arm->semihosting_result); + buf_set_u32(arm->core_cache->reg_list[0].value, 0, 32, target->semihosting->result); arm->core_cache->reg_list[0].dirty = 1; } return ERROR_OK; } -static int do_semihosting(struct target *target) -{ - struct arm *arm = target_to_arm(target); - struct gdb_fileio_info *fileio_info = target->fileio_info; - uint32_t r0 = buf_get_u32(arm->core_cache->reg_list[0].value, 0, 32); - uint32_t r1 = buf_get_u32(arm->core_cache->reg_list[1].value, 0, 32); - uint8_t params[16]; - int retval; - - /* - * TODO: lots of security issues are not considered yet, such as: - * - no validation on target provided file descriptors - * - no safety checks on opened/deleted/renamed file paths - * Beware the target app you use this support with. - * - * TODO: unsupported semihosting fileio operations could be - * implemented if we had a small working area at our disposal. - */ - switch ((arm->semihosting_op = r0)) { - case 0x01: /* SYS_OPEN */ - retval = target_read_memory(target, r1, 4, 3, params); - if (retval != ERROR_OK) - return retval; - else { - uint32_t a = target_buffer_get_u32(target, params+0); - uint32_t m = target_buffer_get_u32(target, params+4); - uint32_t l = target_buffer_get_u32(target, params+8); - uint8_t fn[256]; - retval = target_read_memory(target, a, 1, l, fn); - if (retval != ERROR_OK) - return retval; - fn[l] = 0; - if (arm->is_semihosting_fileio) { - if (strcmp((char *)fn, ":tt") == 0) - arm->semihosting_result = 0; - else { - arm->semihosting_hit_fileio = true; - fileio_info->identifier = "open"; - fileio_info->param_1 = a; - fileio_info->param_2 = l; - fileio_info->param_3 = open_modeflags[m]; - fileio_info->param_4 = 0644; - } - } else { - if (l <= 255 && m <= 11) { - if (strcmp((char *)fn, ":tt") == 0) { - if (m < 4) - arm->semihosting_result = dup(STDIN_FILENO); - else - arm->semihosting_result = dup(STDOUT_FILENO); - } else { - /* cygwin requires the permission setting - * otherwise it will fail to reopen a previously - * written file */ - arm->semihosting_result = open((char *)fn, open_modeflags[m], 0644); - } - arm->semihosting_errno = errno; - } else { - arm->semihosting_result = -1; - arm->semihosting_errno = EINVAL; - } - } - } - break; - - case 0x02: /* SYS_CLOSE */ - retval = target_read_memory(target, r1, 4, 1, params); - if (retval != ERROR_OK) - return retval; - else { - int fd = target_buffer_get_u32(target, params+0); - if (arm->is_semihosting_fileio) { - arm->semihosting_hit_fileio = true; - fileio_info->identifier = "close"; - fileio_info->param_1 = fd; - } else { - arm->semihosting_result = close(fd); - arm->semihosting_errno = errno; - } - } - break; - - case 0x03: /* SYS_WRITEC */ - if (arm->is_semihosting_fileio) { - arm->semihosting_hit_fileio = true; - fileio_info->identifier = "write"; - fileio_info->param_1 = 1; - fileio_info->param_2 = r1; - fileio_info->param_3 = 1; - } else { - unsigned char c; - retval = target_read_memory(target, r1, 1, 1, &c); - if (retval != ERROR_OK) - return retval; - putchar(c); - arm->semihosting_result = 0; - } - break; - - case 0x04: /* SYS_WRITE0 */ - if (arm->is_semihosting_fileio) { - size_t count = 0; - for (uint32_t a = r1;; a++) { - unsigned char c; - retval = target_read_memory(target, a, 1, 1, &c); - if (retval != ERROR_OK) - return retval; - if (c == '\0') - break; - count++; - } - arm->semihosting_hit_fileio = true; - fileio_info->identifier = "write"; - fileio_info->param_1 = 1; - fileio_info->param_2 = r1; - fileio_info->param_3 = count; - } else { - do { - unsigned char c; - retval = target_read_memory(target, r1++, 1, 1, &c); - if (retval != ERROR_OK) - return retval; - if (!c) - break; - putchar(c); - } while (1); - arm->semihosting_result = 0; - } - break; - - case 0x05: /* SYS_WRITE */ - retval = target_read_memory(target, r1, 4, 3, params); - if (retval != ERROR_OK) - return retval; - else { - int fd = target_buffer_get_u32(target, params+0); - uint32_t a = target_buffer_get_u32(target, params+4); - size_t l = target_buffer_get_u32(target, params+8); - if (arm->is_semihosting_fileio) { - arm->semihosting_hit_fileio = true; - fileio_info->identifier = "write"; - fileio_info->param_1 = fd; - fileio_info->param_2 = a; - fileio_info->param_3 = l; - } else { - uint8_t *buf = malloc(l); - if (!buf) { - arm->semihosting_result = -1; - arm->semihosting_errno = ENOMEM; - } else { - retval = target_read_buffer(target, a, l, buf); - if (retval != ERROR_OK) { - free(buf); - return retval; - } - arm->semihosting_result = write(fd, buf, l); - arm->semihosting_errno = errno; - if (arm->semihosting_result >= 0) - arm->semihosting_result = l - arm->semihosting_result; - free(buf); - } - } - } - break; - - case 0x06: /* SYS_READ */ - retval = target_read_memory(target, r1, 4, 3, params); - if (retval != ERROR_OK) - return retval; - else { - int fd = target_buffer_get_u32(target, params+0); - uint32_t a = target_buffer_get_u32(target, params+4); - ssize_t l = target_buffer_get_u32(target, params+8); - if (arm->is_semihosting_fileio) { - arm->semihosting_hit_fileio = true; - fileio_info->identifier = "read"; - fileio_info->param_1 = fd; - fileio_info->param_2 = a; - fileio_info->param_3 = l; - } else { - uint8_t *buf = malloc(l); - if (!buf) { - arm->semihosting_result = -1; - arm->semihosting_errno = ENOMEM; - } else { - arm->semihosting_result = read(fd, buf, l); - arm->semihosting_errno = errno; - if (arm->semihosting_result >= 0) { - retval = target_write_buffer(target, a, arm->semihosting_result, buf); - if (retval != ERROR_OK) { - free(buf); - return retval; - } - arm->semihosting_result = l - arm->semihosting_result; - } - free(buf); - } - } - } - break; - - case 0x07: /* SYS_READC */ - if (arm->is_semihosting_fileio) { - LOG_ERROR("SYS_READC not supported by semihosting fileio"); - return ERROR_FAIL; - } - arm->semihosting_result = getchar(); - break; - - case 0x08: /* SYS_ISERROR */ - retval = target_read_memory(target, r1, 4, 1, params); - if (retval != ERROR_OK) - return retval; - arm->semihosting_result = (target_buffer_get_u32(target, params+0) != 0); - break; - - case 0x09: /* SYS_ISTTY */ - if (arm->is_semihosting_fileio) { - arm->semihosting_hit_fileio = true; - fileio_info->identifier = "isatty"; - fileio_info->param_1 = r1; - } else { - retval = target_read_memory(target, r1, 4, 1, params); - if (retval != ERROR_OK) - return retval; - arm->semihosting_result = isatty(target_buffer_get_u32(target, params+0)); - } - break; - - case 0x0a: /* SYS_SEEK */ - retval = target_read_memory(target, r1, 4, 2, params); - if (retval != ERROR_OK) - return retval; - else { - int fd = target_buffer_get_u32(target, params+0); - off_t pos = target_buffer_get_u32(target, params+4); - if (arm->is_semihosting_fileio) { - arm->semihosting_hit_fileio = true; - fileio_info->identifier = "lseek"; - fileio_info->param_1 = fd; - fileio_info->param_2 = pos; - fileio_info->param_3 = SEEK_SET; - } else { - arm->semihosting_result = lseek(fd, pos, SEEK_SET); - arm->semihosting_errno = errno; - if (arm->semihosting_result == pos) - arm->semihosting_result = 0; - } - } - break; - - case 0x0c: /* SYS_FLEN */ - if (arm->is_semihosting_fileio) { - LOG_ERROR("SYS_FLEN not supported by semihosting fileio"); - return ERROR_FAIL; - } - retval = target_read_memory(target, r1, 4, 1, params); - if (retval != ERROR_OK) - return retval; - else { - int fd = target_buffer_get_u32(target, params+0); - struct stat buf; - arm->semihosting_result = fstat(fd, &buf); - if (arm->semihosting_result == -1) { - arm->semihosting_errno = errno; - arm->semihosting_result = -1; - break; - } - arm->semihosting_result = buf.st_size; - } - break; - - case 0x0e: /* SYS_REMOVE */ - retval = target_read_memory(target, r1, 4, 2, params); - if (retval != ERROR_OK) - return retval; - else { - uint32_t a = target_buffer_get_u32(target, params+0); - uint32_t l = target_buffer_get_u32(target, params+4); - if (arm->is_semihosting_fileio) { - arm->semihosting_hit_fileio = true; - fileio_info->identifier = "unlink"; - fileio_info->param_1 = a; - fileio_info->param_2 = l; - } else { - if (l <= 255) { - uint8_t fn[256]; - retval = target_read_memory(target, a, 1, l, fn); - if (retval != ERROR_OK) - return retval; - fn[l] = 0; - arm->semihosting_result = remove((char *)fn); - arm->semihosting_errno = errno; - } else { - arm->semihosting_result = -1; - arm->semihosting_errno = EINVAL; - } - } - } - break; - - case 0x0f: /* SYS_RENAME */ - retval = target_read_memory(target, r1, 4, 4, params); - if (retval != ERROR_OK) - return retval; - else { - uint32_t a1 = target_buffer_get_u32(target, params+0); - uint32_t l1 = target_buffer_get_u32(target, params+4); - uint32_t a2 = target_buffer_get_u32(target, params+8); - uint32_t l2 = target_buffer_get_u32(target, params+12); - if (arm->is_semihosting_fileio) { - arm->semihosting_hit_fileio = true; - fileio_info->identifier = "rename"; - fileio_info->param_1 = a1; - fileio_info->param_2 = l1; - fileio_info->param_3 = a2; - fileio_info->param_4 = l2; - } else { - if (l1 <= 255 && l2 <= 255) { - uint8_t fn1[256], fn2[256]; - retval = target_read_memory(target, a1, 1, l1, fn1); - if (retval != ERROR_OK) - return retval; - retval = target_read_memory(target, a2, 1, l2, fn2); - if (retval != ERROR_OK) - return retval; - fn1[l1] = 0; - fn2[l2] = 0; - arm->semihosting_result = rename((char *)fn1, (char *)fn2); - arm->semihosting_errno = errno; - } else { - arm->semihosting_result = -1; - arm->semihosting_errno = EINVAL; - } - } - } - break; - - case 0x11: /* SYS_TIME */ - arm->semihosting_result = time(NULL); - break; - - case 0x13: /* SYS_ERRNO */ - arm->semihosting_result = arm->semihosting_errno; - break; - - case 0x15: /* SYS_GET_CMDLINE */ - retval = target_read_memory(target, r1, 4, 2, params); - if (retval != ERROR_OK) - return retval; - else { - uint32_t a = target_buffer_get_u32(target, params+0); - uint32_t l = target_buffer_get_u32(target, params+4); - char *arg = arm->semihosting_cmdline != NULL ? arm->semihosting_cmdline : ""; - uint32_t s = strlen(arg) + 1; - if (l < s) - arm->semihosting_result = -1; - else { - retval = target_write_buffer(target, a, s, (uint8_t *)arg); - if (retval != ERROR_OK) - return retval; - arm->semihosting_result = 0; - } - } - break; - - case 0x16: /* SYS_HEAPINFO */ - retval = target_read_memory(target, r1, 4, 1, params); - if (retval != ERROR_OK) - return retval; - else { - uint32_t a = target_buffer_get_u32(target, params+0); - /* tell the remote we have no idea */ - memset(params, 0, 4*4); - retval = target_write_memory(target, a, 4, 4, params); - if (retval != ERROR_OK) - return retval; - arm->semihosting_result = 0; - } - break; - - case 0x18: /* angel_SWIreason_ReportException */ - switch (r1) { - case 0x20026: /* ADP_Stopped_ApplicationExit */ - fprintf(stderr, "semihosting: *** application exited ***\n"); - break; - case 0x20000: /* ADP_Stopped_BranchThroughZero */ - case 0x20001: /* ADP_Stopped_UndefinedInstr */ - case 0x20002: /* ADP_Stopped_SoftwareInterrupt */ - case 0x20003: /* ADP_Stopped_PrefetchAbort */ - case 0x20004: /* ADP_Stopped_DataAbort */ - case 0x20005: /* ADP_Stopped_AddressException */ - case 0x20006: /* ADP_Stopped_IRQ */ - case 0x20007: /* ADP_Stopped_FIQ */ - case 0x20020: /* ADP_Stopped_BreakPoint */ - case 0x20021: /* ADP_Stopped_WatchPoint */ - case 0x20022: /* ADP_Stopped_StepComplete */ - case 0x20023: /* ADP_Stopped_RunTimeErrorUnknown */ - case 0x20024: /* ADP_Stopped_InternalError */ - case 0x20025: /* ADP_Stopped_UserInterruption */ - case 0x20027: /* ADP_Stopped_StackOverflow */ - case 0x20028: /* ADP_Stopped_DivisionByZero */ - case 0x20029: /* ADP_Stopped_OSSpecific */ - default: - fprintf(stderr, "semihosting: exception %#x\n", - (unsigned) r1); - } - return target_call_event_callbacks(target, TARGET_EVENT_HALTED); - - case 0x12: /* SYS_SYSTEM */ - /* Provide SYS_SYSTEM functionality. Uses the - * libc system command, there may be a reason *NOT* - * to use this, but as I can't think of one, I - * implemented it this way. - */ - retval = target_read_memory(target, r1, 4, 2, params); - if (retval != ERROR_OK) - return retval; - else { - uint32_t len = target_buffer_get_u32(target, params+4); - uint32_t c_ptr = target_buffer_get_u32(target, params); - if (arm->is_semihosting_fileio) { - arm->semihosting_hit_fileio = true; - fileio_info->identifier = "system"; - fileio_info->param_1 = c_ptr; - fileio_info->param_2 = len; - } else { - uint8_t cmd[256]; - if (len > 255) { - arm->semihosting_result = -1; - arm->semihosting_errno = EINVAL; - } else { - memset(cmd, 0x0, 256); - retval = target_read_memory(target, c_ptr, 1, len, cmd); - if (retval != ERROR_OK) - return retval; - else - arm->semihosting_result = system((const char *)cmd); - } - } - } - break; - case 0x0d: /* SYS_TMPNAM */ - case 0x10: /* SYS_CLOCK */ - case 0x17: /* angel_SWIreason_EnterSVC */ - case 0x30: /* SYS_ELAPSED */ - case 0x31: /* SYS_TICKFREQ */ - default: - fprintf(stderr, "semihosting: unsupported call %#x\n", - (unsigned) r0); - arm->semihosting_result = -1; - arm->semihosting_errno = ENOTSUP; - } - - return ERROR_OK; -} - -static int get_gdb_fileio_info(struct target *target, struct gdb_fileio_info *fileio_info) -{ - struct arm *arm = target_to_arm(target); - - /* To avoid uneccessary duplication, semihosting prepares the - * fileio_info structure out-of-band when the target halts. See - * do_semihosting for more detail. - */ - if (!arm->is_semihosting_fileio || !arm->semihosting_hit_fileio) - return ERROR_FAIL; - - return ERROR_OK; -} - -static int gdb_fileio_end(struct target *target, int result, int fileio_errno, bool ctrl_c) -{ - struct arm *arm = target_to_arm(target); - struct gdb_fileio_info *fileio_info = target->fileio_info; - - /* clear pending status */ - arm->semihosting_hit_fileio = false; - - arm->semihosting_result = result; - arm->semihosting_errno = fileio_errno; - - /* Some fileio results do not match up with what the semihosting - * operation expects; for these operations, we munge the results - * below: - */ - switch (arm->semihosting_op) { - case 0x05: /* SYS_WRITE */ - if (result < 0) - arm->semihosting_result = fileio_info->param_3; - else - arm->semihosting_result = 0; - break; - - case 0x06: /* SYS_READ */ - if (result == (int)fileio_info->param_3) - arm->semihosting_result = 0; - if (result <= 0) - arm->semihosting_result = fileio_info->param_3; - break; - - case 0x0a: /* SYS_SEEK */ - if (result > 0) - arm->semihosting_result = 0; - break; - } - - return post_result(target); -} - /** * Initialize ARM semihosting support. * @@ -630,14 +144,9 @@ static int gdb_fileio_end(struct target *target, int result, int fileio_errno, b */ int arm_semihosting_init(struct target *target) { - target->fileio_info = malloc(sizeof(*target->fileio_info)); - if (target->fileio_info == NULL) { - LOG_ERROR("out of memory"); - return ERROR_FAIL; - } - - target->type->get_gdb_fileio_info = get_gdb_fileio_info; - target->type->gdb_fileio_end = gdb_fileio_end; + struct arm *arm = target_to_arm(target); + assert(arm->setup_semihosting); + semihosting_common_init(target, arm->setup_semihosting, post_result); return ERROR_OK; } @@ -662,7 +171,11 @@ int arm_semihosting(struct target *target, int *retval) uint32_t pc, lr, spsr; struct reg *r; - if (!arm->is_semihosting) + struct semihosting *semihosting = target->semihosting; + if (!semihosting) + return 0; + + if (!semihosting->is_active) return 0; if (is_arm7_9(target_to_arm7_9(target)) || @@ -758,6 +271,24 @@ int arm_semihosting(struct target *target, int *retval) /* bkpt 0xAB */ if (insn != 0xBEAB) return 0; + } else if (is_armv8(target_to_armv8(target))) { + if (target->debug_reason != DBG_REASON_BREAKPOINT) + return 0; + + if (arm->core_state == ARM_STATE_AARCH64) { + uint32_t insn = 0; + r = arm->pc; + uint64_t pc64 = buf_get_u64(r->value, 0, 64); + *retval = target_read_u32(target, pc64, &insn); + + if (*retval != ERROR_OK) + return 1; + + /* bkpt 0xAB */ + if (insn != 0xD45E0000) + return 0; + } else + return 1; } else { LOG_ERROR("Unsupported semi-hosting Target"); return 0; @@ -766,32 +297,38 @@ int arm_semihosting(struct target *target, int *retval) /* Perform semihosting if we are not waiting on a fileio * operation to complete. */ - if (!arm->semihosting_hit_fileio) { - *retval = do_semihosting(target); - if (*retval != ERROR_OK) { - LOG_ERROR("Failed semihosting operation"); + if (!semihosting->hit_fileio) { + if (is_armv8(target_to_armv8(target)) && + arm->core_state == ARM_STATE_AARCH64) { + /* Read op and param from register x0 and x1 respectively. */ + semihosting->op = buf_get_u64(arm->core_cache->reg_list[0].value, 0, 64); + semihosting->param = buf_get_u64(arm->core_cache->reg_list[1].value, 0, 64); + semihosting->word_size_bytes = 8; + } else { + /* Read op and param from register r0 and r1 respectively. */ + semihosting->op = buf_get_u32(arm->core_cache->reg_list[0].value, 0, 32); + semihosting->param = buf_get_u32(arm->core_cache->reg_list[1].value, 0, 32); + semihosting->word_size_bytes = 4; + } + + /* Check for ARM operation numbers. */ + if (0 <= semihosting->op && semihosting->op <= 0x31) { + *retval = semihosting_common(target); + if (*retval != ERROR_OK) { + LOG_ERROR("Failed semihosting operation"); + return 0; + } + } else { + /* Unknown operation number, not a semihosting call. */ return 0; } } - /* Post result to target if we are not waiting on a fileio + /* Resume if target it is resumable and we are not waiting on a fileio * operation to complete: */ - if (!arm->semihosting_hit_fileio) { - *retval = post_result(target); - if (*retval != ERROR_OK) { - LOG_ERROR("Failed to post semihosting result"); - return 0; - } - - *retval = target_resume(target, 1, 0, 0, 0); - if (*retval != ERROR_OK) { - LOG_ERROR("Failed to resume target"); - return 0; - } - - return 1; - } + if (semihosting->is_resumable && !semihosting->hit_fileio) + return arm_semihosting_resume(target, retval); return 0; } diff --git a/src/target/arm_semihosting.h b/src/target/arm_semihosting.h index 011f19f..cf1f8de 100644 --- a/src/target/arm_semihosting.h +++ b/src/target/arm_semihosting.h @@ -19,6 +19,8 @@ #ifndef OPENOCD_TARGET_ARM_SEMIHOSTING_H #define OPENOCD_TARGET_ARM_SEMIHOSTING_H +#include "semihosting_common.h" + int arm_semihosting_init(struct target *target); int arm_semihosting(struct target *target, int *retval); diff --git a/src/target/armv4_5.c b/src/target/armv4_5.c index 06994ca..96a63e4 100644 --- a/src/target/armv4_5.c +++ b/src/target/armv4_5.c @@ -8,6 +8,9 @@ * Copyright (C) 2008 by Oyvind Harboe * * oyvind.harboe@zylin.com * * * + * Copyright (C) 2018 by Liviu Ionescu * + * <ilg@livius.net> * + * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * @@ -34,6 +37,7 @@ #include <helper/binarybuffer.h> #include "algorithm.h" #include "register.h" +#include "semihosting_common.h" /* offsets into armv4_5 core register cache */ enum { @@ -748,7 +752,7 @@ int arm_arch_state(struct target *target) } /* avoid filling log waiting for fileio reply */ - if (arm->semihosting_hit_fileio) + if (target->semihosting && target->semihosting->hit_fileio) return ERROR_OK; LOG_USER("target halted in %s state due to %s, current mode: %s\n" @@ -758,8 +762,8 @@ int arm_arch_state(struct target *target) arm_mode_name(arm->core_mode), buf_get_u32(arm->cpsr->value, 0, 32), buf_get_u32(arm->pc->value, 0, 32), - arm->is_semihosting ? ", semihosting" : "", - arm->is_semihosting_fileio ? " fileio" : ""); + (target->semihosting && target->semihosting->is_active) ? ", semihosting" : "", + (target->semihosting && target->semihosting->is_fileio) ? " fileio" : ""); return ERROR_OK; } @@ -1094,119 +1098,10 @@ static int jim_mcrmrc(Jim_Interp *interp, int argc, Jim_Obj * const *argv) return JIM_OK; } -COMMAND_HANDLER(handle_arm_semihosting_command) -{ - struct target *target = get_current_target(CMD_CTX); - - if (target == NULL) { - LOG_ERROR("No target selected"); - return ERROR_FAIL; - } - - struct arm *arm = target_to_arm(target); - - if (!is_arm(arm)) { - command_print(CMD_CTX, "current target isn't an ARM"); - return ERROR_FAIL; - } - - if (!arm->setup_semihosting) { - command_print(CMD_CTX, "semihosting not supported for current target"); - return ERROR_FAIL; - } - - if (CMD_ARGC > 0) { - int semihosting; - - COMMAND_PARSE_ENABLE(CMD_ARGV[0], semihosting); - - if (!target_was_examined(target)) { - LOG_ERROR("Target not examined yet"); - return ERROR_FAIL; - } - - if (arm->setup_semihosting(target, semihosting) != ERROR_OK) { - LOG_ERROR("Failed to Configure semihosting"); - return ERROR_FAIL; - } - - /* FIXME never let that "catch" be dropped! */ - arm->is_semihosting = semihosting; - } - - command_print(CMD_CTX, "semihosting is %s", - arm->is_semihosting - ? "enabled" : "disabled"); - - return ERROR_OK; -} - -COMMAND_HANDLER(handle_arm_semihosting_fileio_command) -{ - struct target *target = get_current_target(CMD_CTX); - - if (target == NULL) { - LOG_ERROR("No target selected"); - return ERROR_FAIL; - } - - struct arm *arm = target_to_arm(target); - - if (!is_arm(arm)) { - command_print(CMD_CTX, "current target isn't an ARM"); - return ERROR_FAIL; - } - - if (!arm->is_semihosting) { - command_print(CMD_CTX, "semihosting is not enabled"); - return ERROR_FAIL; - } - - if (CMD_ARGC > 0) - COMMAND_PARSE_ENABLE(CMD_ARGV[0], arm->is_semihosting_fileio); - - command_print(CMD_CTX, "semihosting fileio is %s", - arm->is_semihosting_fileio - ? "enabled" : "disabled"); - - return ERROR_OK; -} - -COMMAND_HANDLER(handle_arm_semihosting_cmdline) -{ - struct target *target = get_current_target(CMD_CTX); - unsigned int i; - - if (target == NULL) { - LOG_ERROR("No target selected"); - return ERROR_FAIL; - } - - struct arm *arm = target_to_arm(target); - - if (!is_arm(arm)) { - command_print(CMD_CTX, "current target isn't an ARM"); - return ERROR_FAIL; - } - - if (!arm->setup_semihosting) { - command_print(CMD_CTX, "semihosting not supported for current target"); - return ERROR_FAIL; - } - - free(arm->semihosting_cmdline); - arm->semihosting_cmdline = CMD_ARGC > 0 ? strdup(CMD_ARGV[0]) : NULL; - - for (i = 1; i < CMD_ARGC; i++) { - char *cmdline = alloc_printf("%s %s", arm->semihosting_cmdline, CMD_ARGV[i]); - if (cmdline == NULL) - break; - free(arm->semihosting_cmdline); - arm->semihosting_cmdline = cmdline; - } - - return ERROR_OK; -} +extern __COMMAND_HANDLER(handle_common_semihosting_command); +extern __COMMAND_HANDLER(handle_common_semihosting_fileio_command); +extern __COMMAND_HANDLER(handle_common_semihosting_resumable_exit_command); +extern __COMMAND_HANDLER(handle_common_semihosting_cmdline); static const struct command_registration arm_exec_command_handlers[] = { { @@ -1245,26 +1140,32 @@ static const struct command_registration arm_exec_command_handlers[] = { }, { "semihosting", - .handler = handle_arm_semihosting_command, + .handler = handle_common_semihosting_command, .mode = COMMAND_EXEC, .usage = "['enable'|'disable']", .help = "activate support for semihosting operations", }, { "semihosting_cmdline", - .handler = handle_arm_semihosting_cmdline, + .handler = handle_common_semihosting_cmdline, .mode = COMMAND_EXEC, .usage = "arguments", .help = "command line arguments to be passed to program", }, { "semihosting_fileio", - .handler = handle_arm_semihosting_fileio_command, + .handler = handle_common_semihosting_fileio_command, .mode = COMMAND_EXEC, .usage = "['enable'|'disable']", .help = "activate support for semihosting fileio operations", }, - + { + "semihosting_resexit", + .handler = handle_common_semihosting_resumable_exit_command, + .mode = COMMAND_EXEC, + .usage = "['enable'|'disable']", + .help = "activate support for semihosting resumable exit", + }, COMMAND_REGISTRATION_DONE }; const struct command_registration arm_command_handlers[] = { diff --git a/src/target/armv7a.c b/src/target/armv7a.c index fab7363..eecfa70 100644 --- a/src/target/armv7a.c +++ b/src/target/armv7a.c @@ -124,7 +124,7 @@ done: return retval; } -static int armv7a_read_ttbcr(struct target *target) +int armv7a_read_ttbcr(struct target *target) { struct armv7a_common *armv7a = target_to_armv7a(target); struct arm_dpm *dpm = armv7a->arm.dpm; @@ -554,9 +554,6 @@ int armv7a_identify_cache(struct target *target) struct armv7a_cache_common *cache = &(armv7a->armv7a_mmu.armv7a_cache); - if (!armv7a->is_armv7r) - armv7a_read_ttbcr(target); - retval = dpm->prepare(dpm); if (retval != ERROR_OK) goto done; @@ -729,8 +726,6 @@ int armv7a_arch_state(struct target *target) arm_arch_state(target); - armv7a_read_ttbcr(target); - if (armv7a->is_armv7r) { LOG_USER("D-Cache: %s, I-Cache: %s", state[armv7a->armv7a_mmu.armv7a_cache.d_u_cache_enabled], diff --git a/src/target/armv7a.h b/src/target/armv7a.h index 33f6f5d..57779c6 100644 --- a/src/target/armv7a.h +++ b/src/target/armv7a.h @@ -194,6 +194,7 @@ int armv7a_mmu_translate_va(struct target *target, uint32_t va, uint32_t *val); int armv7a_handle_cache_info_command(struct command_context *cmd_ctx, struct armv7a_cache_common *armv7a_cache); +int armv7a_read_ttbcr(struct target *target); extern const struct command_registration armv7a_command_handlers[]; diff --git a/src/target/armv7a_cache.c b/src/target/armv7a_cache.c index 3e5f8d6..7435aab 100644 --- a/src/target/armv7a_cache.c +++ b/src/target/armv7a_cache.c @@ -70,6 +70,7 @@ static int armv7a_l1_d_cache_flush_level(struct arm_dpm *dpm, struct armv7a_cach LOG_DEBUG("cl %" PRId32, cl); do { + keep_alive(); c_way = size->way; do { uint32_t value = (c_index << size->index_shift) @@ -89,6 +90,7 @@ static int armv7a_l1_d_cache_flush_level(struct arm_dpm *dpm, struct armv7a_cach } while (c_index >= 0); done: + keep_alive(); return retval; } @@ -164,7 +166,7 @@ int armv7a_l1_d_cache_inval_virt(struct target *target, uint32_t virt, struct armv7a_cache_common *armv7a_cache = &armv7a->armv7a_mmu.armv7a_cache; uint32_t linelen = armv7a_cache->dminline; uint32_t va_line, va_end; - int retval; + int retval, i = 0; retval = armv7a_l1_d_cache_sanity_check(target); if (retval != ERROR_OK) @@ -198,6 +200,8 @@ int armv7a_l1_d_cache_inval_virt(struct target *target, uint32_t virt, } while (va_line < va_end) { + if ((i++ & 0x3f) == 0) + keep_alive(); /* DCIMVAC - Invalidate data cache line by VA to PoC. */ retval = dpm->instr_write_data_r0(dpm, ARMV4_5_MCR(15, 0, 0, 7, 6, 1), va_line); @@ -206,11 +210,13 @@ int armv7a_l1_d_cache_inval_virt(struct target *target, uint32_t virt, va_line += linelen; } + keep_alive(); dpm->finish(dpm); return retval; done: LOG_ERROR("d-cache invalidate failed"); + keep_alive(); dpm->finish(dpm); return retval; @@ -224,7 +230,7 @@ int armv7a_l1_d_cache_clean_virt(struct target *target, uint32_t virt, struct armv7a_cache_common *armv7a_cache = &armv7a->armv7a_mmu.armv7a_cache; uint32_t linelen = armv7a_cache->dminline; uint32_t va_line, va_end; - int retval; + int retval, i = 0; retval = armv7a_l1_d_cache_sanity_check(target); if (retval != ERROR_OK) @@ -238,6 +244,8 @@ int armv7a_l1_d_cache_clean_virt(struct target *target, uint32_t virt, va_end = virt + size; while (va_line < va_end) { + if ((i++ & 0x3f) == 0) + keep_alive(); /* DCCMVAC - Data Cache Clean by MVA to PoC */ retval = dpm->instr_write_data_r0(dpm, ARMV4_5_MCR(15, 0, 0, 7, 10, 1), va_line); @@ -246,11 +254,13 @@ int armv7a_l1_d_cache_clean_virt(struct target *target, uint32_t virt, va_line += linelen; } + keep_alive(); dpm->finish(dpm); return retval; done: LOG_ERROR("d-cache invalidate failed"); + keep_alive(); dpm->finish(dpm); return retval; @@ -264,7 +274,7 @@ int armv7a_l1_d_cache_flush_virt(struct target *target, uint32_t virt, struct armv7a_cache_common *armv7a_cache = &armv7a->armv7a_mmu.armv7a_cache; uint32_t linelen = armv7a_cache->dminline; uint32_t va_line, va_end; - int retval; + int retval, i = 0; retval = armv7a_l1_d_cache_sanity_check(target); if (retval != ERROR_OK) @@ -278,6 +288,8 @@ int armv7a_l1_d_cache_flush_virt(struct target *target, uint32_t virt, va_end = virt + size; while (va_line < va_end) { + if ((i++ & 0x3f) == 0) + keep_alive(); /* DCCIMVAC */ retval = dpm->instr_write_data_r0(dpm, ARMV4_5_MCR(15, 0, 0, 7, 14, 1), va_line); @@ -286,11 +298,13 @@ int armv7a_l1_d_cache_flush_virt(struct target *target, uint32_t virt, va_line += linelen; } + keep_alive(); dpm->finish(dpm); return retval; done: LOG_ERROR("d-cache invalidate failed"); + keep_alive(); dpm->finish(dpm); return retval; @@ -342,7 +356,7 @@ int armv7a_l1_i_cache_inval_virt(struct target *target, uint32_t virt, &armv7a->armv7a_mmu.armv7a_cache; uint32_t linelen = armv7a_cache->iminline; uint32_t va_line, va_end; - int retval; + int retval, i = 0; retval = armv7a_l1_i_cache_sanity_check(target); if (retval != ERROR_OK) @@ -356,6 +370,8 @@ int armv7a_l1_i_cache_inval_virt(struct target *target, uint32_t virt, va_end = virt + size; while (va_line < va_end) { + if ((i++ & 0x3f) == 0) + keep_alive(); /* ICIMVAU - Invalidate instruction cache by VA to PoU. */ retval = dpm->instr_write_data_r0(dpm, ARMV4_5_MCR(15, 0, 0, 7, 5, 1), va_line); @@ -368,10 +384,13 @@ int armv7a_l1_i_cache_inval_virt(struct target *target, uint32_t virt, goto done; va_line += linelen; } + keep_alive(); + dpm->finish(dpm); return retval; done: LOG_ERROR("i-cache invalidate failed"); + keep_alive(); dpm->finish(dpm); return retval; diff --git a/src/target/armv7m.c b/src/target/armv7m.c index 7b7893f..7d3bd73 100644 --- a/src/target/armv7m.c +++ b/src/target/armv7m.c @@ -11,6 +11,9 @@ * Copyright (C) 2007,2008 Øyvind Harboe * * oyvind.harboe@zylin.com * * * + * Copyright (C) 2018 by Liviu Ionescu * + * <ilg@livius.net> * + * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * @@ -37,6 +40,7 @@ #include "armv7m.h" #include "algorithm.h" #include "register.h" +#include "semihosting_common.h" #if 0 #define _DEBUG_INSTRUCTION_EXECUTION_ @@ -537,7 +541,7 @@ int armv7m_arch_state(struct target *target) uint32_t ctrl, sp; /* avoid filling log waiting for fileio reply */ - if (arm->semihosting_hit_fileio) + if (target->semihosting && target->semihosting->hit_fileio) return ERROR_OK; ctrl = buf_get_u32(arm->core_cache->reg_list[ARMV7M_CONTROL].value, 0, 32); @@ -552,8 +556,8 @@ int armv7m_arch_state(struct target *target) buf_get_u32(arm->pc->value, 0, 32), (ctrl & 0x02) ? 'p' : 'm', sp, - arm->is_semihosting ? ", semihosting" : "", - arm->is_semihosting_fileio ? " fileio" : ""); + (target->semihosting && target->semihosting->is_active) ? ", semihosting" : "", + (target->semihosting && target->semihosting->is_fileio) ? " fileio" : ""); return ERROR_OK; } diff --git a/src/target/armv7m_trace.c b/src/target/armv7m_trace.c index c1e4f5b..62f0f8e 100644 --- a/src/target/armv7m_trace.c +++ b/src/target/armv7m_trace.c @@ -62,7 +62,7 @@ int armv7m_trace_tpiu_config(struct target *target) target_unregister_timer_callback(armv7m_poll_trace, target); - retval = adapter_config_trace(trace_config->config_type == INTERNAL, + retval = adapter_config_trace(trace_config->config_type == TRACE_CONFIG_TYPE_INTERNAL, trace_config->pin_protocol, trace_config->port_size, &trace_config->trace_freq); @@ -83,7 +83,7 @@ int armv7m_trace_tpiu_config(struct target *target) trace_config->trace_freq, trace_config->traceclkin_freq, trace_freq); trace_config->trace_freq = trace_freq; - retval = adapter_config_trace(trace_config->config_type == INTERNAL, + retval = adapter_config_trace(trace_config->config_type == TRACE_CONFIG_TYPE_INTERNAL, trace_config->pin_protocol, trace_config->port_size, &trace_config->trace_freq); @@ -115,7 +115,7 @@ int armv7m_trace_tpiu_config(struct target *target) if (retval != ERROR_OK) return retval; - if (trace_config->config_type == INTERNAL) + if (trace_config->config_type == TRACE_CONFIG_TYPE_INTERNAL) target_register_timer_callback(armv7m_poll_trace, 1, 1, target); target_call_event_callbacks(target, TARGET_EVENT_TRACE_CONFIG); @@ -173,7 +173,7 @@ COMMAND_HANDLER(handle_tpiu_config_command) if (CMD_ARGC == cmd_idx + 1) { close_trace_file(armv7m); - armv7m->trace_config.config_type = DISABLED; + armv7m->trace_config.config_type = TRACE_CONFIG_TYPE_DISABLED; if (CMD_CTX->mode == COMMAND_EXEC) return armv7m_trace_tpiu_config(target); else @@ -183,13 +183,13 @@ COMMAND_HANDLER(handle_tpiu_config_command) !strcmp(CMD_ARGV[cmd_idx], "internal")) { close_trace_file(armv7m); - armv7m->trace_config.config_type = EXTERNAL; + armv7m->trace_config.config_type = TRACE_CONFIG_TYPE_EXTERNAL; if (!strcmp(CMD_ARGV[cmd_idx], "internal")) { cmd_idx++; if (CMD_ARGC == cmd_idx) return ERROR_COMMAND_SYNTAX_ERROR; - armv7m->trace_config.config_type = INTERNAL; + armv7m->trace_config.config_type = TRACE_CONFIG_TYPE_INTERNAL; if (strcmp(CMD_ARGV[cmd_idx], "-") != 0) { armv7m->trace_config.trace_file = fopen(CMD_ARGV[cmd_idx], "ab"); @@ -204,7 +204,7 @@ COMMAND_HANDLER(handle_tpiu_config_command) return ERROR_COMMAND_SYNTAX_ERROR; if (!strcmp(CMD_ARGV[cmd_idx], "sync")) { - armv7m->trace_config.pin_protocol = SYNC; + armv7m->trace_config.pin_protocol = TPIU_PIN_PROTOCOL_SYNC; cmd_idx++; if (CMD_ARGC == cmd_idx) @@ -213,9 +213,9 @@ COMMAND_HANDLER(handle_tpiu_config_command) COMMAND_PARSE_NUMBER(u32, CMD_ARGV[cmd_idx], armv7m->trace_config.port_size); } else { if (!strcmp(CMD_ARGV[cmd_idx], "manchester")) - armv7m->trace_config.pin_protocol = ASYNC_MANCHESTER; + armv7m->trace_config.pin_protocol = TPIU_PIN_PROTOCOL_ASYNC_MANCHESTER; else if (!strcmp(CMD_ARGV[cmd_idx], "uart")) - armv7m->trace_config.pin_protocol = ASYNC_UART; + armv7m->trace_config.pin_protocol = TPIU_PIN_PROTOCOL_ASYNC_UART; else return ERROR_COMMAND_SYNTAX_ERROR; @@ -237,7 +237,7 @@ COMMAND_HANDLER(handle_tpiu_config_command) COMMAND_PARSE_NUMBER(uint, CMD_ARGV[cmd_idx], armv7m->trace_config.trace_freq); cmd_idx++; } else { - if (armv7m->trace_config.config_type != INTERNAL) { + if (armv7m->trace_config.config_type != TRACE_CONFIG_TYPE_INTERNAL) { LOG_ERROR("Trace port frequency can't be omitted in external capture mode"); return ERROR_COMMAND_SYNTAX_ERROR; } diff --git a/src/target/armv7m_trace.h b/src/target/armv7m_trace.h index 4f99394..c63f36d 100644 --- a/src/target/armv7m_trace.h +++ b/src/target/armv7m_trace.h @@ -27,15 +27,15 @@ */ enum trace_config_type { - DISABLED, /**< tracing is disabled */ - EXTERNAL, /**< trace output is captured externally */ - INTERNAL /**< trace output is handled by OpenOCD adapter driver */ + TRACE_CONFIG_TYPE_DISABLED, /**< tracing is disabled */ + TRACE_CONFIG_TYPE_EXTERNAL, /**< trace output is captured externally */ + TRACE_CONFIG_TYPE_INTERNAL /**< trace output is handled by OpenOCD adapter driver */ }; -enum tpio_pin_protocol { - SYNC, /**< synchronous trace output */ - ASYNC_MANCHESTER, /**< asynchronous output with Manchester coding */ - ASYNC_UART /**< asynchronous output with NRZ coding */ +enum tpiu_pin_protocol { + TPIU_PIN_PROTOCOL_SYNC, /**< synchronous trace output */ + TPIU_PIN_PROTOCOL_ASYNC_MANCHESTER, /**< asynchronous output with Manchester coding */ + TPIU_PIN_PROTOCOL_ASYNC_UART /**< asynchronous output with NRZ coding */ }; enum itm_ts_prescaler { @@ -50,7 +50,7 @@ struct armv7m_trace_config { enum trace_config_type config_type; /** Currently active trace output mode */ - enum tpio_pin_protocol pin_protocol; + enum tpiu_pin_protocol pin_protocol; /** TPIU formatter enable/disable (in async mode) */ bool formatter; /** Synchronous output port width */ diff --git a/src/target/armv8.c b/src/target/armv8.c index 82b2b24..dfa2c67 100644 --- a/src/target/armv8.c +++ b/src/target/armv8.c @@ -1,6 +1,9 @@ /*************************************************************************** * Copyright (C) 2015 by David Ung * * * + * Copyright (C) 2018 by Liviu Ionescu * + * <ilg@livius.net> * + * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * @@ -36,6 +39,7 @@ #include "armv8_opcodes.h" #include "target.h" #include "target_type.h" +#include "semihosting_common.h" static const char * const armv8_state_strings[] = { "AArch32", "Thumb", "Jazelle", "ThumbEE", "AArch64", @@ -1013,11 +1017,24 @@ int armv8_handle_cache_info_command(struct command_context *cmd_ctx, return ERROR_OK; } +static int armv8_setup_semihosting(struct target *target, int enable) +{ + struct arm *arm = target_to_arm(target); + + if (arm->core_state != ARM_STATE_AARCH64) { + LOG_ERROR("semihosting only supported in AArch64 state\n"); + return ERROR_FAIL; + } + + return ERROR_OK; +} + int armv8_init_arch_info(struct target *target, struct armv8_common *armv8) { struct arm *arm = &armv8->arm; arm->arch_info = armv8; target->arch_info = &armv8->arm; + arm->setup_semihosting = armv8_setup_semihosting; /* target is useful in all function arm v4 5 compatible */ armv8->arm.target = target; armv8->arm.common_magic = ARM_COMMON_MAGIC; @@ -1046,7 +1063,7 @@ int armv8_aarch64_state(struct target *target) armv8_mode_name(arm->core_mode), buf_get_u32(arm->cpsr->value, 0, 32), buf_get_u64(arm->pc->value, 0, 64), - arm->is_semihosting ? ", semihosting" : ""); + (target->semihosting && target->semihosting->is_active) ? ", semihosting" : ""); return ERROR_OK; } diff --git a/src/target/armv8.h b/src/target/armv8.h index b346462..dfd54ed 100644 --- a/src/target/armv8.h +++ b/src/target/armv8.h @@ -113,6 +113,12 @@ enum { ARMV8_LAST_REG, }; +enum run_control_op { + ARMV8_RUNCONTROL_UNKNOWN = 0, + ARMV8_RUNCONTROL_RESUME = 1, + ARMV8_RUNCONTROL_HALT = 2, + ARMV8_RUNCONTROL_STEP = 3, +}; #define ARMV8_COMMON_MAGIC 0x0A450AAA @@ -210,6 +216,9 @@ struct armv8_common { struct arm_cti *cti; + /* last run-control command issued to this target (resume, halt, step) */ + enum run_control_op last_run_control_op; + /* Direct processor core register read and writes */ int (*read_reg_u64)(struct armv8_common *armv8, int num, uint64_t *value); int (*write_reg_u64)(struct armv8_common *armv8, int num, uint64_t value); @@ -232,6 +241,11 @@ target_to_armv8(struct target *target) return container_of(target->arch_info, struct armv8_common, arm); } +static inline bool is_armv8(struct armv8_common *armv8) +{ + return armv8->common_magic == ARMV8_COMMON_MAGIC; +} + /* register offsets from armv8.debug_base */ #define CPUV8_DBG_MAINID0 0xD00 #define CPUV8_DBG_CPUFEATURE0 0xD20 diff --git a/src/target/breakpoints.c b/src/target/breakpoints.c index 7cf4a69..58bcc86 100644 --- a/src/target/breakpoints.c +++ b/src/target/breakpoints.c @@ -315,11 +315,8 @@ int breakpoint_remove_internal(struct target *target, target_addr_t address) struct breakpoint *breakpoint = target->breakpoints; while (breakpoint) { - if ((breakpoint->address == address) && (breakpoint->asid == 0)) - break; - else if ((breakpoint->address == 0) && (breakpoint->asid == address)) - break; - else if ((breakpoint->address == address) && (breakpoint->asid != 0)) + if ((breakpoint->address == address) || + (breakpoint->address == 0 && breakpoint->asid == address)) break; breakpoint = breakpoint->next; } diff --git a/src/target/cortex_a.c b/src/target/cortex_a.c index 8985051..4aae5e4 100644 --- a/src/target/cortex_a.c +++ b/src/target/cortex_a.c @@ -1297,6 +1297,9 @@ static int cortex_a_post_debug_entry(struct target *target) LOG_DEBUG("cp15_control_reg: %8.8" PRIx32, cortex_a->cp15_control_reg); cortex_a->cp15_control_reg_curr = cortex_a->cp15_control_reg; + if (!armv7a->is_armv7r) + armv7a_read_ttbcr(target); + if (armv7a->armv7a_mmu.armv7a_cache.info == -1) armv7a_identify_cache(target); @@ -3226,6 +3229,20 @@ static int cortex_a_virt2phys(struct target *target, struct armv7a_common *armv7a = target_to_armv7a(target); struct adiv5_dap *swjdp = armv7a->arm.dap; uint8_t apsel = swjdp->apsel; + int mmu_enabled = 0; + + /* + * If the MMU was not enabled at debug entry, there is no + * way of knowing if there was ever a valid configuration + * for it and thus it's not safe to enable it. In this case, + * just return the virtual address as physical. + */ + cortex_a_mmu(target, &mmu_enabled); + if (!mmu_enabled) { + *phys = virt; + return ERROR_OK; + } + if (armv7a->memory_ap_available && (apsel == armv7a->memory_ap->ap_num)) { uint32_t ret; retval = armv7a_mmu_translate_va(target, @@ -3421,7 +3438,7 @@ static const struct command_registration cortex_a_exec_command_handlers[] = { { .name = "dacrfixup", .handler = handle_cortex_a_dacrfixup_command, - .mode = COMMAND_EXEC, + .mode = COMMAND_ANY, .help = "set domain access control (DACR) to all-manager " "on memory access", .usage = "['on'|'off']", diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c index 30439f4..ca3dbec 100644 --- a/src/target/cortex_m.c +++ b/src/target/cortex_m.c @@ -165,7 +165,7 @@ static int cortex_m_single_step_core(struct target *target) struct armv7m_common *armv7m = &cortex_m->armv7m; int retval; - /* Mask interrupts before clearing halt, if done already. This avoids + /* Mask interrupts before clearing halt, if not done already. This avoids * Erratum 377497 (fixed in r1p0) where setting MASKINTS while clearing * HALT can put the core into an unknown state. */ @@ -237,8 +237,11 @@ static int cortex_m_endreset_event(struct target *target) return retval; } - /* clear any interrupt masking */ - cortex_m_write_debug_halt_mask(target, 0, C_MASKINTS); + /* Restore proper interrupt masking setting. */ + if (cortex_m->isrmasking_mode == CORTEX_M_ISRMASK_ON) + cortex_m_write_debug_halt_mask(target, C_MASKINTS, 0); + else + cortex_m_write_debug_halt_mask(target, 0, C_MASKINTS); /* Enable features controlled by ITM and DWT blocks, and catch only * the vectors we were told to pay attention to. @@ -1137,6 +1140,10 @@ int cortex_m_set_breakpoint(struct target *target, struct breakpoint *breakpoint breakpoint->set = fp_num + 1; fpcr_value = breakpoint->address | 1; if (cortex_m->fp_rev == 0) { + if (breakpoint->address > 0x1FFFFFFF) { + LOG_ERROR("Cortex-M Flash Patch Breakpoint rev.1 cannot handle HW breakpoint above address 0x1FFFFFFE"); + return ERROR_FAIL; + } uint32_t hilo; hilo = (breakpoint->address & 0x2) ? FPCR_REPLACE_BKPT_HIGH : FPCR_REPLACE_BKPT_LOW; fpcr_value = (fpcr_value & 0x1FFFFFFC) | hilo | 1; @@ -1806,11 +1813,11 @@ static int cortex_m_dwt_set_reg(struct reg *reg, uint8_t *buf) struct dwt_reg { uint32_t addr; - char *name; + const char *name; unsigned size; }; -static struct dwt_reg dwt_base_regs[] = { +static const struct dwt_reg dwt_base_regs[] = { { DWT_CTRL, "dwt_ctrl", 32, }, /* NOTE that Erratum 532314 (fixed r2p0) affects CYCCNT: it wrongly * increments while the core is asleep. @@ -1819,7 +1826,7 @@ static struct dwt_reg dwt_base_regs[] = { /* plus some 8 bit counters, useful for profiling with TPIU */ }; -static struct dwt_reg dwt_comp[] = { +static const struct dwt_reg dwt_comp[] = { #define DWT_COMPARATOR(i) \ { DWT_COMP0 + 0x10 * (i), "dwt_" #i "_comp", 32, }, \ { DWT_MASK0 + 0x10 * (i), "dwt_" #i "_mask", 4, }, \ @@ -1848,7 +1855,7 @@ static const struct reg_arch_type dwt_reg_type = { .set = cortex_m_dwt_set_reg, }; -static void cortex_m_dwt_addreg(struct target *t, struct reg *r, struct dwt_reg *d) +static void cortex_m_dwt_addreg(struct target *t, struct reg *r, const struct dwt_reg *d) { struct dwt_reg_state *state; @@ -2076,7 +2083,7 @@ int cortex_m_examine(struct target *target) if (retval != ERROR_OK) return retval; - if (armv7m->trace_config.config_type != DISABLED) { + if (armv7m->trace_config.config_type != TRACE_CONFIG_TYPE_DISABLED) { armv7m_trace_tpiu_config(target); armv7m_trace_itm_config(target); } @@ -2270,20 +2277,6 @@ static int cortex_m_verify_pointer(struct command_context *cmd_ctx, * cortexm3_target structure, which is only used with CM3 targets. */ -static const struct { - char name[10]; - unsigned mask; -} vec_ids[] = { - { "hard_err", VC_HARDERR, }, - { "int_err", VC_INTERR, }, - { "bus_err", VC_BUSERR, }, - { "state_err", VC_STATERR, }, - { "chk_err", VC_CHKERR, }, - { "nocp_err", VC_NOCPERR, }, - { "mm_err", VC_MMERR, }, - { "reset", VC_CORERESET, }, -}; - COMMAND_HANDLER(handle_cortex_m_vector_catch_command) { struct target *target = get_current_target(CMD_CTX); @@ -2292,6 +2285,20 @@ COMMAND_HANDLER(handle_cortex_m_vector_catch_command) uint32_t demcr = 0; int retval; + static const struct { + char name[10]; + unsigned mask; + } vec_ids[] = { + { "hard_err", VC_HARDERR, }, + { "int_err", VC_INTERR, }, + { "bus_err", VC_BUSERR, }, + { "state_err", VC_STATERR, }, + { "chk_err", VC_CHKERR, }, + { "nocp_err", VC_NOCPERR, }, + { "mm_err", VC_MMERR, }, + { "reset", VC_CORERESET, }, + }; + retval = cortex_m_verify_pointer(CMD_CTX, cortex_m); if (retval != ERROR_OK) return retval; diff --git a/src/target/image.c b/src/target/image.c index 9f56bea..0d98c57 100644 --- a/src/target/image.c +++ b/src/target/image.c @@ -1048,8 +1048,7 @@ int image_calculate_checksum(uint8_t *buffer, uint32_t nbytes, uint32_t *checksu static bool first_init; if (!first_init) { /* Initialize the CRC table and the decoding table. */ - int i, j; - unsigned int c; + unsigned int i, j, c; for (i = 0; i < 256; i++) { /* as per gdb */ for (c = i << 24, j = 8; j > 0; --j) diff --git a/src/target/mips_m4k.c b/src/target/mips_m4k.c index 78718ca..20c707b 100644 --- a/src/target/mips_m4k.c +++ b/src/target/mips_m4k.c @@ -344,6 +344,8 @@ static int mips_m4k_assert_reset(struct target *target) jtag_add_reset(1, 1); else if (!srst_asserted) jtag_add_reset(0, 1); + } else if (target_has_event_action(target, TARGET_EVENT_RESET_ASSERT)) { + target_handle_event(target, TARGET_EVENT_RESET_ASSERT); } else { if (mips_m4k->is_pic32mx) { LOG_DEBUG("Using MTAP reset to reset processor..."); diff --git a/src/target/nds32.c b/src/target/nds32.c index e4bb17f..4115ea4 100644 --- a/src/target/nds32.c +++ b/src/target/nds32.c @@ -2339,63 +2339,66 @@ int nds32_get_gdb_fileio_info(struct target *target, struct gdb_fileio_info *fil fileio_info->identifier = NULL; } + uint32_t reg_r0, reg_r1, reg_r2; + nds32_get_mapped_reg(nds32, R0, ®_r0); + nds32_get_mapped_reg(nds32, R1, ®_r1); + nds32_get_mapped_reg(nds32, R2, ®_r2); + switch (syscall_id) { case NDS32_SYSCALL_EXIT: fileio_info->identifier = malloc(5); sprintf(fileio_info->identifier, "exit"); - nds32_get_mapped_reg(nds32, R0, &(fileio_info->param_1)); + fileio_info->param_1 = reg_r0; break; case NDS32_SYSCALL_OPEN: { uint8_t filename[256]; fileio_info->identifier = malloc(5); sprintf(fileio_info->identifier, "open"); - nds32_get_mapped_reg(nds32, R0, &(fileio_info->param_1)); + fileio_info->param_1 = reg_r0; /* reserve fileio_info->param_2 for length of path */ - nds32_get_mapped_reg(nds32, R1, &(fileio_info->param_3)); - nds32_get_mapped_reg(nds32, R2, &(fileio_info->param_4)); + fileio_info->param_3 = reg_r1; + fileio_info->param_4 = reg_r2; - target->type->read_buffer(target, fileio_info->param_1, - 256, filename); + target->type->read_buffer(target, reg_r0, 256, filename); fileio_info->param_2 = strlen((char *)filename) + 1; } break; case NDS32_SYSCALL_CLOSE: fileio_info->identifier = malloc(6); sprintf(fileio_info->identifier, "close"); - nds32_get_mapped_reg(nds32, R0, &(fileio_info->param_1)); + fileio_info->param_1 = reg_r0; break; case NDS32_SYSCALL_READ: fileio_info->identifier = malloc(5); sprintf(fileio_info->identifier, "read"); - nds32_get_mapped_reg(nds32, R0, &(fileio_info->param_1)); - nds32_get_mapped_reg(nds32, R1, &(fileio_info->param_2)); - nds32_get_mapped_reg(nds32, R2, &(fileio_info->param_3)); + fileio_info->param_1 = reg_r0; + fileio_info->param_2 = reg_r1; + fileio_info->param_3 = reg_r2; break; case NDS32_SYSCALL_WRITE: fileio_info->identifier = malloc(6); sprintf(fileio_info->identifier, "write"); - nds32_get_mapped_reg(nds32, R0, &(fileio_info->param_1)); - nds32_get_mapped_reg(nds32, R1, &(fileio_info->param_2)); - nds32_get_mapped_reg(nds32, R2, &(fileio_info->param_3)); + fileio_info->param_1 = reg_r0; + fileio_info->param_2 = reg_r1; + fileio_info->param_3 = reg_r2; break; case NDS32_SYSCALL_LSEEK: fileio_info->identifier = malloc(6); sprintf(fileio_info->identifier, "lseek"); - nds32_get_mapped_reg(nds32, R0, &(fileio_info->param_1)); - nds32_get_mapped_reg(nds32, R1, &(fileio_info->param_2)); - nds32_get_mapped_reg(nds32, R2, &(fileio_info->param_3)); + fileio_info->param_1 = reg_r0; + fileio_info->param_2 = reg_r1; + fileio_info->param_3 = reg_r2; break; case NDS32_SYSCALL_UNLINK: { uint8_t filename[256]; fileio_info->identifier = malloc(7); sprintf(fileio_info->identifier, "unlink"); - nds32_get_mapped_reg(nds32, R0, &(fileio_info->param_1)); + fileio_info->param_1 = reg_r0; /* reserve fileio_info->param_2 for length of path */ - target->type->read_buffer(target, fileio_info->param_1, - 256, filename); + target->type->read_buffer(target, reg_r0, 256, filename); fileio_info->param_2 = strlen((char *)filename) + 1; } break; @@ -2404,61 +2407,57 @@ int nds32_get_gdb_fileio_info(struct target *target, struct gdb_fileio_info *fil uint8_t filename[256]; fileio_info->identifier = malloc(7); sprintf(fileio_info->identifier, "rename"); - nds32_get_mapped_reg(nds32, R0, &(fileio_info->param_1)); + fileio_info->param_1 = reg_r0; /* reserve fileio_info->param_2 for length of old path */ - nds32_get_mapped_reg(nds32, R1, &(fileio_info->param_3)); + fileio_info->param_3 = reg_r1; /* reserve fileio_info->param_4 for length of new path */ - target->type->read_buffer(target, fileio_info->param_1, - 256, filename); + target->type->read_buffer(target, reg_r0, 256, filename); fileio_info->param_2 = strlen((char *)filename) + 1; - target->type->read_buffer(target, fileio_info->param_3, - 256, filename); + target->type->read_buffer(target, reg_r1, 256, filename); fileio_info->param_4 = strlen((char *)filename) + 1; } break; case NDS32_SYSCALL_FSTAT: fileio_info->identifier = malloc(6); sprintf(fileio_info->identifier, "fstat"); - nds32_get_mapped_reg(nds32, R0, &(fileio_info->param_1)); - nds32_get_mapped_reg(nds32, R1, &(fileio_info->param_2)); + fileio_info->param_1 = reg_r0; + fileio_info->param_2 = reg_r1; break; case NDS32_SYSCALL_STAT: { uint8_t filename[256]; fileio_info->identifier = malloc(5); sprintf(fileio_info->identifier, "stat"); - nds32_get_mapped_reg(nds32, R0, &(fileio_info->param_1)); + fileio_info->param_1 = reg_r0; /* reserve fileio_info->param_2 for length of old path */ - nds32_get_mapped_reg(nds32, R1, &(fileio_info->param_3)); + fileio_info->param_3 = reg_r1; - target->type->read_buffer(target, fileio_info->param_1, - 256, filename); + target->type->read_buffer(target, reg_r0, 256, filename); fileio_info->param_2 = strlen((char *)filename) + 1; } break; case NDS32_SYSCALL_GETTIMEOFDAY: fileio_info->identifier = malloc(13); sprintf(fileio_info->identifier, "gettimeofday"); - nds32_get_mapped_reg(nds32, R0, &(fileio_info->param_1)); - nds32_get_mapped_reg(nds32, R1, &(fileio_info->param_2)); + fileio_info->param_1 = reg_r0; + fileio_info->param_2 = reg_r1; break; case NDS32_SYSCALL_ISATTY: fileio_info->identifier = malloc(7); sprintf(fileio_info->identifier, "isatty"); - nds32_get_mapped_reg(nds32, R0, &(fileio_info->param_1)); + fileio_info->param_1 = reg_r0; break; case NDS32_SYSCALL_SYSTEM: { uint8_t command[256]; fileio_info->identifier = malloc(7); sprintf(fileio_info->identifier, "system"); - nds32_get_mapped_reg(nds32, R0, &(fileio_info->param_1)); + fileio_info->param_1 = reg_r0; /* reserve fileio_info->param_2 for length of old path */ - target->type->read_buffer(target, fileio_info->param_1, - 256, command); + target->type->read_buffer(target, reg_r0, 256, command); fileio_info->param_2 = strlen((char *)command) + 1; } break; diff --git a/src/target/riscv/Makefile.am b/src/target/riscv/Makefile.am new file mode 100644 index 0000000..83f1a8c --- /dev/null +++ b/src/target/riscv/Makefile.am @@ -0,0 +1,16 @@ +noinst_LTLIBRARIES += %D%/libriscv.la +%C%_libriscv_la_SOURCES = \ + %D%/asm.h \ + %D%/batch.h \ + %D%/debug_defines.h \ + %D%/encoding.h \ + %D%/gdb_regs.h \ + %D%/opcodes.h \ + %D%/program.h \ + %D%/riscv.h \ + %D%/batch.c \ + %D%/program.c \ + %D%/riscv-011.c \ + %D%/riscv-013.c \ + %D%/riscv.c \ + %D%/riscv_semihosting.c diff --git a/src/target/riscv/debug_defines.h b/src/target/riscv/debug_defines.h index 17b1444..d6ddd4f 100644 --- a/src/target/riscv/debug_defines.h +++ b/src/target/riscv/debug_defines.h @@ -229,7 +229,8 @@ * Explains why Debug Mode was entered. * * When there are multiple reasons to enter Debug Mode in a single -* cycle, the cause with the highest priority is the one written. +* cycle, hardware should set \Fcause to the cause with the highest +* priority. * * 1: An {\tt ebreak} instruction was executed. (priority 3) * @@ -245,6 +246,25 @@ #define CSR_DCSR_CAUSE_LENGTH 3 #define CSR_DCSR_CAUSE (0x7U << CSR_DCSR_CAUSE_OFFSET) /* +* When 1, \Fmprv in \Rmstatus takes effect during debug mode. +* When 0, it is ignored during debug mode. +* Implementing this bit is optional. +* If not implemented it should be tied to 0. + */ +#define CSR_DCSR_MPRVEN_OFFSET 4 +#define CSR_DCSR_MPRVEN_LENGTH 1 +#define CSR_DCSR_MPRVEN (0x1U << CSR_DCSR_MPRVEN_OFFSET) +/* +* When set, there is a Non-Maskable-Interrupt (NMI) pending for the hart. +* +* Since an NMI can indicate a hardware error condition, +* reliable debugging may no longer be possible once this bit becomes set. +* This is implementation-dependent. + */ +#define CSR_DCSR_NMIP_OFFSET 3 +#define CSR_DCSR_NMIP_LENGTH 1 +#define CSR_DCSR_NMIP (0x1U << CSR_DCSR_NMIP_OFFSET) +/* * When set and not in Debug Mode, the hart will only execute a single * instruction and then enter Debug Mode. * If the instruction does not complete due to an exception, @@ -269,14 +289,14 @@ #define CSR_DCSR_PRV (0x3U << CSR_DCSR_PRV_OFFSET) #define CSR_DPC 0x7b1 #define CSR_DPC_DPC_OFFSET 0 -#define CSR_DPC_DPC_LENGTH XLEN -#define CSR_DPC_DPC (((1L<<XLEN)-1) << CSR_DPC_DPC_OFFSET) +#define CSR_DPC_DPC_LENGTH MXLEN +#define CSR_DPC_DPC (((1L<<MXLEN)-1) << CSR_DPC_DPC_OFFSET) #define CSR_DSCRATCH0 0x7b2 #define CSR_DSCRATCH1 0x7b3 #define CSR_TSELECT 0x7a0 #define CSR_TSELECT_INDEX_OFFSET 0 -#define CSR_TSELECT_INDEX_LENGTH XLEN -#define CSR_TSELECT_INDEX (((1L<<XLEN)-1) << CSR_TSELECT_INDEX_OFFSET) +#define CSR_TSELECT_INDEX_LENGTH MXLEN +#define CSR_TSELECT_INDEX (((1L<<MXLEN)-1) << CSR_TSELECT_INDEX_OFFSET) #define CSR_TDATA1 0x7a1 /* * 0: There is no trigger at this \Rtselect. @@ -290,12 +310,22 @@ * 3: The trigger is an instruction count trigger. The remaining bits * in this register act as described in \Ricount. * +* 4: The trigger is an interrupt trigger. The remaining bits +* in this register act as described in \Ritrigger. +* +* 5: The trigger is an exception trigger. The remaining bits +* in this register act as described in \Retrigger. +* * 15: This trigger exists (so enumeration shouldn't terminate), but * is not currently available. * * Other values are reserved for future use. +* +* When this field is written to an unsupported value, it takes on its +* reset value instead. The reset value is any one of the types +* supported by the trigger selected by \Rtselect. */ -#define CSR_TDATA1_TYPE_OFFSET (XLEN-4) +#define CSR_TDATA1_TYPE_OFFSET (MXLEN-4) #define CSR_TDATA1_TYPE_LENGTH 4 #define CSR_TDATA1_TYPE (0xfULL << CSR_TDATA1_TYPE_OFFSET) /* @@ -307,39 +337,57 @@ * * This bit is only writable from Debug Mode. */ -#define CSR_TDATA1_DMODE_OFFSET (XLEN-5) +#define CSR_TDATA1_DMODE_OFFSET (MXLEN-5) #define CSR_TDATA1_DMODE_LENGTH 1 #define CSR_TDATA1_DMODE (0x1ULL << CSR_TDATA1_DMODE_OFFSET) /* * Trigger-specific data. */ #define CSR_TDATA1_DATA_OFFSET 0 -#define CSR_TDATA1_DATA_LENGTH (XLEN - 5) -#define CSR_TDATA1_DATA (((1L<<XLEN - 5)-1) << CSR_TDATA1_DATA_OFFSET) +#define CSR_TDATA1_DATA_LENGTH (MXLEN - 5) +#define CSR_TDATA1_DATA (((1L<<MXLEN - 5)-1) << CSR_TDATA1_DATA_OFFSET) #define CSR_TDATA2 0x7a2 #define CSR_TDATA2_DATA_OFFSET 0 -#define CSR_TDATA2_DATA_LENGTH XLEN -#define CSR_TDATA2_DATA (((1L<<XLEN)-1) << CSR_TDATA2_DATA_OFFSET) +#define CSR_TDATA2_DATA_LENGTH MXLEN +#define CSR_TDATA2_DATA (((1L<<MXLEN)-1) << CSR_TDATA2_DATA_OFFSET) #define CSR_TDATA3 0x7a3 #define CSR_TDATA3_DATA_OFFSET 0 -#define CSR_TDATA3_DATA_LENGTH XLEN -#define CSR_TDATA3_DATA (((1L<<XLEN)-1) << CSR_TDATA3_DATA_OFFSET) +#define CSR_TDATA3_DATA_LENGTH MXLEN +#define CSR_TDATA3_DATA (((1L<<MXLEN)-1) << CSR_TDATA3_DATA_OFFSET) +#define CSR_TINFO 0x7a4 +/* +* One bit for each possible \Ftype enumerated in \Rtdataone. Bit N +* corresponds to type N. If the bit is set, then that type is +* supported by the currently selected trigger. +* +* If the currently selected trigger doesn't exist, this field +* contains 1. +* +* If \Ftype is not writable, this register may be unimplemented, in +* which case reading it causes an illegal instruction exception. In +* this case the debugger can read the only supported type from +* \Rtdataone. + */ +#define CSR_TINFO_INFO_OFFSET 0 +#define CSR_TINFO_INFO_LENGTH 16 +#define CSR_TINFO_INFO (0xffffULL << CSR_TINFO_INFO_OFFSET) #define CSR_MCONTROL 0x7a1 -#define CSR_MCONTROL_TYPE_OFFSET (XLEN-4) +#define CSR_MCONTROL_TYPE_OFFSET (MXLEN-4) #define CSR_MCONTROL_TYPE_LENGTH 4 #define CSR_MCONTROL_TYPE (0xfULL << CSR_MCONTROL_TYPE_OFFSET) -#define CSR_MCONTROL_DMODE_OFFSET (XLEN-5) +#define CSR_MCONTROL_DMODE_OFFSET (MXLEN-5) #define CSR_MCONTROL_DMODE_LENGTH 1 #define CSR_MCONTROL_DMODE (0x1ULL << CSR_MCONTROL_DMODE_OFFSET) /* * Specifies the largest naturally aligned powers-of-two (NAPOT) range -* supported by the hardware. The value is the logarithm base 2 of the +* supported by the hardware when \Fmatch is 1. The value is the +* logarithm base 2 of the * number of bytes in that range. A value of 0 indicates that only * exact value matches are supported (one byte range). A value of 63 * corresponds to the maximum NAPOT range, which is $2^{63}$ bytes in * size. */ -#define CSR_MCONTROL_MASKMAX_OFFSET (XLEN-11) +#define CSR_MCONTROL_MASKMAX_OFFSET (MXLEN-11) #define CSR_MCONTROL_MASKMAX_LENGTH 6 #define CSR_MCONTROL_MASKMAX (0x3fULL << CSR_MCONTROL_MASKMAX_OFFSET) /* @@ -390,22 +438,8 @@ #define CSR_MCONTROL_TIMING_LENGTH 1 #define CSR_MCONTROL_TIMING (0x1ULL << CSR_MCONTROL_TIMING_OFFSET) /* -* Determines what happens when this trigger matches. -* -* 0: Raise a breakpoint exception. (Used when software wants to use -* the trigger module without an external debugger attached.) -* -* 1: Enter Debug Mode. (Only supported when \Fdmode is 1.) -* -* 2: Start tracing. -* -* 3: Stop tracing. -* -* 4: Emit trace data for this match. If it is a data access match, -* emit appropriate Load/Store Address/Data. If it is an instruction -* execution, emit its PC. -* -* Other values are reserved for future use. +* The action to take when the trigger fires. The values are explained +* in Table~\ref{tab:action}. */ #define CSR_MCONTROL_ACTION_OFFSET 12 #define CSR_MCONTROL_ACTION_LENGTH 6 @@ -415,6 +449,18 @@ * * 1: While this trigger does not match, it prevents the trigger with * the next index from matching. +* +* Because \Fchain affects the next trigger, hardware must zero it in +* writes to \Rmcontrol that set \Fdmode to 0 if the next trigger has +* \Fdmode of 1. +* In addition hardware should ignore writes to \Rmcontrol that set +* \Fdmode to 1 if the previous trigger has both \Fdmode of 0 and +* \Fchain of 1. Debuggers must avoid the latter case by checking +* \Fchain on the previous trigger if they're writing \Rmcontrol. +* +* Implementations that wish to limit the maximum length of a trigger +* chain (eg. to meet timing requirements) may do so by zeroing +* \Fchain in writes to \Rmcontrol that would make the chain too long. */ #define CSR_MCONTROL_CHAIN_OFFSET 11 #define CSR_MCONTROL_CHAIN_LENGTH 1 @@ -423,7 +469,7 @@ * 0: Matches when the value equals \Rtdatatwo. * * 1: Matches when the top M bits of the value match the top M bits of -* \Rtdatatwo. M is XLEN-1 minus the index of the least-significant +* \Rtdatatwo. M is MXLEN-1 minus the index of the least-significant * bit containing 0 in \Rtdatatwo. * * 2: Matches when the value is greater than (unsigned) or equal to @@ -482,10 +528,10 @@ #define CSR_MCONTROL_LOAD_LENGTH 1 #define CSR_MCONTROL_LOAD (0x1ULL << CSR_MCONTROL_LOAD_OFFSET) #define CSR_ICOUNT 0x7a1 -#define CSR_ICOUNT_TYPE_OFFSET (XLEN-4) +#define CSR_ICOUNT_TYPE_OFFSET (MXLEN-4) #define CSR_ICOUNT_TYPE_LENGTH 4 #define CSR_ICOUNT_TYPE (0xfULL << CSR_ICOUNT_TYPE_OFFSET) -#define CSR_ICOUNT_DMODE_OFFSET (XLEN-5) +#define CSR_ICOUNT_DMODE_OFFSET (MXLEN-5) #define CSR_ICOUNT_DMODE_LENGTH 1 #define CSR_ICOUNT_DMODE (0x1ULL << CSR_ICOUNT_DMODE_OFFSET) /* @@ -529,26 +575,102 @@ #define CSR_ICOUNT_U_LENGTH 1 #define CSR_ICOUNT_U (0x1ULL << CSR_ICOUNT_U_OFFSET) /* -* Determines what happens when this trigger matches. -* -* 0: Raise a breakpoint exception. (Used when software wants to use the -* trigger module without an external debugger attached.) -* -* 1: Enter Debug Mode. (Only supported when \Fdmode is 1.) -* -* 2: Start tracing. -* -* 3: Stop tracing. -* -* 4: Emit trace data for this match. If it is a data access match, -* emit appropriate Load/Store Address/Data. If it is an instruction -* execution, emit its PC. -* -* Other values are reserved for future use. +* The action to take when the trigger fires. The values are explained +* in Table~\ref{tab:action}. */ #define CSR_ICOUNT_ACTION_OFFSET 0 #define CSR_ICOUNT_ACTION_LENGTH 6 #define CSR_ICOUNT_ACTION (0x3fULL << CSR_ICOUNT_ACTION_OFFSET) +#define CSR_ITRIGGER 0x7a1 +#define CSR_ITRIGGER_TYPE_OFFSET (MXLEN-4) +#define CSR_ITRIGGER_TYPE_LENGTH 4 +#define CSR_ITRIGGER_TYPE (0xfULL << CSR_ITRIGGER_TYPE_OFFSET) +#define CSR_ITRIGGER_DMODE_OFFSET (MXLEN-5) +#define CSR_ITRIGGER_DMODE_LENGTH 1 +#define CSR_ITRIGGER_DMODE (0x1ULL << CSR_ITRIGGER_DMODE_OFFSET) +/* +* If this optional bit is implemented, the hardware sets it when this +* trigger matches. The trigger's user can set or clear it at any +* time. The trigger's user can use this bit to determine which +* trigger(s) matched. If the bit is not implemented, it is always 0 +* and writing it has no effect. + */ +#define CSR_ITRIGGER_HIT_OFFSET (MXLEN-6) +#define CSR_ITRIGGER_HIT_LENGTH 1 +#define CSR_ITRIGGER_HIT (0x1ULL << CSR_ITRIGGER_HIT_OFFSET) +/* +* When set, enable this trigger for interrupts that are taken from M +* mode. + */ +#define CSR_ITRIGGER_M_OFFSET 9 +#define CSR_ITRIGGER_M_LENGTH 1 +#define CSR_ITRIGGER_M (0x1ULL << CSR_ITRIGGER_M_OFFSET) +/* +* When set, enable this trigger for interrupts that are taken from S +* mode. + */ +#define CSR_ITRIGGER_S_OFFSET 7 +#define CSR_ITRIGGER_S_LENGTH 1 +#define CSR_ITRIGGER_S (0x1ULL << CSR_ITRIGGER_S_OFFSET) +/* +* When set, enable this trigger for interrupts that are taken from U +* mode. + */ +#define CSR_ITRIGGER_U_OFFSET 6 +#define CSR_ITRIGGER_U_LENGTH 1 +#define CSR_ITRIGGER_U (0x1ULL << CSR_ITRIGGER_U_OFFSET) +/* +* The action to take when the trigger fires. The values are explained +* in Table~\ref{tab:action}. + */ +#define CSR_ITRIGGER_ACTION_OFFSET 0 +#define CSR_ITRIGGER_ACTION_LENGTH 6 +#define CSR_ITRIGGER_ACTION (0x3fULL << CSR_ITRIGGER_ACTION_OFFSET) +#define CSR_ETRIGGER 0x7a1 +#define CSR_ETRIGGER_TYPE_OFFSET (MXLEN-4) +#define CSR_ETRIGGER_TYPE_LENGTH 4 +#define CSR_ETRIGGER_TYPE (0xfULL << CSR_ETRIGGER_TYPE_OFFSET) +#define CSR_ETRIGGER_DMODE_OFFSET (MXLEN-5) +#define CSR_ETRIGGER_DMODE_LENGTH 1 +#define CSR_ETRIGGER_DMODE (0x1ULL << CSR_ETRIGGER_DMODE_OFFSET) +/* +* If this optional bit is implemented, the hardware sets it when this +* trigger matches. The trigger's user can set or clear it at any +* time. The trigger's user can use this bit to determine which +* trigger(s) matched. If the bit is not implemented, it is always 0 +* and writing it has no effect. + */ +#define CSR_ETRIGGER_HIT_OFFSET (MXLEN-6) +#define CSR_ETRIGGER_HIT_LENGTH 1 +#define CSR_ETRIGGER_HIT (0x1ULL << CSR_ETRIGGER_HIT_OFFSET) +/* +* When set, enable this trigger for exceptions that are taken from M +* mode. + */ +#define CSR_ETRIGGER_M_OFFSET 9 +#define CSR_ETRIGGER_M_LENGTH 1 +#define CSR_ETRIGGER_M (0x1ULL << CSR_ETRIGGER_M_OFFSET) +/* +* When set, enable this trigger for exceptions that are taken from S +* mode. + */ +#define CSR_ETRIGGER_S_OFFSET 7 +#define CSR_ETRIGGER_S_LENGTH 1 +#define CSR_ETRIGGER_S (0x1ULL << CSR_ETRIGGER_S_OFFSET) +/* +* When set, enable this trigger for exceptions that are taken from U +* mode. + */ +#define CSR_ETRIGGER_U_OFFSET 6 +#define CSR_ETRIGGER_U_LENGTH 1 +#define CSR_ETRIGGER_U (0x1ULL << CSR_ETRIGGER_U_OFFSET) +/* +* The action to take when the trigger fires. The values are explained +* in Table~\ref{tab:action}. + */ +#define CSR_ETRIGGER_ACTION_OFFSET 0 +#define CSR_ETRIGGER_ACTION_LENGTH 6 +#define CSR_ETRIGGER_ACTION (0x3fULL << CSR_ETRIGGER_ACTION_OFFSET) #define DMI_DMSTATUS 0x11 /* * If 1, then there is an implicit {\tt ebreak} instruction at the @@ -657,6 +779,14 @@ #define DMI_DMSTATUS_AUTHBUSY_LENGTH 1 #define DMI_DMSTATUS_AUTHBUSY (0x1U << DMI_DMSTATUS_AUTHBUSY_OFFSET) /* +* 1 if this Debug Module supports halt-on-reset functionality +* controllable by the \Fsetresethaltreq and \Fclrresethaltreq bits. +* 0 otherwise. + */ +#define DMI_DMSTATUS_HASRESETHALTREQ_OFFSET 5 +#define DMI_DMSTATUS_HASRESETHALTREQ_LENGTH 1 +#define DMI_DMSTATUS_HASRESETHALTREQ (0x1U << DMI_DMSTATUS_HASRESETHALTREQ_OFFSET) +/* * 0: \Rdevtreeaddrzero--\Rdevtreeaddrthree hold information which * is not relevant to the Device Tree. * @@ -762,6 +892,29 @@ #define DMI_DMCONTROL_HARTSELHI_LENGTH 10 #define DMI_DMCONTROL_HARTSELHI (0x3ffU << DMI_DMCONTROL_HARTSELHI_OFFSET) /* +* This optional field writes the halt-on-reset request bit for all +* currently selected harts. +* When set to 1, each selected hart will halt upon the next deassertion +* of its reset. The halt-on-reset request bit is not automatically +* cleared. The debugger must write to \Fclrresethaltreq to clear it. +* +* Writes apply to the new value of \Fhartsel and \Fhasel. +* +* If \Fhasresethaltreq is 0, this field is not implemented. + */ +#define DMI_DMCONTROL_SETRESETHALTREQ_OFFSET 3 +#define DMI_DMCONTROL_SETRESETHALTREQ_LENGTH 1 +#define DMI_DMCONTROL_SETRESETHALTREQ (0x1U << DMI_DMCONTROL_SETRESETHALTREQ_OFFSET) +/* +* This optional field clears the halt-on-reset request bit for all +* currently selected harts. +* +* Writes apply to the new value of \Fhartsel and \Fhasel. + */ +#define DMI_DMCONTROL_CLRRESETHALTREQ_OFFSET 2 +#define DMI_DMCONTROL_CLRRESETHALTREQ_LENGTH 1 +#define DMI_DMCONTROL_CLRRESETHALTREQ (0x1U << DMI_DMCONTROL_CLRRESETHALTREQ_OFFSET) +/* * This bit controls the reset signal from the DM to the rest of the * system. The signal should reset every part of the system, including * every hart, except for the DM and any logic required to access the @@ -786,7 +939,7 @@ * Debug Module after power up, including the platform's system reset * or Debug Transport reset signals. * -* A debugger may pulse this bit low to get the debug module into a +* A debugger may pulse this bit low to get the Debug Module into a * known state. * * Implementations may use this bit to aid debugging, for example by @@ -808,7 +961,7 @@ #define DMI_HARTINFO_NSCRATCH (0xfU << DMI_HARTINFO_NSCRATCH_OFFSET) /* * 0: The {\tt data} registers are shadowed in the hart by CSR -* registers. Each CSR register is XLEN bits in size, and corresponds +* registers. Each CSR register is MXLEN bits in size, and corresponds * to a single argument, per Table~\ref{tab:datareg}. * * 1: The {\tt data} registers are shadowed in the hart's memory map. @@ -999,7 +1152,7 @@ * it's explicitly cleared by the debugger. * * While this field is non-zero, no more system bus accesses can be -* initiated by the debug module. +* initiated by the Debug Module. */ #define DMI_SBCS_SBBUSYERROR_OFFSET 22 #define DMI_SBCS_SBBUSYERROR_LENGTH 1 @@ -1010,8 +1163,9 @@ * bit goes high immediately when a read or write is requested for any * reason, and does not go low until the access is fully completed. * -* To avoid race conditions, debuggers must not try to clear \Fsberror -* until they read \Fsbbusy as 0. +* Writes to \Rsbcs while \Fsbbusy is high result in undefined +* behavior. A debugger must not write to \Rsbcs until it reads +* \Fsbbusy as 0. */ #define DMI_SBCS_SBBUSY_OFFSET 21 #define DMI_SBCS_SBBUSY_LENGTH 1 @@ -1057,11 +1211,13 @@ #define DMI_SBCS_SBREADONDATA_LENGTH 1 #define DMI_SBCS_SBREADONDATA (0x1U << DMI_SBCS_SBREADONDATA_OFFSET) /* -* When the debug module's system bus +* When the Debug Module's system bus * master causes a bus error, this field gets set. The bits in this * field remain set until they are cleared by writing 1 to them. * While this field is non-zero, no more system bus accesses can be -* initiated by the debug module. +* initiated by the Debug Module. +* +* An implementation may report "Other" (7) for any error condition. * * 0: There was no bus error. * @@ -1069,7 +1225,11 @@ * * 2: A bad address was accessed. * -* 3: There was some other error (eg. alignment). +* 3: There was an alignment error. +* +* 4: An access of unsupported size was requested. +* +* 7: Other. */ #define DMI_SBCS_SBERROR_OFFSET 12 #define DMI_SBCS_SBERROR_LENGTH 3 @@ -1252,107 +1412,3 @@ #define VIRT_PRIV_PRV_OFFSET 0 #define VIRT_PRIV_PRV_LENGTH 2 #define VIRT_PRIV_PRV (0x3U << VIRT_PRIV_PRV_OFFSET) -#define DMI_SERCS 0x34 -/* -* Number of supported serial ports. - */ -#define DMI_SERCS_SERIALCOUNT_OFFSET 28 -#define DMI_SERCS_SERIALCOUNT_LENGTH 4 -#define DMI_SERCS_SERIALCOUNT (0xfU << DMI_SERCS_SERIALCOUNT_OFFSET) -/* -* Select which serial port is accessed by \Rserrx and \Rsertx. - */ -#define DMI_SERCS_SERIAL_OFFSET 24 -#define DMI_SERCS_SERIAL_LENGTH 3 -#define DMI_SERCS_SERIAL (0x7U << DMI_SERCS_SERIAL_OFFSET) -#define DMI_SERCS_ERROR7_OFFSET 23 -#define DMI_SERCS_ERROR7_LENGTH 1 -#define DMI_SERCS_ERROR7 (0x1U << DMI_SERCS_ERROR7_OFFSET) -#define DMI_SERCS_VALID7_OFFSET 22 -#define DMI_SERCS_VALID7_LENGTH 1 -#define DMI_SERCS_VALID7 (0x1U << DMI_SERCS_VALID7_OFFSET) -#define DMI_SERCS_FULL7_OFFSET 21 -#define DMI_SERCS_FULL7_LENGTH 1 -#define DMI_SERCS_FULL7 (0x1U << DMI_SERCS_FULL7_OFFSET) -#define DMI_SERCS_ERROR6_OFFSET 20 -#define DMI_SERCS_ERROR6_LENGTH 1 -#define DMI_SERCS_ERROR6 (0x1U << DMI_SERCS_ERROR6_OFFSET) -#define DMI_SERCS_VALID6_OFFSET 19 -#define DMI_SERCS_VALID6_LENGTH 1 -#define DMI_SERCS_VALID6 (0x1U << DMI_SERCS_VALID6_OFFSET) -#define DMI_SERCS_FULL6_OFFSET 18 -#define DMI_SERCS_FULL6_LENGTH 1 -#define DMI_SERCS_FULL6 (0x1U << DMI_SERCS_FULL6_OFFSET) -#define DMI_SERCS_ERROR5_OFFSET 17 -#define DMI_SERCS_ERROR5_LENGTH 1 -#define DMI_SERCS_ERROR5 (0x1U << DMI_SERCS_ERROR5_OFFSET) -#define DMI_SERCS_VALID5_OFFSET 16 -#define DMI_SERCS_VALID5_LENGTH 1 -#define DMI_SERCS_VALID5 (0x1U << DMI_SERCS_VALID5_OFFSET) -#define DMI_SERCS_FULL5_OFFSET 15 -#define DMI_SERCS_FULL5_LENGTH 1 -#define DMI_SERCS_FULL5 (0x1U << DMI_SERCS_FULL5_OFFSET) -#define DMI_SERCS_ERROR4_OFFSET 14 -#define DMI_SERCS_ERROR4_LENGTH 1 -#define DMI_SERCS_ERROR4 (0x1U << DMI_SERCS_ERROR4_OFFSET) -#define DMI_SERCS_VALID4_OFFSET 13 -#define DMI_SERCS_VALID4_LENGTH 1 -#define DMI_SERCS_VALID4 (0x1U << DMI_SERCS_VALID4_OFFSET) -#define DMI_SERCS_FULL4_OFFSET 12 -#define DMI_SERCS_FULL4_LENGTH 1 -#define DMI_SERCS_FULL4 (0x1U << DMI_SERCS_FULL4_OFFSET) -#define DMI_SERCS_ERROR3_OFFSET 11 -#define DMI_SERCS_ERROR3_LENGTH 1 -#define DMI_SERCS_ERROR3 (0x1U << DMI_SERCS_ERROR3_OFFSET) -#define DMI_SERCS_VALID3_OFFSET 10 -#define DMI_SERCS_VALID3_LENGTH 1 -#define DMI_SERCS_VALID3 (0x1U << DMI_SERCS_VALID3_OFFSET) -#define DMI_SERCS_FULL3_OFFSET 9 -#define DMI_SERCS_FULL3_LENGTH 1 -#define DMI_SERCS_FULL3 (0x1U << DMI_SERCS_FULL3_OFFSET) -#define DMI_SERCS_ERROR2_OFFSET 8 -#define DMI_SERCS_ERROR2_LENGTH 1 -#define DMI_SERCS_ERROR2 (0x1U << DMI_SERCS_ERROR2_OFFSET) -#define DMI_SERCS_VALID2_OFFSET 7 -#define DMI_SERCS_VALID2_LENGTH 1 -#define DMI_SERCS_VALID2 (0x1U << DMI_SERCS_VALID2_OFFSET) -#define DMI_SERCS_FULL2_OFFSET 6 -#define DMI_SERCS_FULL2_LENGTH 1 -#define DMI_SERCS_FULL2 (0x1U << DMI_SERCS_FULL2_OFFSET) -#define DMI_SERCS_ERROR1_OFFSET 5 -#define DMI_SERCS_ERROR1_LENGTH 1 -#define DMI_SERCS_ERROR1 (0x1U << DMI_SERCS_ERROR1_OFFSET) -#define DMI_SERCS_VALID1_OFFSET 4 -#define DMI_SERCS_VALID1_LENGTH 1 -#define DMI_SERCS_VALID1 (0x1U << DMI_SERCS_VALID1_OFFSET) -#define DMI_SERCS_FULL1_OFFSET 3 -#define DMI_SERCS_FULL1_LENGTH 1 -#define DMI_SERCS_FULL1 (0x1U << DMI_SERCS_FULL1_OFFSET) -/* -* 1 when the debugger-to-core queue for serial port 0 has -* over or underflowed. This bit will remain set until it is reset by -* writing 1 to this bit. - */ -#define DMI_SERCS_ERROR0_OFFSET 2 -#define DMI_SERCS_ERROR0_LENGTH 1 -#define DMI_SERCS_ERROR0 (0x1U << DMI_SERCS_ERROR0_OFFSET) -/* -* 1 when the core-to-debugger queue for serial port 0 is not empty. - */ -#define DMI_SERCS_VALID0_OFFSET 1 -#define DMI_SERCS_VALID0_LENGTH 1 -#define DMI_SERCS_VALID0 (0x1U << DMI_SERCS_VALID0_OFFSET) -/* -* 1 when the debugger-to-core queue for serial port 0 is full. - */ -#define DMI_SERCS_FULL0_OFFSET 0 -#define DMI_SERCS_FULL0_LENGTH 1 -#define DMI_SERCS_FULL0 (0x1U << DMI_SERCS_FULL0_OFFSET) -#define DMI_SERTX 0x35 -#define DMI_SERTX_DATA_OFFSET 0 -#define DMI_SERTX_DATA_LENGTH 32 -#define DMI_SERTX_DATA (0xffffffffU << DMI_SERTX_DATA_OFFSET) -#define DMI_SERRX 0x36 -#define DMI_SERRX_DATA_OFFSET 0 -#define DMI_SERRX_DATA_LENGTH 32 -#define DMI_SERRX_DATA (0xffffffffU << DMI_SERRX_DATA_OFFSET) diff --git a/src/target/riscv/riscv-011.c b/src/target/riscv/riscv-011.c index 4322f7b..a77b007 100644 --- a/src/target/riscv/riscv-011.c +++ b/src/target/riscv/riscv-011.c @@ -240,6 +240,7 @@ static unsigned int slot_offset(const struct target *target, slot_t slot) case SLOT1: return 5; case SLOT_LAST: return info->dramsize-1; } + break; case 64: switch (slot) { case SLOT0: return 4; @@ -1407,12 +1408,6 @@ static int strict_step(struct target *target, bool announce) LOG_DEBUG("enter"); - struct breakpoint *breakpoint = target->breakpoints; - while (breakpoint) { - riscv_remove_breakpoint(target, breakpoint); - breakpoint = breakpoint->next; - } - struct watchpoint *watchpoint = target->watchpoints; while (watchpoint) { riscv_remove_watchpoint(target, watchpoint); @@ -1423,12 +1418,6 @@ static int strict_step(struct target *target, bool announce) if (result != ERROR_OK) return result; - breakpoint = target->breakpoints; - while (breakpoint) { - riscv_add_breakpoint(target, breakpoint); - breakpoint = breakpoint->next; - } - watchpoint = target->watchpoints; while (watchpoint) { riscv_add_watchpoint(target, watchpoint); @@ -1787,6 +1776,8 @@ static riscv_error_t handle_halt_routine(struct target *target) break; default: assert(0); + LOG_ERROR("Got invalid register result %d", result); + goto error; } if (riscv_xlen(target) == 32) { reg_cache_set(target, reg, data & 0xffffffff); @@ -1847,7 +1838,7 @@ static int handle_halt(struct target *target, bool announce) target->debug_reason = DBG_REASON_BREAKPOINT; break; case DCSR_CAUSE_HWBP: - target->debug_reason = DBG_REASON_WPTANDBKPT; + target->debug_reason = DBG_REASON_WATCHPOINT; /* If we halted because of a data trigger, gdb doesn't know to do * the disable-breakpoints-step-enable-breakpoints dance. */ info->need_strict_step = true; @@ -1873,6 +1864,12 @@ static int handle_halt(struct target *target, bool announce) riscv_enumerate_triggers(target); } + if (target->debug_reason == DBG_REASON_BREAKPOINT) { + int retval; + if (riscv_semihosting(target, &retval) != 0) + return retval; + } + if (announce) target_call_event_callbacks(target, TARGET_EVENT_HALTED); diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c index 9488b79..cce5f47 100644 --- a/src/target/riscv/riscv-013.c +++ b/src/target/riscv/riscv-013.c @@ -189,8 +189,6 @@ typedef struct { * go low. */ unsigned int ac_busy_delay; - bool need_strict_step; - bool abstract_read_csr_supported; bool abstract_write_csr_supported; bool abstract_read_fpr_supported; @@ -264,11 +262,18 @@ static dm013_info_t *get_dm(struct target *target) return dm; } -static uint32_t hartsel_mask(const struct target *target) +static uint32_t set_hartsel(uint32_t initial, uint32_t index) { - RISCV013_INFO(info); - /* TODO: Properly handle hartselhi as well*/ - return ((1L<<info->hartsellen)-1) << DMI_DMCONTROL_HARTSELLO_OFFSET; + initial &= ~DMI_DMCONTROL_HARTSELLO; + initial &= ~DMI_DMCONTROL_HARTSELHI; + + uint32_t index_lo = index & ((1 << DMI_DMCONTROL_HARTSELLO_LENGTH) - 1); + initial |= index_lo << DMI_DMCONTROL_HARTSELLO_OFFSET; + uint32_t index_hi = index >> DMI_DMCONTROL_HARTSELLO_LENGTH; + assert(index_hi < 1 << DMI_DMCONTROL_HARTSELHI_LENGTH); + initial |= index_hi << DMI_DMCONTROL_HARTSELHI_OFFSET; + + return initial; } static void decode_dmi(char *text, unsigned address, unsigned data) @@ -282,8 +287,8 @@ static void decode_dmi(char *text, unsigned address, unsigned data) { DMI_DMCONTROL, DMI_DMCONTROL_RESUMEREQ, "resumereq" }, { DMI_DMCONTROL, DMI_DMCONTROL_HARTRESET, "hartreset" }, { DMI_DMCONTROL, DMI_DMCONTROL_HASEL, "hasel" }, - { DMI_DMCONTROL, ((1L<<10)-1) << DMI_DMCONTROL_HARTSELLO_OFFSET, "hartsello" }, - /* TODO: hartsellhi */ + { DMI_DMCONTROL, DMI_DMCONTROL_HARTSELHI, "hartselhi" }, + { DMI_DMCONTROL, DMI_DMCONTROL_HARTSELLO, "hartsello" }, { DMI_DMCONTROL, DMI_DMCONTROL_NDMRESET, "ndmreset" }, { DMI_DMCONTROL, DMI_DMCONTROL_DMACTIVE, "dmactive" }, { DMI_DMCONTROL, DMI_DMCONTROL_ACKHAVERESET, "ackhavereset" }, @@ -741,8 +746,8 @@ static int write_abstract_arg(struct target *target, unsigned index, /** * @size in bits */ -static uint32_t access_register_command(uint32_t number, unsigned size, - uint32_t flags) +static uint32_t access_register_command(struct target *target, uint32_t number, + unsigned size, uint32_t flags) { uint32_t command = set_field(0, DMI_COMMAND_CMDTYPE, 0); switch (size) { @@ -765,8 +770,13 @@ static uint32_t access_register_command(uint32_t number, unsigned size, } else if (number >= GDB_REGNO_CSR0 && number <= GDB_REGNO_CSR4095) { command = set_field(command, AC_ACCESS_REGISTER_REGNO, number - GDB_REGNO_CSR0); - } else { - assert(0); + } else if (number >= GDB_REGNO_COUNT) { + /* Custom register. */ + assert(target->reg_cache->reg_list[number].arch_info); + riscv_reg_info_t *reg_info = target->reg_cache->reg_list[number].arch_info; + assert(reg_info); + command = set_field(command, AC_ACCESS_REGISTER_REGNO, + 0xc000 + reg_info->custom_number); } command |= flags; @@ -786,7 +796,7 @@ static int register_read_abstract(struct target *target, uint64_t *value, !info->abstract_read_csr_supported) return ERROR_FAIL; - uint32_t command = access_register_command(number, size, + uint32_t command = access_register_command(target, number, size, AC_ACCESS_REGISTER_TRANSFER); int result = execute_abstract_command(target, command); @@ -821,7 +831,7 @@ static int register_write_abstract(struct target *target, uint32_t number, !info->abstract_write_csr_supported) return ERROR_FAIL; - uint32_t command = access_register_command(number, size, + uint32_t command = access_register_command(target, number, size, AC_ACCESS_REGISTER_TRANSFER | AC_ACCESS_REGISTER_WRITE); @@ -917,22 +927,25 @@ typedef struct { riscv_addr_t hart_address; /* Memory address to access the scratch memory from the debugger. */ riscv_addr_t debug_address; + struct working_area *area; } scratch_mem_t; /** * Find some scratch memory to be used with the given program. */ -static int scratch_find(struct target *target, +static int scratch_reserve(struct target *target, scratch_mem_t *scratch, struct riscv_program *program, unsigned size_bytes) { - riscv013_info_t *info = get_info(target); - riscv_addr_t alignment = 1; while (alignment < size_bytes) alignment *= 2; + scratch->area = NULL; + + riscv013_info_t *info = get_info(target); + if (info->dataaccess == 1) { /* Sign extend dataaddr. */ scratch->hart_address = info->dataaddr; @@ -963,8 +976,9 @@ static int scratch_find(struct target *target, return ERROR_OK; } - if (riscv_use_scratch_ram) { - scratch->hart_address = (riscv_scratch_ram_address + alignment - 1) & + if (target_alloc_working_area(target, size_bytes + alignment - 1, + &scratch->area) == ERROR_OK) { + scratch->hart_address = (scratch->area->address + alignment - 1) & ~(alignment - 1); scratch->memory_space = SPACE_DMI_RAM; scratch->debug_address = scratch->hart_address; @@ -972,10 +986,19 @@ static int scratch_find(struct target *target, } LOG_ERROR("Couldn't find %d bytes of scratch RAM to use. Please configure " - "an address with 'riscv set_scratch_ram'.", size_bytes); + "a work area with 'configure -work-area-phys'.", size_bytes); return ERROR_FAIL; } +static int scratch_release(struct target *target, + scratch_mem_t *scratch) +{ + if (scratch->area) + return target_free_working_area(target, scratch->area); + + return ERROR_OK; +} + static int scratch_read64(struct target *target, scratch_mem_t *scratch, uint64_t *value) { @@ -1090,23 +1113,29 @@ static int register_write_direct(struct target *target, unsigned number, if (register_read(target, &s0, GDB_REGNO_S0) != ERROR_OK) return ERROR_FAIL; + scratch_mem_t scratch; + bool use_scratch = false; if (number >= GDB_REGNO_FPR0 && number <= GDB_REGNO_FPR31 && riscv_supports_extension(target, riscv_current_hartid(target), 'D') && riscv_xlen(target) < 64) { /* There are no instructions to move all the bits from a register, so * we need to use some scratch RAM. */ + use_scratch = true; riscv_program_insert(&program, fld(number - GDB_REGNO_FPR0, S0, 0)); - scratch_mem_t scratch; - if (scratch_find(target, &scratch, &program, 8) != ERROR_OK) + if (scratch_reserve(target, &scratch, &program, 8) != ERROR_OK) return ERROR_FAIL; if (register_write_direct(target, GDB_REGNO_S0, scratch.hart_address) - != ERROR_OK) + != ERROR_OK) { + scratch_release(target, &scratch); return ERROR_FAIL; + } - if (scratch_write64(target, &scratch, value) != ERROR_OK) + if (scratch_write64(target, &scratch, value) != ERROR_OK) { + scratch_release(target, &scratch); return ERROR_FAIL; + } } else { if (register_write_direct(target, GDB_REGNO_S0, value) != ERROR_OK) @@ -1133,6 +1162,9 @@ static int register_write_direct(struct target *target, unsigned number, reg->valid = true; } + if (use_scratch) + scratch_release(target, &scratch); + /* Restore S0. */ if (register_write_direct(target, GDB_REGNO_S0, s0) != ERROR_OK) return ERROR_FAIL; @@ -1209,13 +1241,15 @@ static int register_read_direct(struct target *target, uint64_t *value, uint32_t riscv_program_insert(&program, fsd(number - GDB_REGNO_FPR0, S0, 0)); - if (scratch_find(target, &scratch, &program, 8) != ERROR_OK) + if (scratch_reserve(target, &scratch, &program, 8) != ERROR_OK) return ERROR_FAIL; use_scratch = true; if (register_write_direct(target, GDB_REGNO_S0, - scratch.hart_address) != ERROR_OK) + scratch.hart_address) != ERROR_OK) { + scratch_release(target, &scratch); return ERROR_FAIL; + } } else if (riscv_supports_extension(target, riscv_current_hartid(target), 'D')) { riscv_program_insert(&program, fmv_x_d(S0, number - GDB_REGNO_FPR0)); @@ -1234,8 +1268,10 @@ static int register_read_direct(struct target *target, uint64_t *value, uint32_t /* Don't message on error. Probably the register doesn't exist. */ if (use_scratch) { - if (scratch_read64(target, &scratch, value) != ERROR_OK) - return ERROR_FAIL; + result = scratch_read64(target, &scratch, value); + scratch_release(target, &scratch); + if (result != ERROR_OK) + return result; } else { /* Read S0 */ if (register_read_direct(target, value, GDB_REGNO_S0) != ERROR_OK) @@ -1290,6 +1326,7 @@ static void deinit_target(struct target *target) LOG_DEBUG("riscv_deinit_target()"); riscv_info_t *info = (riscv_info_t *) target->arch_info; free(info->version_specific); + /* TODO: free register arch_info */ info->version_specific = NULL; } @@ -1336,8 +1373,8 @@ static int examine(struct target *target) dm->was_reset = true; } - uint32_t max_hartsel_mask = ((1L<<10)-1) << DMI_DMCONTROL_HARTSELLO_OFFSET; - dmi_write(target, DMI_DMCONTROL, max_hartsel_mask | DMI_DMCONTROL_DMACTIVE); + dmi_write(target, DMI_DMCONTROL, DMI_DMCONTROL_HARTSELLO | + DMI_DMCONTROL_HARTSELHI | DMI_DMCONTROL_DMACTIVE); uint32_t dmcontrol; if (dmi_read(target, &dmcontrol, DMI_DMCONTROL) != ERROR_OK) return ERROR_FAIL; @@ -1348,7 +1385,10 @@ static int examine(struct target *target) return ERROR_FAIL; } - uint32_t hartsel = get_field(dmcontrol, max_hartsel_mask); + uint32_t hartsel = + (get_field(dmcontrol, DMI_DMCONTROL_HARTSELHI) << + DMI_DMCONTROL_HARTSELLO_LENGTH) | + get_field(dmcontrol, DMI_DMCONTROL_HARTSELLO); info->hartsellen = 0; while (hartsel & 1) { info->hartsellen++; @@ -1418,8 +1458,7 @@ static int examine(struct target *target) if (get_field(s, DMI_DMSTATUS_ANYHAVERESET)) dmi_write(target, DMI_DMCONTROL, - set_field(DMI_DMCONTROL_DMACTIVE | DMI_DMCONTROL_ACKHAVERESET, - hartsel_mask(target), i)); + set_hartsel(DMI_DMCONTROL_DMACTIVE | DMI_DMCONTROL_ACKHAVERESET, i)); if (!riscv_is_halted(target)) { if (riscv013_halt_current_hart(target) != ERROR_OK) { @@ -1595,7 +1634,7 @@ static int assert_reset(struct target *target) if (!riscv_hart_enabled(target, i)) continue; - control = set_field(control_base, hartsel_mask(target), i); + control = set_hartsel(control_base, i); control = set_field(control, DMI_DMCONTROL_HALTREQ, target->reset_halt ? 1 : 0); dmi_write(target, DMI_DMCONTROL, control); @@ -1606,8 +1645,7 @@ static int assert_reset(struct target *target) } else { /* Reset just this hart. */ - uint32_t control = set_field(control_base, hartsel_mask(target), - r->current_hartid); + uint32_t control = set_hartsel(control_base, r->current_hartid); control = set_field(control, DMI_DMCONTROL_HALTREQ, target->reset_halt ? 1 : 0); control = set_field(control, DMI_DMCONTROL_NDMRESET, 1); @@ -1630,7 +1668,7 @@ static int deassert_reset(struct target *target) control = set_field(control, DMI_DMCONTROL_HALTREQ, target->reset_halt ? 1 : 0); control = set_field(control, DMI_DMCONTROL_DMACTIVE, 1); dmi_write(target, DMI_DMCONTROL, - set_field(control, hartsel_mask(target), r->current_hartid)); + set_hartsel(control, r->current_hartid)); uint32_t dmstatus; int dmi_busy_delay = info->dmi_busy_delay; @@ -1642,7 +1680,7 @@ static int deassert_reset(struct target *target) if (!riscv_hart_enabled(target, index)) continue; dmi_write(target, DMI_DMCONTROL, - set_field(control, hartsel_mask(target), index)); + set_hartsel(control, index)); } else { index = r->current_hartid; } @@ -1682,7 +1720,7 @@ static int deassert_reset(struct target *target) if (get_field(dmstatus, DMI_DMSTATUS_ALLHAVERESET)) { /* Ack reset. */ dmi_write(target, DMI_DMCONTROL, - set_field(control, hartsel_mask(target), index) | + set_hartsel(control, index) | DMI_DMCONTROL_ACKHAVERESET); } @@ -2042,9 +2080,9 @@ static int read_memory_progbuf(struct target *target, target_addr_t address, result = register_write_direct(target, GDB_REGNO_S0, address); if (result != ERROR_OK) goto error; - uint32_t command = access_register_command(GDB_REGNO_S1, riscv_xlen(target), - AC_ACCESS_REGISTER_TRANSFER | - AC_ACCESS_REGISTER_POSTEXEC); + uint32_t command = access_register_command(target, GDB_REGNO_S1, + riscv_xlen(target), + AC_ACCESS_REGISTER_TRANSFER | AC_ACCESS_REGISTER_POSTEXEC); result = execute_abstract_command(target, command); if (result != ERROR_OK) goto error; @@ -2530,7 +2568,8 @@ static int write_memory_progbuf(struct target *target, target_addr_t address, /* Write and execute command that moves value into S1 and * executes program buffer. */ - uint32_t command = access_register_command(GDB_REGNO_S1, 32, + uint32_t command = access_register_command(target, + GDB_REGNO_S1, 32, AC_ACCESS_REGISTER_POSTEXEC | AC_ACCESS_REGISTER_TRANSFER | AC_ACCESS_REGISTER_WRITE); @@ -2723,9 +2762,10 @@ static int riscv013_select_current_hart(struct target *target) return ERROR_OK; uint32_t dmcontrol; + /* TODO: can't we just "dmcontrol = DMI_DMACTIVE"? */ if (dmi_read(target, &dmcontrol, DMI_DMCONTROL) != ERROR_OK) return ERROR_FAIL; - dmcontrol = set_field(dmcontrol, hartsel_mask(target), r->current_hartid); + dmcontrol = set_hartsel(dmcontrol, r->current_hartid); int result = dmi_write(target, DMI_DMCONTROL, dmcontrol); dm->current_hartid = r->current_hartid; return result; @@ -2807,7 +2847,7 @@ static bool riscv013_is_halted(struct target *target) /* TODO: Can we make this more obvious to eg. a gdb user? */ uint32_t dmcontrol = DMI_DMCONTROL_DMACTIVE | DMI_DMCONTROL_ACKHAVERESET; - dmcontrol = set_field(dmcontrol, hartsel_mask(target), hartid); + dmcontrol = set_hartsel(dmcontrol, hartid); /* If we had been halted when we reset, request another halt. If we * ended up running out of reset, then the user will (hopefully) get a * message that a reset happened, that the target is running, and then @@ -2950,7 +2990,7 @@ static int riscv013_step_or_resume_current_hart(struct target *target, bool step /* Issue the resume command, and then wait for the current hart to resume. */ uint32_t dmcontrol = DMI_DMCONTROL_DMACTIVE; - dmcontrol = set_field(dmcontrol, hartsel_mask(target), r->current_hartid); + dmcontrol = set_hartsel(dmcontrol, r->current_hartid); dmi_write(target, DMI_DMCONTROL, dmcontrol | DMI_DMCONTROL_RESUMEREQ); uint32_t dmstatus; diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c index 61b6827..de47d25 100644 --- a/src/target/riscv/riscv.c +++ b/src/target/riscv/riscv.c @@ -185,18 +185,19 @@ int riscv_command_timeout_sec = DEFAULT_COMMAND_TIMEOUT_SEC; /* Wall-clock timeout after reset. Settable via RISC-V Target commands.*/ int riscv_reset_timeout_sec = DEFAULT_RESET_TIMEOUT_SEC; -bool riscv_use_scratch_ram; -uint64_t riscv_scratch_ram_address; - bool riscv_prefer_sba; +typedef struct { + uint16_t low, high; +} range_t; + /* In addition to the ones in the standard spec, we'll also expose additional * CSRs in this list. * The list is either NULL, or a series of ranges (inclusive), terminated with * 1,0. */ -struct { - uint16_t low, high; -} *expose_csr; +range_t *expose_csr; +/* Same, but for custom registers. */ +range_t *expose_custom; static uint32_t dtmcontrol_scan(struct target *target, uint32_t out) { @@ -263,6 +264,8 @@ static int riscv_init_target(struct command_context *cmd_ctx, select_dbus.num_bits = target->tap->ir_length; select_idcode.num_bits = target->tap->ir_length; + riscv_semihosting_init(target); + return ERROR_OK; } @@ -273,8 +276,16 @@ static void riscv_deinit_target(struct target *target) if (tt) { tt->deinit_target(target); riscv_info_t *info = (riscv_info_t *) target->arch_info; + free(info->reg_names); free(info); } + /* Free the shared structure use for most registers. */ + free(target->reg_cache->reg_list[0].arch_info); + /* Free the ones we allocated separately. */ + for (unsigned i = GDB_REGNO_COUNT; i < target->reg_cache->num_regs; i++) + free(target->reg_cache->reg_list[i].arch_info); + free(target->reg_cache->reg_list); + free(target->reg_cache); target->arch_info = NULL; } @@ -644,6 +655,89 @@ int riscv_remove_watchpoint(struct target *target, return ERROR_OK; } +/* Sets *hit_watchpoint to the first watchpoint identified as causing the + * current halt. + * + * The GDB server uses this information to tell GDB what data address has + * been hit, which enables GDB to print the hit variable along with its old + * and new value. */ +int riscv_hit_watchpoint(struct target *target, struct watchpoint **hit_watchpoint) +{ + struct watchpoint *wp = target->watchpoints; + + LOG_DEBUG("Current hartid = %d", riscv_current_hartid(target)); + + /*TODO instead of disassembling the instruction that we think caused the + * trigger, check the hit bit of each watchpoint first. The hit bit is + * simpler and more reliable to check but as it is optional and relatively + * new, not all hardware will implement it */ + riscv_reg_t dpc; + riscv_get_register(target, &dpc, GDB_REGNO_DPC); + const uint8_t length = 4; + LOG_DEBUG("dpc is 0x%" PRIx64, dpc); + + /* fetch the instruction at dpc */ + uint8_t buffer[length]; + if (target_read_buffer(target, dpc, length, buffer) != ERROR_OK) { + LOG_ERROR("Failed to read instruction at dpc 0x%" PRIx64, dpc); + return ERROR_FAIL; + } + + uint32_t instruction = 0; + + for (int i = 0; i < length; i++) { + LOG_DEBUG("Next byte is %x", buffer[i]); + instruction += (buffer[i] << 8 * i); + } + LOG_DEBUG("Full instruction is %x", instruction); + + /* find out which memory address is accessed by the instruction at dpc */ + /* opcode is first 7 bits of the instruction */ + uint8_t opcode = instruction & 0x7F; + uint32_t rs1; + int16_t imm; + riscv_reg_t mem_addr; + + if (opcode == MATCH_LB || opcode == MATCH_SB) { + rs1 = (instruction & 0xf8000) >> 15; + riscv_get_register(target, &mem_addr, rs1); + + if (opcode == MATCH_SB) { + LOG_DEBUG("%x is store instruction", instruction); + imm = ((instruction & 0xf80) >> 7) | ((instruction & 0xfe000000) >> 20); + } else { + LOG_DEBUG("%x is load instruction", instruction); + imm = (instruction & 0xfff00000) >> 20; + } + /* sign extend 12-bit imm to 16-bits */ + if (imm & (1 << 11)) + imm |= 0xf000; + mem_addr += imm; + LOG_DEBUG("memory address=0x%" PRIx64, mem_addr); + } else { + LOG_DEBUG("%x is not a RV32I load or store", instruction); + return ERROR_FAIL; + } + + while (wp) { + /*TODO support length/mask */ + if (wp->address == mem_addr) { + *hit_watchpoint = wp; + LOG_DEBUG("Hit address=%" TARGET_PRIxADDR, wp->address); + return ERROR_OK; + } + wp = wp->next; + } + + /* No match found - either we hit a watchpoint caused by an instruction that + * this function does not yet disassemble, or we hit a breakpoint. + * + * OpenOCD will behave as if this function had never been implemented i.e. + * report the halt to GDB with no address information. */ + return ERROR_FAIL; +} + + static int oldriscv_step(struct target *target, int current, uint32_t address, int handle_breakpoints) { @@ -802,7 +896,7 @@ static int riscv_get_gdb_reg_list(struct target *target, *reg_list_size = 32; break; case REG_CLASS_ALL: - *reg_list_size = GDB_REGNO_COUNT; + *reg_list_size = target->reg_cache->num_regs; break; default: LOG_ERROR("Unsupported reg_class: %d", reg_class); @@ -1068,9 +1162,17 @@ int riscv_openocd_poll(struct target *target) if (riscv_rtos_enabled(target)) { target->rtos->current_threadid = halted_hart + 1; target->rtos->current_thread = halted_hart + 1; + riscv_set_rtos_hartid(target, halted_hart); } target->state = TARGET_HALTED; + + if (target->debug_reason == DBG_REASON_BREAKPOINT) { + int retval; + if (riscv_semihosting(target, &retval) != 0) + return retval; + } + target_call_event_callbacks(target, TARGET_EVENT_HALTED); return ERROR_OK; } @@ -1240,31 +1342,6 @@ COMMAND_HANDLER(riscv_test_compliance) { } } -COMMAND_HANDLER(riscv_set_scratch_ram) -{ - if (CMD_ARGC != 1) { - LOG_ERROR("Command takes exactly 1 parameter"); - return ERROR_COMMAND_SYNTAX_ERROR; - } - if (!strcmp(CMD_ARGV[0], "none")) { - riscv_use_scratch_ram = false; - return ERROR_OK; - } - - /* TODO: use COMMAND_PARSE_NUMBER */ - long long unsigned int address; - int result = sscanf(CMD_ARGV[0], "%llx", &address); - if (result != (int) strlen(CMD_ARGV[0])) { - LOG_ERROR("%s is not a valid address for command.", CMD_ARGV[0]); - riscv_use_scratch_ram = false; - return ERROR_FAIL; - } - - riscv_scratch_ram_address = address; - riscv_use_scratch_ram = true; - return ERROR_OK; -} - COMMAND_HANDLER(riscv_set_prefer_sba) { if (CMD_ARGC != 1) { @@ -1288,20 +1365,15 @@ void parse_error(const char *string, char c, unsigned position) LOG_ERROR("%s", buf); } -COMMAND_HANDLER(riscv_set_expose_csrs) +int parse_ranges(range_t **ranges, const char **argv) { - if (CMD_ARGC != 1) { - LOG_ERROR("Command takes exactly 1 parameter"); - return ERROR_COMMAND_SYNTAX_ERROR; - } - for (unsigned pass = 0; pass < 2; pass++) { unsigned range = 0; unsigned low = 0; bool parse_low = true; unsigned high = 0; - for (unsigned i = 0; i == 0 || CMD_ARGV[0][i-1]; i++) { - char c = CMD_ARGV[0][i]; + for (unsigned i = 0; i == 0 || argv[0][i-1]; i++) { + char c = argv[0][i]; if (isspace(c)) { /* Ignore whitespace. */ continue; @@ -1315,13 +1387,13 @@ COMMAND_HANDLER(riscv_set_expose_csrs) parse_low = false; } else if (c == ',' || c == 0) { if (pass == 1) { - expose_csr[range].low = low; - expose_csr[range].high = low; + (*ranges)[range].low = low; + (*ranges)[range].high = low; } low = 0; range++; } else { - parse_error(CMD_ARGV[0], c, i); + parse_error(argv[0], c, i); return ERROR_COMMAND_SYNTAX_ERROR; } @@ -1332,31 +1404,52 @@ COMMAND_HANDLER(riscv_set_expose_csrs) } else if (c == ',' || c == 0) { parse_low = true; if (pass == 1) { - expose_csr[range].low = low; - expose_csr[range].high = high; + (*ranges)[range].low = low; + (*ranges)[range].high = high; } low = 0; high = 0; range++; } else { - parse_error(CMD_ARGV[0], c, i); + parse_error(argv[0], c, i); return ERROR_COMMAND_SYNTAX_ERROR; } } } if (pass == 0) { - if (expose_csr) - free(expose_csr); - expose_csr = calloc(range + 2, sizeof(*expose_csr)); + if (*ranges) + free(*ranges); + *ranges = calloc(range + 2, sizeof(range_t)); } else { - expose_csr[range].low = 1; - expose_csr[range].high = 0; + (*ranges)[range].low = 1; + (*ranges)[range].high = 0; } } + return ERROR_OK; } +COMMAND_HANDLER(riscv_set_expose_csrs) +{ + if (CMD_ARGC != 1) { + LOG_ERROR("Command takes exactly 1 parameter"); + return ERROR_COMMAND_SYNTAX_ERROR; + } + + return parse_ranges(&expose_csr, CMD_ARGV); +} + +COMMAND_HANDLER(riscv_set_expose_custom) +{ + if (CMD_ARGC != 1) { + LOG_ERROR("Command takes exactly 1 parameter"); + return ERROR_COMMAND_SYNTAX_ERROR; + } + + return parse_ranges(&expose_custom, CMD_ARGV); +} + COMMAND_HANDLER(riscv_authdata_read) { if (CMD_ARGC != 0) { @@ -1487,13 +1580,6 @@ static const struct command_registration riscv_exec_command_handlers[] = { .help = "Set the wall-clock timeout (in seconds) after reset is deasserted" }, { - .name = "set_scratch_ram", - .handler = riscv_set_scratch_ram, - .mode = COMMAND_ANY, - .usage = "riscv set_scratch_ram none|[address]", - .help = "Set address of 16 bytes of scratch RAM the debugger can use, or 'none'." - }, - { .name = "set_prefer_sba", .handler = riscv_set_prefer_sba, .mode = COMMAND_ANY, @@ -1511,6 +1597,15 @@ static const struct command_registration riscv_exec_command_handlers[] = { "`init`." }, { + .name = "expose_custom", + .handler = riscv_set_expose_custom, + .mode = COMMAND_ANY, + .usage = "riscv expose_custom n0[-m0][,n1[-m1]]...", + .help = "Configure a list of inclusive ranges for custom registers to " + "expose. custom0 is accessed as abstract register number 0xc000, " + "etc. This must be executed before `init`." + }, + { .name = "authdata_read", .handler = riscv_authdata_read, .mode = COMMAND_ANY, @@ -1541,6 +1636,56 @@ static const struct command_registration riscv_exec_command_handlers[] = { COMMAND_REGISTRATION_DONE }; +extern __COMMAND_HANDLER(handle_common_semihosting_command); +extern __COMMAND_HANDLER(handle_common_semihosting_fileio_command); +extern __COMMAND_HANDLER(handle_common_semihosting_resumable_exit_command); +extern __COMMAND_HANDLER(handle_common_semihosting_cmdline); + +/* + * To be noted that RISC-V targets use the same semihosting commands as + * ARM targets. + * + * The main reason is compatibility with existing tools. For example the + * Eclipse OpenOCD/SEGGER J-Link/QEMU plug-ins have several widgets to + * configure semihosting, which generate commands like `arm semihosting + * enable`. + * A secondary reason is the fact that the protocol used is exactly the + * one specified by ARM. If RISC-V will ever define its own semihosting + * protocol, then a command like `riscv semihosting enable` will make + * sense, but for now all semihosting commands are prefixed with `arm`. + */ +static const struct command_registration arm_exec_command_handlers[] = { + { + "semihosting", + .handler = handle_common_semihosting_command, + .mode = COMMAND_EXEC, + .usage = "['enable'|'disable']", + .help = "activate support for semihosting operations", + }, + { + "semihosting_cmdline", + .handler = handle_common_semihosting_cmdline, + .mode = COMMAND_EXEC, + .usage = "arguments", + .help = "command line arguments to be passed to program", + }, + { + "semihosting_fileio", + .handler = handle_common_semihosting_fileio_command, + .mode = COMMAND_EXEC, + .usage = "['enable'|'disable']", + .help = "activate support for semihosting fileio operations", + }, + { + "semihosting_resexit", + .handler = handle_common_semihosting_resumable_exit_command, + .mode = COMMAND_EXEC, + .usage = "['enable'|'disable']", + .help = "activate support for semihosting resumable exit", + }, + COMMAND_REGISTRATION_DONE +}; + const struct command_registration riscv_command_handlers[] = { { .name = "riscv", @@ -1549,6 +1694,13 @@ const struct command_registration riscv_command_handlers[] = { .usage = "", .chain = riscv_exec_command_handlers }, + { + .name = "arm", + .mode = COMMAND_ANY, + .help = "ARM Command Group", + .usage = "", + .chain = arm_exec_command_handlers + }, COMMAND_REGISTRATION_DONE }; @@ -1581,6 +1733,7 @@ struct target_type riscv_target = { .add_watchpoint = riscv_add_watchpoint, .remove_watchpoint = riscv_remove_watchpoint, + .hit_watchpoint = riscv_hit_watchpoint, .arch_state = riscv_arch_state, @@ -1760,7 +1913,7 @@ void riscv_invalidate_register_cache(struct target *target) RISCV_INFO(r); register_cache_invalidate(target->reg_cache); - for (size_t i = 0; i < GDB_REGNO_COUNT; ++i) { + for (size_t i = 0; i < target->reg_cache->num_regs; ++i) { struct reg *reg = &target->reg_cache->reg_list[i]; reg->valid = false; } @@ -2033,7 +2186,8 @@ const char *gdb_regno_name(enum gdb_regno regno) static int register_get(struct reg *reg) { - struct target *target = (struct target *) reg->arch_info; + riscv_reg_info_t *reg_info = reg->arch_info; + struct target *target = reg_info->target; uint64_t value; int result = riscv_get_register(target, &value, reg->number); if (result != ERROR_OK) @@ -2044,7 +2198,8 @@ static int register_get(struct reg *reg) static int register_set(struct reg *reg, uint8_t *buf) { - struct target *target = (struct target *) reg->arch_info; + riscv_reg_info_t *reg_info = reg->arch_info; + struct target *target = reg_info->target; uint64_t value = buf_get_u64(buf, 0, reg->size); @@ -2086,12 +2241,26 @@ int riscv_init_registers(struct target *target) target->reg_cache->name = "RISC-V Registers"; target->reg_cache->num_regs = GDB_REGNO_COUNT; - target->reg_cache->reg_list = calloc(GDB_REGNO_COUNT, sizeof(struct reg)); + if (expose_custom) { + for (unsigned i = 0; expose_custom[i].low <= expose_custom[i].high; i++) { + for (unsigned number = expose_custom[i].low; + number <= expose_custom[i].high; + number++) + target->reg_cache->num_regs++; + } + } + + LOG_DEBUG("create register cache for %d registers", + target->reg_cache->num_regs); + + target->reg_cache->reg_list = + calloc(target->reg_cache->num_regs, sizeof(struct reg)); const unsigned int max_reg_name_len = 12; if (info->reg_names) free(info->reg_names); - info->reg_names = calloc(1, GDB_REGNO_COUNT * max_reg_name_len); + info->reg_names = + calloc(target->reg_cache->num_regs, max_reg_name_len); char *reg_name = info->reg_names; static struct reg_feature feature_cpu = { @@ -2106,6 +2275,9 @@ int riscv_init_registers(struct target *target) static struct reg_feature feature_virtual = { .name = "org.gnu.gdb.riscv.virtual" }; + static struct reg_feature feature_custom = { + .name = "org.gnu.gdb.riscv.custom" + }; static struct reg_data_type type_ieee_single = { .type = REG_TYPE_IEEE_SINGLE, @@ -2124,18 +2296,24 @@ int riscv_init_registers(struct target *target) qsort(csr_info, DIM(csr_info), sizeof(*csr_info), cmp_csr_info); unsigned csr_info_index = 0; - /* When gdb request register N, gdb_get_register_packet() assumes that this + unsigned custom_range_index = 0; + int custom_within_range = 0; + + riscv_reg_info_t *shared_reg_info = calloc(1, sizeof(riscv_reg_info_t)); + shared_reg_info->target = target; + + /* When gdb requests register N, gdb_get_register_packet() assumes that this * is register at index N in reg_list. So if there are certain registers * that don't exist, we need to leave holes in the list (or renumber, but * it would be nice not to have yet another set of numbers to translate * between). */ - for (uint32_t number = 0; number < GDB_REGNO_COUNT; number++) { + for (uint32_t number = 0; number < target->reg_cache->num_regs; number++) { struct reg *r = &target->reg_cache->reg_list[number]; r->dirty = false; r->valid = false; r->exist = true; r->type = &riscv_reg_arch_type; - r->arch_info = target; + r->arch_info = shared_reg_info; r->number = number; r->size = riscv_xlen(target); /* r->size is set in riscv_invalidate_register_cache, maybe because the @@ -2495,11 +2673,35 @@ int riscv_init_registers(struct target *target) r->group = "general"; r->feature = &feature_virtual; r->size = 8; + + } else { + /* Custom registers. */ + assert(expose_custom); + + range_t *range = &expose_custom[custom_range_index]; + assert(range->low <= range->high); + unsigned custom_number = range->low + custom_within_range; + + r->group = "custom"; + r->feature = &feature_custom; + r->arch_info = calloc(1, sizeof(riscv_reg_info_t)); + assert(r->arch_info); + ((riscv_reg_info_t *) r->arch_info)->target = target; + ((riscv_reg_info_t *) r->arch_info)->custom_number = custom_number; + sprintf(reg_name, "custom%d", custom_number); + + custom_within_range++; + if (custom_within_range > range->high - range->low) { + custom_within_range = 0; + custom_range_index++; + } } + if (reg_name[0]) r->name = reg_name; reg_name += strlen(reg_name) + 1; - assert(reg_name < info->reg_names + GDB_REGNO_COUNT * max_reg_name_len); + assert(reg_name < info->reg_names + target->reg_cache->num_regs * + max_reg_name_len); r->value = &info->reg_cache_values[number]; } diff --git a/src/target/riscv/riscv.h b/src/target/riscv/riscv.h index 1e7e328..419d051 100644 --- a/src/target/riscv/riscv.h +++ b/src/target/riscv/riscv.h @@ -7,7 +7,7 @@ struct riscv_program; #include "opcodes.h" #include "gdb_regs.h" -/* The register cache is staticly allocated. */ +/* The register cache is statically allocated. */ #define RISCV_MAX_HARTS 32 #define RISCV_MAX_REGISTERS 5000 #define RISCV_MAX_TRIGGERS 32 @@ -36,6 +36,11 @@ enum riscv_halt_reason { }; typedef struct { + struct target *target; + unsigned custom_number; +} riscv_reg_info_t; + +typedef struct { unsigned dtm_version; struct command_context *cmd_ctx; @@ -58,7 +63,9 @@ typedef struct { uint64_t saved_registers[RISCV_MAX_HARTS][RISCV_MAX_REGISTERS]; bool valid_saved_registers[RISCV_MAX_HARTS][RISCV_MAX_REGISTERS]; - /* The register cache points into here. */ + /* OpenOCD's register cache points into here. This is not per-hart because + * we just invalidate the entire cache when we change which hart is + * selected. */ uint64_t reg_cache_values[RISCV_MAX_REGISTERS]; /* Single buffer that contains all register names, instead of calling @@ -129,9 +136,6 @@ extern int riscv_command_timeout_sec; /* Wall-clock timeout after reset. Settable via RISC-V Target commands.*/ extern int riscv_reset_timeout_sec; -extern bool riscv_use_scratch_ram; -extern uint64_t riscv_scratch_ram_address; - extern bool riscv_prefer_sba; /* Everything needs the RISC-V specific info structure, so here's a nice macro @@ -257,7 +261,11 @@ int riscv_remove_breakpoint(struct target *target, int riscv_add_watchpoint(struct target *target, struct watchpoint *watchpoint); int riscv_remove_watchpoint(struct target *target, struct watchpoint *watchpoint); +int riscv_hit_watchpoint(struct target *target, struct watchpoint **hit_wp_address); int riscv_init_registers(struct target *target); +void riscv_semihosting_init(struct target *target); +int riscv_semihosting(struct target *target, int *retval); + #endif diff --git a/src/target/riscv/riscv_semihosting.c b/src/target/riscv/riscv_semihosting.c new file mode 100644 index 0000000..c4b6653 --- /dev/null +++ b/src/target/riscv/riscv_semihosting.c @@ -0,0 +1,194 @@ +/*************************************************************************** + * Copyright (C) 2018 by Liviu Ionescu * + * ilg@livius.net * + * * + * Copyright (C) 2009 by Marvell Technology Group Ltd. * + * Written by Nicolas Pitre <nico@marvell.com> * + * * + * Copyright (C) 2010 by Spencer Oliver * + * spen@spen-soft.co.uk * + * * + * Copyright (C) 2016 by Square, Inc. * + * Steven Stallion <stallion@squareup.com> * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ + +/** + * @file + * Hold RISC-V semihosting support. + * + * The RISC-V code is inspired from ARM semihosting. + * + * Details can be found in chapter 8 of DUI0203I_rvct_developer_guide.pdf + * from ARM Ltd. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "log.h" + +#include "target/target.h" +#include "target/semihosting_common.h" +#include "riscv.h" + +static int riscv_semihosting_setup(struct target *target, int enable); +static int riscv_semihosting_post_result(struct target *target); + +/** + * Initialize RISC-V semihosting. Use common ARM code. + */ +void riscv_semihosting_init(struct target *target) +{ + semihosting_common_init(target, riscv_semihosting_setup, + riscv_semihosting_post_result); +} + +/** + * Check for and process a semihosting request using the ARM protocol). This + * is meant to be called when the target is stopped due to a debug mode entry. + * If the value 0 is returned then there was nothing to process. A non-zero + * return value signifies that a request was processed and the target resumed, + * or an error was encountered, in which case the caller must return + * immediately. + * + * @param target Pointer to the target to process. + * @param retval Pointer to a location where the return code will be stored + * @return non-zero value if a request was processed or an error encountered + */ +int riscv_semihosting(struct target *target, int *retval) +{ + struct semihosting *semihosting = target->semihosting; + if (!semihosting) + return 0; + + if (!semihosting->is_active) + return 0; + + riscv_reg_t dpc; + int result = riscv_get_register(target, &dpc, GDB_REGNO_DPC); + if (result != ERROR_OK) + return 0; + + uint8_t tmp[12]; + + /* Read the current instruction, including the bracketing */ + *retval = target_read_memory(target, dpc - 4, 2, 6, tmp); + if (*retval != ERROR_OK) + return 0; + + /* + * The instructions that trigger a semihosting call, + * always uncompressed, should look like: + * + * 01f01013 slli zero,zero,0x1f + * 00100073 ebreak + * 40705013 srai zero,zero,0x7 + */ + uint32_t pre = target_buffer_get_u32(target, tmp); + uint32_t ebreak = target_buffer_get_u32(target, tmp + 4); + uint32_t post = target_buffer_get_u32(target, tmp + 8); + LOG_DEBUG("check %08x %08x %08x from 0x%" PRIx64 "-4", pre, ebreak, post, dpc); + + if (pre != 0x01f01013 || ebreak != 0x00100073 || post != 0x40705013) { + + /* Not the magic sequence defining semihosting. */ + return 0; + } + + /* + * Perform semihosting call if we are not waiting on a fileio + * operation to complete. + */ + if (!semihosting->hit_fileio) { + + /* RISC-V uses A0 and A1 to pass function arguments */ + riscv_reg_t r0; + riscv_reg_t r1; + + result = riscv_get_register(target, &r0, GDB_REGNO_A0); + if (result != ERROR_OK) + return 0; + + result = riscv_get_register(target, &r1, GDB_REGNO_A1); + if (result != ERROR_OK) + return 0; + + semihosting->op = r0; + semihosting->param = r1; + semihosting->word_size_bytes = riscv_xlen(target) / 8; + + /* Check for ARM operation numbers. */ + if (0 <= semihosting->op && semihosting->op <= 0x31) { + *retval = semihosting_common(target); + if (*retval != ERROR_OK) { + LOG_ERROR("Failed semihosting operation"); + return 0; + } + } else { + /* Unknown operation number, not a semihosting call. */ + return 0; + } + } + + /* + * Resume target if we are not waiting on a fileio + * operation to complete. + */ + if (semihosting->is_resumable && !semihosting->hit_fileio) { + /* Resume right after the EBREAK 4 bytes instruction. */ + *retval = target_resume(target, 0, dpc+4, 0, 0); + if (*retval != ERROR_OK) { + LOG_ERROR("Failed to resume target"); + return 0; + } + + return 1; + } + + return 0; +} + +/* ------------------------------------------------------------------------- + * Local functions. */ + +/** + * Called via semihosting->setup() later, after the target is known, + * usually on the first semihosting command. + */ +static int riscv_semihosting_setup(struct target *target, int enable) +{ + LOG_DEBUG("enable=%d", enable); + + struct semihosting *semihosting = target->semihosting; + if (semihosting) + semihosting->setup_time = clock(); + + return ERROR_OK; +} + +static int riscv_semihosting_post_result(struct target *target) +{ + struct semihosting *semihosting = target->semihosting; + if (!semihosting) { + /* If not enabled, silently ignored. */ + return 0; + } + + LOG_DEBUG("0x%" PRIx64, semihosting->result); + riscv_set_register(target, GDB_REGNO_A0, semihosting->result); + return 0; +} diff --git a/src/target/semihosting_common.c b/src/target/semihosting_common.c new file mode 100644 index 0000000..5920789 --- /dev/null +++ b/src/target/semihosting_common.c @@ -0,0 +1,1595 @@ +/*************************************************************************** + * Copyright (C) 2018 by Liviu Ionescu * + * <ilg@livius.net> * + * * + * Copyright (C) 2018 by Marvell Technology Group Ltd. * + * Written by Nicolas Pitre <nico@marvell.com> * + * * + * Copyright (C) 2010 by Spencer Oliver * + * spen@spen-soft.co.uk * + * * + * Copyright (C) 2016 by Square, Inc. * + * Steven Stallion <stallion@squareup.com> * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ + +/** + * @file + * Common ARM semihosting support. + * + * Semihosting enables code running on a target to use some of the I/O + * facilities on the host computer. The target application must be linked + * against a library that forwards operation requests by using an + * instruction trapped by the debugger. + * + * Details can be found in + * "Semihosting for AArch32 and AArch64, Release 2.0" + * https://static.docs.arm.com/100863/0200/semihosting.pdf + * from ARM Ltd. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "target.h" +#include "target_type.h" +#include "semihosting_common.h" + +#include <helper/binarybuffer.h> +#include <helper/log.h> +#include <sys/stat.h> + +static const int open_modeflags[12] = { + O_RDONLY, + O_RDONLY | O_BINARY, + O_RDWR, + O_RDWR | O_BINARY, + O_WRONLY | O_CREAT | O_TRUNC, + O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, + O_RDWR | O_CREAT | O_TRUNC, + O_RDWR | O_CREAT | O_TRUNC | O_BINARY, + O_WRONLY | O_CREAT | O_APPEND, + O_WRONLY | O_CREAT | O_APPEND | O_BINARY, + O_RDWR | O_CREAT | O_APPEND, + O_RDWR | O_CREAT | O_APPEND | O_BINARY +}; + +static int semihosting_common_fileio_info(struct target *target, + struct gdb_fileio_info *fileio_info); +static int semihosting_common_fileio_end(struct target *target, int result, + int fileio_errno, bool ctrl_c); + +static int semihosting_read_fields(struct target *target, size_t number, + uint8_t *fields); +static int semihosting_write_fields(struct target *target, size_t number, + uint8_t *fields); +static uint64_t semihosting_get_field(struct target *target, size_t index, + uint8_t *fields); +static void semihosting_set_field(struct target *target, uint64_t value, + size_t index, + uint8_t *fields); + +/* Attempts to include gdb_server.h failed. */ +extern int gdb_actual_connections; + +/** + * Initialize common semihosting support. + * + * @param target Pointer to the target to initialize. + * @return An error status if there is a problem during initialization. + */ +int semihosting_common_init(struct target *target, void *setup, + void *post_result) +{ + LOG_DEBUG(" "); + + target->fileio_info = malloc(sizeof(*target->fileio_info)); + if (target->fileio_info == NULL) { + LOG_ERROR("out of memory"); + return ERROR_FAIL; + } + memset(target->fileio_info, 0, sizeof(*target->fileio_info)); + + struct semihosting *semihosting; + semihosting = malloc(sizeof(*target->semihosting)); + if (semihosting == NULL) { + LOG_ERROR("out of memory"); + return ERROR_FAIL; + } + + semihosting->is_active = false; + semihosting->is_fileio = false; + semihosting->hit_fileio = false; + semihosting->is_resumable = false; + semihosting->has_resumable_exit = false; + semihosting->word_size_bytes = 0; + semihosting->op = -1; + semihosting->param = 0; + semihosting->result = -1; + semihosting->sys_errno = -1; + semihosting->cmdline = NULL; + + /* If possible, update it in setup(). */ + semihosting->setup_time = clock(); + + semihosting->setup = setup; + semihosting->post_result = post_result; + + target->semihosting = semihosting; + + target->type->get_gdb_fileio_info = semihosting_common_fileio_info; + target->type->gdb_fileio_end = semihosting_common_fileio_end; + + return ERROR_OK; +} + +/** + * Portable implementation of ARM semihosting calls. + * Performs the currently pending semihosting operation + * encoded in target->semihosting. + */ +int semihosting_common(struct target *target) +{ + struct semihosting *semihosting = target->semihosting; + if (!semihosting) { + /* Silently ignore if the semhosting field was not set. */ + return ERROR_OK; + } + + struct gdb_fileio_info *fileio_info = target->fileio_info; + + /* + * By default return an error. + * The actual result must be set by each function + */ + semihosting->result = -1; + + /* Most operations are resumable, except the two exit calls. */ + semihosting->is_resumable = true; + + int retval; + + /* Enough space to hold 4 long words. */ + uint8_t fields[4*8]; + + LOG_DEBUG("op=0x%x, param=0x%" PRIx64, (int)semihosting->op, + semihosting->param); + + switch (semihosting->op) { + + case SEMIHOSTING_SYS_CLOCK: /* 0x10 */ + /* + * Returns the number of centiseconds (hundredths of a second) + * since the execution started. + * + * Values returned can be of limited use for some benchmarking + * purposes because of communication overhead or other + * agent-specific factors. For example, with a debug hardware + * unit the request is passed back to the host for execution. + * This can lead to unpredictable delays in transmission and + * process scheduling. + * + * Use this function to calculate time intervals, by calculating + * differences between intervals with and without the code + * sequence to be timed. + * + * Entry + * The PARAMETER REGISTER must contain 0. There are no other + * parameters. + * + * Return + * On exit, the RETURN REGISTER contains: + * - The number of centiseconds since some arbitrary start + * point, if the call is successful. + * - –1 if the call is not successful. For example, because + * of a communications error. + */ + { + clock_t delta = clock() - semihosting->setup_time; + + semihosting->result = delta / (CLOCKS_PER_SEC / 100); + } + break; + + case SEMIHOSTING_SYS_CLOSE: /* 0x02 */ + /* + * Closes a file on the host system. The handle must reference + * a file that was opened with SYS_OPEN. + * + * Entry + * On entry, the PARAMETER REGISTER contains a pointer to a + * one-field argument block: + * - field 1 Contains a handle for an open file. + * + * Return + * On exit, the RETURN REGISTER contains: + * - 0 if the call is successful + * - –1 if the call is not successful. + */ + retval = semihosting_read_fields(target, 1, fields); + if (retval != ERROR_OK) + return retval; + else { + int fd = semihosting_get_field(target, 0, fields); + if (semihosting->is_fileio) { + if (fd == 0 || fd == 1 || fd == 2) { + semihosting->result = 0; + break; + } + semihosting->hit_fileio = true; + fileio_info->identifier = "close"; + fileio_info->param_1 = fd; + } else { + semihosting->result = close(fd); + semihosting->sys_errno = errno; + + LOG_DEBUG("close(%d)=%d", fd, (int)semihosting->result); + } + } + break; + + case SEMIHOSTING_SYS_ERRNO: /* 0x13 */ + /* + * Returns the value of the C library errno variable that is + * associated with the semihosting implementation. The errno + * variable can be set by a number of C library semihosted + * functions, including: + * - SYS_REMOVE + * - SYS_OPEN + * - SYS_CLOSE + * - SYS_READ + * - SYS_WRITE + * - SYS_SEEK. + * + * Whether errno is set or not, and to what value, is entirely + * host-specific, except where the ISO C standard defines the + * behavior. + * + * Entry + * There are no parameters. The PARAMETER REGISTER must be 0. + * + * Return + * On exit, the RETURN REGISTER contains the value of the C + * library errno variable. + */ + semihosting->result = semihosting->sys_errno; + break; + + case SEMIHOSTING_SYS_EXIT: /* 0x18 */ + /* + * Note: SYS_EXIT was called angel_SWIreason_ReportException in + * previous versions of the documentation. + * + * An application calls this operation to report an exception + * to the debugger directly. The most common use is to report + * that execution has completed, using ADP_Stopped_ApplicationExit. + * + * Note: This semihosting operation provides no means for 32-bit + * callers to indicate an application exit with a specified exit + * code. Semihosting callers may prefer to check for the presence + * of the SH_EXT_EXTENDED_REPORT_EXCEPTION extension and use + * the SYS_REPORT_EXCEPTION_EXTENDED operation instead, if it + * is available. + * + * Entry (32-bit) + * On entry, the PARAMETER register is set to a reason code + * describing the cause of the trap. Not all semihosting client + * implementations will necessarily trap every corresponding + * event. Important reason codes are: + * + * - ADP_Stopped_ApplicationExit 0x20026 + * - ADP_Stopped_RunTimeErrorUnknown 0x20023 + * + * Entry (64-bit) + * On entry, the PARAMETER REGISTER contains a pointer to a + * two-field argument block: + * - field 1 The exception type, which is one of the set of + * reason codes in the above tables. + * - field 2 A subcode, whose meaning depends on the reason + * code in field 1. + * In particular, if field 1 is ADP_Stopped_ApplicationExit + * then field 2 is an exit status code, as passed to the C + * standard library exit() function. A simulator receiving + * this request must notify a connected debugger, if present, + * and then exit with the specified status. + * + * Return + * No return is expected from these calls. However, it is + * possible for the debugger to request that the application + * continues by performing an RDI_Execute request or equivalent. + * In this case, execution continues with the registers as they + * were on entry to the operation, or as subsequently modified + * by the debugger. + */ + if (semihosting->word_size_bytes == 8) { + retval = semihosting_read_fields(target, 2, fields); + if (retval != ERROR_OK) + return retval; + else { + int type = semihosting_get_field(target, 0, fields); + int code = semihosting_get_field(target, 1, fields); + + if (type == ADP_STOPPED_APPLICATION_EXIT) { + if (!gdb_actual_connections) + exit(code); + else { + fprintf(stderr, + "semihosting: *** application exited with %d ***\n", + code); + } + } else { + fprintf(stderr, + "semihosting: application exception %#x\n", + type); + } + } + } else { + if (semihosting->param == ADP_STOPPED_APPLICATION_EXIT) { + if (!gdb_actual_connections) + exit(0); + else { + fprintf(stderr, + "semihosting: *** application exited normally ***\n"); + } + } else if (semihosting->param == ADP_STOPPED_RUN_TIME_ERROR) { + /* Chosen more or less arbitrarly to have a nicer message, + * otherwise all other return the same exit code 1. */ + if (!gdb_actual_connections) + exit(1); + else { + fprintf(stderr, + "semihosting: *** application exited with error ***\n"); + } + } else { + if (!gdb_actual_connections) + exit(1); + else { + fprintf(stderr, + "semihosting: application exception %#x\n", + (unsigned) semihosting->param); + } + } + } + if (!semihosting->has_resumable_exit) { + semihosting->is_resumable = false; + return target_call_event_callbacks(target, TARGET_EVENT_HALTED); + } + break; + + case SEMIHOSTING_SYS_EXIT_EXTENDED: /* 0x20 */ + /* + * This operation is only supported if the semihosting extension + * SH_EXT_EXIT_EXTENDED is implemented. SH_EXT_EXIT_EXTENDED is + * reported using feature byte 0, bit 0. If this extension is + * supported, then the implementation provides a means to + * report a normal exit with a nonzero exit status in both 32-bit + * and 64-bit semihosting APIs. + * + * The implementation must provide the semihosting call + * SYS_EXIT_EXTENDED for both A64 and A32/T32 semihosting APIs. + * + * SYS_EXIT_EXTENDED is used by an application to report an + * exception or exit to the debugger directly. The most common + * use is to report that execution has completed, using + * ADP_Stopped_ApplicationExit. + * + * Entry + * On entry, the PARAMETER REGISTER contains a pointer to a + * two-field argument block: + * - field 1 The exception type, which should be one of the set + * of reason codes that are documented for the SYS_EXIT + * (0x18) call. For example, ADP_Stopped_ApplicationExit. + * - field 2 A subcode, whose meaning depends on the reason + * code in field 1. In particular, if field 1 is + * ADP_Stopped_ApplicationExit then field 2 is an exit status + * code, as passed to the C standard library exit() function. + * A simulator receiving this request must notify a connected + * debugger, if present, and then exit with the specified status. + * + * Return + * No return is expected from these calls. + * + * For the A64 API, this call is identical to the behavior of + * the mandatory SYS_EXIT (0x18) call. If this extension is + * supported, then both calls must be implemented. + */ + retval = semihosting_read_fields(target, 2, fields); + if (retval != ERROR_OK) + return retval; + else { + int type = semihosting_get_field(target, 0, fields); + int code = semihosting_get_field(target, 1, fields); + + if (type == ADP_STOPPED_APPLICATION_EXIT) { + if (!gdb_actual_connections) + exit(code); + else { + fprintf(stderr, + "semihosting: *** application exited with %d ***\n", + code); + } + } else { + fprintf(stderr, "semihosting: exception %#x\n", + type); + } + } + if (!semihosting->has_resumable_exit) { + semihosting->is_resumable = false; + return target_call_event_callbacks(target, TARGET_EVENT_HALTED); + } + break; + + case SEMIHOSTING_SYS_FLEN: /* 0x0C */ + /* + * Returns the length of a specified file. + * + * Entry + * On entry, the PARAMETER REGISTER contains a pointer to a + * one-field argument block: + * - field 1 A handle for a previously opened, seekable file + * object. + * + * Return + * On exit, the RETURN REGISTER contains: + * - The current length of the file object, if the call is + * successful. + * - –1 if an error occurs. + */ + if (semihosting->is_fileio) { + semihosting->result = -1; + semihosting->sys_errno = EINVAL; + } + retval = semihosting_read_fields(target, 1, fields); + if (retval != ERROR_OK) + return retval; + else { + int fd = semihosting_get_field(target, 0, fields); + struct stat buf; + semihosting->result = fstat(fd, &buf); + if (semihosting->result == -1) { + semihosting->sys_errno = errno; + LOG_DEBUG("fstat(%d)=%d", fd, (int)semihosting->result); + break; + } + LOG_DEBUG("fstat(%d)=%d", fd, (int)semihosting->result); + semihosting->result = buf.st_size; + } + break; + + case SEMIHOSTING_SYS_GET_CMDLINE: /* 0x15 */ + /* + * Returns the command line that is used for the call to the + * executable, that is, argc and argv. + * + * Entry + * On entry, the PARAMETER REGISTER points to a two-field data + * block to be used for returning the command string and its length: + * - field 1 A pointer to a buffer of at least the size that is + * specified in field 2. + * - field 2 The length of the buffer in bytes. + * + * Return + * On exit: + * If the call is successful, then the RETURN REGISTER contains 0, + * the PARAMETER REGISTER is unchanged, and the data block is + * updated as follows: + * - field 1 A pointer to a null-terminated string of the command + * line. + * - field 2 The length of the string in bytes. + * If the call is not successful, then the RETURN REGISTER + * contains -1. + * + * Note: The semihosting implementation might impose limits on + * the maximum length of the string that can be transferred. + * However, the implementation must be able to support a + * command-line length of at least 80 bytes. + */ + retval = semihosting_read_fields(target, 2, fields); + if (retval != ERROR_OK) + return retval; + else { + uint64_t addr = semihosting_get_field(target, 0, fields); + size_t size = semihosting_get_field(target, 1, fields); + + char *arg = semihosting->cmdline != NULL ? + semihosting->cmdline : ""; + uint32_t len = strlen(arg) + 1; + if (len > size) + semihosting->result = -1; + else { + semihosting_set_field(target, len, 1, fields); + retval = target_write_buffer(target, addr, len, + (uint8_t *)arg); + if (retval != ERROR_OK) + return retval; + semihosting->result = 0; + + retval = semihosting_write_fields(target, 2, fields); + if (retval != ERROR_OK) + return retval; + } + LOG_DEBUG("SYS_GET_CMDLINE=[%s],%d", arg, + (int)semihosting->result); + } + break; + + case SEMIHOSTING_SYS_HEAPINFO: /* 0x16 */ + /* + * Returns the system stack and heap parameters. + * + * Entry + * On entry, the PARAMETER REGISTER contains the address of a + * pointer to a four-field data block. The contents of the data + * block are filled by the function. The following C-like + * pseudocode describes the layout of the block: + * struct block { + * void* heap_base; + * void* heap_limit; + * void* stack_base; + * void* stack_limit; + * }; + * + * Return + * On exit, the PARAMETER REGISTER is unchanged and the data + * block has been updated. + */ + retval = semihosting_read_fields(target, 1, fields); + if (retval != ERROR_OK) + return retval; + else { + uint64_t addr = semihosting_get_field(target, 0, fields); + /* tell the remote we have no idea */ + memset(fields, 0, 4 * semihosting->word_size_bytes); + retval = target_write_memory(target, addr, 4, + semihosting->word_size_bytes, + fields); + if (retval != ERROR_OK) + return retval; + semihosting->result = 0; + } + break; + + case SEMIHOSTING_SYS_ISERROR: /* 0x08 */ + /* + * Determines whether the return code from another semihosting + * call is an error status or not. + * + * This call is passed a parameter block containing the error + * code to examine. + * + * Entry + * On entry, the PARAMETER REGISTER contains a pointer to a + * one-field data block: + * - field 1 The required status word to check. + * + * Return + * On exit, the RETURN REGISTER contains: + * - 0 if the status field is not an error indication + * - A nonzero value if the status field is an error indication. + */ + retval = semihosting_read_fields(target, 1, fields); + if (retval != ERROR_OK) + return retval; + + uint64_t code = semihosting_get_field(target, 0, fields); + semihosting->result = (code != 0); + break; + + case SEMIHOSTING_SYS_ISTTY: /* 0x09 */ + /* + * Checks whether a file is connected to an interactive device. + * + * Entry + * On entry, the PARAMETER REGISTER contains a pointer to a + * one-field argument block: + * field 1 A handle for a previously opened file object. + * + * Return + * On exit, the RETURN REGISTER contains: + * - 1 if the handle identifies an interactive device. + * - 0 if the handle identifies a file. + * - A value other than 1 or 0 if an error occurs. + */ + if (semihosting->is_fileio) { + semihosting->hit_fileio = true; + fileio_info->identifier = "isatty"; + fileio_info->param_1 = semihosting->param; + } else { + retval = semihosting_read_fields(target, 1, fields); + if (retval != ERROR_OK) + return retval; + int fd = semihosting_get_field(target, 0, fields); + semihosting->result = isatty(fd); + LOG_DEBUG("isatty(%d)=%d", fd, (int)semihosting->result); + } + break; + + case SEMIHOSTING_SYS_OPEN: /* 0x01 */ + /* + * Opens a file on the host system. + * + * The file path is specified either as relative to the current + * directory of the host process, or absolute, using the path + * conventions of the host operating system. + * + * Semihosting implementations must support opening the special + * path name :semihosting-features as part of the semihosting + * extensions reporting mechanism. + * + * ARM targets interpret the special path name :tt as meaning + * the console input stream, for an open-read or the console + * output stream, for an open-write. Opening these streams is + * performed as part of the standard startup code for those + * applications that reference the C stdio streams. The + * semihosting extension SH_EXT_STDOUT_STDERR allows the + * semihosting caller to open separate output streams + * corresponding to stdout and stderr. This extension is + * reported using feature byte 0, bit 1. Use SYS_OPEN with + * the special path name :semihosting-features to access the + * feature bits. + * + * If this extension is supported, the implementation must + * support the following additional semantics to SYS_OPEN: + * - If the special path name :tt is opened with an fopen + * mode requesting write access (w, wb, w+, or w+b), then + * this is a request to open stdout. + * - If the special path name :tt is opened with a mode + * requesting append access (a, ab, a+, or a+b), then this is + * a request to open stderr. + * + * Entry + * On entry, the PARAMETER REGISTER contains a pointer to a + * three-field argument block: + * - field 1 A pointer to a null-terminated string containing + * a file or device name. + * - field 2 An integer that specifies the file opening mode. + * - field 3 An integer that gives the length of the string + * pointed to by field 1. + * + * The length does not include the terminating null character + * that must be present. + * + * Return + * On exit, the RETURN REGISTER contains: + * - A nonzero handle if the call is successful. + * - –1 if the call is not successful. + */ + retval = semihosting_read_fields(target, 3, fields); + if (retval != ERROR_OK) + return retval; + else { + uint64_t addr = semihosting_get_field(target, 0, fields); + uint32_t mode = semihosting_get_field(target, 1, fields); + size_t len = semihosting_get_field(target, 2, fields); + + if (mode > 11) { + semihosting->result = -1; + semihosting->sys_errno = EINVAL; + break; + } + uint8_t *fn = malloc(len+1); + if (!fn) { + semihosting->result = -1; + semihosting->sys_errno = ENOMEM; + } else { + retval = target_read_memory(target, addr, 1, len, fn); + if (retval != ERROR_OK) { + free(fn); + return retval; + } + fn[len] = 0; + /* TODO: implement the :semihosting-features special file. + * */ + if (semihosting->is_fileio) { + if (strcmp((char *)fn, ":semihosting-features") == 0) { + semihosting->result = -1; + semihosting->sys_errno = EINVAL; + } else if (strcmp((char *)fn, ":tt") == 0) { + if (mode == 0) + semihosting->result = 0; + else if (mode == 4) + semihosting->result = 1; + else if (mode == 8) + semihosting->result = 2; + else + semihosting->result = -1; + } else { + semihosting->hit_fileio = true; + fileio_info->identifier = "open"; + fileio_info->param_1 = addr; + fileio_info->param_2 = len; + fileio_info->param_3 = open_modeflags[mode]; + fileio_info->param_4 = 0644; + } + } else { + if (strcmp((char *)fn, ":tt") == 0) { + /* Mode is: + * - 0-3 ("r") for stdin, + * - 4-7 ("w") for stdout, + * - 8-11 ("a") for stderr */ + if (mode < 4) { + semihosting->result = dup( + STDIN_FILENO); + semihosting->sys_errno = errno; + LOG_DEBUG("dup(STDIN)=%d", + (int)semihosting->result); + } else if (mode < 8) { + semihosting->result = dup( + STDOUT_FILENO); + semihosting->sys_errno = errno; + LOG_DEBUG("dup(STDOUT)=%d", + (int)semihosting->result); + } else { + semihosting->result = dup( + STDERR_FILENO); + semihosting->sys_errno = errno; + LOG_DEBUG("dup(STDERR)=%d", + (int)semihosting->result); + } + } else { + /* cygwin requires the permission setting + * otherwise it will fail to reopen a previously + * written file */ + semihosting->result = open((char *)fn, + open_modeflags[mode], + 0644); + semihosting->sys_errno = errno; + LOG_DEBUG("open('%s')=%d", fn, + (int)semihosting->result); + } + } + free(fn); + } + } + break; + + case SEMIHOSTING_SYS_READ: /* 0x06 */ + /* + * Reads the contents of a file into a buffer. The file position + * is specified either: + * - Explicitly by a SYS_SEEK. + * - Implicitly one byte beyond the previous SYS_READ or + * SYS_WRITE request. + * + * The file position is at the start of the file when it is + * opened, and is lost when the file is closed. Perform the + * file operation as a single action whenever possible. For + * example, do not split a read of 16KB into four 4KB chunks + * unless there is no alternative. + * + * Entry + * On entry, the PARAMETER REGISTER contains a pointer to a + * three-field data block: + * - field 1 Contains a handle for a file previously opened + * with SYS_OPEN. + * - field 2 Points to a buffer. + * - field 3 Contains the number of bytes to read to the buffer + * from the file. + * + * Return + * On exit, the RETURN REGISTER contains the number of bytes not + * filled in the buffer (buffer_length - bytes_read) as follows: + * - If the RETURN REGISTER is 0, the entire buffer was + * successfully filled. + * - If the RETURN REGISTER is the same as field 3, no bytes + * were read (EOF can be assumed). + * - If the RETURN REGISTER contains a value smaller than + * field 3, the read succeeded but the buffer was only partly + * filled. For interactive devices, this is the most common + * return value. + */ + retval = semihosting_read_fields(target, 3, fields); + if (retval != ERROR_OK) + return retval; + else { + int fd = semihosting_get_field(target, 0, fields); + uint64_t addr = semihosting_get_field(target, 1, fields); + size_t len = semihosting_get_field(target, 2, fields); + if (semihosting->is_fileio) { + semihosting->hit_fileio = true; + fileio_info->identifier = "read"; + fileio_info->param_1 = fd; + fileio_info->param_2 = addr; + fileio_info->param_3 = len; + } else { + uint8_t *buf = malloc(len); + if (!buf) { + semihosting->result = -1; + semihosting->sys_errno = ENOMEM; + } else { + semihosting->result = read(fd, buf, len); + semihosting->sys_errno = errno; + LOG_DEBUG("read(%d, 0x%" PRIx64 ", %zu)=%d", + fd, + addr, + len, + (int)semihosting->result); + if (semihosting->result >= 0) { + retval = target_write_buffer(target, addr, + semihosting->result, + buf); + if (retval != ERROR_OK) { + free(buf); + return retval; + } + /* the number of bytes NOT filled in */ + semihosting->result = len - + semihosting->result; + } + free(buf); + } + } + } + break; + + case SEMIHOSTING_SYS_READC: /* 0x07 */ + /* + * Reads a byte from the console. + * + * Entry + * The PARAMETER REGISTER must contain 0. There are no other + * parameters or values possible. + * + * Return + * On exit, the RETURN REGISTER contains the byte read from + * the console. + */ + if (semihosting->is_fileio) { + LOG_ERROR("SYS_READC not supported by semihosting fileio"); + return ERROR_FAIL; + } + semihosting->result = getchar(); + LOG_DEBUG("getchar()=%d", (int)semihosting->result); + break; + + case SEMIHOSTING_SYS_REMOVE: /* 0x0E */ + /* + * Deletes a specified file on the host filing system. + * + * Entry + * On entry, the PARAMETER REGISTER contains a pointer to a + * two-field argument block: + * - field 1 Points to a null-terminated string that gives the + * path name of the file to be deleted. + * - field 2 The length of the string. + * + * Return + * On exit, the RETURN REGISTER contains: + * - 0 if the delete is successful + * - A nonzero, host-specific error code if the delete fails. + */ + retval = semihosting_read_fields(target, 2, fields); + if (retval != ERROR_OK) + return retval; + else { + uint64_t addr = semihosting_get_field(target, 0, fields); + size_t len = semihosting_get_field(target, 1, fields); + if (semihosting->is_fileio) { + semihosting->hit_fileio = true; + fileio_info->identifier = "unlink"; + fileio_info->param_1 = addr; + fileio_info->param_2 = len; + } else { + uint8_t *fn = malloc(len+1); + if (!fn) { + semihosting->result = -1; + semihosting->sys_errno = ENOMEM; + } else { + retval = + target_read_memory(target, addr, 1, len, + fn); + if (retval != ERROR_OK) { + free(fn); + return retval; + } + fn[len] = 0; + semihosting->result = remove((char *)fn); + semihosting->sys_errno = errno; + LOG_DEBUG("remove('%s')=%d", fn, + (int)semihosting->result); + + free(fn); + } + } + } + break; + + case SEMIHOSTING_SYS_RENAME: /* 0x0F */ + /* + * Renames a specified file. + * + * Entry + * On entry, the PARAMETER REGISTER contains a pointer to a + * four-field data block: + * - field 1 A pointer to the name of the old file. + * - field 2 The length of the old filename. + * - field 3 A pointer to the new filename. + * - field 4 The length of the new filename. Both strings are + * null-terminated. + * + * Return + * On exit, the RETURN REGISTER contains: + * - 0 if the rename is successful. + * - A nonzero, host-specific error code if the rename fails. + */ + retval = semihosting_read_fields(target, 4, fields); + if (retval != ERROR_OK) + return retval; + else { + uint64_t addr1 = semihosting_get_field(target, 0, fields); + size_t len1 = semihosting_get_field(target, 1, fields); + uint64_t addr2 = semihosting_get_field(target, 2, fields); + size_t len2 = semihosting_get_field(target, 3, fields); + if (semihosting->is_fileio) { + semihosting->hit_fileio = true; + fileio_info->identifier = "rename"; + fileio_info->param_1 = addr1; + fileio_info->param_2 = len1; + fileio_info->param_3 = addr2; + fileio_info->param_4 = len2; + } else { + uint8_t *fn1 = malloc(len1+1); + uint8_t *fn2 = malloc(len2+1); + if (!fn1 || !fn2) { + semihosting->result = -1; + semihosting->sys_errno = ENOMEM; + } else { + retval = target_read_memory(target, addr1, 1, len1, + fn1); + if (retval != ERROR_OK) { + free(fn1); + free(fn2); + return retval; + } + retval = target_read_memory(target, addr2, 1, len2, + fn2); + if (retval != ERROR_OK) { + free(fn1); + free(fn2); + return retval; + } + fn1[len1] = 0; + fn2[len2] = 0; + semihosting->result = rename((char *)fn1, + (char *)fn2); + semihosting->sys_errno = errno; + LOG_DEBUG("rename('%s', '%s')=%d", fn1, fn2, + (int)semihosting->result); + + free(fn1); + free(fn2); + } + } + } + break; + + case SEMIHOSTING_SYS_SEEK: /* 0x0A */ + /* + * Seeks to a specified position in a file using an offset + * specified from the start of the file. The file is assumed + * to be a byte array and the offset is given in bytes. + * + * Entry + * On entry, the PARAMETER REGISTER contains a pointer to a + * two-field data block: + * - field 1 A handle for a seekable file object. + * - field 2 The absolute byte position to seek to. + * + * Return + * On exit, the RETURN REGISTER contains: + * - 0 if the request is successful. + * - A negative value if the request is not successful. + * Use SYS_ERRNO to read the value of the host errno variable + * describing the error. + * + * Note: The effect of seeking outside the current extent of + * the file object is undefined. + */ + retval = semihosting_read_fields(target, 2, fields); + if (retval != ERROR_OK) + return retval; + else { + int fd = semihosting_get_field(target, 0, fields); + off_t pos = semihosting_get_field(target, 1, fields); + if (semihosting->is_fileio) { + semihosting->hit_fileio = true; + fileio_info->identifier = "lseek"; + fileio_info->param_1 = fd; + fileio_info->param_2 = pos; + fileio_info->param_3 = SEEK_SET; + } else { + semihosting->result = lseek(fd, pos, SEEK_SET); + semihosting->sys_errno = errno; + LOG_DEBUG("lseek(%d, %d)=%d", fd, (int)pos, + (int)semihosting->result); + if (semihosting->result == pos) + semihosting->result = 0; + } + } + break; + + case SEMIHOSTING_SYS_SYSTEM: /* 0x12 */ + /* + * Passes a command to the host command-line interpreter. + * This enables you to execute a system command such as dir, + * ls, or pwd. The terminal I/O is on the host, and is not + * visible to the target. + * + * Entry + * On entry, the PARAMETER REGISTER contains a pointer to a + * two-field argument block: + * - field 1 Points to a string to be passed to the host + * command-line interpreter. + * - field 2 The length of the string. + * + * Return + * On exit, the RETURN REGISTER contains the return status. + */ + + /* Provide SYS_SYSTEM functionality. Uses the + * libc system command, there may be a reason *NOT* + * to use this, but as I can't think of one, I + * implemented it this way. + */ + retval = semihosting_read_fields(target, 2, fields); + if (retval != ERROR_OK) + return retval; + else { + uint64_t addr = semihosting_get_field(target, 0, fields); + size_t len = semihosting_get_field(target, 1, fields); + if (semihosting->is_fileio) { + semihosting->hit_fileio = true; + fileio_info->identifier = "system"; + fileio_info->param_1 = addr; + fileio_info->param_2 = len; + } else { + uint8_t *cmd = malloc(len+1); + if (!cmd) { + semihosting->result = -1; + semihosting->sys_errno = ENOMEM; + } else { + retval = target_read_memory(target, + addr, + 1, + len, + cmd); + if (retval != ERROR_OK) { + free(cmd); + return retval; + } else { + cmd[len] = 0; + semihosting->result = system( + (const char *)cmd); + LOG_DEBUG("system('%s')=%d", + cmd, + (int)semihosting->result); + } + + free(cmd); + } + } + } + break; + + case SEMIHOSTING_SYS_TIME: /* 0x11 */ + /* + * Returns the number of seconds since 00:00 January 1, 1970. + * This value is real-world time, regardless of any debug agent + * configuration. + * + * Entry + * There are no parameters. + * + * Return + * On exit, the RETURN REGISTER contains the number of seconds. + */ + semihosting->result = time(NULL); + break; + + case SEMIHOSTING_SYS_WRITE: /* 0x05 */ + /* + * Writes the contents of a buffer to a specified file at the + * current file position. The file position is specified either: + * - Explicitly, by a SYS_SEEK. + * - Implicitly as one byte beyond the previous SYS_READ or + * SYS_WRITE request. + * + * The file position is at the start of the file when the file + * is opened, and is lost when the file is closed. + * + * Perform the file operation as a single action whenever + * possible. For example, do not split a write of 16KB into + * four 4KB chunks unless there is no alternative. + * + * Entry + * On entry, the PARAMETER REGISTER contains a pointer to a + * three-field data block: + * - field 1 Contains a handle for a file previously opened + * with SYS_OPEN. + * - field 2 Points to the memory containing the data to be written. + * - field 3 Contains the number of bytes to be written from + * the buffer to the file. + * + * Return + * On exit, the RETURN REGISTER contains: + * - 0 if the call is successful. + * - The number of bytes that are not written, if there is an error. + */ + retval = semihosting_read_fields(target, 3, fields); + if (retval != ERROR_OK) + return retval; + else { + int fd = semihosting_get_field(target, 0, fields); + uint64_t addr = semihosting_get_field(target, 1, fields); + size_t len = semihosting_get_field(target, 2, fields); + if (semihosting->is_fileio) { + semihosting->hit_fileio = true; + fileio_info->identifier = "write"; + fileio_info->param_1 = fd; + fileio_info->param_2 = addr; + fileio_info->param_3 = len; + } else { + uint8_t *buf = malloc(len); + if (!buf) { + semihosting->result = -1; + semihosting->sys_errno = ENOMEM; + } else { + retval = target_read_buffer(target, addr, len, buf); + if (retval != ERROR_OK) { + free(buf); + return retval; + } + semihosting->result = write(fd, buf, len); + semihosting->sys_errno = errno; + LOG_DEBUG("write(%d, 0x%" PRIx64 ", %zu)=%d", + fd, + addr, + len, + (int)semihosting->result); + if (semihosting->result >= 0) { + /* The number of bytes that are NOT written. + * */ + semihosting->result = len - + semihosting->result; + } + + free(buf); + } + } + } + break; + + case SEMIHOSTING_SYS_WRITEC: /* 0x03 */ + /* + * Writes a character byte, pointed to by the PARAMETER REGISTER, + * to the debug channel. When executed under a semihosting + * debugger, the character appears on the host debugger console. + * + * Entry + * On entry, the PARAMETER REGISTER contains a pointer to the + * character. + * + * Return + * None. The RETURN REGISTER is corrupted. + */ + if (semihosting->is_fileio) { + semihosting->hit_fileio = true; + fileio_info->identifier = "write"; + fileio_info->param_1 = 1; + fileio_info->param_2 = semihosting->param; + fileio_info->param_3 = 1; + } else { + uint64_t addr = semihosting->param; + unsigned char c; + retval = target_read_memory(target, addr, 1, 1, &c); + if (retval != ERROR_OK) + return retval; + putchar(c); + semihosting->result = 0; + } + break; + + case SEMIHOSTING_SYS_WRITE0: /* 0x04 */ + /* + * Writes a null-terminated string to the debug channel. + * When executed under a semihosting debugger, the characters + * appear on the host debugger console. + * + * Entry + * On entry, the PARAMETER REGISTER contains a pointer to the + * first byte of the string. + * + * Return + * None. The RETURN REGISTER is corrupted. + */ + if (semihosting->is_fileio) { + size_t count = 0; + uint64_t addr = semihosting->param; + for (;; addr++) { + unsigned char c; + retval = target_read_memory(target, addr, 1, 1, &c); + if (retval != ERROR_OK) + return retval; + if (c == '\0') + break; + count++; + } + semihosting->hit_fileio = true; + fileio_info->identifier = "write"; + fileio_info->param_1 = 1; + fileio_info->param_2 = semihosting->param; + fileio_info->param_3 = count; + } else { + uint64_t addr = semihosting->param; + do { + unsigned char c; + retval = target_read_memory(target, addr++, 1, 1, &c); + if (retval != ERROR_OK) + return retval; + if (!c) + break; + putchar(c); + } while (1); + semihosting->result = 0; + } + break; + + case SEMIHOSTING_SYS_ELAPSED: /* 0x30 */ + /* + * Returns the number of elapsed target ticks since execution + * started. + * Use SYS_TICKFREQ to determine the tick frequency. + * + * Entry (32-bit) + * On entry, the PARAMETER REGISTER points to a two-field data + * block to be used for returning the number of elapsed ticks: + * - field 1 The least significant field and is at the low address. + * - field 2 The most significant field and is at the high address. + * + * Entry (64-bit) + * On entry the PARAMETER REGISTER points to a one-field data + * block to be used for returning the number of elapsed ticks: + * - field 1 The number of elapsed ticks as a 64-bit value. + * + * Return + * On exit: + * - On success, the RETURN REGISTER contains 0, the PARAMETER + * REGISTER is unchanged, and the data block pointed to by the + * PARAMETER REGISTER is filled in with the number of elapsed + * ticks. + * - On failure, the RETURN REGISTER contains -1, and the + * PARAMETER REGISTER contains -1. + * + * Note: Some semihosting implementations might not support this + * semihosting operation, and they always return -1 in the + * RETURN REGISTER. + */ + + case SEMIHOSTING_SYS_TICKFREQ: /* 0x31 */ + /* + * Returns the tick frequency. + * + * Entry + * The PARAMETER REGISTER must contain 0 on entry to this routine. + * + * Return + * On exit, the RETURN REGISTER contains either: + * - The number of ticks per second. + * - –1 if the target does not know the value of one tick. + * + * Note: Some semihosting implementations might not support + * this semihosting operation, and they always return -1 in the + * RETURN REGISTER. + */ + + case SEMIHOSTING_SYS_TMPNAM: /* 0x0D */ + /* + * Returns a temporary name for a file identified by a system + * file identifier. + * + * Entry + * On entry, the PARAMETER REGISTER contains a pointer to a + * three-word argument block: + * - field 1 A pointer to a buffer. + * - field 2 A target identifier for this filename. Its value + * must be an integer in the range 0-255. + * - field 3 Contains the length of the buffer. The length must + * be at least the value of L_tmpnam on the host system. + * + * Return + * On exit, the RETURN REGISTER contains: + * - 0 if the call is successful. + * - –1 if an error occurs. + * + * The buffer pointed to by the PARAMETER REGISTER contains + * the filename, prefixed with a suitable directory name. + * If you use the same target identifier again, the same + * filename is returned. + * + * Note: The returned string must be null-terminated. + */ + + default: + fprintf(stderr, "semihosting: unsupported call %#x\n", + (unsigned) semihosting->op); + semihosting->result = -1; + semihosting->sys_errno = ENOTSUP; + } + + if (!semihosting->hit_fileio) { + retval = semihosting->post_result(target); + if (retval != ERROR_OK) { + LOG_ERROR("Failed to post semihosting result"); + return retval; + } + } + + return ERROR_OK; +} + +/* ------------------------------------------------------------------------- + * Local functions. */ + +static int semihosting_common_fileio_info(struct target *target, + struct gdb_fileio_info *fileio_info) +{ + struct semihosting *semihosting = target->semihosting; + if (!semihosting) + return ERROR_FAIL; + + /* + * To avoid unnecessary duplication, semihosting prepares the + * fileio_info structure out-of-band when the target halts. See + * do_semihosting for more detail. + */ + if (!semihosting->is_fileio || !semihosting->hit_fileio) + return ERROR_FAIL; + + return ERROR_OK; +} + +static int semihosting_common_fileio_end(struct target *target, int result, + int fileio_errno, bool ctrl_c) +{ + struct gdb_fileio_info *fileio_info = target->fileio_info; + struct semihosting *semihosting = target->semihosting; + if (!semihosting) + return ERROR_FAIL; + + /* clear pending status */ + semihosting->hit_fileio = false; + + semihosting->result = result; + semihosting->sys_errno = fileio_errno; + + /* + * Some fileio results do not match up with what the semihosting + * operation expects; for these operations, we munge the results + * below: + */ + switch (semihosting->op) { + case SEMIHOSTING_SYS_WRITE: /* 0x05 */ + if (result < 0) + semihosting->result = fileio_info->param_3; + else + semihosting->result = 0; + break; + + case SEMIHOSTING_SYS_READ: /* 0x06 */ + if (result == (int)fileio_info->param_3) + semihosting->result = 0; + if (result <= 0) + semihosting->result = fileio_info->param_3; + break; + + case SEMIHOSTING_SYS_SEEK: /* 0x0a */ + if (result > 0) + semihosting->result = 0; + break; + } + + return semihosting->post_result(target); +} + +/** + * Read all fields of a command from target to buffer. + */ +static int semihosting_read_fields(struct target *target, size_t number, + uint8_t *fields) +{ + struct semihosting *semihosting = target->semihosting; + /* Use 4-byte multiples to trigger fast memory access. */ + return target_read_memory(target, semihosting->param, 4, + number * (semihosting->word_size_bytes / 4), fields); +} + +/** + * Write all fields of a command from buffer to target. + */ +static int semihosting_write_fields(struct target *target, size_t number, + uint8_t *fields) +{ + struct semihosting *semihosting = target->semihosting; + /* Use 4-byte multiples to trigger fast memory access. */ + return target_write_memory(target, semihosting->param, 4, + number * (semihosting->word_size_bytes / 4), fields); +} + +/** + * Extract a field from the buffer, considering register size and endianness. + */ +static uint64_t semihosting_get_field(struct target *target, size_t index, + uint8_t *fields) +{ + struct semihosting *semihosting = target->semihosting; + if (semihosting->word_size_bytes == 8) + return target_buffer_get_u64(target, fields + (index * 8)); + else + return target_buffer_get_u32(target, fields + (index * 4)); +} + +/** + * Store a field in the buffer, considering register size and endianness. + */ +static void semihosting_set_field(struct target *target, uint64_t value, + size_t index, + uint8_t *fields) +{ + struct semihosting *semihosting = target->semihosting; + if (semihosting->word_size_bytes == 8) + target_buffer_set_u64(target, fields + (index * 8), value); + else + target_buffer_set_u32(target, fields + (index * 4), value); +} + + +/* ------------------------------------------------------------------------- + * Common semihosting commands handlers. */ + +__COMMAND_HANDLER(handle_common_semihosting_command) +{ + struct target *target = get_current_target(CMD_CTX); + + if (target == NULL) { + LOG_ERROR("No target selected"); + return ERROR_FAIL; + } + + struct semihosting *semihosting = target->semihosting; + if (!semihosting) { + command_print(CMD_CTX, "semihosting not supported for current target"); + return ERROR_FAIL; + } + + if (CMD_ARGC > 0) { + int is_active; + + COMMAND_PARSE_ENABLE(CMD_ARGV[0], is_active); + + if (!target_was_examined(target)) { + LOG_ERROR("Target not examined yet"); + return ERROR_FAIL; + } + + if (semihosting && semihosting->setup(target, is_active) != ERROR_OK) { + LOG_ERROR("Failed to Configure semihosting"); + return ERROR_FAIL; + } + + /* FIXME never let that "catch" be dropped! (???) */ + semihosting->is_active = is_active; + } + + command_print(CMD_CTX, "semihosting is %s", + semihosting->is_active + ? "enabled" : "disabled"); + + return ERROR_OK; +} + + +__COMMAND_HANDLER(handle_common_semihosting_fileio_command) +{ + struct target *target = get_current_target(CMD_CTX); + + if (target == NULL) { + LOG_ERROR("No target selected"); + return ERROR_FAIL; + } + + struct semihosting *semihosting = target->semihosting; + if (!semihosting) { + command_print(CMD_CTX, "semihosting not supported for current target"); + return ERROR_FAIL; + } + + if (!semihosting->is_active) { + command_print(CMD_CTX, "semihosting not yet enabled for current target"); + return ERROR_FAIL; + } + + if (CMD_ARGC > 0) + COMMAND_PARSE_ENABLE(CMD_ARGV[0], semihosting->is_fileio); + + command_print(CMD_CTX, "semihosting fileio is %s", + semihosting->is_fileio + ? "enabled" : "disabled"); + + return ERROR_OK; +} + +__COMMAND_HANDLER(handle_common_semihosting_cmdline) +{ + struct target *target = get_current_target(CMD_CTX); + unsigned int i; + + if (target == NULL) { + LOG_ERROR("No target selected"); + return ERROR_FAIL; + } + + struct semihosting *semihosting = target->semihosting; + if (!semihosting) { + command_print(CMD_CTX, "semihosting not supported for current target"); + return ERROR_FAIL; + } + + free(semihosting->cmdline); + semihosting->cmdline = CMD_ARGC > 0 ? strdup(CMD_ARGV[0]) : NULL; + + for (i = 1; i < CMD_ARGC; i++) { + char *cmdline = alloc_printf("%s %s", semihosting->cmdline, CMD_ARGV[i]); + if (cmdline == NULL) + break; + free(semihosting->cmdline); + semihosting->cmdline = cmdline; + } + + command_print(CMD_CTX, "semihosting command line is [%s]", + semihosting->cmdline); + + return ERROR_OK; +} + +__COMMAND_HANDLER(handle_common_semihosting_resumable_exit_command) +{ + struct target *target = get_current_target(CMD_CTX); + + if (target == NULL) { + LOG_ERROR("No target selected"); + return ERROR_FAIL; + } + + struct semihosting *semihosting = target->semihosting; + if (!semihosting) { + command_print(CMD_CTX, "semihosting not supported for current target"); + return ERROR_FAIL; + } + + if (!semihosting->is_active) { + command_print(CMD_CTX, "semihosting not yet enabled for current target"); + return ERROR_FAIL; + } + + if (CMD_ARGC > 0) + COMMAND_PARSE_ENABLE(CMD_ARGV[0], semihosting->has_resumable_exit); + + command_print(CMD_CTX, "semihosting resumable exit is %s", + semihosting->has_resumable_exit + ? "enabled" : "disabled"); + + return ERROR_OK; +} diff --git a/src/target/semihosting_common.h b/src/target/semihosting_common.h new file mode 100644 index 0000000..8fb5e0c --- /dev/null +++ b/src/target/semihosting_common.h @@ -0,0 +1,163 @@ +/*************************************************************************** + * Copyright (C) 2018 by Liviu Ionescu * + * <ilg@livius.net> * + * * + * Copyright (C) 2009 by Marvell Technology Group Ltd. * + * Written by Nicolas Pitre <nico@marvell.com> * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * + ***************************************************************************/ + +#ifndef OPENOCD_TARGET_SEMIHOSTING_COMMON_H +#define OPENOCD_TARGET_SEMIHOSTING_COMMON_H + +#include <stdint.h> +#include <stdbool.h> +#include <time.h> + +/* + * According to: + * "Semihosting for AArch32 and AArch64, Release 2.0" + * https://static.docs.arm.com/100863/0200/semihosting.pdf + * from ARM Ltd. + * + * The available semihosting operation numbers passed in R0 are allocated + * as follows: + * - 0x00-0x31 Used by ARM. + * - 0x32-0xFF Reserved for future use by ARM. + * - 0x100-0x1FF Reserved for user applications. These are not used by ARM. + * However, if you are writing your own SVC operations, you are advised + * to use a different SVC number rather than using the semihosted + * SVC number and these operation type numbers. + * - 0x200-0xFFFFFFFF Undefined and currently unused. It is recommended + * that you do not use these. + */ + +enum semihosting_operation_numbers { + /* + * ARM semihosting operations, in lexicographic order. + */ + SEMIHOSTING_ENTER_SVC = 0x17, /* DEPRECATED */ + + SEMIHOSTING_SYS_CLOSE = 0x02, + SEMIHOSTING_SYS_CLOCK = 0x10, + SEMIHOSTING_SYS_ELAPSED = 0x30, + SEMIHOSTING_SYS_ERRNO = 0x13, + SEMIHOSTING_SYS_EXIT = 0x18, + SEMIHOSTING_SYS_EXIT_EXTENDED = 0x20, + SEMIHOSTING_SYS_FLEN = 0x0C, + SEMIHOSTING_SYS_GET_CMDLINE = 0x15, + SEMIHOSTING_SYS_HEAPINFO = 0x16, + SEMIHOSTING_SYS_ISERROR = 0x08, + SEMIHOSTING_SYS_ISTTY = 0x09, + SEMIHOSTING_SYS_OPEN = 0x01, + SEMIHOSTING_SYS_READ = 0x06, + SEMIHOSTING_SYS_READC = 0x07, + SEMIHOSTING_SYS_REMOVE = 0x0E, + SEMIHOSTING_SYS_RENAME = 0x0F, + SEMIHOSTING_SYS_SEEK = 0x0A, + SEMIHOSTING_SYS_SYSTEM = 0x12, + SEMIHOSTING_SYS_TICKFREQ = 0x31, + SEMIHOSTING_SYS_TIME = 0x11, + SEMIHOSTING_SYS_TMPNAM = 0x0D, + SEMIHOSTING_SYS_WRITE = 0x05, + SEMIHOSTING_SYS_WRITEC = 0x03, + SEMIHOSTING_SYS_WRITE0 = 0x04, +}; + +/* + * Codes used by SEMIHOSTING_SYS_EXIT (formerly + * SEMIHOSTING_REPORT_EXCEPTION). + * On 64-bits, the exit code is passed explicitly. + */ +enum semihosting_reported_exceptions { + /* On 32 bits, use it for exit(0) */ + ADP_STOPPED_APPLICATION_EXIT = ((2 << 16) + 38), + /* On 32 bits, use it for exit(1) */ + ADP_STOPPED_RUN_TIME_ERROR = ((2 << 16) + 35), +}; + +struct target; + +/* + * A pointer to this structure was added to the target structure. + */ +struct semihosting { + + /** A flag reporting whether semihosting is active. */ + bool is_active; + + /** A flag reporting whether semihosting fileio is active. */ + bool is_fileio; + + /** A flag reporting whether semihosting fileio operation is active. */ + bool hit_fileio; + + /** Most are resumable, except the two exit calls. */ + bool is_resumable; + + /** + * When SEMIHOSTING_SYS_EXIT is called outside a debug session, + * things are simple, the openocd process calls exit() and passes + * the value returned by the target. + * When SEMIHOSTING_SYS_EXIT is called during a debug session, + * by default execution returns to the debugger, leaving the + * debugger in a HALT state, similar to the state entered when + * encountering a break. + * In some use cases, it is useful to have SEMIHOSTING_SYS_EXIT + * return normally, as any semihosting call, and do not break + * to the debugger. + * The standard allows this to happen, but the condition + * to trigger it is a bit obscure ("by performing an RDI_Execute + * request or equivalent"). + * + * To make the SEMIHOSTING_SYS_EXIT call return normally, enable + * this variable via the dedicated command (default: disabled). + */ + bool has_resumable_exit; + + /** The Target (hart) word size; 8 for 64-bits targets. */ + size_t word_size_bytes; + + /** The current semihosting operation (R0 on ARM). */ + int op; + + /** The current semihosting parameter (R1 or ARM). */ + uint64_t param; + + /** + * The current semihosting result to be returned to the application. + * Usually 0 for success, -1 for error, + * but sometimes a useful value, even a pointer. + */ + int64_t result; + + /** The value to be returned by semihosting SYS_ERRNO request. */ + int sys_errno; + + /** The semihosting command line to be passed to the target. */ + char *cmdline; + + /** The current time when 'execution starts' */ + clock_t setup_time; + + int (*setup)(struct target *target, int enable); + int (*post_result)(struct target *target); +}; + +int semihosting_common_init(struct target *target, void *setup, + void *post_result); +int semihosting_common(struct target *target); + +#endif /* OPENOCD_TARGET_SEMIHOSTING_COMMON_H */ diff --git a/src/target/target.c b/src/target/target.c index 890f727..8240e65 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -1895,6 +1895,9 @@ static void target_destroy(struct target *target) if (target->type->deinit_target) target->type->deinit_target(target); + if (target->semihosting) + free(target->semihosting); + jtag_unregister_event_callback(jtag_enable_callback, target); struct target_event_action *teap = target->event_action; @@ -4143,8 +4146,9 @@ static int target_mem2array(Jim_Interp *interp, struct target *target, int argc, * argv[3] = memory address * argv[4] = count of times to read */ + if (argc < 4 || argc > 5) { - Jim_WrongNumArgs(interp, 1, argv, "varname width addr nelems [phys]"); + Jim_WrongNumArgs(interp, 0, argv, "varname width addr nelems [phys]"); return JIM_ERR; } varname = Jim_GetString(argv[0], &len); @@ -5448,21 +5452,19 @@ static const struct command_registration target_instance_command_handlers[] = { .mode = COMMAND_EXEC, .jim_handler = jim_target_examine, .help = "used internally for reset processing", - .usage = "arp_examine ['allow-defer']", + .usage = "['allow-defer']", }, { .name = "was_examined", .mode = COMMAND_EXEC, .jim_handler = jim_target_was_examined, .help = "used internally for reset processing", - .usage = "was_examined", }, { .name = "examine_deferred", .mode = COMMAND_EXEC, .jim_handler = jim_target_examine_deferred, .help = "used internally for reset processing", - .usage = "examine_deferred", }, { .name = "arp_halt_gdb", @@ -6429,7 +6431,7 @@ static const struct command_registration target_exec_command_handlers[] = { .handler = handle_bp_command, .mode = COMMAND_EXEC, .help = "list or set hardware or software breakpoint", - .usage = "<address> [<asid>]<length> ['hw'|'hw_ctx']", + .usage = "<address> [<asid>] <length> ['hw'|'hw_ctx']", }, { .name = "rbp", diff --git a/src/target/target.h b/src/target/target.h index c5fb55b..51a5b69 100644 --- a/src/target/target.h +++ b/src/target/target.h @@ -205,6 +205,9 @@ struct target { /* file-I/O information for host to do syscall */ struct gdb_fileio_info *fileio_info; + + /* The semihosting information, extracted from the target. */ + struct semihosting *semihosting; }; struct target_list { @@ -214,10 +217,10 @@ struct target_list { struct gdb_fileio_info { char *identifier; - uint32_t param_1; - uint32_t param_2; - uint32_t param_3; - uint32_t param_4; + uint64_t param_1; + uint64_t param_2; + uint64_t param_3; + uint64_t param_4; }; /** Returns the instance-specific name of the specified target. */ diff --git a/tcl/board/8devices-lima.cfg b/tcl/board/8devices-lima.cfg new file mode 100644 index 0000000..136f861 --- /dev/null +++ b/tcl/board/8devices-lima.cfg @@ -0,0 +1,30 @@ +# Product page: +# https://www.8devices.com/products/lima +# +# Location of JTAG pins: +# J2 GPIO0 JTAG TCK +# J2 GPIO1 JTAG TDI +# J2 GPIO2 JTAG TDO +# J2 GPIO3 JTAG TMS +# J2 RST directly connected to RESET_L of the SoC and can be used as +# JTAG SRST. Note: this pin will also reset the debug engine. +# J1 +3,3V Can be use as JTAG Vref +# J1 or J2 GND Can be used for JTAG GND +# +# This board is powered from mini USB connecter which is also used +# as USB to UART converted based on FTDI FT230XQ chip + +source [find target/qualcomm_qca4531.cfg] + +proc board_init { } { + qca4531_ddr2_550_550_init +} + +$_TARGETNAME configure -event reset-init { + board_init +} + +set ram_boot_address 0xa0000000 +$_TARGETNAME configure -work-area-phys 0xa1FFE000 -work-area-size 0x1000 + +flash bank flash0 ath79 0 0 0 0 $_TARGETNAME cs0 diff --git a/tcl/board/atmel_samd10_xplained_mini.cfg b/tcl/board/atmel_samd10_xplained_mini.cfg new file mode 100644 index 0000000..64ae11e --- /dev/null +++ b/tcl/board/atmel_samd10_xplained_mini.cfg @@ -0,0 +1,10 @@ +# +# Atmel SAMD10 Xplained mini evaluation kit. +# http://www.atmel.com/tools/atsamd10-xmini.aspx + +source [find interface/cmsis-dap.cfg] + +# chip name +set CHIPNAME at91samd10d14 + +source [find target/at91samdXX.cfg] diff --git a/tcl/board/atmel_samd11_xplained_pro.cfg b/tcl/board/atmel_samd11_xplained_pro.cfg new file mode 100644 index 0000000..8ce9751 --- /dev/null +++ b/tcl/board/atmel_samd11_xplained_pro.cfg @@ -0,0 +1,10 @@ +# +# Atmel SAMD11 Xplained Pro evaluation kit. +# + +source [find interface/cmsis-dap.cfg] + +# chip name +set CHIPNAME at91samd11d14 + +source [find target/at91samdXX.cfg] diff --git a/tcl/board/dptechnics_dpt-board-v1.cfg b/tcl/board/dptechnics_dpt-board-v1.cfg new file mode 100644 index 0000000..de31c7c --- /dev/null +++ b/tcl/board/dptechnics_dpt-board-v1.cfg @@ -0,0 +1,32 @@ +# Product page: +# https://www.dptechnics.com/en/products/dpt-board-v1.html +# +# JTAG is a 5 pin array located close to main module in following order: +# 1. JTAG TCK +# 2. JTAG TDO +# 3. JTAG TDI +# 4. JTAG TMS +# 5. GND The GND is located near letter G of word JTAG on board. +# +# Two RST pins are connected to: +# 1. GND +# 2. GPIO11 this pin is located near letter R of word RST. +# +# To enable EJTAG mode, GPIO11 (RST[1]) pin should be pulled up. For example +# with 10K resistor connected to V3.3 pin. +# +# This board is powered from micro USB connector. No real reset pin or button, for +# example RESET_L is available. + +source [find target/atheros_ar9331.cfg] + +$_TARGETNAME configure -event reset-init { + ar9331_25mhz_pll_init + sleep 1 + ar9331_ddr2_init +} + +set ram_boot_address 0xa0000000 +$_TARGETNAME configure -work-area-phys 0xa1FFE000 -work-area-size 0x1000 + +flash bank flash0 ath79 0 0 0 0 $_TARGETNAME cs0 diff --git a/tcl/board/nxp_frdm-ls1012a.cfg b/tcl/board/nxp_frdm-ls1012a.cfg new file mode 100644 index 0000000..3973b3c --- /dev/null +++ b/tcl/board/nxp_frdm-ls1012a.cfg @@ -0,0 +1,15 @@ +# +# NXP FRDM-LS1012A (Freedom) +# + +# +# NXP Kinetis K20 +# +source [find interface/cmsis-dap.cfg] +transport select jtag + +# Also offers a 10-pin 0.05" CoreSight JTAG connector. + +source [find target/ls1012a.cfg] + +reset_config srst_only diff --git a/tcl/board/reflexces_achilles_i-dev_kit_arria10.cfg b/tcl/board/reflexces_achilles_i-dev_kit_arria10.cfg new file mode 100644 index 0000000..a6e8065 --- /dev/null +++ b/tcl/board/reflexces_achilles_i-dev_kit_arria10.cfg @@ -0,0 +1,13 @@ +# Achilles Instant-Development Kit Arria 10 SoC SoM +# https://www.reflexces.com/products-solutions/achilles-instant-development-kit-arria-10-soc-som +# + +if { [info exists USE_EXTERNAL_DEBUGGER] } { + echo "Using external debugger" +} else { + source [find interface/altera-usb-blaster2.cfg] + usb_blaster_device_desc "Arria10 IDK" +} + +source [find fpga/altera-10m50.cfg] +source [find target/altera_fpgasoc_arria10.cfg] diff --git a/tcl/board/renesas_gen2_common.cfg b/tcl/board/renesas_gen2_common.cfg new file mode 100644 index 0000000..00fa777 --- /dev/null +++ b/tcl/board/renesas_gen2_common.cfg @@ -0,0 +1,14 @@ +# Renesas R-Car Gen2 Evaluation Board common settings + +reset_config trst_and_srst srst_nogate + +proc init_reset {mode} { + # Assert both resets: equivalent to a power-on reset + jtag_reset 1 1 + + # Deassert TRST to begin TAP communication + jtag_reset 0 1 + + # TAP should now be responsive, validate the scan-chain + jtag arp_init +} diff --git a/tcl/board/renesas_porter.cfg b/tcl/board/renesas_porter.cfg new file mode 100644 index 0000000..c8032f5 --- /dev/null +++ b/tcl/board/renesas_porter.cfg @@ -0,0 +1,4 @@ +# Renesas R-Car M2 Evaluation Board + +source [find target/renesas_r8a7791.cfg] +source [find board/renesas_gen2_common.cfg] diff --git a/tcl/board/renesas_silk.cfg b/tcl/board/renesas_silk.cfg new file mode 100644 index 0000000..a026537 --- /dev/null +++ b/tcl/board/renesas_silk.cfg @@ -0,0 +1,4 @@ +# Renesas R-Car E2 Evaluation Board + +source [find target/renesas_r8a7794.cfg] +source [find board/renesas_gen2_common.cfg] diff --git a/tcl/board/renesas_stout.cfg b/tcl/board/renesas_stout.cfg new file mode 100644 index 0000000..d35f874 --- /dev/null +++ b/tcl/board/renesas_stout.cfg @@ -0,0 +1,4 @@ +# Renesas R-Car H2 Evaluation Board + +source [find target/renesas_r8a7790.cfg] +source [find board/renesas_gen2_common.cfg] diff --git a/tcl/board/st_nucleo_f7.cfg b/tcl/board/st_nucleo_f7.cfg index 88a8a30..f94679b 100644 --- a/tcl/board/st_nucleo_f7.cfg +++ b/tcl/board/st_nucleo_f7.cfg @@ -1,7 +1,7 @@ # STMicroelectronics STM32F7 Nucleo development board # Known boards: NUCLEO-F746ZG and NUCLEO-F767ZI -source [find interface/stlink-v2-1.cfg] +source [find interface/stlink.cfg] transport select hla_swd diff --git a/tcl/board/st_nucleo_h743zi.cfg b/tcl/board/st_nucleo_h743zi.cfg index baedeb6..cfe2cda 100644 --- a/tcl/board/st_nucleo_h743zi.cfg +++ b/tcl/board/st_nucleo_h743zi.cfg @@ -1,7 +1,7 @@ # This is an ST NUCLEO-H743ZI board with single STM32H743ZI chip. # http://www.st.com/en/evaluation-tools/nucleo-h743zi.html -source [find interface/stlink-v2-1.cfg] +source [find interface/stlink.cfg] transport select hla_swd diff --git a/tcl/board/st_nucleo_l073rz.cfg b/tcl/board/st_nucleo_l073rz.cfg index fa9dc87..b32f8d5 100644 --- a/tcl/board/st_nucleo_l073rz.cfg +++ b/tcl/board/st_nucleo_l073rz.cfg @@ -1,6 +1,6 @@ # This is an ST NUCLEO-L073RZ board with single STM32L073RZ chip. # http://www.st.com/en/evaluation-tools/nucleo-l073rz.html -source [find interface/stlink-v2-1.cfg] +source [find interface/stlink.cfg] transport select hla_swd diff --git a/tcl/board/stm32h7x3i_eval.cfg b/tcl/board/stm32h7x3i_eval.cfg index 2949ded..caf68b6 100644 --- a/tcl/board/stm32h7x3i_eval.cfg +++ b/tcl/board/stm32h7x3i_eval.cfg @@ -4,7 +4,7 @@ # This is an ST EVAL-H753XI board with single STM32H753XI chip. # http://www.st.com/en/evaluation-tools/stm32h753i-eval.html -source [find interface/stlink-v2-1.cfg] +source [find interface/stlink.cfg] transport select hla_swd diff --git a/tcl/board/ti_cc13x0_launchpad.cfg b/tcl/board/ti_cc13x0_launchpad.cfg new file mode 100644 index 0000000..9e1c1ea --- /dev/null +++ b/tcl/board/ti_cc13x0_launchpad.cfg @@ -0,0 +1,7 @@ +# +# TI CC13x0 LaunchPad Evaluation Kit +# +source [find interface/xds110.cfg] +transport select jtag +adapter_khz 2500 +source [find target/ti_cc13x0.cfg] diff --git a/tcl/board/ti_cc13x2_launchpad.cfg b/tcl/board/ti_cc13x2_launchpad.cfg new file mode 100644 index 0000000..18c5ce5 --- /dev/null +++ b/tcl/board/ti_cc13x2_launchpad.cfg @@ -0,0 +1,7 @@ +# +# TI CC13x2 LaunchPad Evaluation Kit +# +source [find interface/xds110.cfg] +adapter_khz 2500 +transport select jtag +source [find target/ti_cc13x2.cfg] diff --git a/tcl/board/ti_cc26x0_launchpad.cfg b/tcl/board/ti_cc26x0_launchpad.cfg new file mode 100644 index 0000000..3613a47 --- /dev/null +++ b/tcl/board/ti_cc26x0_launchpad.cfg @@ -0,0 +1,7 @@ +# +# TI CC26x0 LaunchPad Evaluation Kit +# +source [find interface/xds110.cfg] +adapter_khz 2500 +transport select jtag +source [find target/ti_cc26x0.cfg] diff --git a/tcl/board/ti_cc26x2_launchpad.cfg b/tcl/board/ti_cc26x2_launchpad.cfg new file mode 100644 index 0000000..2f2b34b --- /dev/null +++ b/tcl/board/ti_cc26x2_launchpad.cfg @@ -0,0 +1,7 @@ +# +# TI CC26x2 LaunchPad Evaluation Kit +# +source [find interface/xds110.cfg] +adapter_khz 2500 +transport select jtag +source [find target/ti_cc26x2.cfg] diff --git a/tcl/board/ti_cc3220sf_launchpad.cfg b/tcl/board/ti_cc3220sf_launchpad.cfg new file mode 100644 index 0000000..a3dac62 --- /dev/null +++ b/tcl/board/ti_cc3220sf_launchpad.cfg @@ -0,0 +1,7 @@ +# +# TI CC3220SF-LaunchXL LaunchPad Evaluation Kit +# +source [find interface/xds110.cfg] +adapter_khz 2500 +transport select swd +source [find target/ti_cc3220sf.cfg] diff --git a/tcl/board/ti_cc32xx_launchpad.cfg b/tcl/board/ti_cc32xx_launchpad.cfg new file mode 100644 index 0000000..f657bdf --- /dev/null +++ b/tcl/board/ti_cc32xx_launchpad.cfg @@ -0,0 +1,7 @@ +# +# TI CC32xx-LaunchXL LaunchPad Evaluation Kit +# +source [find interface/xds110.cfg] +adapter_khz 2500 +transport select swd +source [find target/ti_cc32xx.cfg] diff --git a/tcl/board/ti_msp432_launchpad.cfg b/tcl/board/ti_msp432_launchpad.cfg new file mode 100644 index 0000000..bfad322 --- /dev/null +++ b/tcl/board/ti_msp432_launchpad.cfg @@ -0,0 +1,7 @@ +# +# TI MSP432 LaunchPad Evaluation Kit +# +source [find interface/xds110.cfg] +adapter_khz 2500 +transport select swd +source [find target/ti_msp432.cfg] diff --git a/tcl/board/tp-link_tl-mr3020.cfg b/tcl/board/tp-link_tl-mr3020.cfg index 7e040b3..48fb698 100644 --- a/tcl/board/tp-link_tl-mr3020.cfg +++ b/tcl/board/tp-link_tl-mr3020.cfg @@ -1,39 +1,5 @@ source [find target/atheros_ar9331.cfg] -proc ar9331_25mhz_pll_init {} { - mww 0xb8050008 0x00018004 ;# bypass PLL; AHB_POST_DIV - ratio 4 - mww 0xb8050004 0x00000352 ;# 34000(ns)/40ns(25MHz) = 0x352 (850) - mww 0xb8050000 0x40818000 ;# Power down control for CPU PLL - ;# OUTDIV | REFDIV | DIV_INT - mww 0xb8050010 0x001003e8 ;# CPU PLL Dither FRAC Register - ;# (disabled?) - mww 0xb8050000 0x00818000 ;# Power on | OUTDIV | REFDIV | DIV_INT - mww 0xb8050008 0x00008000 ;# remove bypass; - ;# AHB_POST_DIV - ratio 2 -} - -proc ar9331_ddr1_init {} { - mww 0xb8000000 0x7fbc8cd0 ;# DDR_CONFIG - lots of DRAM confs - mww 0xb8000004 0x9dd0e6a8 ;# DDR_CONFIG2 - more DRAM confs - - mww 0xb8000010 0x8 ;# Forces a PRECHARGE ALL cycle - mww 0xb8000008 0x133 ;# mode reg: 0x133 - default - mww 0xb8000010 0x1 ;# Forces an MRS update cycl - mww 0xb800000c 0x2 ;# Extended mode register value. - ;# default 0x2 - Reset to weak driver, DLL on - mww 0xb8000010 0x2 ;# Forces an EMRS update cycle - mww 0xb8000010 0x8 ;# Forces a PRECHARGE ALL cycle - mww 0xb8000008 0x33 ;# mode reg: remove some bit? - mww 0xb8000010 0x1 ;# Forces an MRS update cycl - mww 0xb8000014 0x4186 ;# enable refres: bit(14) - set refresh rate - mww 0xb800001c 0x8 ;# This register is used along with DQ Lane 0, - ;# DQ[7:0], DQS_0 - mww 0xb8000020 0x9 ;# This register is used along with DQ Lane 1, - ;# DQ[15:8], DQS_1. - mww 0xb8000018 0xff ;# DDR read and capture bit mask. - ;# Each bit represents a cycle of valid data. -} - $_TARGETNAME configure -event reset-init { ar9331_25mhz_pll_init sleep 1 diff --git a/tcl/fpga/altera-10m50.cfg b/tcl/fpga/altera-10m50.cfg index 9d00daa..d5af710 100644 --- a/tcl/fpga/altera-10m50.cfg +++ b/tcl/fpga/altera-10m50.cfg @@ -1,6 +1,22 @@ -# Altera MAX10 10M50SAE144C8GES FPGA # see MAX 10 FPGA Device Architecture # Table 3-1: IDCODE Information for MAX 10 Devices -# Version Part Number Manuf. ID LSB -# 0000 0011 0001 1000 0101 000 0110 1110 1 -jtag newtap 10m50 tap -expected-id 0x031850dd -irlen 10 +# Intel MAX 10M02 0x31810dd +# Intel MAX 10M04 0x318a0dd +# Intel MAX 10M08 0x31820dd +# Intel MAX 10M16 0x31830dd +# Intel MAX 10M25 0x31840dd +# Intel MAX 10M40 0x318d0dd +# Intel MAX 10M50 0x31850dd +# Intel MAX 10M02 0x31010dd +# Intel MAX 10M04 0x310a0dd +# Intel MAX 10M08 0x31020dd +# Intel MAX 10M16 0x31030dd +# Intel MAX 10M25 0x31040dd +# Intel MAX 10M40 0x310d0dd +# Intel MAX 10M50 0x31050dd + +jtag newtap 10m50 tap -irlen 10 -expected-id 0x31810dd -expected-id 0x318a0dd \ + -expected-id 0x31820dd -expected-id 0x31830dd -expected-id 0x31840dd \ + -expected-id 0x318d0dd -expected-id 0x31850dd -expected-id 0x31010dd \ + -expected-id 0x310a0dd -expected-id 0x31020dd -expected-id 0x31030dd \ + -expected-id 0x31040dd -expected-id 0x310d0dd -expected-id 0x31050dd diff --git a/tcl/interface/xds110.cfg b/tcl/interface/xds110.cfg new file mode 100644 index 0000000..495e202 --- /dev/null +++ b/tcl/interface/xds110.cfg @@ -0,0 +1,12 @@ +# +# Texas Instruments XDS110 +# +# http://processors.wiki.ti.com/index.php/XDS110 +# http://processors.wiki.ti.com/index.php/Emulation_Software_Package#XDS110_Support_Utilities +# + +interface xds110 + +# Use serial number option to use a specific XDS110 +# when more than one are connected to the host. +#xds110_serial 00000000 diff --git a/tcl/target/allwinner_v3s.cfg b/tcl/target/allwinner_v3s.cfg new file mode 100644 index 0000000..32fd188 --- /dev/null +++ b/tcl/target/allwinner_v3s.cfg @@ -0,0 +1,71 @@ +# This is the config for an Allwinner V3/V3s (sun8iw8). +# +# Notes: +# - Single core ARM Cortex-A7 with a maximum frequency of 1.2 GHz. +# - Thumb-2 Technology +# - Support NEON Advanced SIMD(Single Instruction Multiple Data)instruction +# for acceleration of media and signal processing functions +# - Support Large Physical Address Extensions(LPAE) +# - VFPv4 Floating Point Unit +# - 32KB L1 Instruction cache and 32KB L1 Data cache +# - 128KB L2 cache +# - has some integrated DDR2 RAM. +# +# Pins related for debug and bootstrap: +# JTAG +# JTAG_TMS PF0, SDC0_D1 +# JTAG_TDI PF1, SDC0_D0 +# JTAG_TDO PF3, SDC0_CMD +# JTAG_TCK PF5, SDC0_D2 +# UART +# None of UART ports seems to be enabled by ROM. +# UART0_TX PF2, SDC0_CLK Per default disabled +# UART0_RX PF4, SDC0_D3 Per default disabled +# UART1_TX PE21 Per default disabled +# UART1_RX PE22 Per default disabled +# UART2_TX PB0 Per default disabled +# UART2_RX PB1 Per default disabled +# +# JTAG is enabled by default after power on on listed JTAG_* pins. So far the +# boot sequence is: +# Time Action +# 0000ms Power ON +# 0200ms JTAG enabled +# 0220ms JTAG pins switched to SD mode +# +# The time frame of 20ms can be not enough to init and halt the CPU. In this +# case I would recommend to set: "adapter_khz 15000" +# To get more or less precise timings, the board should provide reset pin, +# or some bench power supply with remote function. In my case I used +# EEZ H24005 with this command to power on and halt the target: +# "exec echo "*TRG" > /dev/ttyACM0; sleep 220; reset halt" +# After this it is possible to enable JTAG mode again from boot loader or OS. +# Following DAPs are available: +# dap[0]->MEM-AP AHB +# dap[1]->MEM-AP APB->CA7[0] +# + +if { [info exists CHIPNAME] } { + set _CHIPNAME $CHIPNAME +} else { + set _CHIPNAME v3s +} + +if { [info exists DAP_TAPID] } { + set _DAP_TAPID $DAP_TAPID +} else { + set _DAP_TAPID 0x5ba00477 +} + +# No NRST or SRST is present on the SoC. Boards may provide +# some sort of Power cycle reset for complete board or SoC. +# For this case we provide srst_pulls_trst so the board config +# only needs to set srst_only. +reset_config none srst_pulls_trst + +jtag newtap $_CHIPNAME dap -irlen 4 -ircapture 0x01 -irmask 0x0f \ + -expected-id $_DAP_TAPID + +# Add Cortex A7 core +set _TARGETNAME $_CHIPNAME.cpu +target create $_TARGETNAME cortex_a -chain-position $_CHIPNAME.dap diff --git a/tcl/target/altera_fpgasoc_arria10.cfg b/tcl/target/altera_fpgasoc_arria10.cfg new file mode 100644 index 0000000..c9c5ab6 --- /dev/null +++ b/tcl/target/altera_fpgasoc_arria10.cfg @@ -0,0 +1,56 @@ +# Intel (Altera) Arria10 FPGA SoC + +if { [info exists CHIPNAME] } { + set _CHIPNAME $CHIPNAME +} else { + set _CHIPNAME arria10 +} + +# ARM CoreSight Debug Access Port (dap HPS) +if { [info exists DAP_TAPID] } { + set _DAP_TAPID $DAP_TAPID +} else { + set _DAP_TAPID 0x4ba00477 +} +jtag newtap $_CHIPNAME cpu -irlen 4 -expected-id $_DAP_TAPID + +# Subsidiary TAP: fpga (tap) +# See Intel Arria 10 Handbook +# https://www.altera.com/content/dam/altera-www/global/en_US/pdfs/literature/hb/arria-10/a10_handbook.pdf +# Intel Arria 10 GX 160 0x02ee20dd +# Intel Arria 10 GX 220 0x02e220dd +# Intel Arria 10 GX 270 0x02ee30dd +# Intel Arria 10 GX 320 0x02e230dd +# Intel Arria 10 GX 480 0x02e240dd +# Intel Arria 10 GX 570 0x02ee50dd +# Intel Arria 10 GX 660 0x02e250dd +# Intel Arria 10 GX 900 0x02ee60dd +# Intel Arria 10 GX 1150 0x02e660dd +# Intel Arria 10 GT 900 0x02e260dd +# Intel Arria 10 GT 1150 0x02e060dd +# Intel Arria 10 SX 160 0x02e620dd +# Intel Arria 10 SX 220 0x02e020dd +# Intel Arria 10 SX 270 0x02e630dd +# Intel Arria 10 SX 320 0x02e030dd +# Intel Arria 10 SX 480 0x02e040dd +# Intel Arria 10 SX 570 0x02e650dd +# Intel Arria 10 SX 660 0x02e050dd +jtag newtap $_CHIPNAME.fpga tap -irlen 10 -expected-id 0x02ee20dd -expected-id 0x02e220dd \ + -expected-id 0x02ee30dd -expected-id 0x02e230dd -expected-id 0x02e240dd \ + -expected-id 0x02ee50dd -expected-id 0x02e250dd -expected-id 0x02ee60dd \ + -expected-id 0x02e660dd -expected-id 0x02e260dd -expected-id 0x02e060dd \ + -expected-id 0x02e620dd -expected-id 0x02e020dd -expected-id 0x02e630dd \ + -expected-id 0x02e030dd -expected-id 0x02e040dd -expected-id 0x02e650dd \ + -expected-id 0x02e050dd + +set _TARGETNAME $_CHIPNAME.cpu + +# +# Cortex-A9 target + +dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu + +target create $_TARGETNAME.0 cortex_a -dap $_CHIPNAME.dap -coreid 0 +target create $_TARGETNAME.1 cortex_a -dap $_CHIPNAME.dap -coreid 1 \ + -defer-examine +target smp $_TARGETNAME.0 $_TARGETNAME.1 diff --git a/tcl/target/atheros_ar9331.cfg b/tcl/target/atheros_ar9331.cfg index c5609bb..bea37ed 100644 --- a/tcl/target/atheros_ar9331.cfg +++ b/tcl/target/atheros_ar9331.cfg @@ -1,16 +1,171 @@ +# The Atheros AR9331 is a highly integrated and cost effective +# IEEE 802.11n 1x1 2.4 GHz System- on-a-Chip (SoC) for wireless +# local area network (WLAN) AP and router platforms. +# +# Notes: +# - MIPS Processor ID (PRId): 0x00019374 +# - 24Kc MIPS processor with 64 KB I-Cache and 32 KB D-Cache, +# operating at up to 400 MHz +# - External 16-bit DDR1, DDR2, or SDRAM memory interface +# - TRST is not available. +# - EJTAG PrRst signal is not supported +# - RESET_L pin A72 on the SoC will reset internal JTAG logic. +# + +# Pins related for debug and bootstrap: +# Name Pin Description +# JTAG +# JTAG_TCK GPIO0, (A27) Software configurable, default JTAG +# JTAG_TDI GPIO6, (B46) Software configurable, default JTAG +# JTAG_TDO GPIO7, (A54) Software configurable, default JTAG +# JTAG_TMS GPIO8, (A52) Software configurable, default JTAG +# Reset +# RESET_L -, (A72) Input only +# SYS_RST_L ???????? Output reset request or GPIO +# Bootstrap +# MEM_TYPE[1] GPIO28, (A74) 0 - SDRAM, 1 - DDR1 RAM, 2 - DDR2 RAM +# MEM_TYPE[0] GPIO12, (A56) +# FW_DOWNLOAD GPIO16, (A75) Used if BOOT_FROM_SPI = 0. 0 - boot from USB +# 1 - boot from MDIO. +# JTAG_MODE(JS) GPIO11, (B48) 0 - JTAG (Default); 1 - EJTAG +# BOOT_FROM_SPI GPIO1, (A77) 0 - ROM boot; 1 - SPI boot +# SEL_25M_40M GPIO0, (A78) 0 - 25MHz; 1 - 40MHz +# UART +# UART0_SOUT GPIO10, (A79) +# UART0_SIN GPIO9, (B68) + +# Per default we need to use "none" variant to be able properly "reset init" +# or "reset halt" the CPU. +reset_config none srst_pulls_trst + +# For SRST based variant we still need proper timings. +# For ETH part the reset should be asserted at least for 10ms +# Since there is no other information let's take 100ms to be sure. +adapter_nsrst_assert_width 100 + +# according to the SoC documentation it should take at least 5ms from +# reset end till bootstrap end. In the practice we need 8ms to get JTAG back +# to live. +adapter_nsrst_delay 8 + if { [info exists CHIPNAME] } { set _CHIPNAME $_CHIPNAME } else { set _CHIPNAME ar9331 } -if { [info exists CPUTAPID] } { - set _CPUTAPID $CPUTAPID -} else { - set _CPUTAPID 0x00000001 -} - -jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id $_CPUTAPID +jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x00000001 set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME mips_m4k -endian big -chain-position $_TARGETNAME + +# provide watchdog helper. +proc disable_watchdog { } { + mww 0xb8060008 0x0 +} + +$_TARGETNAME configure -event halted { disable_watchdog } + +# Since PrRst is not supported and SRST will reset complete chip +# with JTAG engine, we need to reset CPU from CPU itself. +$_TARGETNAME configure -event reset-assert-pre { + halt +} + +$_TARGETNAME configure -event reset-assert { + catch "mww 0xb806001C 0x01000000" +} + +# To be able to trigger complete chip reset, in case JTAG is blocked +# or CPU not responding, we still can use this helper. +proc full_reset { } { + reset_config srst_only + reset + halt + reset_config none +} + +proc disable_watchdog { } { + ;# disable watchdog + mww 0xb8060008 0x0 +} + +$_TARGETNAME configure -event reset-end { disable_watchdog } + +# Section with helpers which can be used by boards +proc ar9331_25mhz_pll_init {} { + mww 0xb8050008 0x00018004 ;# bypass PLL; AHB_POST_DIV - ratio 4 + mww 0xb8050004 0x00000352 ;# 34000(ns)/40ns(25MHz) = 0x352 (850) + mww 0xb8050000 0x40818000 ;# Power down control for CPU PLL + ;# OUTDIV | REFDIV | DIV_INT + mww 0xb8050010 0x001003e8 ;# CPU PLL Dither FRAC Register + ;# (disabled?) + mww 0xb8050000 0x00818000 ;# Power on | OUTDIV | REFDIV | DIV_INT + mww 0xb8050008 0x00008000 ;# remove bypass; + ;# AHB_POST_DIV - ratio 2 +} + +proc ar9331_ddr1_init {} { + mww 0xb8000000 0x7fbc8cd0 ;# DDR_CONFIG - lots of DRAM confs + mww 0xb8000004 0x9dd0e6a8 ;# DDR_CONFIG2 - more DRAM confs + + mww 0xb8000010 0x8 ;# Forces a PRECHARGE ALL cycle + mww 0xb8000008 0x133 ;# mode reg: 0x133 - default + mww 0xb8000010 0x1 ;# Forces an MRS update cycl + mww 0xb800000c 0x2 ;# Extended mode register value. + ;# default 0x2 - Reset to weak driver, DLL on + mww 0xb8000010 0x2 ;# Forces an EMRS update cycle + mww 0xb8000010 0x8 ;# Forces a PRECHARGE ALL cycle + mww 0xb8000008 0x33 ;# mode reg: remove some bit? + mww 0xb8000010 0x1 ;# Forces an MRS update cycl + mww 0xb8000014 0x4186 ;# enable refres: bit(14) - set refresh rate + mww 0xb800001c 0x8 ;# This register is used along with DQ Lane 0, + ;# DQ[7:0], DQS_0 + mww 0xb8000020 0x9 ;# This register is used along with DQ Lane 1, + ;# DQ[15:8], DQS_1. + mww 0xb8000018 0xff ;# DDR read and capture bit mask. + ;# Each bit represents a cycle of valid data. +} + +proc ar9331_ddr2_init {} { + mww 0xb8000000 0x7fbc8cd0 ;# DDR_CONFIG - lots of DRAM confs + mww 0xb8000004 0x9dd0e6a8 ;# DDR_CONFIG2 - more DRAM confs + + mww 0xb800008c 0x00000a59 + mww 0xb8000010 0x00000008 ;# PRECHARGE ALL cycle + + mww 0xb8000090 0x00000000 + mww 0xb8000010 0x00000010 ;# EMR2S update cycle + + mww 0xb8000094 0x00000000 + mww 0xb8000010 0x00000020 ;# EMR3S update cycle + + mww 0xb800000c 0x00000000 + mww 0xb8000010 0x00000002 ;# EMRS update cycle + + mww 0xb8000008 0x00000100 + mww 0xb8000010 0x00000001 ;# MRS update cycle + + mww 0xb8000010 0x00000008 ;# PRECHARGE ALL cycle + + mww 0xb8000010 0x00000004 + mww 0xb8000010 0x00000004 ;# AUTO REFRESH cycle + + mww 0xb8000008 0x00000a33 + mww 0xb8000010 0x00000001 ;# MRS update cycle + + mww 0xb800000c 0x00000382 + mww 0xb8000010 0x00000002 ;# EMRS update cycle + + mww 0xb800000c 0x00000402 + mww 0xb8000010 0x00000002 ;# EMRS update cycle + + mww 0xb8000014 0x00004186 ;# DDR_REFRESH + mww 0xb800001c 0x00000008 ;# DDR_TAP_CTRL0 + mww 0xb8000020 0x00000009 ;# DDR_TAP_CTRL1 + + ;# DDR read and capture bit mask. + ;# Each bit represents a cycle of valid data. + ;# 0xff: use 16-bit DDR + mww 0xb8000018 0x000000ff +} diff --git a/tcl/target/cc32xx.cfg b/tcl/target/cc32xx.cfg deleted file mode 100755 index dfc4c17..0000000 --- a/tcl/target/cc32xx.cfg +++ /dev/null @@ -1,54 +0,0 @@ -# Config for Texas Instruments SoC CC32xx family - -source [find target/swj-dp.tcl] - -adapter_khz 100 - -source [find target/icepick.cfg] - -if { [info exists CHIPNAME] } { - set _CHIPNAME $CHIPNAME -} else { - set _CHIPNAME cc32xx -} - -# -# Main DAP -# -if { [info exists DAP_TAPID] } { - set _DAP_TAPID $DAP_TAPID -} else { - if {[using_jtag]} { - set _DAP_TAPID 0x4BA00477 - } else { - set _DAP_TAPID 0x2BA01477 - } -} - -if {[using_jtag]} { - jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_DAP_TAPID -disable - jtag configure $_CHIPNAME.cpu -event tap-enable "icepick_c_tapenable $_CHIPNAME.jrc 0" -} else { - swj_newdap $_CHIPNAME cpu -expected-id $_DAP_TAPID -} - -# -# ICEpick-C (JTAG route controller) -# -if { [info exists JRC_TAPID] } { - set _JRC_TAPID $JRC_TAPID -} else { - set _JRC_TAPID 0x0B97C02F -} - -if {[using_jtag]} { - jtag newtap $_CHIPNAME jrc -irlen 6 -ircapture 0x1 -irmask 0x3f -expected-id $_JRC_TAPID -ignore-version - jtag configure $_CHIPNAME.jrc -event setup "jtag tapenable $_CHIPNAME.dap" -} - -# -# Cortex-M3 target -# -set _TARGETNAME $_CHIPNAME.cpu -dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu -target create $_TARGETNAME cortex_m -dap $_CHIPNAME.dap diff --git a/tcl/target/ls1012a.cfg b/tcl/target/ls1012a.cfg new file mode 100644 index 0000000..9a9e684 --- /dev/null +++ b/tcl/target/ls1012a.cfg @@ -0,0 +1,35 @@ +# +# NXP LS1012A +# + +if { [info exists CHIPNAME] } { + set _CHIPNAME $CHIPNAME +} else { + set _CHIPNAME ls1012a +} + +if { [info exists DAP_TAPID] } { + set _DAP_TAPID $DAP_TAPID +} else { + set _DAP_TAPID 0x5ba00477 +} + +if { [info exists SAP_TAPID] } { + set _SAP_TAPID $SAP_TAPID +} else { + set _SAP_TAPID 0x06b2001d +} + +jtag newtap $_CHIPNAME dap -irlen 4 -expected-id $_DAP_TAPID +jtag newtap $_CHIPNAME sap -irlen 8 -expected-id $_SAP_TAPID + +dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.dap + +cti create $_CHIPNAME.cti -dap $_CHIPNAME.dap -ap-num 1 -ctibase 0x80420000 + +set _TARGETNAME $_CHIPNAME.cpu +target create $_TARGETNAME aarch64 -dap $_CHIPNAME.dap -dbgbase 0x80410000 -cti $_CHIPNAME.cti + +target smp $_TARGETNAME + +adapter_khz 2000 diff --git a/tcl/target/psoc5lp.cfg b/tcl/target/psoc5lp.cfg index 230ca07..b4e8d05 100644 --- a/tcl/target/psoc5lp.cfg +++ b/tcl/target/psoc5lp.cfg @@ -28,6 +28,38 @@ dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu set _TARGETNAME $_CHIPNAME.cpu target create $_TARGETNAME cortex_m -dap $_CHIPNAME.dap +if { [info exists WORKAREASIZE] } { + set _WORKAREASIZE $WORKAREASIZE +} else { + set _WORKAREASIZE 0x2000 +} + +$_TARGETNAME configure -work-area-phys [expr 0x20000000 - $_WORKAREASIZE / 2] \ + -work-area-size $_WORKAREASIZE -work-area-backup 0 + +source [find mem_helper.tcl] + +$_TARGETNAME configure -event reset-init { + # Configure Target Device (PSoC 5LP Device Programming Specification 5.2) + + set PANTHER_DBG_CFG 0x4008000C + set PANTHER_DBG_CFG_BYPASS [expr 1 << 1] + mmw $PANTHER_DBG_CFG $PANTHER_DBG_CFG_BYPASS 0 + + set PM_ACT_CFG0 0x400043A0 + mww $PM_ACT_CFG0 0xBF + + set FASTCLK_IMO_CR 0x40004200 + set FASTCLK_IMO_CR_F_RANGE_2 [expr 2 << 0] + set FASTCLK_IMO_CR_F_RANGE_MASK [expr 7 << 0] + mmw $FASTCLK_IMO_CR $FASTCLK_IMO_CR_F_RANGE_2 $FASTCLK_IMO_CR_F_RANGE_MASK +} + +set _FLASHNAME $_CHIPNAME.flash +flash bank $_FLASHNAME psoc5lp 0x00000000 0 0 0 $_TARGETNAME +flash bank $_CHIPNAME.eeprom psoc5lp_eeprom 0x40008000 0 0 0 $_TARGETNAME +flash bank $_CHIPNAME.nvl psoc5lp_nvl 0 0 0 0 $_TARGETNAME + if {![using_hla]} { cortex_m reset_config sysresetreq } diff --git a/tcl/target/qualcomm_qca4531.cfg b/tcl/target/qualcomm_qca4531.cfg new file mode 100644 index 0000000..3d21578 --- /dev/null +++ b/tcl/target/qualcomm_qca4531.cfg @@ -0,0 +1,154 @@ +# The QCA4531 is a two stream (2x2) 802.11b/g/n single-band programmable +# Wi-Fi System-on-Chip (SoC) for the Internet of Things (IoT). +# +# Product page: +# https://www.qualcomm.com/products/qca4531 +# +# Notes: +# - MIPS Processor ID (PRId): 0x00019374 +# - 24Kc MIPS processor with 64 KB I-Cache and 32 KB D-Cache, +# operating at up to 650 MHz +# - External 16-bit DDR1, operating at up to 200 MHz, DDR2 operating at up +# to 300 MHz +# - TRST is not available. +# - EJTAG PrRst signal is not supported +# - RESET_L pin B56 on the SoC will reset internal JTAG logic. +# +# Pins related for debug and bootstrap: +# Name Pin Description +# JTAG +# JTAG_TCK GPIO0, (A27) Software configurable, default JTAG +# JTAG_TDI GPIO1, (B23) Software configurable, default JTAG +# JTAG_TDO GPIO2, (A28) Software configurable, default JTAG +# JTAG_TMS GPIO3, (A29) Software configurable, default JTAG +# Reset +# RESET_L -, (B56) Input only +# SYS_RST_L GPIO17, (A79) Output reset request or GPIO +# Bootstrap +# JTAG_MODE GPIO16, (A78) 0 - JTAG (Default); 1 - EJTAG +# DDR_SELECT GPIO10, (A57) 0 - DDR2; 1 - DDR1 +# UART +# UART0_SOUT GPIO10, (A57) +# UART0_SIN GPIO9, (B49) + +# Per default we need to use "none" variant to be able properly "reset init" +# or "reset halt" the CPU. +reset_config none srst_pulls_trst + +# For SRST based variant we still need proper timings. +# For ETH part the reset should be asserted at least for 10ms +# Since there is no other information let's take 100ms to be sure. +adapter_nsrst_assert_width 100 + +# according to the SoC documentation it should take at least 5ms from +# reset end till bootstrap end. In the practice we need 8ms to get JTAG back +# to live. +adapter_nsrst_delay 8 + +if { [info exists CHIPNAME] } { + set _CHIPNAME $_CHIPNAME +} else { + set _CHIPNAME qca4531 +} + +jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x00000001 + +set _TARGETNAME $_CHIPNAME.cpu +target create $_TARGETNAME mips_m4k -endian big -chain-position $_TARGETNAME + +# provide watchdog helper. +proc disable_watchdog { } { + mww 0xb8060008 0x0 +} + +$_TARGETNAME configure -event halted { disable_watchdog } + +# Since PrRst is not supported and SRST will reset complete chip +# with JTAG engine, we need to reset CPU from CPU itself. +$_TARGETNAME configure -event reset-assert-pre { + halt +} + +$_TARGETNAME configure -event reset-assert { + catch "mww 0xb806001C 0x01000000" +} + +# To be able to trigger complete chip reset, in case JTAG is blocked +# or CPU not responding, we still can use this helper. +proc full_reset { } { + reset_config srst_only + reset + halt + reset_config none +} + +# Section with helpers which can be used by boards +proc qca4531_ddr2_550_550_init {} { + # Clear reset flags for different SoC components + mww 0xb806001c 0xfeceffff + mww 0xb806001c 0xeeceffff + mww 0xb806001c 0xe6ceffff + + # PMU configurations + # Internal Switcher + mww 0xb8116c40 0x633c8176 + # Increase the DDR voltage + mww 0xb8116c44 0x10200000 + # XTAL Configurations + mww 0xb81162c0 0x4b962100 + mww 0xb81162c4 0x480 + mww 0xb81162c8 0x04000144 + # Recommended PLL configurations + mww 0xb81161c4 0x54086000 + mww 0xb8116244 0x54086000 + + # PLL init + mww 0xb8050008 0x0131001c + mww 0xb8050000 0x40001580 + mww 0xb8050004 0x40015800 + mww 0xb8050008 0x0131001c + mww 0xb8050000 0x00001580 + mww 0xb8050004 0x00015800 + mww 0xb8050008 0x01310000 + mww 0xb8050044 0x781003ff + mww 0xb8050048 0x003c103f + + # DDR2 init + mww 0xb8000108 0x401f0042 + mww 0xb80000b8 0x0000166d + mww 0xb8000000 0xcfaaf33b + mww 0xb800015c 0x0000000f + mww 0xb8000004 0xa272efa8 + mww 0xb8000018 0x0000ffff + mww 0xb80000c4 0x74444444 + mww 0xb80000c8 0x00000444 + mww 0xb8000004 0xa210ee28 + mww 0xb8000004 0xa2b2e1a8 + mww 0xb8000010 0x8 + mww 0xb80000bc 0x0 + mww 0xb8000010 0x10 + mww 0xb80000c0 0x0 + mww 0xb8000010 0x40 + mww 0xb800000c 0x2 + mww 0xb8000010 0x2 + mww 0xb8000008 0xb43 + mww 0xb8000010 0x1 + mww 0xb8000010 0x8 + mww 0xb8000010 0x4 + mww 0xb8000010 0x4 + mww 0xb8000008 0xa43 + mww 0xb8000010 0x1 + mww 0xb800000c 0x382 + mww 0xb8000010 0x2 + mww 0xb800000c 0x402 + mww 0xb8000010 0x2 + mww 0xb8000014 0x40be + mww 0xb800001C 0x20 + mww 0xb8000020 0x20 + mww 0xb80000cc 0xfffff + + # UART GPIO programming + mww 0xb8040000 0xff30b + mww 0xb8040044 0x908 + mww 0xb8040034 0x160000 +} diff --git a/tcl/target/renesas_r8a7794.cfg b/tcl/target/renesas_r8a7794.cfg new file mode 100644 index 0000000..e3e2724 --- /dev/null +++ b/tcl/target/renesas_r8a7794.cfg @@ -0,0 +1,27 @@ +# Renesas R-Car E2 +# https://www.renesas.com/en-us/solutions/automotive/products/rcar-e2.html + +if { [info exists DAP_TAPID] } { + set _DAP_TAPID $DAP_TAPID +} else { + set _DAP_TAPID 0x4ba00477 +} + +if { [info exists CHIPNAME] } { + set _CHIPNAME $CHIPNAME +} else { + set _CHIPNAME r8a7794 +} + +jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x01 -irmask 0x0f -expected-id $_DAP_TAPID + +# Configuring only one core using DAP. +# Base addresses of cores: +# core 0 - 0x800F0000 +# core 1 - 0x800F2000 +set _TARGETNAME $_CHIPNAME.ca7. +dap create ${_CHIPNAME}.dap -chain-position $_CHIPNAME.cpu +target create ${_TARGETNAME}0 cortex_a -dap ${_CHIPNAME}.dap -coreid 0 -dbgbase 0x800F0000 +target create ${_TARGETNAME}1 cortex_a -dap ${_CHIPNAME}.dap -coreid 1 -dbgbase 0x800F2000 -defer-examine + +targets ${_TARGETNAME}0 diff --git a/tcl/target/stm32f0x.cfg b/tcl/target/stm32f0x.cfg index b8c0de9..baac9b6 100644 --- a/tcl/target/stm32f0x.cfg +++ b/tcl/target/stm32f0x.cfg @@ -22,6 +22,14 @@ if { [info exists WORKAREASIZE] } { set _WORKAREASIZE 0x1000 } +# Allow overriding the Flash bank size +if { [info exists FLASH_SIZE] } { + set _FLASH_SIZE $FLASH_SIZE +} else { + # autodetect size + set _FLASH_SIZE 0 +} + #jtag scan chain if { [info exists CPUTAPID] } { set _CPUTAPID $CPUTAPID @@ -41,7 +49,7 @@ $_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE # flash size will be probed set _FLASHNAME $_CHIPNAME.flash -flash bank $_FLASHNAME stm32f1x 0x08000000 0 0 0 $_TARGETNAME +flash bank $_FLASHNAME stm32f1x 0x08000000 $_FLASH_SIZE 0 0 $_TARGETNAME # adapter speed should be <= F_CPU/6. F_CPU after reset is 8MHz, so use F_JTAG = 1MHz adapter_khz 1000 diff --git a/tcl/target/stm32f7x.cfg b/tcl/target/stm32f7x.cfg index dc310da..562de30 100755 --- a/tcl/target/stm32f7x.cfg +++ b/tcl/target/stm32f7x.cfg @@ -82,3 +82,66 @@ $_TARGETNAME configure -event trace-config { # assignment mmw 0xE0042004 0x00000020 0 } + +$_TARGETNAME configure -event reset-init { + # If the HSE was previously enabled and the external clock source + # disappeared, RCC_CR.HSERDY can get stuck at 1 and the PLL cannot be + # properly switched back to HSI. This situation persists even over a system + # reset, including a pin reset via SRST. However, activating the clock + # security system will detect the problem and clear HSERDY to 0, which in + # turn allows the PLL to switch back to HSI properly. Since we just came + # out of reset, HSEON should be 0. If HSERDY is 1, then this situation must + # have happened; in that case, activate the clock security system to clear + # HSERDY. + if {[mrw 0x40023800] & 0x00020000} { + mmw 0x40023800 0x00090000 0 ;# RCC_CR = CSSON | HSEON + sleep 10 ;# Wait for CSS to fire, if it wants to + mmw 0x40023800 0 0x00090000 ;# RCC_CR &= ~CSSON & ~HSEON + mww 0x4002380C 0x00800000 ;# RCC_CIR = CSSC + sleep 1 ;# Wait for CSSF to clear + } + + # If the clock security system fired, it will pend an NMI. A pending NMI + # will cause a bad time for any subsequent executing code, such as a + # programming algorithm. + if {[mrw 0xE000ED04] & 0x80000000} { + # ICSR.NMIPENDSET reads as 1. Need to clear it. A pending NMI can’t be + # cleared by any normal means (such as ICSR or NVIC). It can only be + # cleared by entering the NMI handler or by resetting the processor. + echo "[target current]: Clock security system generated NMI. Clearing." + + # Keep the old DEMCR value. + set old [mrw 0xE000EDFC] + + # Enable vector catch on reset. + mww 0xE000EDFC 0x01000001 + + # Issue local reset via AIRCR. + mww 0xE000ED0C 0x05FA0001 + + # Restore old DEMCR value. + mww 0xE000EDFC $old + } + + # Configure PLL to boost clock to HSI x 10 (160 MHz) + mww 0x40023804 0x08002808 ;# RCC_PLLCFGR 16 Mhz /10 (M) * 128 (N) /2(P) + mww 0x40023C00 0x00000107 ;# FLASH_ACR = PRFTBE | 7(Latency) + mmw 0x40023800 0x01000000 0 ;# RCC_CR |= PLLON + sleep 10 ;# Wait for PLL to lock + mww 0x40023808 0x00009400 ;# RCC_CFGR_PPRE1 = 5(div 4), PPRE2 = 4(div 2) + mmw 0x40023808 0x00000002 0 ;# RCC_CFGR |= RCC_CFGR_SW_PLL + + # Boost SWD frequency + # Do not boost JTAG frequency and slow down JTAG memory access or flash write algo + # suffers from DAP WAITs + if {[using_jtag]} { + [[target current] cget -dap] memaccess 16 + } { + adapter_khz 8000 + } +} + +$_TARGETNAME configure -event reset-start { + # Reduce speed since CPU speed will slow down to 16MHz with the reset + adapter_khz 2000 +} diff --git a/tcl/target/ti_cc13x0.cfg b/tcl/target/ti_cc13x0.cfg new file mode 100644 index 0000000..6ea9bd8 --- /dev/null +++ b/tcl/target/ti_cc13x0.cfg @@ -0,0 +1,11 @@ +# +# Texas Instruments CC13x0 - ARM Cortex-M3 +# +# http://www.ti.com +# + +set CHIPNAME cc13x0 +set JRC_TAPID 0x0B9BE02F +set WORKAREASIZE 0x4000 + +source [find target/ti_cc26x0.cfg] diff --git a/tcl/target/ti_cc13x2.cfg b/tcl/target/ti_cc13x2.cfg new file mode 100644 index 0000000..280eef4 --- /dev/null +++ b/tcl/target/ti_cc13x2.cfg @@ -0,0 +1,11 @@ +# +# Texas Instruments CC13x2 - ARM Cortex-M4 +# +# http://www.ti.com +# + +set CHIPNAME cc13x2 +set JRC_TAPID 0x0BB4102F +set WORKAREASIZE 0x7000 + +source [find target/ti_cc26x0.cfg] diff --git a/tcl/target/cc26xx.cfg b/tcl/target/ti_cc26x0.cfg index c3ac847..7efecb6 100755..100644 --- a/tcl/target/cc26xx.cfg +++ b/tcl/target/ti_cc26x0.cfg @@ -1,23 +1,25 @@ -# Config for Texas Instruments low power SoC CC26xx family - -adapter_khz 100 +# +# Texas Instruments CC26x0 - ARM Cortex-M3 +# +# http://www.ti.com +# source [find target/icepick.cfg] source [find target/ti-cjtag.cfg] if { [info exists CHIPNAME] } { - set _CHIPNAME $CHIPNAME + set _CHIPNAME $CHIPNAME } else { - set _CHIPNAME cc26xx + set _CHIPNAME cc26x0 } # # Main DAP # if { [info exists DAP_TAPID] } { - set _DAP_TAPID $DAP_TAPID + set _DAP_TAPID $DAP_TAPID } else { - set _DAP_TAPID 0x4BA00477 + set _DAP_TAPID 0x4BA00477 } jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_DAP_TAPID -disable jtag configure $_CHIPNAME.cpu -event tap-enable "icepick_c_tapenable $_CHIPNAME.jrc 0" @@ -26,19 +28,29 @@ jtag configure $_CHIPNAME.cpu -event tap-enable "icepick_c_tapenable $_CHIPNAME. # ICEpick-C (JTAG route controller) # if { [info exists JRC_TAPID] } { - set _JRC_TAPID $JRC_TAPID + set _JRC_TAPID $JRC_TAPID } else { - set _JRC_TAPID 0x1B99A02F + set _JRC_TAPID 0x0B99A02F } jtag newtap $_CHIPNAME jrc -irlen 6 -ircapture 0x1 -irmask 0x3f -expected-id $_JRC_TAPID -ignore-version -# A start sequence is needed to change from cJTAG (Compact JTAG) to -# 4-pin JTAG before talking via JTAG commands jtag configure $_CHIPNAME.jrc -event setup "jtag tapenable $_CHIPNAME.cpu" +# A start sequence is needed to change from 2-pin cJTAG to 4-pin JTAG jtag configure $_CHIPNAME.jrc -event post-reset "ti_cjtag_to_4pin_jtag $_CHIPNAME.jrc" -# -# Cortex-M3 target -# set _TARGETNAME $_CHIPNAME.cpu dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu target create $_TARGETNAME cortex_m -dap $_CHIPNAME.dap + +if { [info exists WORKAREASIZE] } { + set _WORKAREASIZE $WORKAREASIZE +} else { + set _WORKAREASIZE 0x4000 +} + +$_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0 + +set _FLASHNAME $_CHIPNAME.flash +flash bank $_FLASHNAME cc26xx 0 0 0 0 $_TARGETNAME + +reset_config srst_only +adapter_nsrst_delay 100 diff --git a/tcl/target/ti_cc26x2.cfg b/tcl/target/ti_cc26x2.cfg new file mode 100644 index 0000000..ecee3fa --- /dev/null +++ b/tcl/target/ti_cc26x2.cfg @@ -0,0 +1,11 @@ +# +# Texas Instruments CC26x2 - ARM Cortex-M4 +# +# http://www.ti.com +# + +set CHIPNAME cc26x2 +set JRC_TAPID 0x0BB4102F +set WORKAREASIZE 0x7000 + +source [find target/ti_cc26x0.cfg] diff --git a/tcl/target/ti_cc3220sf.cfg b/tcl/target/ti_cc3220sf.cfg new file mode 100644 index 0000000..f7d9bfe --- /dev/null +++ b/tcl/target/ti_cc3220sf.cfg @@ -0,0 +1,12 @@ +# +# Texas Instruments CC3220SF - ARM Cortex-M4 +# +# http://www.ti.com/CC3220SF +# + +source [find target/swj-dp.tcl] +source [find target/icepick.cfg] +source [find target/ti_cc32xx.cfg] + +set _FLASHNAME $_CHIPNAME.flash +flash bank $_FLASHNAME cc3220sf 0 0 0 0 $_TARGETNAME diff --git a/tcl/target/ti_cc32xx.cfg b/tcl/target/ti_cc32xx.cfg new file mode 100644 index 0000000..bc3038d --- /dev/null +++ b/tcl/target/ti_cc32xx.cfg @@ -0,0 +1,64 @@ +# +# Texas Instruments CC32xx - ARM Cortex-M4 +# +# http://www.ti.com/product/CC3200 +# http://www.ti.com/product/CC3220 +# + +source [find target/swj-dp.tcl] +source [find target/icepick.cfg] + +if { [info exists CHIPNAME] } { + set _CHIPNAME $CHIPNAME +} else { + set _CHIPNAME cc32xx +} + +# +# Main DAP +# +if { [info exists DAP_TAPID] } { + set _DAP_TAPID $DAP_TAPID +} else { + if {[using_jtag]} { + set _DAP_TAPID 0x4BA00477 + } else { + set _DAP_TAPID 0x2BA01477 + } +} + +if {[using_jtag]} { + jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_DAP_TAPID -disable + jtag configure $_CHIPNAME.cpu -event tap-enable "icepick_c_tapenable $_CHIPNAME.jrc 0" +} else { + swj_newdap $_CHIPNAME cpu -expected-id $_DAP_TAPID +} + +# +# ICEpick-C (JTAG route controller) +# +if { [info exists JRC_TAPID] } { + set _JRC_TAPID $JRC_TAPID +} else { + set _JRC_TAPID 0x0B97C02F +} + +if {[using_jtag]} { + jtag newtap $_CHIPNAME jrc -irlen 6 -ircapture 0x1 -irmask 0x3f -expected-id $_JRC_TAPID -ignore-version + jtag configure $_CHIPNAME.jrc -event setup "jtag tapenable $_CHIPNAME.cpu" +} + +set _TARGETNAME $_CHIPNAME.cpu +dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu +target create $_TARGETNAME cortex_m -dap $_CHIPNAME.dap + +if { [info exists WORKAREASIZE] } { + set _WORKAREASIZE $WORKAREASIZE +} else { + set _WORKAREASIZE 0x2000 +} + +$_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0 + +reset_config srst_only +adapter_nsrst_delay 1100 diff --git a/tcl/target/ti_msp432p4xx.cfg b/tcl/target/ti_msp432.cfg index 461b595..3407f75 100644 --- a/tcl/target/ti_msp432p4xx.cfg +++ b/tcl/target/ti_msp432.cfg @@ -1,5 +1,5 @@ # -# Texas Instruments MSP432P4xx - ARM Cortex-M4F @ up to 48 MHz +# Texas Instruments MSP432 - ARM Cortex-M4F @ up to 48 MHz # # http://www.ti.com/MSP432 # @@ -7,7 +7,7 @@ if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME } else { - set _CHIPNAME msp432p4xx + set _CHIPNAME msp432 } if { [info exists CPUTAPID] } { @@ -39,15 +39,13 @@ target create $_TARGETNAME cortex_m -dap $_CHIPNAME.dap if { [info exists WORKAREASIZE] } { set _WORKAREASIZE $WORKAREASIZE } else { - # On MSP432P401x Bank0 (8k) is always powered - set _WORKAREASIZE 0x2000 + set _WORKAREASIZE 0x4000 } -$_TARGETNAME configure -work-area-phys 0x20000000 \ - -work-area-size $_WORKAREASIZE -work-area-backup 0 +$_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0 -if { ![using_hla] } { - cortex_m reset_config sysresetreq -} +set _FLASHNAME $_CHIPNAME.flash +flash bank $_FLASHNAME msp432 0 0 0 0 $_TARGETNAME -adapter_khz 500 +reset_config srst_only +adapter_nsrst_delay 100 diff --git a/testing/examples/ledtest-imx27ads/test.c b/testing/examples/ledtest-imx27ads/test.c index 92deaf4..a3dd522 100644 --- a/testing/examples/ledtest-imx27ads/test.c +++ b/testing/examples/ledtest-imx27ads/test.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * ***************************************************************************/ void delay() diff --git a/testing/examples/ledtest-imx31pdk/test.c b/testing/examples/ledtest-imx31pdk/test.c index c80cc61..4135f89 100644 --- a/testing/examples/ledtest-imx31pdk/test.c +++ b/testing/examples/ledtest-imx31pdk/test.c @@ -13,9 +13,7 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * + * along with this program. If not, see <http://www.gnu.org/licenses/>. * ***************************************************************************/ void delay() |