blackmagic/upgrade/stm32mem.c

104 lines
2.6 KiB
C

/*
* This file is part of the Black Magic Debug project.
*
* Copyright (C) 2011 Black Sphere Technologies Ltd.
* Written by Gareth McMullin <gareth@blacksphere.co.nz>
*
* 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 3 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/>.
*/
#include <string.h>
#ifdef WIN32
# include <windows.h>
# include <lusb0_usb.h>
#else
# include <unistd.h>
# include <usb.h>
#endif
#include "dfu.h"
#include "stm32mem.h"
#define STM32_CMD_GETCOMMANDS 0x00
#define STM32_CMD_SETADDRESSPOINTER 0x21
#define STM32_CMD_ERASE 0x41
static int stm32_download(usb_dev_handle *dev, uint16_t iface,
uint16_t wBlockNum, void *data, int size)
{
dfu_status status;
int i;
if((i = dfu_dnload(dev, iface, wBlockNum, data, size)) < 0) return i;
while(1) {
if((i = dfu_getstatus(dev, iface, &status)) < 0) return i;
switch(status.bState) {
case STATE_DFU_DOWNLOAD_BUSY:
#ifdef WIN32
Sleep(status.bwPollTimeout);
#else
usleep(status.bwPollTimeout * 1000);
#endif
break;
case STATE_DFU_DOWNLOAD_IDLE:
return 0;
default:
return -1;
}
}
}
int stm32_mem_erase(usb_dev_handle *dev, uint16_t iface, uint32_t addr)
{
uint8_t request[5];
request[0] = STM32_CMD_ERASE;
memcpy(request+1, &addr, sizeof(addr));
return stm32_download(dev, iface, 0, request, sizeof(request));
}
int stm32_mem_write(usb_dev_handle *dev, uint16_t iface, void *data, int size, uint32_t addr)
{
uint8_t request[5];
request[0] = STM32_CMD_SETADDRESSPOINTER;
memcpy(request+1, &addr, sizeof(addr));
stm32_download(dev, iface, 0, request, sizeof(request));
return stm32_download(dev, iface, 2, data, size);
}
int stm32_mem_manifest(usb_dev_handle *dev, uint16_t iface)
{
dfu_status status;
int i;
if((i = dfu_dnload(dev, iface, 0, NULL, 0)) < 0) return i;
while(1) {
if((i = dfu_getstatus(dev, iface, &status)) < 0) return 0;
#ifdef WIN32
Sleep(status.bwPollTimeout);
#else
usleep(status.bwPollTimeout * 1000);
#endif
switch(status.bState) {
case STATE_DFU_MANIFEST:
return 0;
default:
return -1;
}
}
}