STM32 ISP 下载程序, C源码,

鉴于flymcu下载时有点慢,flash_loader.exe容易卡死的原因,所以决定自己写个串口编程和控制台程序。然后写成bat文件,再整合到Visual studio的外部工具里,实现一键下载。

STM32_ISP的协议文档可以在st的官网上找到。

先说下控制台的大致思路:

程序的目标:把*.bin文件通过指定串口发送到stm32,stm32把收到的*.bin文件数据存到指定的flash地址。

控制台这边要给的指令是:例如:COM4 256000 0X08000000 M:\code\debug\text.bin

1.电脑的串口编号: COM4

2.要使用的串口波特率: 256000

3.编程地址: 0X08000000

4.*.bin文件路径: M:\code\debug\text.bin

所有的指令可以通过int main(int argc, char** argv),的**argv指针获得。

例如:把上面的指令通过CMD输入后

程序:
 

int main(int argc, char** argv)
{
    for (int i = 0; i < argc; i++)
    {
        printf("argv[%d]:%s\n", i, argv[i]);
    }

}

运行结果:

argv[0]:M:\stm32_isp_programer\stm32_isp_programmer\Debug\stm32_isp_programmer.exe
argv[1]:COM6
argv[2]:256000
argv[3]:0X08000000
argv[4]:M:\code\debug\text.bin

但是获得只是文本类型(char *)。

windows 要打开串口的话用需要用WCHAR* 类型。

所以要做一定的类型转换。

字符串转WCHAR:

#include <Windows.h>
wchar_t wstr[20];
swprintf(wstr, 20, L"%S", str);
LPCWSTR wstr_p= wstr;

字符串转10进制

字符串转16进制

#include <stdlib.h>
long baudrate = strtol(setBuadrate_p, &endptr, 10);
long writeAddress = strtol(writeAddress_p, &endptr, 16);

然后是打开串口:

SerialPort.hSerial = CreateFile(filename, //lpFileName
		GENERIC_READ | GENERIC_WRITE,//dwDesiredAccess
		0, //dwShareMode
		NULL,//lpSecurityAttributes
		OPEN_EXISTING,//dwCreationDisposition
		FILE_ATTRIBUTE_NORMAL,
		NULL);//hTemplateFile

串口配制:

SerialPort.NewDCBParams.BaudRate = baudrate;
SerialPort.NewDCBParams.ByteSize = 8;
SerialPort.NewDCBParams.StopBits = ONESTOPBIT;
SerialPort.NewDCBParams.Parity = EVENPARITY;
if (!SetCommState(SerialPort.hSerial, &SerialPort.NewDCBParams)) {
    printf("\nSetCommState error!\n");
    fflush(stdout);
    return(1);
}
COMMTIMEOUTS timeouts = { 0 };
timeouts.ReadIntervalTimeout = 1000;
timeouts.ReadTotalTimeoutConstant = 1000;
timeouts.ReadTotalTimeoutMultiplier = 10;
timeouts.WriteTotalTimeoutConstant = 50;
timeouts.WriteTotalTimeoutMultiplier = 10;
if (!SetCommTimeouts(SerialPort.hSerial, &timeouts)) {
    printf("\nSetCommTimeouts error!\n");
    fflush(stdout);
    return(1);
}

串口读写:

DWORD serial_write(unsigned char* buffer, DWORD len)
{
	DWORD lengthwrote;
	if (!WriteFile(SerialPort.hSerial, buffer, len, &lengthwrote, NULL)) {
		if (GetLastError() == ERROR_IO_PENDING)
		{
			printf("Error:%d Serial write fail, exiting lengthwrote:%d\n", GetLastError(), lengthwrote);
		}
		printf("Error:%d Serial write fail, exiting lengthwrote:%d\n", GetLastError(), lengthwrote);
		exit(1);
	}
	return(lengthwrote);
}
DWORD serial_read(unsigned char* buffer, size_t len) //windows version
{
	DWORD bytesread;
	if (!ReadFile(SerialPort.hSerial, buffer, len, &bytesread, NULL)) {
		printf("Error: Serial read fail, exiting\n");
		exit(1);
	}
	return(bytesread);
}

如果有加了RTS#控制的话,还可以用RTS来控制单片机复位:

