calmbreaker.c

来自「eCos操作系统源码」· C语言 代码 · 共 542 行

C
542
字号
/*=============================================================================////      calmbreaker.c////      Host to CalmBreaker communication utility.////=============================================================================//####ECOSGPLCOPYRIGHTBEGIN####// -------------------------------------------// This file is part of eCos, the Embedded Configurable Operating System.// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.//// eCos 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 or (at your option) any later version.//// eCos 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 eCos; if not, write to the Free Software Foundation, Inc.,// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.//// As a special exception, if other files instantiate templates or use macros// or inline functions from this file, or you compile this file and link it// with other works to produce a work based on this file, this file does not// by itself cause the resulting work to be covered by the GNU General Public// License. However the source code for this file must still be made available// in accordance with section (3) of the GNU General Public License.//// This exception does not invalidate any other reasons why a work based on// this file might be covered by the GNU General Public License.//// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.// at http://sources.redhat.com/ecos/ecos-license/// -------------------------------------------//####ECOSGPLCOPYRIGHTEND####//=============================================================================//#####DESCRIPTIONBEGIN####//// Author(s):    msalter// Contributors: msalter// Date:         2001-03-02// Purpose:      // Description:  Host to CalmBreaker communication utility.////####DESCRIPTIONEND####////===========================================================================*/#include <termios.h>#include <fcntl.h>#include <stdio.h>int ser_fd;  // The com portint is_risc16;voidtty_setup(int fd){    struct termios t;    memset(&t, 0, sizeof(struct termios));    t.c_oflag = 0;    t.c_lflag = 0;        t.c_cflag &= ~(CSIZE | PARENB);    t.c_cflag |= CS8 | CREAD /*| CSTOPB*/;    t.c_cflag |= CLOCAL;                   // ignore modem status lines    t.c_iflag = IGNBRK | IGNPAR /* | ISTRIP */ ;    t.c_lflag &= ~ICANON;                  // non-canonical mode    t.c_lflag &= ~(ECHO|ECHOE|ECHOK|ECHOKE);               t.c_cc[VMIN]  = 0;    t.c_cc[VTIME] = 10;  // 1 second timeout    t.c_cflag &= ~CRTSCTS;    /* set speed */    cfsetispeed(&t, B57600);    cfsetospeed(&t, B57600);    tcdrain(fd);    if (tcsetattr(fd, TCSANOW, &t) < 0)    {	perror("tcssetattr");	exit(1);    }}static voiddo_putc(unsigned char ch){    // keep retrying until sent or an error is returned    while (write(ser_fd, &ch, 1) == 0);}static intdo_getc(unsigned char *ucp){    return read(ser_fd, ucp, 1);}static intwait_for_ack(void){    unsigned char ch;    int i;    // try for 5 seconds    for (i = 0; i < 5; i++) {	if (do_getc(&ch)) {	    if (ch == '+')		return 1;	    printf("Bad ack [0x%x]\n", ch);	}    }    printf("No ack\n");    return 0;}// Add prefix and checksum to packet and send to MDS board.voidsend_packet_noack(unsigned char *pkt, int len){    unsigned char cksum = 0;    do_putc(':');    while (len-- > 0) {	cksum += *pkt;	do_putc(*pkt++);    }    do_putc(0x100 - cksum);}// Add prefix and checksum to packet and send to MDS board.voidsend_packet(unsigned char *pkt, int len){    send_packet_noack(pkt, len);    wait_for_ack();}// Send a packet of code or data (max 0xff bytes)intsend_data_packet(int is_data, unsigned addr, unsigned char *buf, int buflen){    unsigned char uc, cksum = 0;    int i;        do_putc(':');        // code or data?    uc = is_data ? 0x52 : 0x51;    cksum += uc;    do_putc(uc);    // code/data nwords?    uc = buflen >> 1;    cksum += uc;    do_putc(uc);    // code/data address    uc = (unsigned char)(addr >> 24);    cksum += uc;    do_putc(uc);    uc = (unsigned char)(addr >> 16);    cksum += uc;    do_putc(uc);    uc = (unsigned char)(addr >> 8);    cksum += uc;    do_putc(uc);    uc = (unsigned char)addr;    cksum += uc;    do_putc(uc);    while (buflen-- > 0) {	cksum += *buf;	do_putc(*buf++);    }    do_putc(0x100 - cksum);    return wait_for_ack();}voidsend_command(unsigned char uc){    send_packet(&uc, 1);}voidsend_command_noack(unsigned char uc){    send_packet_noack(&uc, 1);}// Simple single-byte commandsvoid target_reset(void) { send_command(0x20); }void target_singlestep(void) { send_command(0x22); }void target_singlecycle(void) { send_command(0x23); }void target_stop(void) { send_command(0x24); }void target_run(void) { send_command_noack(0x25); }#define DOWNLOAD_CHUNK_SIZE 254intdownload_words(int is_data, unsigned addr, unsigned char *buf, int buflen){    while (buflen >= DOWNLOAD_CHUNK_SIZE) {	if (!send_data_packet(is_data, addr, buf, DOWNLOAD_CHUNK_SIZE)) {	    printf("Error downloading %d bytes of %s to 0x%x\n",		   DOWNLOAD_CHUNK_SIZE, (is_data ? "data" : "code"), addr);	    return 0;	}	addr += DOWNLOAD_CHUNK_SIZE;	buf += DOWNLOAD_CHUNK_SIZE;	buflen -= DOWNLOAD_CHUNK_SIZE;    }    if (buflen && !send_data_packet(is_data, addr, buf, buflen)) {	printf("Error downloading %d bytes of %s to 0x%x\n",	       buflen, (is_data ? "data" : "code"), addr);	return 0;    }    return 1;}static inline intgethexnibble(FILE *fp){    int ch;    ch = getc(fp);    if (ch >= '0' && ch <= '9')	return (ch - '0');    if (ch >= 'a' && ch <= 'f')	return (ch - 'a' + 10);    if (ch >= 'A' && ch <= 'F')	return (ch - 'A' + 10);    if (ch == EOF)	fprintf(stderr, "Unexpected EOF\n");    else	fprintf(stderr, "Bad hex char\n");    return -1;}static inline intgethexbyte(FILE *fp){    int nib;    unsigned char n;    if ((nib = gethexnibble(fp)) < 0)	return -1;    n = nib << 4;    if ((nib = gethexnibble(fp)) < 0)	return -1;    n |= nib;    return n;}static inline intchk_cksum(FILE *fp, unsigned int cksum){    int n;    if ((n = gethexbyte(fp)) < 0)	return -1;    cksum = ~cksum & 0xff;    if (cksum != n) {	fprintf(stderr, "Bad cksum[%02x]\n", cksum);	return -1;    }    return 0;}intload_srec(FILE *fp, int is_data){    int count, dcount, data, n, addr_bytes = 0, is_term, is_comment;    unsigned long address, cksum;    unsigned char data_buf[256];    is_comment = is_term = 0;    do {	if ((n = getc(fp)) == EOF)	    return 1;    } while (n != 'S');	        switch (n = gethexnibble(fp)) {      case 0:      case 5:	is_comment = 1;	break;      case 1:      case 2:      case 3:	addr_bytes = n + 1;	break;      case 7:      case 8:      case 9:	is_term = 1;	addr_bytes = 11 - n;	break;      default:	if (n < 0)	    return -1;	fprintf(stderr, "Bad record type: %d\n", n);	return -1;    }    if ((count = gethexbyte(fp)) < 0)	return -1;    cksum = count;    --count; // don't count chksum    if (is_comment) {	while (count > 0) {	    if ((n = gethexbyte(fp)) < 0)		return -1;	    cksum += n;	    --count;	}	if (chk_cksum(fp,cksum) < 0)	    return -1;	return 0;    }    address = 0;    while (count > 0 && addr_bytes) {	if ((n = gethexbyte(fp)) < 0)	    return -1;	cksum += n;	address = (address << 8) | n;	--addr_bytes;	--count;    }    if (is_risc16 && (address & 0x400000))	address &= 0x3fffff;    if (is_term) {	if (count || addr_bytes) {	    fprintf(stderr, "Malformed record cnt[%d] abytes[%d]\n",		    count, addr_bytes);	    return -1;	}	if (chk_cksum(fp, cksum) == 0) {	    fprintf(stderr, "Setting start address: 0x%08x\n", address);	    return 1;	}	return -1;    }    for (dcount = 0; dcount < count; dcount++) {	if ((data = gethexbyte(fp)) < 0)	    return -1;	cksum += data;	data_buf[dcount] = data;    }        if (chk_cksum(fp, cksum) < 0)	return -1;    if (dcount & 1)	dcount++;    if (!download_words(is_data, address, data_buf, dcount))	return -1;        return 0;}intload_hex(FILE *fp, int is_data){    int count, n, i;    unsigned long address;    unsigned char data_buf[256];        do {	if ((n = getc(fp)) == EOF)	    return 1;    } while (n == '\r' || n == '\n');    if (n == '#') {	do {	    if ((n = getc(fp)) == EOF)		return 1;	} while (n != '\r' && n != '\n');	return 0;    }    if (n != ':') {	fprintf(stderr, "Unrecognized HEX line start.\n");	return -1;    }    if ((count = gethexbyte(fp)) < 0)	return -1;    address = 0;    for (i = 0; i < 4; i++) {	if ((n = gethexbyte(fp)) < 0)	    return -1;	address = (address << 8) | n;    }    // skip type byte    if ((n = gethexbyte(fp)) < 0)	return -1;    for (i = 0; i < count; i++) {	if ((n = gethexbyte(fp)) < 0)	    return -1;	data_buf[i] = n;    }    // skip chksum byte    if ((n = gethexbyte(fp)) < 0)	return -1;    if (count & 1)	++count;    if (!download_words(is_data, address, data_buf, count))	return -1;        return 0;}intmain(int argc, char *argv[]){    int i;    int do_download = 0, is_data, is_hex;    int do_run = 0, do_reset = 0;    char *filename = NULL;    char *portname = "/dev/ttyS0";    FILE *infile;    if (argc == 1) {	fprintf(stderr, "Usage: mds_talk [--run] [--reset] [--srec-code | --srec-date | --hex-code | --hex-data] [-f filename] [-p serial_dev]\n");	exit(1);    }    is_risc16 = 0;    for (i = 1; i < argc; i++) {	if (!strcmp(argv[i], "--srec-code")) {	    do_download = 1;	    is_data = 0;	    is_hex = 0;	} else if (!strcmp(argv[i], "--srec-data")) {	    do_download = 1;	    is_data = 1;	    is_hex = 0;	} else if (!strcmp(argv[i], "--hex-code")) {	    do_download = 1;	    is_data = 0;	    is_hex = 1;	} else if (!strcmp(argv[i], "--hex-data")) {	    do_download = 1;	    is_data = 1;	    is_hex = 1;	} else if (!strcmp(argv[i], "--reset"))	    do_reset = 1;	else if (!strcmp(argv[i], "--run"))	    do_run = 1;	else if (!strcmp(argv[i], "-f")) {	    if (++i >= argc) {		fprintf(stderr, "Missing filename\n");		exit(1);	    }	    filename = argv[i];	} else if (!strcmp(argv[i], "-p")) {	    if (++i >= argc) {		fprintf(stderr, "Missing serial port name\n");		exit(1);	    }	    portname = argv[i];	} else if (!strcmp(argv[i], "--risc16")) {	    is_risc16 = 1;	} else {	    fprintf(stderr, "Unknown argument \"%s\"\n", argv[i]);	    exit(1);	}    }    if ((ser_fd = open(portname, O_RDWR | O_NOCTTY)) < 0) {	fprintf(stderr, "Can't open port %s\n", portname);	exit(1);    }    tty_setup(ser_fd);    if (filename) {	if ((infile = fopen(filename, "r")) == NULL) {	    fprintf(stderr, "Can't open file %s\n", filename);	    exit(1);	}    } else	infile = stdin;    if (do_reset)	target_reset();    if (do_download) {	if (is_hex)	    while (!load_hex(infile, is_data)) ;	else	    while (!load_srec(infile, is_data)) ;    }    if (do_run)	target_run();}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?