diff --git a/Makefile b/Makefile index 53a55c8..3d1e71c 100644 --- a/Makefile +++ b/Makefile @@ -124,6 +124,7 @@ OBJ=\ transport/rf2500.o \ transport/ti3410.o \ transport/comport.o \ + transport/bslhid.o \ drivers/device.o \ drivers/bsl.o \ drivers/fet.o \ @@ -142,6 +143,8 @@ OBJ=\ drivers/jtdev.o \ drivers/jtaglib.o \ drivers/pif.o \ + drivers/loadbsl.o \ + drivers/loadbsl_fw.o \ formats/binfile.o \ formats/coff.o \ formats/elf32.o \ diff --git a/drivers/loadbsl.c b/drivers/loadbsl.c new file mode 100644 index 0000000..0ec5928 --- /dev/null +++ b/drivers/loadbsl.c @@ -0,0 +1,461 @@ +/* MSPDebug - debugging tool for MSP430 MCUs + * Copyright (C) 2009-2013 Daniel Beer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +#include "output.h" +#include "util.h" +#include "loadbsl.h" +#include "loadbsl_fw.h" +#include "bslhid.h" + +#define BSL_MAX_CORE 62 +#define BSL_MAX_BLOCK 52 + +#define BSL_CMD_RX_BLOCK 0x10 +#define BSL_CMD_RX_BLOCK_FAST 0x1B +#define BSL_CMD_RX_PASSWORD 0x11 +#define BSL_CMD_ERASE_SEGMENT 0x12 +#define BSL_CMD_UNLOCK_LOCK_INFO 0x13 +#define BSL_CMD_MASS_ERASE 0x15 +#define BSL_CMD_CRC_CHECK 0x16 +#define BSL_CMD_LOAD_PC 0x17 +#define BSL_CMD_TX_BLOCK 0x18 +#define BSL_CMD_TX_VERSION 0x19 +#define BSL_CMD_TX_BUFSIZE 0x1A + +#define BSL_PACKET_HEADER 0x80 +#define BSL_PACKET_ACK 0x90 + +/* BSL error codes: from SLAU319C ("MSP430 Programming via the Bootstrap + * Loader"). + */ +static const char *const bsl_error_table[9] = { + [0x00] = "Success", + [0x01] = "Flash write check failed", + [0x02] = "Flash fail bit set", + [0x03] = "Voltage change during program", + [0x04] = "BSL locked", + [0x05] = "BSL password error", + [0x06] = "Byte write forbidden", + [0x07] = "Unknown command", + [0x08] = "Packet length exceeds buffer size" +}; + +static const char *bsl_error_message(int code) +{ + const char *text = NULL; + + if (code >= 0 && code < ARRAY_LEN(bsl_error_table)) + text = bsl_error_table[code]; + + if (text) + return text; + + return "Unknown error code"; +} + +struct loadbsl_device { + struct device base; + transport_t trans; +}; + +static int send_command(transport_t trans, uint8_t cmd, + address_t addr, const uint8_t *data, int datalen) +{ + uint8_t outbuf[BSL_MAX_CORE]; + const int addrlen = (addr != ADDRESS_NONE) ? 3 : 0; + const int corelen = datalen + addrlen + 1; + + if (datalen > BSL_MAX_BLOCK) { + printc_err("loadbsl: send_command: MAX_BLOCK exceeded: %d\n", + datalen); + return -1; + } + + outbuf[0] = cmd; + + if (addrlen > 0) { + outbuf[1] = addr & 0xff; + outbuf[2] = (addr >> 8) & 0xff; + outbuf[3] = (addr >> 16) & 0xff; + } + + memcpy(outbuf + 1 + addrlen, data, datalen); + + if (trans->ops->send(trans, outbuf, corelen) < 0) { + printc_err("loadbsl: send_command failed\n"); + return -1; + } + + return 0; +} + +static int recv_packet(transport_t trans, uint8_t *data, int max_len) +{ + uint8_t inbuf[BSL_MAX_CORE]; + int len = trans->ops->recv(trans, inbuf, sizeof(inbuf)); + int type; + int code; + + if (len < 0) { + printc_err("loadbsl: recv_packet: transport error\n"); + return -1; + } + + if (len < 1) { + printc_err("loadbsl: recv_packet: zero-length packet\n"); + return -1; + } + + type = inbuf[0]; + if (type == 0x3a) { + const int data_len = len - 1; + + if (!data) + return 0; + + if (data_len > max_len) { + printc_err("loadbsl: recv_packet: packet too " + "long for buffer (%d bytes)\n", data_len); + return -1; + } + + memcpy(data, inbuf + 1, data_len); + return data_len; + } + + if (type != 0x3b) { + printc_err("loadbsl: recv_packet: unknown packet type: " + "0x%02x\n", type); + return -1; + } + + if (len < 2) { + printc_err("loadbsl: recv_packet: missing response code\n"); + return -1; + } + + code = inbuf[1]; + if (code) { + printc_err("loadbsl: recv_packet: BSL error code: %d (%s)\n", + code, bsl_error_message(code)); + return -1; + } + + return 0; +} + +/* Retrieve and display BSL version info. Returns API version byte. */ +static int version_check(transport_t trans) +{ + uint8_t data[4]; + int r; + + if (send_command(trans, BSL_CMD_TX_VERSION, + ADDRESS_NONE, NULL, 0) < 0) { + printc_err("loadbsl: failed to send TX_VERSION command\n"); + return -1; + } + + r = recv_packet(trans, data, 4); + if (r < 0) { + printc_err("loadbsl: failed to receive version\n"); + return -1; + } + + if (r < 4) { + printc_err("loadbsl: short version response\n"); + return -1; + } + + printc_dbg("BSL version: [vendor: %02x, int: %02x, " + "API: %02x, per: %02x]\n", + data[0], data[1], data[2], data[3]); + + return data[2]; +} + +static int do_writemem(transport_t trans, + address_t addr, const uint8_t *mem, address_t len) +{ + while (len) { + int plen = len; + + if (plen > BSL_MAX_BLOCK) + plen = BSL_MAX_BLOCK; + + if (send_command(trans, BSL_CMD_RX_BLOCK_FAST, + addr, mem, plen) < 0) { + printc_err("loadbsl: failed to write block " + "to 0x%04x\n", addr); + return -1; + } + + addr += plen; + mem += plen; + len -= plen; + } + + return 0; +} + +static int rx_password(transport_t trans) +{ + uint8_t password[32]; + + memset(password, 0xff, sizeof(password)); + if (send_command(trans, BSL_CMD_RX_PASSWORD, ADDRESS_NONE, + password, sizeof(password)) < 0 || + recv_packet(trans, NULL, 0) < 0) { + printc_err("loadbsl: rx_password failed\n"); + return -1; + } + + return 0; +} + +static int check_and_load(transport_t trans) +{ + const struct loadbsl_fw *fw = &loadbsl_fw_usb5xx; + int api_version = version_check(trans); + + if ((api_version >= 0) && (api_version != 0x80)) + return 0; + + printc_dbg("Uploading BSL firmware (%d bytes at address 0x%04x)...\n", + fw->size, fw->prog_addr); + + if (do_writemem(trans, fw->prog_addr, fw->data, fw->size) < 0) { + printc_err("loadbsl: firmware upload failed\n"); + return -1; + } + + printc_dbg("Starting new firmware (PC: 0x%04x)...\n", fw->entry_point); + + if (send_command(trans, BSL_CMD_LOAD_PC, fw->entry_point, + NULL, 0) < 0) { + printc_err("loadbsl: PC load failed\n"); + return -1; + } + + if (trans->ops->suspend && trans->ops->resume && + trans->ops->suspend(trans) < 0) { + printc_err("loadbsl: transport suspend failed\n"); + return -1; + } + + printc_dbg("Done, waiting for startup\n"); + delay_ms(1000); + + if (trans->ops->suspend && trans->ops->resume && + trans->ops->resume(trans) < 0) { + printc_err("loadbsl: transport resume failed\n"); + return -1; + } + + if (rx_password(trans) < 0) { + printc_err("loadbsl: failed to unlock new firmware\n"); + return -1; + } + + return version_check(trans); +} + +static void loadbsl_destroy(device_t base) +{ + struct loadbsl_device *dev = (struct loadbsl_device *)base; + + dev->trans->ops->destroy(dev->trans); + free(dev); +} + +static int loadbsl_readmem(device_t base, address_t addr, + uint8_t *mem, address_t len) +{ + struct loadbsl_device *dev = (struct loadbsl_device *)base; + + while (len) { + int plen = len; + uint8_t len_param[2]; + int r; + + if (plen > BSL_MAX_BLOCK) + plen = BSL_MAX_BLOCK; + + len_param[0] = plen & 0xff; + len_param[1] = plen >> 8; + + if (send_command(dev->trans, BSL_CMD_TX_BLOCK, + addr, len_param, 2) < 0) + goto fail; + + r = recv_packet(dev->trans, mem, plen); + if (r < 0) + goto fail; + + if (r < plen) { + printc_err("loadbsl: short response to " + "memory read\n"); + return -1; + } + + addr += plen; + mem += plen; + len -= plen; + } + + return 0; + +fail: + printc_err("loadbsl: failed to read block from 0x%04x\n", addr); + return -1; +} + +static int loadbsl_writemem(device_t base, address_t addr, + const uint8_t *mem, address_t len) +{ + struct loadbsl_device *dev = (struct loadbsl_device *)base; + + return do_writemem(dev->trans, addr, mem, len); +} + +static int loadbsl_getregs(device_t base, address_t *regs) +{ + (void)base; + (void)regs; + + printc_err("loadbsl: register fetch is not implemented\n"); + return -1; +} + +static int loadbsl_setregs(device_t base, const address_t *regs) +{ + (void)base; + (void)regs; + + printc_err("loadbsl: register store is not implemented\n"); + return -1; +} + +static int loadbsl_erase(device_t base, device_erase_type_t type, + address_t addr) +{ + struct loadbsl_device *dev = (struct loadbsl_device *)base; + + switch (type) { + case DEVICE_ERASE_ALL: + printc_err("loadbsl: ERASE_ALL not supported\n"); + return -1; + + case DEVICE_ERASE_MAIN: + if (send_command(dev->trans, BSL_CMD_MASS_ERASE, + ADDRESS_NONE, NULL, 0) < 0 || + recv_packet(dev->trans, NULL, 0) < 0) { + printc_err("loadbsl: ERASE_MAIN failed\n"); + return -1; + } + break; + + case DEVICE_ERASE_SEGMENT: + if (send_command(dev->trans, BSL_CMD_ERASE_SEGMENT, + addr, NULL, 0) < 0 || + recv_packet(dev->trans, NULL, 0) < 0) { + printc_err("loadbsl: ERASE_SEGMENT failed\n"); + return -1; + } + break; + } + + return 0; +} + +static int loadbsl_ctl(device_t base, device_ctl_t type) +{ + (void)base; + + switch (type) { + case DEVICE_CTL_HALT: + case DEVICE_CTL_RESET: + return 0; + + default: + printc_err("loadbsl: CPU control is not possible\n"); + } + + return 0; +} + +static device_status_t loadbsl_poll(device_t base) +{ + (void)base; + + return DEVICE_STATUS_HALTED; +} + +static device_t loadbsl_open(const struct device_args *args) +{ + struct loadbsl_device *dev; + + if (args->flags & DEVICE_FLAG_TTY) { + printc_err("loadbsl: this driver does not support " + "tty access\n"); + return NULL; + } + + dev = malloc(sizeof(*dev)); + memset(dev, 0, sizeof(*dev)); + + dev->base.type = &device_loadbsl; + dev->base.max_breakpoints = 0; + + dev->trans = bslhid_open(args->path, args->requested_serial); + if (!dev->trans) { + free(dev); + return NULL; + } + + if (rx_password(dev->trans) < 0) { + dev->trans->ops->destroy(dev->trans); + free(dev); + return NULL; + } + + if (check_and_load(dev->trans) < 0) { + dev->trans->ops->destroy(dev->trans); + free(dev); + return NULL; + } + + return &dev->base; +} + +const struct device_class device_loadbsl = { + .name = "load-bsl", + .help = "Loadable USB BSL driver (USB 5xx/6xx).", + .open = loadbsl_open, + .destroy = loadbsl_destroy, + .readmem = loadbsl_readmem, + .writemem = loadbsl_writemem, + .erase = loadbsl_erase, + .getregs = loadbsl_getregs, + .setregs = loadbsl_setregs, + .ctl = loadbsl_ctl, + .poll = loadbsl_poll +}; diff --git a/drivers/loadbsl.h b/drivers/loadbsl.h new file mode 100644 index 0000000..02dd9de --- /dev/null +++ b/drivers/loadbsl.h @@ -0,0 +1,27 @@ +/* MSPDebug - debugging tool for MSP430 MCUs + * Copyright (C) 2009-2013 Daniel Beer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef LOADBSL_H_ +#define LOADBSL_H_ + +#include "device.h" + +/* MSP430 loadable BSL implementation */ +extern const struct device_class device_loadbsl; + +#endif diff --git a/drivers/loadbsl_fw.c b/drivers/loadbsl_fw.c new file mode 100644 index 0000000..f6e5651 --- /dev/null +++ b/drivers/loadbsl_fw.c @@ -0,0 +1,356 @@ +/* + * MSPBLS_RAM_BSL.00.05.04.34 + * + * An array holding the bytes to be programmed into device RAM for full USB BSL cabability + * + * Copyright (C) 2012 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 "loadbsl_fw.h" + +/* program start addr 0x2504 + * first mem addr 0x2500 + */ + +static const uint8_t RAM_BSL_00_05_04_34[] = { + 0x00, 0x05, 0x04, 0x34, 0x31, 0x40, 0x90, 0x33, + 0xB0, 0x13, 0x5E, 0x2E, 0x0C, 0x93, 0x00, 0x24, + 0xB0, 0x13, 0xF4, 0x2D, 0xFF, 0x3F, 0x12, 0x01, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x47, 0x20, + 0x00, 0x02, 0x04, 0x01, 0x00, 0x00, 0x00, 0x01, + 0x06, 0x00, 0xFF, 0x09, 0x01, 0xA1, 0x01, 0x85, + 0x3F, 0x95, 0x3F, 0x75, 0x08, 0x25, 0x01, 0x15, + 0x01, 0x09, 0x01, 0x81, 0x02, 0x85, 0x3F, 0x95, + 0x3F, 0x75, 0x08, 0x25, 0x01, 0x15, 0x01, 0x09, + 0x01, 0x91, 0x02, 0xC0, 0x09, 0x02, 0x29, 0x00, + 0x01, 0x01, 0x00, 0x80, 0x32, 0x09, 0x04, 0x00, + 0x00, 0x02, 0x03, 0x00, 0x00, 0x00, 0x09, 0x21, + 0x01, 0x01, 0x00, 0x01, 0x22, 0x24, 0x00, 0x07, + 0x05, 0x81, 0x03, 0x40, 0x00, 0x01, 0x07, 0x05, + 0x01, 0x03, 0x40, 0x00, 0x01, 0x57, 0xF2, 0xD2, + 0x20, 0x09, 0xF2, 0xD2, 0x22, 0x09, 0x10, 0x01, + 0x5E, 0x42, 0x02, 0x24, 0x7E, 0x93, 0x25, 0x24, + 0x7E, 0x90, 0x09, 0x00, 0x04, 0x28, 0x7D, 0x42, + 0x7E, 0x82, 0x5F, 0x43, 0x0C, 0x3C, 0x7E, 0x92, + 0x02, 0x2C, 0x4D, 0x4E, 0x06, 0x3C, 0x7D, 0x42, + 0xD2, 0x93, 0x0E, 0x24, 0x02, 0x20, 0x4E, 0x43, + 0xF4, 0x3F, 0x7E, 0x43, 0x4F, 0x43, 0xC2, 0x4F, + 0x10, 0x24, 0xC2, 0x4E, 0x02, 0x24, 0x4F, 0x43, + 0x07, 0x3C, 0x1E, 0x42, 0x06, 0x24, 0xEF, 0x4E, + 0x78, 0x23, 0x92, 0x53, 0x06, 0x24, 0x5F, 0x53, + 0x4F, 0x9D, 0xF7, 0x2B, 0xC2, 0x4D, 0x21, 0x09, + 0x10, 0x01, 0xC2, 0x43, 0x10, 0x24, 0x10, 0x01, + 0x82, 0x4C, 0x06, 0x24, 0x5E, 0x42, 0x86, 0x23, + 0xC2, 0x9E, 0x02, 0x24, 0x04, 0x28, 0xC2, 0x4E, + 0x02, 0x24, 0x4E, 0x43, 0x01, 0x3C, 0x5E, 0x43, + 0xC2, 0x4E, 0x0E, 0x24, 0x80, 0x00, 0x80, 0x25, + 0xF2, 0xB0, 0x0F, 0x00, 0x84, 0x23, 0x14, 0x20, + 0xC2, 0x93, 0x84, 0x23, 0x03, 0x34, 0x5E, 0x42, + 0x20, 0x09, 0x02, 0x3C, 0x5E, 0x42, 0x22, 0x09, + 0x7E, 0xF2, 0xC2, 0x4E, 0x60, 0x24, 0x5E, 0x42, + 0x60, 0x24, 0x42, 0x19, 0x4E, 0x10, 0xC2, 0x4E, + 0x60, 0x24, 0xB0, 0x13, 0xC4, 0x27, 0x09, 0x3C, + 0xC2, 0x93, 0x84, 0x23, 0x03, 0x34, 0x5E, 0x42, + 0xC8, 0x23, 0xEE, 0x3F, 0x5E, 0x42, 0x88, 0x23, + 0xEB, 0x3F, 0x3C, 0x40, 0x60, 0x24, 0x80, 0x00, + 0xD8, 0x25, 0xF2, 0x43, 0x02, 0x24, 0xC2, 0x43, + 0x10, 0x24, 0xC2, 0x43, 0x21, 0x09, 0x10, 0x01, + 0xC2, 0x93, 0x82, 0x23, 0x12, 0x20, 0x5E, 0x42, + 0x84, 0x23, 0x7E, 0xF0, 0x0F, 0x00, 0x02, 0x20, + 0x80, 0x00, 0x42, 0x26, 0x5E, 0x93, 0x0B, 0x20, + 0xC2, 0x93, 0x84, 0x23, 0x03, 0x34, 0xF2, 0xD2, + 0xC8, 0x23, 0xF6, 0x3F, 0xF2, 0xD2, 0x88, 0x23, + 0xF3, 0x3F, 0xB0, 0x13, 0x76, 0x25, 0x10, 0x01, + 0xC2, 0x93, 0x80, 0x23, 0x04, 0x34, 0x1F, 0x43, + 0xD2, 0xD3, 0x3C, 0x09, 0x03, 0x3C, 0x0F, 0x43, + 0xD2, 0xC3, 0x3C, 0x09, 0x5E, 0x42, 0x80, 0x23, + 0x7E, 0xB0, 0x60, 0x00, 0x90, 0x20, 0x5D, 0x42, + 0x81, 0x23, 0x4D, 0x83, 0x81, 0x24, 0x5D, 0x83, + 0x6B, 0x24, 0x6D, 0x83, 0x67, 0x24, 0x6D, 0x83, + 0x45, 0x24, 0x5D, 0x83, 0x09, 0x24, 0x6D, 0x83, + 0x52, 0x24, 0x5D, 0x83, 0x46, 0x24, 0x5D, 0x83, + 0x33, 0x24, 0x5D, 0x83, 0x54, 0x24, 0x7B, 0x3C, + 0x0F, 0x93, 0x79, 0x24, 0x5E, 0x42, 0x83, 0x23, + 0x5E, 0x83, 0x08, 0x24, 0x5E, 0x83, 0x0F, 0x24, + 0x7E, 0x80, 0x1F, 0x00, 0x1C, 0x24, 0x5E, 0x83, + 0x13, 0x24, 0x6D, 0x3C, 0xC2, 0x43, 0x23, 0x09, + 0xF2, 0x40, 0x12, 0x00, 0x02, 0x24, 0x3C, 0x40, + 0x16, 0x25, 0x80, 0x00, 0xD8, 0x25, 0xC2, 0x43, + 0x23, 0x09, 0xF2, 0x40, 0x29, 0x00, 0x02, 0x24, + 0x3C, 0x40, 0x4C, 0x25, 0x80, 0x00, 0xD8, 0x25, + 0xF2, 0x40, 0x24, 0x00, 0x02, 0x24, 0x3C, 0x40, + 0x28, 0x25, 0x80, 0x00, 0xD8, 0x25, 0xC2, 0x43, + 0x23, 0x09, 0xF2, 0x40, 0x09, 0x00, 0x02, 0x24, + 0x3C, 0x40, 0x5E, 0x25, 0x80, 0x00, 0xD8, 0x25, + 0x0F, 0x93, 0x49, 0x24, 0xB0, 0x13, 0xC4, 0x27, + 0xC2, 0x43, 0x60, 0x24, 0xD2, 0x42, 0x01, 0x24, + 0x61, 0x24, 0x3B, 0x3C, 0xB0, 0x13, 0xCE, 0x27, + 0xD2, 0x42, 0x82, 0x23, 0x3F, 0x09, 0x80, 0x00, + 0x42, 0x26, 0xB0, 0x13, 0xCE, 0x27, 0xD2, 0x42, + 0x82, 0x23, 0x00, 0x24, 0xB0, 0x13, 0x42, 0x26, + 0xD2, 0x43, 0x12, 0x24, 0x10, 0x01, 0xC2, 0x43, + 0x23, 0x09, 0xD2, 0x43, 0x02, 0x24, 0x3C, 0x40, + 0x00, 0x24, 0x80, 0x00, 0xD8, 0x25, 0xB0, 0x13, + 0xCE, 0x27, 0xD2, 0x42, 0x84, 0x23, 0x01, 0x24, + 0x80, 0x00, 0x42, 0x26, 0x80, 0x00, 0x50, 0x26, + 0x5E, 0x42, 0x84, 0x23, 0x7E, 0xF0, 0x0F, 0x00, + 0x02, 0x20, 0x80, 0x00, 0x42, 0x26, 0x5E, 0x93, + 0x18, 0x20, 0xC2, 0x93, 0x84, 0x23, 0x04, 0x34, + 0xF2, 0xF0, 0xD7, 0x00, 0xC8, 0x23, 0xF5, 0x3F, + 0xF2, 0xF0, 0xD7, 0x00, 0x88, 0x23, 0xF1, 0x3F, + 0x7E, 0x90, 0x80, 0x00, 0x03, 0x20, 0xB0, 0x13, + 0xC4, 0x27, 0x43, 0x3F, 0x7E, 0x90, 0x82, 0x00, + 0x02, 0x20, 0x80, 0x00, 0xF8, 0x25, 0xB0, 0x13, + 0x76, 0x25, 0x10, 0x01, 0xC2, 0x43, 0x23, 0x09, + 0xE2, 0x43, 0x02, 0x24, 0x10, 0x01, 0xD5, 0x3E, + 0x1B, 0x15, 0x1F, 0x42, 0x5A, 0x24, 0x5B, 0x4F, + 0x03, 0x00, 0x5E, 0x4F, 0x01, 0x00, 0x5C, 0x4F, + 0x02, 0x00, 0x8C, 0x10, 0x0C, 0xDE, 0x0D, 0x4B, + 0x0E, 0x4F, 0x2E, 0x52, 0x6A, 0x4F, 0x7A, 0x80, + 0x10, 0x00, 0x29, 0x24, 0x5A, 0x83, 0x14, 0x24, + 0x5A, 0x83, 0x2A, 0x24, 0x5A, 0x83, 0x2E, 0x24, + 0x6A, 0x83, 0x23, 0x24, 0x5A, 0x83, 0x3A, 0x24, + 0x5A, 0x83, 0x15, 0x24, 0x5A, 0x83, 0x3B, 0x24, + 0x5A, 0x83, 0x3E, 0x24, 0x6A, 0x83, 0x41, 0x20, + 0x5F, 0x43, 0xB0, 0x13, 0xE2, 0x2B, 0x41, 0x3C, + 0x1F, 0x53, 0x0C, 0x4F, 0xB0, 0x13, 0x38, 0x2C, + 0x4C, 0x93, 0x02, 0x20, 0x4C, 0x43, 0x37, 0x3C, + 0x7C, 0x40, 0x05, 0x00, 0x34, 0x3C, 0xB0, 0x13, + 0x66, 0x2E, 0x03, 0x20, 0xB0, 0x13, 0x6E, 0x2E, + 0xF5, 0x3F, 0x6C, 0x42, 0x2C, 0x3C, 0x4F, 0x43, + 0xE8, 0x3F, 0xB0, 0x13, 0xD4, 0x2D, 0x27, 0x3C, + 0x0E, 0x4C, 0x0F, 0x4B, 0x4C, 0x43, 0xB0, 0x13, + 0xD4, 0x2C, 0x21, 0x3C, 0xB0, 0x13, 0x66, 0x2E, + 0xF0, 0x23, 0x4C, 0x43, 0x1F, 0x42, 0x58, 0x24, + 0x3F, 0x50, 0x40, 0x00, 0x1B, 0x42, 0x44, 0x01, + 0x3B, 0xF0, 0x10, 0x00, 0x0F, 0x5B, 0x82, 0x4F, + 0x44, 0x01, 0x11, 0x3C, 0xB0, 0x13, 0x3C, 0x2E, + 0xB0, 0x13, 0x12, 0x2B, 0x0E, 0x3C, 0xB0, 0x13, + 0x3C, 0x2E, 0xB0, 0x13, 0x66, 0x29, 0x09, 0x3C, + 0x2E, 0x42, 0x3C, 0x40, 0x00, 0x25, 0x0D, 0x43, + 0xF8, 0x3F, 0x7C, 0x40, 0x07, 0x00, 0xB0, 0x13, + 0x12, 0x2E, 0x1A, 0x17, 0x10, 0x01, 0xE2, 0xB2, + 0x3E, 0x09, 0x14, 0x28, 0xF2, 0x40, 0x80, 0x00, + 0x23, 0x09, 0x03, 0x3C, 0xF2, 0xF0, 0xFA, 0x00, + 0x3E, 0x09, 0xC2, 0x43, 0x10, 0x24, 0xC2, 0x43, + 0x60, 0x24, 0xC2, 0x43, 0x61, 0x24, 0xB0, 0x13, + 0x80, 0x26, 0xD2, 0xB3, 0x3E, 0x09, 0xF2, 0x2F, + 0xE2, 0xC2, 0x3E, 0x09, 0x1F, 0x42, 0x32, 0x09, + 0x7F, 0x90, 0x0A, 0x00, 0x0C, 0x20, 0xB0, 0x13, + 0x4A, 0x2E, 0xB0, 0x13, 0x86, 0x2C, 0xB0, 0x13, + 0x08, 0x2A, 0xB2, 0xF0, 0xF9, 0xFF, 0x08, 0x09, + 0xA2, 0xD3, 0x02, 0x09, 0x10, 0x01, 0x7F, 0x90, + 0x0C, 0x00, 0x06, 0x20, 0xB0, 0x13, 0x4A, 0x2E, + 0xB2, 0x40, 0x04, 0xA5, 0x20, 0x01, 0x10, 0x01, + 0x7F, 0x90, 0x12, 0x00, 0x0A, 0x20, 0xC2, 0x43, + 0x23, 0x09, 0xD2, 0x93, 0x10, 0x24, 0x02, 0x20, + 0x80, 0x00, 0x80, 0x25, 0xF2, 0xD2, 0x20, 0x09, + 0x10, 0x01, 0x7F, 0x90, 0x16, 0x00, 0x02, 0x20, + 0x80, 0x00, 0x08, 0x2A, 0x7F, 0x90, 0x18, 0x00, + 0x0C, 0x20, 0xD2, 0x43, 0x11, 0x24, 0xF2, 0xC0, + 0x40, 0x00, 0x3E, 0x09, 0xB2, 0x40, 0x80, 0x00, + 0x10, 0x09, 0xF2, 0x40, 0x20, 0x00, 0x3D, 0x09, + 0x10, 0x01, 0x7F, 0x90, 0x1A, 0x00, 0x0A, 0x20, + 0xB0, 0x13, 0x86, 0x2C, 0xF2, 0xF0, 0x9F, 0x00, + 0x3E, 0x09, 0xF2, 0x40, 0xC0, 0x00, 0x3D, 0x09, + 0xC2, 0x43, 0x11, 0x24, 0x10, 0x01, 0x7B, 0x15, + 0x0A, 0x4C, 0x0B, 0x4D, 0x0F, 0x4E, 0x3F, 0xE3, + 0x0F, 0x5F, 0x0F, 0x7F, 0x08, 0x4C, 0x09, 0x4D, + 0x08, 0x5E, 0x09, 0x6F, 0x47, 0x43, 0x0B, 0x3C, + 0x1F, 0x42, 0x5C, 0x24, 0xFF, 0x40, 0x3A, 0x00, + 0x00, 0x00, 0x0C, 0x46, 0x1C, 0x53, 0xB0, 0x13, + 0x2A, 0x2E, 0x0A, 0x56, 0x0B, 0x63, 0x0B, 0x99, + 0x03, 0x28, 0x34, 0x20, 0x0A, 0x98, 0x32, 0x2C, + 0x47, 0x93, 0x30, 0x20, 0x0E, 0x48, 0x0F, 0x49, + 0x0E, 0x8A, 0x0F, 0x7B, 0x03, 0x20, 0x3E, 0x90, + 0x3E, 0x00, 0x03, 0x28, 0x36, 0x40, 0x3D, 0x00, + 0x02, 0x3C, 0x06, 0x48, 0x06, 0x8A, 0x14, 0x42, + 0x5C, 0x24, 0x14, 0x53, 0x0E, 0x46, 0x0F, 0x46, + 0x3F, 0xE3, 0x0F, 0x5F, 0x0F, 0x7F, 0x0E, 0x5A, + 0x0F, 0x6B, 0x09, 0x3C, 0x1F, 0x15, 0x0D, 0x16, + 0x6C, 0x4D, 0x0D, 0x4E, 0x0D, 0x8A, 0x05, 0x44, + 0x05, 0x5D, 0xC5, 0x4C, 0x00, 0x00, 0x3E, 0x53, + 0x3F, 0x63, 0x0F, 0x9B, 0xC9, 0x2B, 0x02, 0x20, + 0x0E, 0x9A, 0xC6, 0x2B, 0xB0, 0x13, 0x66, 0x2E, + 0xED, 0x27, 0x67, 0x42, 0x6C, 0x42, 0xB0, 0x13, + 0x12, 0x2E, 0xC7, 0x3F, 0x74, 0x17, 0x10, 0x01, + 0xF2, 0x40, 0x10, 0x00, 0x3C, 0x09, 0xC2, 0x43, + 0x12, 0x24, 0xC2, 0x43, 0x11, 0x24, 0xC2, 0x43, + 0x00, 0x24, 0xC2, 0x43, 0x01, 0x24, 0xC2, 0x43, + 0x3C, 0x09, 0xF2, 0x43, 0x02, 0x24, 0xF2, 0x43, + 0x04, 0x24, 0xC2, 0x43, 0x10, 0x24, 0x7E, 0x40, + 0x80, 0x00, 0xC2, 0x4E, 0x21, 0x09, 0xC2, 0x4E, + 0x23, 0x09, 0xF2, 0x40, 0x8C, 0x00, 0x20, 0x09, + 0xF2, 0x40, 0x8C, 0x00, 0x22, 0x09, 0xF2, 0x40, + 0x03, 0x00, 0x2F, 0x09, 0xF2, 0x40, 0x03, 0x00, + 0x2E, 0x09, 0xC2, 0x4E, 0xC8, 0x23, 0xF2, 0x40, + 0x10, 0x00, 0xC9, 0x23, 0xC2, 0x4E, 0xCA, 0x23, + 0xC2, 0x4E, 0xCE, 0x23, 0xF2, 0x40, 0x40, 0x00, + 0xCF, 0x23, 0xC2, 0x4E, 0x88, 0x23, 0xC2, 0x43, + 0x89, 0x23, 0xC2, 0x43, 0x8A, 0x23, 0xF2, 0x40, + 0x40, 0x00, 0x8F, 0x23, 0xF2, 0x40, 0x40, 0x00, + 0x3C, 0x09, 0xC2, 0x43, 0x3E, 0x09, 0xF2, 0x40, + 0xC0, 0x00, 0x3D, 0x09, 0x10, 0x01, 0x7B, 0x15, + 0x08, 0x4C, 0x07, 0x4D, 0x04, 0x4F, 0x4C, 0x43, + 0x0A, 0x48, 0x0B, 0x4D, 0x0F, 0x4E, 0x3F, 0xE3, + 0x0F, 0x5F, 0x0F, 0x7F, 0x06, 0x48, 0x06, 0x5E, + 0x07, 0x6F, 0x02, 0x3C, 0x1A, 0x53, 0x0B, 0x63, + 0x0B, 0x97, 0x03, 0x28, 0x2C, 0x20, 0x0A, 0x96, + 0x2A, 0x2C, 0x18, 0xB3, 0x08, 0x2C, 0x0E, 0x46, + 0x0F, 0x47, 0x3E, 0x53, 0x3F, 0x63, 0x0A, 0x9E, + 0x19, 0x20, 0x0B, 0x9F, 0x17, 0x20, 0x6E, 0x44, + 0xB0, 0x13, 0x66, 0x2E, 0x10, 0x20, 0x4C, 0x43, + 0xB0, 0x13, 0x56, 0x2E, 0x1B, 0x15, 0x0F, 0x16, + 0xCF, 0x4E, 0x00, 0x00, 0xB0, 0x13, 0x56, 0x2E, + 0x1B, 0x15, 0x0F, 0x16, 0x6D, 0x4F, 0x4E, 0x9D, + 0x03, 0x24, 0x5C, 0x43, 0x01, 0x3C, 0x6C, 0x42, + 0x14, 0x53, 0x07, 0x3C, 0x3E, 0x44, 0x0C, 0x4A, + 0x0D, 0x4B, 0xB0, 0x13, 0x64, 0x2D, 0x1A, 0x53, + 0x0B, 0x63, 0x4C, 0x93, 0xCF, 0x27, 0x74, 0x17, + 0x10, 0x01, 0x3B, 0x15, 0x0A, 0x4E, 0xB2, 0x43, + 0x54, 0x01, 0x08, 0x4C, 0x09, 0x4D, 0x07, 0x3C, + 0x19, 0x15, 0x0E, 0x16, 0x6F, 0x4E, 0xC2, 0x4F, + 0x52, 0x01, 0x18, 0x53, 0x09, 0x63, 0x0E, 0x4C, + 0x0F, 0x4D, 0x0E, 0x5A, 0x0F, 0x63, 0x09, 0x9F, + 0x03, 0x28, 0x09, 0x20, 0x08, 0x9E, 0x07, 0x2C, + 0xB0, 0x13, 0x66, 0x2E, 0xED, 0x27, 0x6C, 0x42, + 0xB0, 0x13, 0x12, 0x2E, 0x15, 0x3C, 0x1E, 0x42, + 0x54, 0x01, 0x1F, 0x42, 0x5C, 0x24, 0xFF, 0x40, + 0x3A, 0x00, 0x00, 0x00, 0x1B, 0x42, 0x5C, 0x24, + 0xCB, 0x4E, 0x01, 0x00, 0x47, 0x18, 0x0E, 0x11, + 0x1F, 0x42, 0x5C, 0x24, 0xCF, 0x4E, 0x02, 0x00, + 0x3C, 0x40, 0x03, 0x00, 0xB0, 0x13, 0x2A, 0x2E, + 0x38, 0x17, 0x10, 0x01, 0x32, 0xC2, 0x03, 0x43, + 0xB2, 0x40, 0x02, 0x1C, 0x5A, 0x24, 0xB2, 0x40, + 0x17, 0x24, 0x5C, 0x24, 0xB2, 0x40, 0x28, 0x96, + 0x00, 0x09, 0x82, 0x43, 0x02, 0x09, 0x82, 0x43, + 0x60, 0x01, 0xB2, 0x40, 0xF3, 0x10, 0x64, 0x01, + 0xB2, 0x40, 0x40, 0x00, 0x62, 0x01, 0xB2, 0x40, + 0x44, 0x02, 0x68, 0x01, 0xC2, 0x43, 0x0E, 0x24, + 0xC2, 0x43, 0x11, 0x24, 0xB2, 0x40, 0x28, 0x96, + 0x00, 0x09, 0xB2, 0x40, 0x40, 0x1E, 0x08, 0x09, + 0xB2, 0x40, 0x80, 0x00, 0x04, 0x09, 0xB0, 0x13, + 0x4A, 0x2E, 0xC2, 0x43, 0x12, 0x24, 0xB2, 0xB2, + 0x08, 0x09, 0x06, 0x28, 0xB0, 0x13, 0x86, 0x2C, + 0xB0, 0x13, 0x08, 0x2A, 0xA2, 0xD3, 0x02, 0x09, + 0x10, 0x01, 0x3B, 0x15, 0x4A, 0x4F, 0x6F, 0x42, + 0x3B, 0x40, 0x58, 0x24, 0xB0, 0x13, 0x66, 0x2E, + 0x08, 0x20, 0x4F, 0x43, 0xA2, 0x4B, 0x44, 0x01, + 0x28, 0x4B, 0x38, 0x50, 0x40, 0x00, 0x82, 0x48, + 0x40, 0x01, 0x4F, 0x93, 0x0B, 0x20, 0xB2, 0x90, + 0x05, 0x00, 0x5E, 0x24, 0x07, 0x38, 0x0F, 0x4E, + 0x1E, 0x42, 0x5E, 0x24, 0x2E, 0x82, 0xB0, 0x13, + 0x8E, 0x2A, 0x4F, 0x4C, 0x4A, 0x93, 0x03, 0x20, + 0x4C, 0x4F, 0xB0, 0x13, 0x12, 0x2E, 0xA2, 0x4B, + 0x40, 0x01, 0x2F, 0x4B, 0x3F, 0x50, 0x10, 0x00, + 0x82, 0x4F, 0x44, 0x01, 0x38, 0x17, 0x10, 0x01, + 0x1B, 0x15, 0x21, 0x83, 0x0D, 0x43, 0x3A, 0x40, + 0xE0, 0xFF, 0x0B, 0x43, 0x7E, 0x4A, 0x0F, 0x4C, + 0x0F, 0x5B, 0x6F, 0x4F, 0x0E, 0xEF, 0x0D, 0xDE, + 0x1B, 0x53, 0x3B, 0x90, 0x20, 0x00, 0xF6, 0x2B, + 0x0D, 0x93, 0x0E, 0x20, 0xB1, 0x40, 0xFF, 0x7F, + 0x00, 0x00, 0x02, 0x3C, 0xB1, 0x53, 0x00, 0x00, + 0x91, 0x93, 0x00, 0x00, 0xFB, 0x37, 0xB2, 0x40, + 0xA5, 0xA5, 0x56, 0x24, 0x4C, 0x43, 0x04, 0x3C, + 0xB0, 0x13, 0xD4, 0x2D, 0x7C, 0x40, 0x05, 0x00, + 0x21, 0x53, 0x1A, 0x17, 0x10, 0x01, 0x21, 0x82, + 0x81, 0x43, 0x02, 0x00, 0xB2, 0x40, 0x28, 0x96, + 0x00, 0x09, 0x92, 0xD3, 0x02, 0x09, 0x92, 0x42, + 0x14, 0x24, 0x12, 0x09, 0xB2, 0x40, 0x00, 0x13, + 0x10, 0x09, 0x82, 0x43, 0x14, 0x09, 0x81, 0x43, + 0x00, 0x00, 0x02, 0x3C, 0x91, 0x53, 0x00, 0x00, + 0xB1, 0x90, 0x64, 0x00, 0x00, 0x00, 0xFA, 0x2B, + 0x1F, 0x41, 0x02, 0x00, 0x0E, 0x4F, 0x1E, 0x53, + 0x81, 0x4E, 0x02, 0x00, 0x3F, 0x90, 0xE9, 0x03, + 0x03, 0x2C, 0x82, 0x93, 0x14, 0x09, 0xE9, 0x23, + 0x21, 0x52, 0x10, 0x01, 0xB0, 0x13, 0x66, 0x2E, + 0x0E, 0x20, 0x4C, 0x43, 0xB0, 0x13, 0xFA, 0x2C, + 0x1D, 0x42, 0x58, 0x24, 0x2D, 0x53, 0x82, 0x4D, + 0x40, 0x01, 0x1F, 0x15, 0x0D, 0x16, 0xCD, 0x43, + 0x00, 0x00, 0x80, 0x00, 0x08, 0x2D, 0x6C, 0x42, + 0x10, 0x01, 0x92, 0xB3, 0x44, 0x01, 0xFD, 0x2F, + 0x92, 0x42, 0x58, 0x24, 0x44, 0x01, 0x10, 0x01, + 0x92, 0xB3, 0x44, 0x01, 0xFD, 0x2F, 0x1F, 0x42, + 0x58, 0x24, 0x3F, 0x50, 0x10, 0x00, 0x82, 0x4F, + 0x44, 0x01, 0x10, 0x01, 0x82, 0x43, 0x5E, 0x24, + 0xC2, 0x43, 0x8A, 0x23, 0xB0, 0x13, 0xA6, 0x28, + 0xD2, 0x93, 0x12, 0x24, 0x0D, 0x20, 0xC2, 0x93, + 0x11, 0x24, 0x0A, 0x20, 0x4F, 0x43, 0xC2, 0x93, + 0x8A, 0x23, 0x04, 0x34, 0x5F, 0x42, 0x8A, 0x23, + 0x7F, 0xF0, 0x7F, 0x00, 0x82, 0x4F, 0x5E, 0x24, + 0x82, 0x93, 0x5E, 0x24, 0xEB, 0x27, 0x92, 0x93, + 0x5E, 0x24, 0x06, 0x38, 0x5F, 0x42, 0x01, 0x1C, + 0x82, 0x4F, 0x5E, 0x24, 0x5C, 0x43, 0x10, 0x01, + 0x4C, 0x43, 0x10, 0x01, 0x1B, 0x15, 0xB0, 0x13, + 0x66, 0x2E, 0x15, 0x20, 0x4F, 0x43, 0xB0, 0x13, + 0x56, 0x2E, 0x1D, 0x15, 0x0A, 0x16, 0x8A, 0x4E, + 0x00, 0x00, 0xB0, 0x13, 0x56, 0x2E, 0x1D, 0x15, + 0x0A, 0x16, 0x2B, 0x4A, 0x0E, 0x9B, 0x01, 0x24, + 0x5F, 0x43, 0x92, 0xB3, 0x46, 0x01, 0x04, 0x28, + 0x7F, 0x40, 0x03, 0x00, 0x01, 0x3C, 0x6F, 0x42, + 0x4C, 0x4F, 0x1A, 0x17, 0x10, 0x01, 0x0A, 0x12, + 0x7E, 0x40, 0x3F, 0x00, 0xC2, 0x93, 0xCA, 0x23, + 0x11, 0x34, 0xC2, 0x4E, 0x80, 0x1C, 0x3D, 0x40, + 0x81, 0x1C, 0x4F, 0x43, 0x0A, 0x4C, 0x0A, 0x5F, + 0xED, 0x4A, 0x00, 0x00, 0x1D, 0x53, 0x5F, 0x53, + 0x4F, 0x9E, 0xF8, 0x2B, 0xF2, 0x40, 0x40, 0x00, + 0xCA, 0x23, 0x01, 0x3C, 0x4E, 0x43, 0x4C, 0x4E, + 0x3A, 0x41, 0x10, 0x01, 0xB0, 0x13, 0xFA, 0x2C, + 0xB0, 0x13, 0x56, 0x2E, 0x1F, 0x42, 0x58, 0x24, + 0x3F, 0x50, 0x06, 0x00, 0x82, 0x4F, 0x40, 0x01, + 0xC2, 0x43, 0xE0, 0xFF, 0xB0, 0x13, 0x08, 0x2D, + 0x4C, 0x43, 0x10, 0x01, 0xB2, 0x40, 0xA5, 0xA5, + 0x56, 0x24, 0xB2, 0x40, 0x00, 0xA5, 0x58, 0x24, + 0xB0, 0x13, 0x7C, 0x2B, 0xB0, 0x13, 0x1C, 0x2D, + 0x5C, 0xB3, 0xFC, 0x2B, 0xB0, 0x13, 0xD0, 0x27, + 0xF9, 0x3F, 0x1F, 0x42, 0x5C, 0x24, 0xFF, 0x40, + 0x3B, 0x00, 0x00, 0x00, 0x1F, 0x42, 0x5C, 0x24, + 0xCF, 0x4C, 0x01, 0x00, 0x2C, 0x43, 0x80, 0x00, + 0x2A, 0x2E, 0xC2, 0x4C, 0x16, 0x24, 0x3C, 0x40, + 0x16, 0x24, 0xB0, 0x13, 0x9E, 0x2D, 0x4C, 0x93, + 0xFA, 0x27, 0x10, 0x01, 0x6E, 0x4E, 0x5F, 0x4F, + 0x05, 0x00, 0x47, 0x18, 0x0F, 0x5F, 0x0E, 0xDF, + 0x10, 0x01, 0x03, 0x43, 0x3F, 0x40, 0xDE, 0x2E, + 0x3F, 0x53, 0xFE, 0x2F, 0x10, 0x01, 0x92, 0xB3, + 0x44, 0x01, 0xFD, 0x2F, 0x10, 0x01, 0xB2, 0x40, + 0x80, 0x5A, 0x5C, 0x01, 0x10, 0x01, 0xB2, 0x90, + 0xA5, 0xA5, 0x56, 0x24, 0x10, 0x01, 0x1D, 0x15, + 0x10, 0x01 +}; + +const struct loadbsl_fw loadbsl_fw_usb5xx = { + .data = RAM_BSL_00_05_04_34, + .size = sizeof(RAM_BSL_00_05_04_34), + .prog_addr = 0x2500, + .entry_point = 0x2504 +}; diff --git a/drivers/loadbsl_fw.h b/drivers/loadbsl_fw.h new file mode 100644 index 0000000..15fa1a7 --- /dev/null +++ b/drivers/loadbsl_fw.h @@ -0,0 +1,34 @@ +/* MSPDebug - debugging tool for the eZ430 + * Copyright (C) 2009-2012 Daniel Beer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef LOADBSL_FW_H_ +#define LOADBSL_FW_H_ + +#include + +/* USB BSL firmware image */ +struct loadbsl_fw { + const uint8_t *data; + const uint32_t size; + const uint32_t prog_addr; + const uint32_t entry_point; +}; + +extern const struct loadbsl_fw loadbsl_fw_usb5xx; + +#endif diff --git a/transport/bslhid.c b/transport/bslhid.c new file mode 100644 index 0000000..f816132 --- /dev/null +++ b/transport/bslhid.c @@ -0,0 +1,378 @@ +/* MSPDebug - debugging tool for MSP430 MCUs + * Copyright (C) 2009-2013 Daniel Beer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include +#include "usbutil.h" +#include "output.h" +#include "output_util.h" +#include "bslhid.h" + +#define BSLHID_VID 0x2047 +#define BSLHID_PID 0x0200 + +#define BSLHID_CLASS USB_CLASS_HID + +#define BSLHID_XFER_SIZE 64 +#define BSLHID_MTU (BSLHID_XFER_SIZE - 2) +#define BSLHID_HEADER 0x3F +#define BSLHID_TIMEOUT 5000 + +struct bslhid_transport { + struct transport base; + + int cfg_number; + int int_number; + + struct usb_dev_handle *handle; + + int in_ep; + int out_ep; + + char bus_name[PATH_MAX + 1]; +}; + +static int find_interface(struct bslhid_transport *tr, + const struct usb_device *dev) +{ + int c; + + for (c = 0; c < dev->descriptor.bNumConfigurations; c++) { + const struct usb_config_descriptor *cfg = &dev->config[c]; + int i; + + for (i = 0; i < cfg->bNumInterfaces; i++) { + const struct usb_interface *intf = &cfg->interface[i]; + const struct usb_interface_descriptor *desc = + &intf->altsetting[0]; + + if (desc->bInterfaceClass == BSLHID_CLASS) { + tr->cfg_number = c; + tr->int_number = i; + return 0; + } + } + } + + printc_err("bslhid: can't find a matching interface\n"); + return -1; +} + +static int find_endpoints(struct bslhid_transport *tr, + const struct usb_device *dev) +{ + const struct usb_interface_descriptor *desc = + &dev->config[tr->cfg_number].interface[tr->int_number]. + altsetting[0]; + int i; + + tr->in_ep = -1; + tr->out_ep = -1; + + for (i = 0; i < desc->bNumEndpoints; i++) { + int addr = desc->endpoint[i].bEndpointAddress; + + if (addr & USB_ENDPOINT_DIR_MASK) + tr->in_ep = addr; + else + tr->out_ep = addr; + } + + if (tr->in_ep < 0 || tr->out_ep < 0) { + printc_err("bslhid: can't find suitable endpoints\n"); + return -1; + } + + return 0; +} + +static int open_device(struct bslhid_transport *tr, struct usb_device *dev) +{ + if (find_interface(tr, dev) < 0) + return -1; + + printc_dbg("Opening interface %d (config %d)...\n", + tr->int_number, tr->cfg_number); + + if (find_endpoints(tr, dev) < 0) + return -1; + + printc_dbg("Found endpoints: IN: 0x%02x, OUT: 0x%02x\n", + tr->in_ep, tr->out_ep); + + tr->handle = usb_open(dev); + if (!tr->handle) { + pr_error("bslhid: can't open device"); + return -1; + } + +#ifdef __Windows__ + if (usb_set_configuration(tr->handle, tr->cfg_number) < 0) + pr_error("warning: bslhid: can't set configuration"); +#endif + +#ifdef __linux__ + if (usb_detach_kernel_driver_np(tr->handle, tr->int_number) < 0) + pr_error("warning: bslhid: can't detach kernel driver"); +#endif + + if (usb_claim_interface(tr->handle, tr->int_number) < 0) { + pr_error("bslhid: can't claim interface"); + usb_close(tr->handle); + return -1; + } + + /* Save the bus path for a future suspend/resume */ + strncpy(tr->bus_name, dev->bus->dirname, sizeof(tr->bus_name)); + tr->bus_name[sizeof(tr->bus_name) - 1] = 0; + + return 0; +} + +static void bslhid_destroy(transport_t base) +{ + struct bslhid_transport *tr = (struct bslhid_transport *)base; + + if (tr->handle) { + usb_release_interface(tr->handle, tr->int_number); + usb_close(tr->handle); + } + + free(tr); +} + +static int bslhid_flush(transport_t base) +{ +#ifndef __APPLE__ + struct bslhid_transport *tr = (struct bslhid_transport *)base; + uint8_t inbuf[BSLHID_XFER_SIZE]; + + if (!tr->handle) + return 0; + + while (usb_bulk_read(tr->handle, tr->in_ep, + (char *)inbuf, sizeof(inbuf), 100) > 0); +#endif + + return 0; +} + +static int bslhid_send(transport_t base, const uint8_t *data, int len) +{ + struct bslhid_transport *tr = (struct bslhid_transport *)base; + uint8_t outbuf[BSLHID_XFER_SIZE]; + + if (!tr->handle) { + printc_err("bslhid: send on suspended device\n"); + return -1; + } + + memset(outbuf, 0xac, sizeof(outbuf)); + + if (len > BSLHID_MTU) { + printc_err("bslhid: send in excess of MTU: %d\n", len); + return -1; + } + + outbuf[0] = BSLHID_HEADER; + outbuf[1] = len; + memcpy(outbuf + 2, data, len); + +#ifdef DEBUG_BSLHID + debug_hexdump("bslhid_send", outbuf, sizeof(outbuf)); +#endif + + if (usb_bulk_write(tr->handle, tr->out_ep, + (char *)outbuf, sizeof(outbuf), + BSLHID_TIMEOUT) < 0) { + printc_err("bslhid: usb_bulk_write: %s\n", usb_strerror()); + return -1; + } + + return 0; +} + +static int bslhid_recv(transport_t base, uint8_t *data, int max_len) +{ + struct bslhid_transport *tr = (struct bslhid_transport *)base; + uint8_t inbuf[BSLHID_XFER_SIZE]; + int r; + int len; + + if (!tr->handle) { + printc_err("bslhid: recv on suspended device\n"); + return -1; + } + + r = usb_bulk_read(tr->handle, tr->in_ep, + (char *)inbuf, sizeof(inbuf), BSLHID_TIMEOUT); + if (r <= 0) { + printc_err("bslhid_recv: usb_bulk_read: %s\n", usb_strerror()); + return -1; + } + +#ifdef DEBUG_BSLHID + debug_hexdump("bslhid_recv", inbuf, r); +#endif + + if (r < 2) { + printc_err("bslhid_recv: short transfer\n"); + return -1; + } + + if (inbuf[0] != BSLHID_HEADER) { + printc_err("bslhid_recv: missing transfer header\n"); + return -1; + } + + len = inbuf[1]; + if ((len > max_len) || (len + 2 > r)) { + printc_err("bslhid_recv: bad length: %d (%d byte transfer)\n", + len, r); + return -1; + } + + memcpy(data, inbuf + 2, len); + return len; +} + +static int bslhid_set_modem(transport_t base, transport_modem_t state) +{ + printc_err("bslhid: unsupported operation: set_modem\n"); + return -1; +} + +static int bslhid_suspend(transport_t base) +{ + struct bslhid_transport *tr = (struct bslhid_transport *)base; + + if (tr->handle) { + usb_release_interface(tr->handle, tr->int_number); + usb_close(tr->handle); + tr->handle = NULL; + } + + return 0; +} + +static struct usb_bus *find_by_name(const char *name) +{ + struct usb_bus *b; + + for (b = usb_get_busses(); b; b = b->next) + if (!strcmp(name, b->dirname)) + return b; + + return NULL; +} + +static struct usb_device *find_first_bsl(struct usb_bus *bus) +{ + struct usb_device *d; + + for (d = bus->devices; d; d = d->next) + if ((d->descriptor.idVendor == BSLHID_VID) && + (d->descriptor.idProduct == BSLHID_PID)) + return d; + + return NULL; +} + +static int bslhid_resume(transport_t base) +{ + struct bslhid_transport *tr = (struct bslhid_transport *)base; + struct usb_bus *bus; + struct usb_device *dev; + + if (tr->handle) + return 0; + + usb_init(); + usb_find_busses(); + usb_find_devices(); + + bus = find_by_name(tr->bus_name); + if (!bus) { + printc_err("bslhid: can't find bus to resume from\n"); + return -1; + } + + /* We can't portably distinguish physical locations, so this + * will have to do. + */ + dev = find_first_bsl(bus); + if (!dev) { + printc_err("bslhid: can't find a BSL HID on this bus\n"); + return -1; + } + + if (open_device(tr, dev) < 0) { + printc_err("bslhid: failed to resume BSL HID device\n"); + return -1; + } + + return 0; +} + +static const struct transport_class bslhid_transport_class = { + .destroy = bslhid_destroy, + .send = bslhid_send, + .recv = bslhid_recv, + .flush = bslhid_flush, + .set_modem = bslhid_set_modem, + .suspend = bslhid_suspend, + .resume = bslhid_resume +}; + +transport_t bslhid_open(const char *dev_path, const char *requested_serial) +{ + struct bslhid_transport *tr = malloc(sizeof(*tr)); + struct usb_device *dev; + + if (!tr) { + pr_error("bslhid: can't allocate memory"); + return NULL; + } + + memset(tr, 0, sizeof(*tr)); + tr->base.ops = &bslhid_transport_class; + + usb_init(); + usb_find_busses(); + usb_find_devices(); + + if (dev_path) + dev = usbutil_find_by_loc(dev_path); + else + dev = usbutil_find_by_id(BSLHID_VID, BSLHID_PID, + requested_serial); + + if (!dev) { + free(tr); + return NULL; + } + + if (open_device(tr, dev) < 0) { + printc_err("bslhid: failed to open BSL HID device\n"); + free(tr); + return NULL; + } + + bslhid_flush(&tr->base); + return &tr->base; +} diff --git a/transport/bslhid.h b/transport/bslhid.h new file mode 100644 index 0000000..3ec95eb --- /dev/null +++ b/transport/bslhid.h @@ -0,0 +1,30 @@ +/* MSPDebug - debugging tool for MSP430 MCUs + * Copyright (C) 2009-2013 Daniel Beer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef BSLHID_H_ +#define BSLHID_H_ + +#include "transport.h" + +/* Open a USB HID device used to wrap the USB bootstrap loader serial + * protocol. The interface is described in SLAU319C: "MSP430 Programming + * via the Bootstrap Loader". + */ +transport_t bslhid_open(const char *dev_path, const char *requested_serial); + +#endif diff --git a/ui/main.c b/ui/main.c index 364a992..a84db63 100644 --- a/ui/main.c +++ b/ui/main.c @@ -54,6 +54,7 @@ #include "input.h" #include "input_async.h" #include "pif.h" +#include "loadbsl.h" #ifdef __CYGWIN__ #include @@ -82,7 +83,8 @@ static const struct device_class *const driver_table[] = { &device_gdbc, &device_tilib, &device_goodfet, - &device_pif + &device_pif, + &device_loadbsl }; static const char *version_text = diff --git a/util/usbutil.c b/util/usbutil.c index 9eab111..32831d1 100644 --- a/util/usbutil.c +++ b/util/usbutil.c @@ -1,5 +1,5 @@ /* MSPDebug - debugging tool for MSP430 MCUs - * Copyright (C) 2009, 2010 Daniel Beer + * Copyright (C) 2009-2013 Daniel Beer * * 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 @@ -36,7 +36,8 @@ static const char *device_help(const struct usb_device *dev) {0x15ba, 0x0002, "Olimex MSP430-JTAG-TINY (v1)"}, {0x15ba, 0x0008, "Olimex MSP430-JTAG-ISO"}, {0x15ba, 0x0031, "Olimex MSP430-JTAG-TINY (v2)"}, - {0x15ba, 0x0100, "Olimex MSP430-JTAG-ISO-MK2 (v2)"} + {0x15ba, 0x0100, "Olimex MSP430-JTAG-ISO-MK2 (v2)"}, + {0x2047, 0x0200, "USB bootstrap loader"} }; int i;