void hardwareReset()
{
	UINT8 restTime = 5;
	while (restTime--)
	{
		if (!EscapeCommFunction(SerialPort.hSerial, SETRTS)) {
			printf("\nEscapeCommFunction error in serial_config, SETRTS\n");
			fflush(stdout);
			exit(1);
		}
		Sleep(100);
		if (!EscapeCommFunction(SerialPort.hSerial, CLRRTS)) {
			printf("\nEscapeCommFunction error in serial_config, SETRTS\n");
			fflush(stdout);
			exit(1);
		}
		Sleep(100);
		printf("%d\n", restTime);
	}
}

后面是STM32 ISP协议部分:

主要用到这几个:

void autoBaudrateStart(void);//自动识别波特率
void clear_writeprotect(void);//清除写保护
void get_version(void);//获取bootloader版本号,不同版本支持的指令不一样
void get_id(void);//获取芯片ID
void globalerase_flash(void);//全片清除flash
void program_memory(void);//flash编程

然后是通信格式:

基本是:

1字节命令+1字节命令反码

N字节内容+1字节所有内容字节的^(异或运算)

通信流程:发送指令,等待ACK或者NACK,发送内容,等待ACK或者NACK

主程序:

#include <Windows.h>
#include <stdio.h>
#include <tchar.h>
#include "Serial.h"
#include "action.h"
#include <stdlib.h>
/*
COM3 115200 0X08000000 D:SDALJGG.BIN

*/
int main(int argc, char** argv)
{
	SYSTEMTIME bootTime;
	SYSTEMTIME exitTime;
	char* selectPort_p;
	char* setBuadrate_p;
	char* writeAddress_p;
	char* loadFile;
	GetSystemTime(&bootTime);
	for (int i = 0; i < argc; i++)
	{
		printf("argv[%d]:%s\n", i, argv[i]);
	}
	selectPort_p = argv[1];
	setBuadrate_p = argv[2];
	writeAddress_p = argv[3];
	loadFile = argv[4];
	printf("selectPort:%s\n", selectPort_p); 
	printf("setBuadrate_p:%s\n", setBuadrate_p);
	printf("writeAddress_p:%s\n", writeAddress_p);
	printf("loadFile:%s\n", loadFile);
	char *endptr;	
	long baudrate = strtol(setBuadrate_p, &endptr, 10);
	long writeAddress = strtol(writeAddress_p, &endptr, 16);
	hostHandle.baudrate = baudrate;
	hostHandle.loadFile = loadFile;
	hostHandle.serialDev = selectPort_p;
	hostHandle.writeAddress = writeAddress;
	serial_init(selectPort_p, baudrate);
	autoBaudrateStart();
	get_version();
	get_id();
	clear_writeprotect();
	globalerase_flash();
	program_memory();
	printf("Isp complete and reseting...\n");
	hardwareReset();
	GetSystemTime(&exitTime);
	size_t timeUse = (exitTime.wMinute * 60 + exitTime.wSecond) * 1000 + exitTime.wMilliseconds;
	timeUse = timeUse - ((bootTime.wMinute * 60 + bootTime.wSecond) * 1000 + bootTime.wMilliseconds);
	printf("Total time use: %d.%d seconds\n", timeUse/1000, timeUse%1000);	
}

串口配置:

#pragma once
#include <Windows.h>
char serial_init(char * serialPortName, UINT32 baudrate);
DWORD serial_write(unsigned char* buffer, DWORD len);
DWORD serial_read(unsigned char* buffer, size_t len);
void Serial_putc(unsigned char c);
unsigned char Serial_getc(void);
void hardwareReset();
typedef struct  {
	int open;
	int status;
	HANDLE hSerial;
	DCB OldDCBParams;
	DCB NewDCBParams;
}SerialPort_s;
extern SerialPort_s SerialPort;
#include <Windows.h>
#include <tchar.h>
#include <stdio.h>
#include "Serial.h"

