读出stm32芯片的唯一id 并写入 0x8000000地址中
// JkIsp.cpp : Defines the entry point for the console application.
//#include "stdafx.h"
HANDLE m_hIDComDev; //串口句柄
int OpenCom()
{
DCB dcb = { 0 };
m_hIDComDev = CreateFile("COM2", GENERIC_READ | GENERIC_WRITE, 0, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); //打开串口
if (m_hIDComDev == INVALID_HANDLE_VALUE)
{
printf("打开串口失败!\n");
return 1;
}
//GetCommTimeouts(m_hIDComDev, &CommTimeOuts); //获取串口超时配置
//总超时=时间系数×要求读/写的字符数+时间常量
//读总超时=ReadTotalTimeoutMultiplier×10+ReadTotalTimeoutConstant
COMMTIMEOUTS CommTimeOuts =// 串口超时控制参数
{
50, // 读字符间隔超时时间
1, // 读操作时每字符的时间
50, // 基本的(额外的)读超时时间
2, // 写操作时每字符的时间
10 // 基本的(额外的)写超时时间
};
SetCommTimeouts(m_hIDComDev, &CommTimeOuts); //设置超时
dcb.DCBlength = sizeof(DCB);
GetCommState(m_hIDComDev, &dcb); //
dcb.BaudRate = 115200; //设置波特率
dcb.ByteSize = 8; //设置校验字节
dcb.StopBits = 0; //停止字节1位 0/1 1/1.5 2/2
dcb.Parity = EVENPARITY; //偶校验
if (!SetCommState(m_hIDComDev, &dcb))//设置串口和收发缓冲器的大小
{
DWORD dwError = GetLastError();
CloseHandle(m_hIDComDev);
return 2;
}
if (!SetupComm(m_hIDComDev, 1024, 1024))
{
DWORD dwError = GetLastError();
CloseHandle(m_hIDComDev);
return 3;
}
PurgeComm(m_hIDComDev, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_TXABORT | PURGE_RXABORT);//清收发缓冲器
return 0;
}
int CloseCom()
{
CloseHandle(m_hIDComDev);
return 1;
}
enum ProCmd{
eProGetVC = 0, //获取版本已经命令集
eProGetVP = 1, //获取版本以及保护状态
eProGetID, //读取ic芯片型号
eProRdMem = 0x11, //读取memory
eProGo = 0x21, //程序跳转指令
eProWrMem = 0x31, //最多写入256个字节
eProErase0 = 0x43,
eProErase1 = 0x44,
eProWrPt = 0x63, //写保护
eProWrUPt = 0x73, //解除写保护
eProRdPt = 0x82,
eProRdUPt = 0x92,
eProEraseFull=0xff,
};
#define ACK 0x79
#define NACK 0x1F
int RecData(BYTE *pt)
{
BOOL bReadState;
DWORD readcnt;
DWORD len=0;
bReadState = ReadFile(m_hIDComDev, &len, 1, &readcnt, NULL);
if (bReadState == TRUE)
{
++len;
bReadState = ReadFile(m_hIDComDev, pt, len + 1, &readcnt, NULL); //读出字节数+ack
if (bReadState == FALSE || readcnt != len + 1 || pt[len] != ACK) return 0;
return len;
}
return 0;
}
BOOL WriteProCmd(BYTE cmd)
{
BYTE cmdbuf[2];
DWORD writecnt, readcnt, cnt = 0;
BYTE readbuf[1024] = { NACK };
BOOL bReadState;
cmdbuf[0] = cmd;
cmdbuf[1] = cmd ^ 0xff;
PurgeComm(m_hIDComDev, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_TXABORT | PURGE_RXABORT); //清收发缓冲器
do{
WriteFile(m_hIDComDev, &cmdbuf, 2, &writecnt, NULL);
bReadState = ReadFile(m_hIDComDev, readbuf, 1, &readcnt, NULL);
} while (++cnt < 4 && ((bReadState == FALSE) || (readbuf[0] != ACK && readbuf[0] != NACK)));
return (readbuf[0] == ACK);
}
BOOL TestLink()
{
BYTE cmdbuf[1];
DWORD writecnt, readcnt,cnt=0;
BYTE readbuf[16];
BOOL bReadState;
cmdbuf[0] = 0x7F;
PurgeComm(m_hIDComDev, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_TXABORT | PURGE_RXABORT); //清收发缓冲器
do{
WriteFile(m_hIDComDev, &cmdbuf, 1, &writecnt, NULL);
bReadState = ReadFile(m_hIDComDev, readbuf, 1, &readcnt, NULL);
} while (++cnt < 100 && ((bReadState == FALSE) || readbuf[0] != 0x79));
return (cnt < 100);
}
BYTE m_EraseCode = ProCmd::eProErase0;
BOOL GetVersionAndCmd()
{
int rdCnt=0,i;
BYTE buf[256];
if (WriteProCmd(ProCmd::eProGetVC) == TRUE)
{
rdCnt = RecData(buf);
if (rdCnt != 0)
{
printf("boot version:%X\r\n", buf[0]);
for (i = 1; i < rdCnt; i++)
{
if (buf[i] == ProCmd::eProErase0 || buf[i] == ProCmd::eProErase1)
{
m_EraseCode = buf[i];
break;
}
}
printf("Erase Mode:%d\r\n", m_EraseCode - ProCmd::eProErase0);
}
else printf("Get version and command set failed\r\n");
}
else printf("Get version and command set failed\r\n");
return (rdCnt != 0);
}
BOOL EraseFlash(void)
{
BOOL ret = FALSE;
if (WriteProCmd(m_EraseCode) == TRUE)
{
if (WriteProCmd(ProCmd::eProEraseFull))
{
printf("Erase successful\r\n");
ret = TRUE;
}
}
if (ret == FALSE)
{
printf("Erase failed\r\n");
}
return ret;
}
BOOL ReadMemory(DWORD addr, int len, BYTE *pt)
{
BYTE addr2byte[5];
DWORD optcnt;
BYTE readbuf[2];
BOOL bReadState;
int i;
if (WriteProCmd(ProCmd::eProRdMem))
{
addr2byte[4] = 0x00;
for (i = 0; i < 4; i++)
{
addr2byte[3 - i] = addr & 0xff; addr >>= 8;
addr2byte[4] ^= addr2byte[3 - i];
}
WriteFile(m_hIDComDev, &addr2byte, 5, &optcnt, NULL);
bReadState = ReadFile(m_hIDComDev, readbuf, 1, &optcnt, NULL);
if (bReadState == FALSE || readbuf[0] != ACK)
{
return FALSE;
}
addr2byte[0] = len-1; //要接收的长度减去一 为了能最大接收256 个字节
addr2byte[1] = addr2byte[0] ^ 0xff;
WriteFile(m_hIDComDev, &addr2byte, 2, &optcnt, NULL);
bReadState = ReadFile(m_hIDComDev, readbuf, 1, &optcnt, NULL);
if (bReadState == FALSE || readbuf[0] != ACK)
{
return FALSE;
}
bReadState = ReadFile(m_hIDComDev, pt, len, &optcnt, NULL);
if (bReadState == FALSE || len != optcnt) return FALSE;
return TRUE;
}
return FALSE;
}
BOOL WriteMemory(DWORD addr, int len, BYTE *pt)
{
BYTE wr2byte[252]; //写入的字节数 1 写入的数据 256 校验和 前面包括 长度的抑或
DWORD optcnt;
BYTE readbuf[4];
BOOL bReadState;
int i;
if (WriteProCmd(ProCmd::eProWrMem))
{
wr2byte[4] = 0x00;
for (i = 0; i < 4; i++)
{
wr2byte[3 - i] = addr & 0xff; addr >>= 8;
wr2byte[4] ^= wr2byte[3 - i];
}
WriteFile(m_hIDComDev, &wr2byte, 5, &optcnt, NULL);
bReadState = ReadFile(m_hIDComDev, readbuf, 1, &optcnt, NULL);
if (bReadState == FALSE || readbuf[0] != ACK)
{
return FALSE;
}
wr2byte[0] = len - 1;
wr2byte[len + 1] = wr2byte[0];
for (i = 0; i < len; i++)
{
wr2byte[i + 1] = pt[i];
wr2byte[len + 1] ^= pt[i];
}
WriteFile(m_hIDComDev, &wr2byte, len+2, &optcnt, NULL);
bReadState = ReadFile(m_hIDComDev, readbuf, 1, &optcnt, NULL);
if (bReadState == FALSE || readbuf[0] != ACK)
{
return FALSE;
}
return TRUE;
}
return FALSE;
}
int _tmain(int argc, _TCHAR* argv[])
{
int ret,cnt=0;
DWORD Stm32ID[3];
ret = OpenCom();
if (ret == 0)
{
if(TestLink() == FALSE)
{
printf("连接STM32失败\r\n");
return 1;
}
GetVersionAndCmd();
if(EraseFlash() == false)
{
ret = WriteProCmd(eProRdUPt);
if (ret == 0)
{
printf("解锁失败\r\n");
return 2;
}
if (TestLink() == FALSE)
{
printf("二次连接STM32失败\r\n");
return 3;
}
EraseFlash();
}
if (ReadMemory(0x1FFFF7E8, 12, (BYTE*)Stm32ID) == FALSE)
{
printf("Read Stm32 ID failed\r\n");
return 4;
}
printf("STM32ID:%08X %08X %08X\r\n", Stm32ID[0], Stm32ID[1], Stm32ID[2]);
WriteMemory(0x08000000, 12, (BYTE*)Stm32ID);
CloseCom();
}
return 0;
}