概述
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#pragma pack(1)
// config MCU clock
#define MCU_CONFIG
//#define MCU_6TO6
//#define MCU_6TO12
//#define MCU_12TO12
//#define MCU_12TO6
#ifdef MCU_6TO6
#define MCU_CLOCK
#endif
#ifdef MCU_6TO12
#define MCU_CLOCK
#endif
#ifdef MCU_12TO12
#define MCU_CLOCK
#define MCU_CLOCK_12MHZ
#undef MCU_CONFIG
#endif
#ifdef MCU_12TO6
#define MCU_CLOCK
#define MCU_CLOCK_12MHZ
#endif
#ifndef MCU_CLOCK
#error "You must define MCU clock!"
#endif
#define VERSION "0.1"
#define DEFAULT_PORT "/dev/ttyS1"
#define LOW_BAUD B2400
#ifdef MCU_CLOCK_12MHZ
#define HIGH_BAUD B57600
#define MSG_HIGH_BAUD "57600bps"
#else
#define HIGH_BAUD B38400
#define MSG_HIGH_BAUD "38400bps"
#endif
#define BUFFSIZE 1024
#define TIMEOUT 2
#define BLOCK_SIZE 128
#define PKG_MINIMAL_LEN 9
#define PKG_SIGN1 'x46'
#define PKG_SIGN2 'xb9'
#define PKG_SIGN3 'x16'
#define PKG_SIGN 0x46b9
enum pkg_type {
PKG_TYPE1=0x68,
PKG_TYPE2=0x6a,
};
enum pkg_code {
CODE_INFO=0x50,
CODE_MODI=0x8f,
CODE_NEWB=0x8e,
CODE_ERASE=0x84,
CODE_DATA=0x00,
CODE_END =0x69,
CODE_CONF=0x8d,
CODE_BYE =0x82,
};
int port_fd=-1;
FILE *rom_file;
int file_length;
int debug=0;
enum pkg_code step;
int block_no;
struct timeval start_tv;
typedef unsigned int uint32;
typedef unsigned short int uint16;
typedef unsigned char uint8;
// Package format: head + data + tail
typedef struct _pkg_head {
uint16 sign; // 0x46b9
uint8 type; // 68: MCU to PC; 6a: PC to MCU
uint16 lenth; // from 'type' to 'pkg_tail.sign'
uint8 code;
} pkg_head, *ppkg_head;
typedef struct _pkg_tail {
uint16 cksum; // from 'pkg_head.type' to 'data'
uint8 sign; // 0x16
} pkg_tail, *ppkg_tail;
typedef struct _pkg_data_head {
uint16 dummy; // always 0x0000
uint16 addr; // start addr
uint16 lenth; // 0x0080
} pkg_data_head, *ppkg_data_head;
void print_data(char *data, int len)
{
unsigned char ch;
int i, j;
printf("Length: %xn", len);
for(i=0; i
ch=data[i];
if((i&0x0f)==0)
printf("%04x: ", i);
if((i&0x07)!=0x07)
printf("%02x ", ch);
else
if((i&0x0f)!=0x0f)
printf("%02x-", ch);
else {
printf("%02x ", ch);
for(j=0x0f; j>=0; j--) {
ch=data[i-j];
if(!isascii(ch) || iscntrl(ch))
ch='.';
putchar(ch);
}
putchar('n');
}
}
if(len&0x0f) {
for(; i
printf(" ");
putchar(' ');
for(j=len&~0x0f; j
ch=data[j];
if(!isascii(ch) || iscntrl(ch))
ch='.';
putchar(ch);
}
putchar('n');
}
}
enum dbg_type {RECV, SEND};
void print_dbg(int type, char *buf, int buf_len)
{
struct timeval tv;
unsigned int sec, usec;
if(debug) {
if(type==SEND)
printf("n[Send]tt");
else
printf("n[Received]t");
gettimeofday(&tv, NULL);
if(start_tv.tv_usec>tv.tv_usec) {
usec=tv.tv_usec-start_tv.tv_usec+1000000;
sec=tv.tv_sec-start_tv.tv_sec-1;
} else {
usec=tv.tv_usec-start_tv.tv_usec;
sec=tv.tv_sec-start_tv.tv_sec;
}
printf("[%d.%06d]n", sec, usec);
printf("Step: %02xt", step);
print_data(buf, buf_len);
}
}
int checksum(char *buf, int buf_len)
{
int i, sum=0;
for(i=0; i
sum+=(unsigned char)buf[i];
return sum;
}
// return: -1: bad pkg; >=0: pkg start position
int check_pkg(int code, char *buf, int buf_len)
{
int i, len;
ppkg_head ph=NULL;
ppkg_tail pt=NULL;
for(i=0; i
if(buf[i]==PKG_SIGN1 && buf[i+1]==PKG_SIGN2 && i+PKG_MINIMAL_LEN<=buf_len) {
ph=(ppkg_head)buf+i;
if(ph->type==PKG_TYPE1 && ph->code==code) {
len=ntohs(ph->lenth);
pt=(ppkg_tail)((char *)ph+len-1);
if(pt->sign==PKG_SIGN3 && ntohs(pt->cksum)==checksum((char *)ph+2, len-3)) break;
pt=NULL;
break;
}
}
}
if(ph==NULL || pt==NULL)
i=-1;
return i;
}
typedef struct port_info {
int port_fd;
int baud_rate;
char parity;
char stop_bit;
char flow_ctrl;
char data_bits;
} *pport_info;
int set_port(pport_info p_info)
{
struct termios old_opt,new_opt;
memset(&old_opt,0,sizeof(old_opt));
memset(&new_opt,0,sizeof(new_opt));
cfmakeraw(&new_opt);
tcgetattr(p_info->port_fd,&old_opt);
//修改new_opt结构中的串口输入/输出波特率参数
cfsetispeed(&new_opt,p_info->baud_rate);
cfsetospeed(&new_opt,p_info->baud_rate);
//修改控制模式,保证程序不会占用串口
new_opt.c_cflag |=CLOCAL;
//修改控制模式,使得能够从串口中读取输入数据
new_opt.c_cflag |=CREAD;
/*===========设置数据流控制==========*/
switch(p_info->flow_ctrl){
case '0':
//不使用流控制
new_opt.c_cflag &=~CRTSCTS;
break;
case '1':
//使用硬件进行流控制
new_opt.c_cflag |=CRTSCTS;
break;
case '2':
new_opt.c_cflag |= IXON | IXOFF | IXANY;
break;
}
/*===========设置数据位============*/
new_opt.c_cflag &=~CSIZE;
switch(p_info->data_bits){
case '5':
new_opt.c_cflag |=CS5;
break;
case '6':
new_opt.c_cflag |=CS6;
break;
case '7':
new_opt.c_cflag |=CS7;
break;
case '8':
new_opt.c_cflag |=CS8;
break;
default:
new_opt.c_cflag |=CS8;
}
/*===========设置奇偶效验位==========*/
switch(p_info->parity){
case '0': //不使用奇偶效验
new_opt.c_cflag &=~PARENB;
break;
case '1': //使用偶效验
new_opt.c_cflag |=PARENB;
new_opt.c_cflag &=~PARODD;
break;
case '2': //使用奇效验
new_opt.c_cflag |=PARENB;
new_opt.c_cflag |=PARODD;
break;
}
/*============设置停止位===========*/
if(p_info->stop_bit=='2')
new_opt.c_cflag |=CSTOPB;
else
new_opt.c_cflag &=~CSTOPB;
//修改输出模式,原始数据输出
new_opt.c_oflag &=~OPOST;
//修改控制字符,读取字符的最少个数为1
new_opt.c_cc[VMIN]=1;
//修改控制字符,读取第一个字符等待1*(1/10)s
new_opt.c_cc[VTIME]=1;
//如果发生数据溢出,接收数据,但是不再读取
tcflush(p_info->port_fd,TCIFLUSH);
int result=tcsetattr(p_info->port_fd,TCSANOW,&new_opt);
if(result==-1){
perror("Cannot set the serial port parameters");
return -1;
}
tcgetattr(p_info->port_fd,&old_opt);
return result;
}
int open_port(char *port_name, int baud_rate)
{
int port_fd;
if((port_fd=open(port_name, O_RDWR | O_NOCTTY | O_NONBLOCK))==-1){
fprintf(stderr, "Failed to open serial port: %sn", port_name);
return -1;
}
//设置串口通信参数
struct port_info info;
info.port_fd=port_fd;
info.baud_rate=baud_rate;
info.data_bits='8';
info.flow_ctrl='0';
info.stop_bit='1';
info.parity='1';
if(set_port(&info)==-1) {
fprintf(stderr, "Failed to setup serial port: %sn", port_name);
close(port_fd);
return -1;
}
return port_fd;
}
void close_port()
{
if(rom_file!=NULL) {
fclose(rom_file);
rom_file=NULL;
}
if(port_fd!=-1) {
close(port_fd);
port_fd=-1;
}
}
void reopen_port(char *port_name, int baud_rate)
{
if(port_fd!=-1)
close(port_fd);
if((port_fd=open_port(port_name, baud_rate))==-1)
{
close_port();
exit(1);
}
}
int send_data(int fd, char *data, int data_len)
{
int len=write(fd, data, data_len);
//如果出现溢出的情况
if(len!=data_len)
tcflush(fd, TCOFLUSH);
return len;
}
int send_mcu(int fd, char *data, int data_len)
{
int i, len=0, total=0;
for(i=0; i
usleep(150);
len=send_data(fd,data+i,1);
if(len>0)
total+=len;
}
print_dbg(SEND, data, total);
return total;
}
int recv_data(int fd, char *data, int data_len)
{
static int timeout=0;
int len=0, fs_sel;
fd_set fs_read;
struct timeval time;
FD_ZERO(&fs_read);
FD_SET(fd, &fs_read);
if(step==CODE_MODI)
timeout=TIMEOUT;
time.tv_sec=timeout;
time.tv_usec=10000;
//使用select实现串口的多路通信
fs_sel=select(fd+1, &fs_read, NULL, NULL, &time);
if(fs_sel)
len=read(fd, data, data_len);
return len;
}
int recv_mcu(int fd, char *buf, int buf_len)
{
int i, len=0;
do {
if(step==CODE_INFO)
usleep(100000);
i=recv_data(fd, buf+len, buf_len-len);
if(i>0) len+=i;
if(check_pkg(step, buf, len)>=0)
break;
} while(i>0);
return len;
}
int check_recv(int expect_code, char *buf, int buf_len) {
int i;
print_dbg(RECV, buf, buf_len);
i=check_pkg(expect_code, buf, buf_len);
if(i<0) {
printf("nError received datan");
close_port();
exit(1);
}
return i;
}
void mcu_info(char *buf, int buf_len) {
int i, len;
ppkg_head ph;
ppkg_tail pt;
ph=(ppkg_head)buf;
len=ntohs(ph->lenth);
pt=(ppkg_tail)((char *)ph+len-1);
/*
MCU Type is: STC11F04E
MCU Firmware Version: 6.5K
Next Power-Up-Reset, use External Crystal/Clock
RESET/P3.6 is used as RESET
Power-Up Reset,add extra Reset-Delay-Time
Oscillator Gain: High gain
P1.0/P1.1 are not related to STC ISP Programming
Next ISP Programming Code,don't erase EEPROM data
Wait n clocks after MCU is waked up: 32768
Low Voltage Reset, when MCU-VCC < 4.1V
WDT_CONTR be write-protected except CLR_WDT:NO
WDT is enabled automatically during power-up:NO
Stop WatchDog Timer counting in Idle mode: YES
Pre-scale time of WDT(did not start): 256
MCU Clock:12.019038MHz.
*/
i=sizeof(pkg_head)+16;
printf("nnMCU Type: n");
printf("MCU Firmware Version: %1d.%1d%cn", buf[i]>>4&0x0f, buf[i]&0x0f, buf[i+1]);
i=ntohl(*((int *)((char *)pt-4)));
printf("MCU Internal Clock: %2d.%6dMhzn", i/1000000, i%1000000);
}
//return: pkg length
int make_pkg(int code, char *inbuf, int ibuf_len, char *outbuf, int obuf_len)
{
int i, len;
ppkg_head ph;
ppkg_tail pt;
ppkg_data_head pd;
static char request_mcu[]={
0x46,0xB9,0x6A,0x00,0x0D,0x50,0x09,0x00,0x36,0x01,0xE2,0x24,0x02,0x0D,0x16};
static char erase[]={
0x46,0xB9,0x6A,0x00,0x8C,0x84,0xFF,0x00,0x02,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
static char end[]={
0x46,0xB9,0x6A,0x00,0x0D,0x69,0x09,0x00,0x36,0x01,0xE2,0x24,0x02,0x26,0x16};
static char bye[]={
0xFE,0xFE,0xFE,0xFE,0x46,0xB9,0x6A,0x00,0x07,0x82,0x00,0xF3,0x16};
/* 38400bps @ 6.2MHz, internal clock */
#ifdef MCU_6TO6
static char inform_change[]={
0x46,0xB9,0x6A,0x00,0x0D,0x8F,0xC0,0xF6,0x3F,0x14,0x2D,0x84,0x03,0xC0,0x16};
static char confirm_newrate[]={
0x46,0xB9,0x6A,0x00,0x0C,0x8E,0xC0,0xF6,0x3F,0x14,0x2D,0x03,0x3A,0x16};
static char config[]={
0x46,0xB9,0x6A,0x00,0x1B,0x8D,0xBF,0x7D,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x5E,0x90,0x04,0x11,0x2A,0x16};
#endif
/* 38400bps @ 6.2MHz, change 6.2MHz to 12MHz */
#ifdef MCU_6TO12
static char inform_change[]={
0x46,0xB9,0x6A,0x00,0x0D,0x8F,0xC0,0xF6,0x3F,0x14,0x2D,0x84,0x03,0xC0,0x16};
static char confirm_newrate[]={
0x46,0xB9,0x6A,0x00,0x0C,0x8E,0xC0,0xF6,0x3F,0x14,0x2D,0x03,0x3A,0x16};
static char config[]={
0x46,0xB9,0x6A,0x00,0x1B,0x8D,0xBF,0x7F,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x5E,0x27,0x41,0x11,0x00,0x16};
#endif
/* 57600bps @ 12MHz, change back to 6.2MHz if run conf_mcu() */
#ifdef MCU_CLOCK_12MHZ
static char inform_change[]={
0x46,0xB9,0x6A,0x00,0x0D,0x8F,0xC0,0xF3,0x3F,0x1A,0x2D,0x83,0x03,0xC2,0x16};
static char confirm_newrate[]={
0x46,0xB9,0x6A,0x00,0x0C,0x8E,0xC0,0xF3,0x3F,0x1A,0x2D,0x03,0x3D,0x16};
static char config[]={
0x46,0xB9,0x6A,0x00,0x1B,0x8D,0xBF,0x7D,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0xB7,0x65,0x5E,0x11,0xB2,0x16};
#endif
switch(code) {
case CODE_INFO:
len=sizeof(request_mcu);
memcpy(outbuf, request_mcu, len);
break;
case CODE_MODI:
len=sizeof(inform_change);
memcpy(outbuf, inform_change, len);
break;
case CODE_NEWB:
len=sizeof(confirm_newrate);
memcpy(outbuf, confirm_newrate, len);
break;
case CODE_ERASE:
len=sizeof(erase);
memcpy(outbuf, erase, len);
*(short int *)(outbuf+7)=htons((file_length+255)>>8);
for(i=0x80; i>=0x0e; i--)
outbuf[len++]=i;
i=htons(checksum(outbuf+2, len-2));
*(int *)(outbuf+len)=i;
len+=2;
outbuf[len++]=PKG_SIGN3;
break;
case CODE_DATA:
ph=(ppkg_head)outbuf;
ph->sign=htons(PKG_SIGN);
ph->type=PKG_TYPE2;
i=sizeof(pkg_head)+sizeof(pkg_data_head);
len=i+ibuf_len+sizeof(pkg_tail);
ph->lenth=htons(len-2);
ph->code=CODE_DATA;
pd=(ppkg_data_head)(outbuf+sizeof(pkg_head));
pd->dummy=htons(0x0000);
pd->addr=htons(block_no*BLOCK_SIZE);
pd->lenth=htons(ibuf_len);
memcpy(outbuf+i, inbuf, ibuf_len);
pt=(ppkg_tail)(outbuf+i+ibuf_len);
pt->cksum=htons(checksum(outbuf+2, i+ibuf_len-2));
pt->sign=PKG_SIGN3;
break;
case CODE_END:
len=sizeof(end);
memcpy(outbuf, end, len);
break;
case CODE_CONF:
len=sizeof(config);
memcpy(outbuf, config, len);
break;
case CODE_BYE:
len=sizeof(bye);
memcpy(outbuf, bye, len);
break;
default:
fprintf(stderr, "make_pkg(): invalid package coden");
len=0;
}
return len;
}
// return: 0: fail; 1: success
int conf_mcu(char *port_name, int baud_rate)
{
int i, len=0;
char recv_buf[BUFFSIZE], send_buf[BUFFSIZE];
reopen_port(port_name, baud_rate);
step=CODE_CONF;
len=make_pkg(step, recv_buf, len, send_buf, BUFFSIZE);
len=send_mcu(port_fd, send_buf, len);
step=CODE_INFO;
len=recv_mcu(port_fd, recv_buf, BUFFSIZE);
i=check_recv(step, recv_buf, len);
step=CODE_BYE;
len=make_pkg(step, recv_buf+i, len-i, send_buf, BUFFSIZE);
len=send_data(port_fd, send_buf, len);
close_port();
if(i>=0)
i=1;
else
i=0;
return i;
}
void help(char *cmd_name)
{
printf("STC MCU flash ROM programmer, Version " VERSION " (2011), GPLv2 Lisencen");
printf("Warning: this is not an official release, use it on your own risk.nn");
printf("Surpport MCU type: STC11F04Enn");
printf("Usage:n %s [options] [.bin filename]nn", cmd_name);
printf("Options:n -httprint this textn"
" -d devtuse given device, default: " DEFAULT_PORT "n"
" -Dttenable debug outputn");
exit(0);
}
int main(int argc, char *argv[])
{
static char default_dev[]=DEFAULT_PORT;
char *port_name=default_dev;
char *file_name=NULL;
int i, len;
char recv_buf[BUFFSIZE], send_buf[BUFFSIZE];
while((i=getopt(argc, argv, "hd:D"))!=-1) {
switch(i) {
case 'h':
help(argv[0]);
break;
case 'd':
port_name=optarg;
break;
case 'D':
debug=1;
break;
case '?':
exit(1);
}
}
for(; optind
file_name=argv[optind];
break;
}
if(file_name!=NULL) {
if(strcasestr(file_name, ".bin")==NULL) {
fprintf(stderr, "Invalid file namen");
exit(1);
}
rom_file=fopen(file_name, "rb");
if(rom_file==NULL) {
fprintf(stderr, "Cannot open filen");
exit(1);
}
i=fileno(rom_file);
if(fstat(i, (struct stat *)recv_buf)==-1) {
perror("Cannot get length of the filen");
close_port();
exit(1);
}
file_length=((struct stat *)recv_buf)->st_size;
}
printf("Use port %sn", port_name);
printf("Connecting to target MCU at 2400bps ... ");
if((port_fd=open_port(port_name, LOW_BAUD))==-1)
exit(1);
// Power off and power on MCU via DTR & RTS signal
ioctl(port_fd, TIOCMGET, &i);
i&=~(TIOCM_RTS | TIOCM_DTR);
ioctl(port_fd, TIOCMSET, &i);
usleep(100000);
i|=TIOCM_RTS | TIOCM_DTR;
ioctl(port_fd, TIOCMSET, &i);
step=CODE_INFO;
for(i=150; i>0; i--) {
len=send_data(port_fd, "x7fx7fx7fx7f", 4);
if(len<1) {
printf("bbSend data failedn");
close_port();
exit(1);
}
if(i%5==0) {
printf("bb%2d", i/5);
fflush(stdout);
}
len=recv_mcu(port_fd, recv_buf, BUFFSIZE);
if(len>=PKG_MINIMAL_LEN)
break;
}
if(len
printf("bbFailedn");
close_port();
exit(1);
}
gettimeofday(&start_tv, NULL);
i=check_recv(step, recv_buf, len);
mcu_info(recv_buf+i, len-i);
if(rom_file==NULL) {
close_port();
exit(0);
}
// confirm MCU, procedure: make_pkg -> send -> recv -> check_recv
len=make_pkg(step, recv_buf+i, len-i, send_buf, BUFFSIZE);
len=send_mcu(port_fd, send_buf, len);
step=CODE_MODI;
len=recv_mcu(port_fd, recv_buf, BUFFSIZE);
i=check_recv(step, recv_buf, len);
// Inform to modify baud rate
if(debug) printf("nInform MCU to modify baud rate ...n");
len=make_pkg(step, recv_buf+i, len-i, send_buf, BUFFSIZE);
len=send_mcu(port_fd, send_buf, len);
reopen_port(port_name, HIGH_BAUD);
len=recv_mcu(port_fd, recv_buf, BUFFSIZE);
i=check_recv(step, recv_buf, len);
// Send at 2400bps to confirm the new baud rate
if(debug) printf("nConfirm MCU with new baud rate ... n");
step=CODE_NEWB;
reopen_port(port_name, LOW_BAUD);
len=make_pkg(step, recv_buf+i, len-i, send_buf, BUFFSIZE);
len=send_mcu(port_fd, send_buf, len);
// Change to new baud rate
printf("nReconnecting to target MCU at " MSG_HIGH_BAUD " ... ");
step=CODE_ERASE;
reopen_port(port_name, HIGH_BAUD);
********余下代码下载附件*********
最后
以上就是勤恳小白菜为你收集整理的linux开发 stc_仿STC-ISP写的Linux版编程烧录软件,附源代码的全部内容,希望文章能够帮你解决linux开发 stc_仿STC-ISP写的Linux版编程烧录软件,附源代码所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复