SerialPort_s SerialPort;
void hardwareReset()
{
	UINT8 restTime = 5;
	while (restTime--)
	{
		if (!EscapeCommFunction(SerialPort.hSerial, SETRTS)) {
			printf("\nEscapeCommFunction error in serial_config, SETRTS\n");
			fflush(stdout);
			exit(1);
		}
		Sleep(100);
		if (!EscapeCommFunction(SerialPort.hSerial, CLRRTS)) {
			printf("\nEscapeCommFunction error in serial_config, SETRTS\n");
			fflush(stdout);
			exit(1);
		}
		Sleep(100);
		printf("%d\n", restTime);
	}
}
char serial_init(char *serialPortName, UINT32 baudrate)
{
	wchar_t portName[20];
	swprintf(portName, 20, L"%S", serialPortName);
	LPCWSTR filename = portName;
	SerialPort.hSerial = CreateFile(filename, //lpFileName
		GENERIC_READ | GENERIC_WRITE,//dwDesiredAccess
		0, //dwShareMode
		NULL,//lpSecurityAttributes
		OPEN_EXISTING,//dwCreationDisposition
		FILE_ATTRIBUTE_NORMAL,
		NULL);//hTemplateFile

	if (SerialPort.hSerial == INVALID_HANDLE_VALUE)
	{
		if (GetLastError() == ERROR_FILE_NOT_FOUND) 
		{
			printf("ERROR_FILE_NOT_FOUND: Serial port: %ws not found on your computer.\n", filename);
			fflush(stdout);
			return(1);
		}
		else if (GetLastError() == ERROR_ACCESS_DENIED) 
		{
			printf("ERROR_ACCESS_DENIED: Serisl port: %ws Access denied!\n", filename);
			fflush(stdout);
			return(1);
		}
		else if (GetLastError() == ERROR_INVALID_NAME)
		{
			printf("ERROR_INVALID_NAME Error: Serisl port: %ws !\n", filename);
			fflush(stdout);
			return(1);
		}
		else {
			printf("Error: Serial operat failure. Error Code:%ld\n", GetLastError());
			fflush(stdout);
			return(1);
		}
	}			
	printf("Serial port: %s open success!\n", serialPortName);
	//success!

	switch (baudrate) {
	case 2400:
		SerialPort.NewDCBParams.BaudRate = CBR_2400;
		break;
	case 4800:
		SerialPort.NewDCBParams.BaudRate = CBR_4800;
		break;
	case 9600:
		SerialPort.NewDCBParams.BaudRate = CBR_9600;
		break;
	case 19200:
		SerialPort.NewDCBParams.BaudRate = CBR_19200;
		break;
	case 38400:
		SerialPort.NewDCBParams.BaudRate = CBR_38400;
		break;
	case 57600:
		SerialPort.NewDCBParams.BaudRate = CBR_57600;
		break;
	case 115200:
		SerialPort.NewDCBParams.BaudRate = CBR_115200;
		break;
	case 256000:
		SerialPort.NewDCBParams.BaudRate = CBR_256000;
		break;
	default:
		SerialPort.NewDCBParams.BaudRate = baudrate;
		printf("baudrate:%d may not support.\n", baudrate);
		fflush(stdout);
		break;
	}
	SerialPort.NewDCBParams.ByteSize = 8;
	SerialPort.NewDCBParams.StopBits = ONESTOPBIT;
	SerialPort.NewDCBParams.Parity = EVENPARITY;
	if (!SetCommState(SerialPort.hSerial, &SerialPort.NewDCBParams)) {
		printf("\nSetCommState error!\n");
		fflush(stdout);
		return(1);
	}
	COMMTIMEOUTS timeouts = { 0 };
	timeouts.ReadIntervalTimeout = 1000;
	timeouts.ReadTotalTimeoutConstant = 1000;
	timeouts.ReadTotalTimeoutMultiplier = 10;
	timeouts.WriteTotalTimeoutConstant = 50;
	timeouts.WriteTotalTimeoutMultiplier = 10;
	if (!SetCommTimeouts(SerialPort.hSerial, &timeouts)) {
		printf("\nSetCommTimeouts error!\n");
		fflush(stdout);
		return(1);
	}
	printf("Serial port: %s\n", serialPortName);
	printf("Buadrate: %d\n", baudrate);
	printf("Data bits: 8\n");
	printf("Parity: Even\n");
	printf("Stop bits: 1\n");
	printf("Flow control: none\n");
	printf("Serial init complete!\n");
	printf("\n\n\nTrying to rest and connet target, please push and hold ""boot0"" button!\n");
	printf("Using RTS LOW to reset taeget...\n");
	hardwareReset();
	PurgeComm(SerialPort.hSerial, (PURGE_RXCLEAR));
	return 0;
}
DWORD serial_write(unsigned char* buffer, DWORD len)
{
	DWORD lengthwrote;
	if (!WriteFile(SerialPort.hSerial, buffer, len, &lengthwrote, NULL)) {
		if (GetLastError() == ERROR_IO_PENDING)
		{
			printf("Error:%d Serial write fail, exiting lengthwrote:%d\n", GetLastError(), lengthwrote);
		}
		printf("Error:%d Serial write fail, exiting lengthwrote:%d\n", GetLastError(), lengthwrote);
		exit(1);
	}
	return(lengthwrote);
}
DWORD serial_read(unsigned char* buffer, size_t len) //windows version
{
	DWORD bytesread;
	if (!ReadFile(SerialPort.hSerial, buffer, len, &bytesread, NULL)) {
		printf("Error: Serial read fail, exiting\n");
		exit(1);
	}
	return(bytesread);
}
void Serial_putc(unsigned char c)
{
	if (serial_write(&c, 1) != (size_t)1)
	{
		perror("Error:Serial write one byte fail, exiting\n");
		exit(1);
	}
}
unsigned char Serial_getc(void)
{
	unsigned char byte;
	int bytesread;
	int trycount;
	bytesread = 0;
	trycount = 0;
	while (bytesread == 0 && trycount < 10) 
	{
		bytesread = serial_read(&byte, 1);
		trycount++;
		if (trycount > 1) {
			printf("Waiting data from serial port: %i rx:%x\n", trycount, bytesread);
			fflush(stdout);
		}
	}
	if (bytesread != 1) {
		perror("Error: serial port no reponse, exiting\n");
		exit(1);
	}
	return(byte);
}

通信协议:

#pragma once

// * Usart config*/
// * 1bit start
// * 0x7F data bits
// * even parity bit
// * one stop bit
// */

#define STM32_ISP_CMD_AUTOBUADRATE 0x7f
#define STM32_ISP_ACK 0x79
#define STM32_ISP_NACK 0x1f

#define STM32_ISP_CMD_GET 0x00
#define STM32_ISP_CMD_GETVERSION 0x01
#define STM32_ISP_CMD_GETID 0x02
#define STM32_ISP_CMD_READMEMORY 0x11
#define STM32_ISP_CMD_GO 0x21
#define STM32_ISP_CMD_WRITEMEMORY 0x31
#define STM32_ISP_CMD_ERASE 0x43
#define STM32_ISP_CMD_EXTENDEDERASE 0x44
#define STM32_ISP_CMD_WRITEPROTECT 0x63
#define STM32_ISP_CMD_WRITEUNPROTECT 0x73
#define STM32_ISP_CMD_READOUTPROTECT 0x82
#define STM32_ISP_CMD_READOUTUNPROTECT 0x92

#define STM32_ISP_CMD_GETVERSIONBYTESTOREAD 3
#define STM32_ISP_CMD_GETVERSION_VERSIONBYTE 0
#define STM32_ISP_CMD_GETVERSION_RDPROTDISABLEDQTYBYTE 1
#define STM32_ISP_CMD_GETVERSION_RDPROTENABLEDQTYBYTE 2

#define STM32_CMD_ERASEGLOBALPAGEQTYFIELD 0xff

#define READPACKETMAXDATA 0x80
#define WRITEPACKETMAXDATA 0x80
#define READPACKETREADCALLSMAX 20 

#define STM32FLASHSTART 0x08000000

#define COMMANDWAIT 10 
#define COMMANDRETRYCOUNT 4

#define SENDPACKETWAIT 0
#define PACKETREADWAIT 0

#define AUTOBAUDRETRYCOUNT 4
#define AUTOBAUDRETRYWAIT 1000


协议驱动:

#pragma once
#include <Windows.h>
#define MAXPACKLEN 250
typedef struct {
	char* serialDev;
	DWORD32 baudrate;
	DWORD32 writeAddress;
	char* loadFile;
}hostHandle_s;
typedef struct{
	unsigned char storage[MAXPACKLEN];
	int length;
}Packet;
extern hostHandle_s hostHandle;
void waitms(int mstowait);
void packet_append(Packet* packet, unsigned char c);
void packet_append16(Packet* packet, unsigned short int c);
void packet_checksumappend(Packet* packet);
void packet_appendcommandandcheck(Packet* packet, unsigned char command);
void packet_zero(Packet* packet);
void packet_send(Packet* packet);
int  packet_sendandgetack(Packet* packet, int trycount);
void autoBaudrateStart(void);
void clear_writeprotect(void);
void get_version(void);
void get_id(void);
void globalerase_flash(void);
void program_memory(void);
#include <Windows.h>
#include <stdio.h>
#include "Serial.h"
#include "action.h"
#include "STM32_ISP_CommandDefs.h"
hostHandle_s hostHandle;
void waitms(int mstowait)
{
	Sleep(mstowait);		//windows Sleep() takes ms.  
	return;
}
void packet_append(Packet* packet, unsigned char c)
{
	if (packet->length >= MAXPACKLEN - 1) {
		printf("packet too long in packet_append, exiting!");
		exit(1);
	}
	packet->storage[packet->length] = c;
	packet->length++;
	return;
}
void packet_append16(Packet* packet, unsigned short int c)
{
	if (packet->length >= MAXPACKLEN - 1) {
		printf("packet too long in packet_append, exiting!");
		exit(1);
	}
	packet->storage[packet->length] = c >> 8;
	packet->storage[packet->length + 1] = (unsigned char)c;
	packet->length++;
	return;
}
void packet_checksumappend(Packet* packet)
{
	int i;
	unsigned char checksum = 0;
	for (i = 0; i < packet->length; i++)
		checksum = checksum ^ packet->storage[i];
	packet_append(packet, checksum);
	return;
}

void packet_appendcommandandcheck(Packet* packet, unsigned char command)
{
	packet_append(packet, command);
	packet_append(packet, ~command);	//checksum for commands is the inverted command.
	return;
}


void packet_zero(Packet* packet)
{
	packet->length = 0;
	return;
}

void packet_send(Packet* packet)
{
	int lengthleft;
	int bytesactuallyread;
	unsigned char* packptr;
	packptr = packet->storage;

	lengthleft = packet->length;
	while (1) {
		bytesactuallyread = serial_write(packptr, lengthleft);
		lengthleft -= bytesactuallyread;
		packptr += (size_t)bytesactuallyread;
		if (lengthleft == 0) break;
	}
	waitms(SENDPACKETWAIT);
	return;
}

int  packet_sendandgetack(Packet* packet, int trycount)
{
	int packsendtrycount = 0;
	while (1) {
		packet_send(packet);
		if (Serial_getc() == STM32_ISP_ACK) break;
		if (++packsendtrycount >= trycount)
			return(1);
	}
	return(0);//success if we got ACK
}
void autoBaudrateStart(void)
{
	UINT16 trycount = 0;
	char autobaudestablished = 0;
	printf("Auto Baudrate Start ...\n"); fflush(stdout);
	while (1)
	{
		trycount++;
		Serial_putc(STM32_ISP_CMD_AUTOBUADRATE);
		unsigned char readByte;
		readByte = Serial_getc();
		if (readByte == STM32_ISP_ACK)
		{
			autobaudestablished = 1; break;
			printf("\nReceived ACK.\n");
		}
		else if (readByte == STM32_ISP_NACK)
		{
			printf("\nReceived NACK.\n");
			autobaudestablished = 1; break;
		}
		if (trycount > 15) break;
		printf(".");
		fflush(stdout);
	}
	if (autobaudestablished)
	{
		printf("Done!\n");
		///*printf("Serial port: %s\n", hostopts.serialdevname);
		//printf("Buadrate: %d\n", hostopts.baudrate);*/
		printf("Data bits: 8\n");
		printf("Parity: Even");
		printf("Stop bits: 1\n");
		printf("Flow control: none\n");
		fflush(stdout);
	}
	else
	{
		perror("no respone!\n");
		exit(0);
	}
}
void clear_writeprotect(void)
{
	Packet packet;

	packet_zero(&packet);
	packet_appendcommandandcheck(&packet, STM32_ISP_CMD_WRITEUNPROTECT);
	if (packet_sendandgetack(&packet, COMMANDRETRYCOUNT)) {
		printf("tried sending write unprotect command %i times w/o ack, exiting\n", COMMANDRETRYCOUNT); fflush(stdout);
		exit(1);
	}
	printf("got first ACK from writeunprotect.. good\n"); fflush(stdout);
	packet_zero(&packet);
	if (packet_sendandgetack(&packet, 1)) {
		printf("didn't get second ack from writeunprotect, exiting\n"); fflush(stdout);
		exit(1);
	}
	printf("got second ACK from writeunprotect, assumed successful\n");
	fflush(stdout);
	return;
}
void get_version(void)
{
	Packet outpacket, inpacket;
	int packsendtrycount = 0;
	int bytestoreadfromtarget;
	int bytesactuallyread = 0;
	unsigned char* packptr;

	packet_zero(&outpacket);
	packet_zero(&inpacket);

	packet_appendcommandandcheck(&outpacket, STM32_ISP_CMD_GETVERSION);

	if (packet_sendandgetack(&outpacket, COMMANDRETRYCOUNT))
	{
		printf("tried getversion command %i times w/o ack, exiting\n", packsendtrycount);
		exit(1);
	}
	bytestoreadfromtarget = STM32_ISP_CMD_GETVERSIONBYTESTOREAD;

	packptr = inpacket.storage;
	while (1) {
		bytesactuallyread = serial_read(packptr, bytestoreadfromtarget);
		inpacket.length += bytesactuallyread;
		packptr += (size_t)bytesactuallyread;
		bytestoreadfromtarget -= bytesactuallyread;
		if (bytestoreadfromtarget == 0)  break;
	}
	printf("... got %i data bytes from get_version, waiting for an ACK\n", inpacket.length);
	if (Serial_getc() == STM32_ISP_ACK)
		printf("got ACK after data in get_version, good\n");
	else {
		printf("didn't get ACK after data in get_version, exiting\n");
		exit(1);
	}

	printf("byte %.2i : bootloader version = %.2x\n",
		STM32_ISP_CMD_GETVERSION_VERSIONBYTE, inpacket.storage[STM32_ISP_CMD_GETVERSION_VERSIONBYTE]);
	printf("byte %.2i : bootloader version = %.2x\n",
		STM32_ISP_CMD_GETVERSION_RDPROTDISABLEDQTYBYTE, inpacket.storage[STM32_ISP_CMD_GETVERSION_RDPROTDISABLEDQTYBYTE]);
	printf("byte %.2i : bootloader version = %.2x\n",
		STM32_ISP_CMD_GETVERSION_RDPROTENABLEDQTYBYTE, inpacket.storage[STM32_ISP_CMD_GETVERSION_RDPROTENABLEDQTYBYTE]);
	fflush(stdout);
}
void get_id(void)
{
	Packet outpacket, inpacket;
	int packsendtrycount = 0;
	int bytestoreadfromtarget;
	int bytesactuallyread = 0;
	unsigned char* packptr;
	int i;
	packet_zero(&outpacket);
	packet_zero(&inpacket);
	packet_appendcommandandcheck(&outpacket, STM32_ISP_CMD_GETID);

	if (packet_sendandgetack(&outpacket, COMMANDRETRYCOUNT)) {
		printf("tried getid command %i times w/o ack, exiting\n", packsendtrycount);
		exit(1);
	}

	//now get the number of bytes the target says it's going to send us.
	bytestoreadfromtarget = (int)Serial_getc() + 1;

	packptr = inpacket.storage;
	while (1) {
		bytesactuallyread = serial_read(packptr, bytestoreadfromtarget);
		inpacket.length += bytesactuallyread;
		packptr += (size_t)bytesactuallyread;
		bytestoreadfromtarget -= bytesactuallyread;
		if (bytestoreadfromtarget == 0)  break;
	}
	printf("... got %i data bytes from get_command, waiting for an ACK\n", inpacket.length);
	if (Serial_getc() == STM32_ISP_ACK)
		printf("got ACK after data in get_id, good\n");
	else {
		printf("didn't get ACK after data in get_id, exiting\n");
		exit(1);
	}

	printf("got PID: \n");
	for (i = 0; i < inpacket.length; i++)
		printf("%.2x ", inpacket.storage[i]);
	printf("\n");
	fflush(stdout);

	return;
}
void globalerase_flash(void)
{
	Packet packet;

	printf("\nStarting global flash erase...\n"); fflush(stdout);
	packet_zero(&packet);
	packet_appendcommandandcheck(&packet, STM32_ISP_CMD_ERASE);
	if (packet_sendandgetack(&packet, COMMANDRETRYCOUNT)) {
		printf("tried sending erase command %i times w/o ack, exiting\n", COMMANDRETRYCOUNT); fflush(stdout);
		exit(1);
	}

	packet_zero(&packet);

	packet_append(&packet, STM32_CMD_ERASEGLOBALPAGEQTYFIELD);
	packet_append(&packet, (unsigned char)~STM32_CMD_ERASEGLOBALPAGEQTYFIELD);
	if (packet_sendandgetack(&packet, 1)) {
		printf("didn't get second ack from globalerase, exiting\n"); fflush(stdout);
		exit(1);
	}
	printf("Done!\n"); fflush(stdout);
	return;
}
void program_memory(void)
{
	Packet datapacket; //for data
	Packet outpacket; //for command
	unsigned int address;
	char hitEOFinloadfile = 0;
	int packsendtrycount;
	DWORD bytestosendthispacket;
	int bytessenttotal = 0;
	FILE* fp;
	if ((fp = fopen(hostHandle.loadFile, "rb")) == NULL)
	{
		printf("\nerror on open %s!", hostHandle.loadFile);
		exit(0);
	}
	//printf("\nfseek error:%d\n", GetLastError());
	if (fseek(fp, 0L, SEEK_END))
	{
		printf("\nfseek error:%d\n", GetLastError());
		exit(0);
	}
	long fsize = ftell(fp);
	fclose(fp);
	address = hostHandle.writeAddress;  //starting address
	printf("Starting program memory...\n"); fflush(stdout);
	if (hostHandle.loadFile[0] == '\0') {
		printf("*.bin file needs --loadfile <filename> defined, exiting\n");
		exit(1);
	}
	wchar_t loadfile[256];
	swprintf(loadfile, 256, L"%S", hostHandle.loadFile);
	LPCWSTR filename = loadfile;
	HANDLE hfile = CreateFile(
		filename,
		GENERIC_READ,//dwDesiredAccess
		0, //dwShareMode
		NULL,//lpSecurityAttributes
		OPEN_EXISTING,//dwCreationDisposition
		FILE_ATTRIBUTE_NORMAL,//dwFlagsAndAttributes
		0);//hTemplateFile

	//ReadFile(

	//)
	//hostresources.inputfile_fd = CreateFile(hostopts.loadfilename, O_RDONLY | O_BINARY);
	if (hfile == INVALID_HANDLE_VALUE)
	{
		if (GetLastError() == ERROR_FILE_NOT_FOUND)
		{
			printf("ERROR_FILE_NOT_FOUND:%ws\n", filename);
			fflush(stdout);
			/*return(1);*/
		}
		else if (GetLastError() == ERROR_ACCESS_DENIED)
		{
			printf("ERROR_ACCESS_DENIED:%ws\n", filename);
			fflush(stdout);
			/*return(1);*/
		}
		else if (GetLastError() == ERROR_INVALID_NAME)
		{
			printf("ERROR_INVALID_NAME Error:%ws\n", filename);
			fflush(stdout);
			/*return(1);*/
		}
		else {
			printf("Error: Serial operat failure. Error Code:%ld\n", GetLastError());
			fflush(stdout);
			/*return(1);*/
		}
		exit(0);
	}
	printf("Load file:%s\n", hostHandle.loadFile);
	printf("Code size:%ld bytes\n", fsize);
	printf("Starting programming....\n"); fflush(stdout);
	putchar('\n');
	unsigned char totalStep = 0;
	if (fsize / WRITEPACKETMAXDATA < 100)
		totalStep = fsize / WRITEPACKETMAXDATA;
	else
		totalStep = 100;
	for (unsigned char cc = 0; cc < totalStep; cc++)
	{
		putchar('=');
	}
	putchar('\n');
	fflush(stdout);
	int lastDP = 0;
	while (!hitEOFinloadfile) {

		BOOL readStatus = ReadFile(hfile, datapacket.storage, WRITEPACKETMAXDATA,&bytestosendthispacket,NULL);
		if (!readStatus)
		{
			printf("read file error:%d\n",GetLastError());
			exit(1);
		}
		if (bytestosendthispacket < 0) {
			perror("Trouble reading loadfile!, exiting"); fflush(stdout);
			exit(1);
		}

		if (bytestosendthispacket == 0) {
			//printf("\nLoading 0 byte, no more data to send.\n");fflush(stdout);
			hitEOFinloadfile = 1;
			break;	//avoid sending 0 length write packet.
		}

		datapacket.length = bytestosendthispacket;

		//now send the command packet.
		packet_zero(&outpacket);

		packet_appendcommandandcheck(&outpacket, STM32_ISP_CMD_WRITEMEMORY);

		if (packet_sendandgetack(&outpacket, COMMANDRETRYCOUNT)) {
			printf("Tried sending writememory command %i times w/o ack, exiting\n", COMMANDRETRYCOUNT);
			exit(1);
		}

		int DownloadProgress = bytessenttotal * 100 / fsize;
		//send address
		packet_zero(&outpacket);
		packet_append(&outpacket, ((address & 0xff000000) >> 24));
		packet_append(&outpacket, ((address & 0x00ff0000) >> 16));
		packet_append(&outpacket, ((address & 0x0000ff00) >> 8));
		packet_append(&outpacket, (address & 0x000000ff));
		packet_checksumappend(&outpacket);
		packsendtrycount = 0;


		if (packet_sendandgetack(&outpacket, 1)) {
			printf("didn't get ack after address+checksum in program_memory exiting\n");
			exit(1);
		}


		packet_zero(&outpacket);
		packet_append(&outpacket, (unsigned char)bytestosendthispacket - 1); //number of bytes to write
		memcpy((outpacket.storage + (size_t)1), datapacket.storage, bytestosendthispacket);
		outpacket.length += bytestosendthispacket;
		packet_checksumappend(&outpacket);

		packet_send(&outpacket);
		if (Serial_getc() != STM32_ISP_ACK) {
			printf("didn't get ack after length,data,checksum in program_memory exiting\n");
			exit(1);
		}
		bytessenttotal += bytestosendthispacket;
		address += bytestosendthispacket;		//address now at next memory location to write.
		//Gotoxy(currentXY.X+DownloadProgress/2,currentXY.Y);
		if (DownloadProgress > lastDP) {
			//printf(">%d",DownloadProgress);
			putchar('>');
			fflush(stdout);
			//printf("%d %d \n ",DownloadProgress);
			//putchar('>');

		}
		lastDP = DownloadProgress;
		// Gotoxy(21,4);


	}  //end while !hitEOFinreadfile
	putchar('\n');
	for (unsigned char cc = 0; cc < totalStep; cc++)
	{
		putchar('=');
	}
	putchar('\n');
	fflush(stdout);
	printf("Total send %i bytes, program complete!\n", bytessenttotal);
	CloseHandle(hfile); fflush(stdout);
	return;
}

总体测试情况:

argv[0]:M:\stm32_isp_programer\stm32_isp_programmer\Debug\stm32_isp_programmer.exe
argv[1]:COM6
argv[2]:256000
argv[3]:0X08000000
argv[4]:M:\Work\serial_wireless_v1.1\wirelessUsartv1.1.bin
selectPort:COM6
setBuadrate_p:256000
writeAddress_p:0X08000000
loadFile:M:\Work\serial_wireless_v1.1\wirelessUsartv1.1.bin
Serial port: COM6 open success!
Serial port: COM6
Buadrate: 256000
Data bits: 8
Parity: Even
Stop bits: 1
Flow control: none
Serial init complete!



Trying to rest and connet target, please push and hold boot0 button!
Using RTS LOW to reset taeget...
4
3
2
1
0
Auto Baudrate Start ...
Done!
Data bits: 8
Parity: EvenStop bits: 1
Flow control: none
... got 3 data bytes from get_version, waiting for an ACK
got ACK after data in get_version, good
byte 00 : bootloader version = 22
byte 01 : bootloader version = 00
byte 02 : bootloader version = 00
... got 2 data bytes from get_command, waiting for an ACK
got ACK after data in get_id, good
got PID: 
04 10 
got first ACK from writeunprotect.. good
got second ACK from writeunprotect, assumed successful

Starting global flash erase...
Done!
Starting program memory...
Load file:M:\Work\serial_wireless_v1.1\wirelessUsartv1.1.bin
Code size:10660 bytes
Starting programming....

===================================================================================
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
===================================================================================
Total send 10660 bytes, program complete!
Isp complete and reseting...
4
3
2
1
0
Total time use: 2.970 seconds

猜你喜欢

转载自blog.csdn.net/u013866683/article/details/105781048
今日推荐