⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 loadpgm.c

📁 DOS 串口通迅程序﹐下載BINARY 文件到單片機﹐有效驗和握手協議﹐發行版。
💻 C
字号:
#include <time.h>
#include <stdio.h>
#include <dos.h>
#include <conio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <math.h>

#define RETRIES         64
#define BLOCK_NUM       9               // (32 * 1024) / 4096
#define BUF_SIZE        4096

#define BAUD2400        24
#define BAUD9600        12
#define BAUD19200       6
#define BAUD28800       2

#define PIC_EOI1 0x20        /* 8259 pic assignments */
#define PIC_MSK1 0x21

#define PIC_EOI2 0xA0
#define PIC_MSK2 0xA1

#define COM1_ADR 0x03f8     /* COM1 port base address */
#define COM1_MSK 0x10       /* COM1 8259 pic interrupt mask */
#define COM1_INT 0x0c       /* COM1 interrupt number */

#define COM2_ADR 0x02f8     /* COM2 port base address */
#define COM2_MSK 0x08       /* COM2 8259 pic interrupt mask */
#define COM2_INT 0x0b       /* COM2 interrupt number */

#define COM3_ADR 0x03e8     /* COM3 port base address */
#define COM3_MSK 0x04       /* COM3 8259 pic interrupt mask */
#define COM3_INT 0x72       /* COM3 interrupt number */

#define COM4_ADR 0x0270     /* COM4 port base address */
#define COM4_MSK 0x08       /* COM4 8259 pic interrupt mask */
#define COM4_INT 0x73       /* COM4 interrupt number */

unsigned int    com_DATA;       /* data register */
unsigned int    com_IER;        /* interrupt enable register */
unsigned int    com_LCR;        /* line control register */
unsigned int    com_MCR;        /* mode control register */
unsigned int    com_LSR;        /* status register */
unsigned int    com_MSR;        /* modem status register */
unsigned int    com_MSK;        /* interupt mask */
unsigned int    com_INT;        /* interrupt number */

void (interrupt far *oldvector)();  /* save old intr vector addr */
void interrupt far handler();       /* declaration for intr handler */

unsigned int    oldlcr;
unsigned int    olddll;
unsigned int    olddlm;

#define BUFSIZE 0x3ff              /* input buffer size */

volatile unsigned char Buffer[BUFSIZE+1]; /* rx in buffer for COM1     */
volatile unsigned int    AscIn, AscOut;  /* buffer in,out ptr offsets */

int debug, skip;

FILE *fp;


//***************************************************

char    filename[40];
char    cmd_erase[6] = { 0x1B, '%', '1', 'E', 0, 0 };
char    cmd[10];
char    cmd_response[256];
unsigned char xmit_buffer[BUF_SIZE];


//***************************************************

void dlysec( unsigned int sec )
{
    time_t tstart, tend;

    time( &tstart );
    do
    {
		time( &tend );
    } while( difftime( tend, tstart ) < sec );
}

void dlymsec( unsigned int msec )
{
    clock_t cstart;

    cstart = clock();
    while( (clock() - cstart) < msec );
}

error_exit( int code )
{

	//** debug
	int i;
	for( i=0; i<100; i++ )
	{
		outp( com_MCR, 0x02 );
		outp( com_MCR, 0 );
	}
	//** debug

	async_dis();
	exit(code);
}

/*===================================================*/
/* setup addressing for both com ports               */
/*===================================================*/
void com_init( int addr, int mask, int intr )
{
    com_MSK  = mask;
    com_INT  = intr;
    com_DATA = addr;             /* data register */
    com_IER  = addr + 1;         /* interrupt enable register */
    com_LCR  = addr + 3;         /* line control register */
    com_MCR  = addr + 4;         /* modem control register */
    com_LSR  = addr + 5;         /* status register */
    com_MSR  = addr + 6;         /* modem status register */

    oldlcr = inp(com_LCR);              /* save original com port setup */
    olddll = inp(com_DATA);
    olddlm = inp(com_IER);
}


void set_baud( int baud )
{
    unsigned int divisor;
	int	lcr;

    divisor  = baud;

    outp(com_LCR, 0x80);

    outp(com_IER, divisor >> 8);
    outp(com_DATA, divisor);            /* set baud rate */
    outp(com_LCR, 0x0b);                /* set length,stop bits, etc. */
}


/*=====================================================*/
/* set up interrupt vector, and initialize serial port */
/*=====================================================*/
async_en()
{
    int data,msk;

    oldvector = _dos_getvect(com_INT);  /* store old interupt vector */
    _dos_setvect(com_INT, handler);     /* init interrupt vector table */

    _disable();                                 /* cli */
    data = 0x0b;
    outp(com_MCR, data);                        /* setup mode control */

    inp(com_DATA);                              /* clear potential pending intr */

	if( com_INT == 0x0c || com_INT == 0x0b )
		msk = PIC_MSK1;
	else
		msk = PIC_MSK2;

    data = inp(msk);                            /* unmask com interupt */
    data &= ~(com_MSK);
    outp(msk, data);
    _enable();                          /* sti */

    outp(com_IER, 1);                           /* enable interrupt */
    outp(PIC_EOI2, 0x20);               /* issue eoi to 8259 */
    outp(PIC_EOI1, 0x20);               /* issue eoi to 8259 */
}


/*======================================================*/
/* disable com interrupts, restore old interrupt vector */
/*======================================================*/
async_dis()
{
    int data,msk;

	if(debug)
		printf("\nRestore interrupt vector");

	if( com_INT == 0x0c || com_INT == 0x0b )
		msk = PIC_MSK1;
	else
		msk = PIC_MSK2;

    outp(com_MCR, 0);                      /* clear mode control reg */
    data = inp(msk);                    /* set mask bit for com port */
    data |= com_MSK;
    outp(msk, data);
    _dos_setvect(com_INT, oldvector);     /* init interrupt vector table */

    outp(com_LCR, oldlcr | 0x80);         /* restore com setup */
    outp(com_DATA, olddll);
    outp(com_IER, olddlm);
    outp(com_LCR, oldlcr);
}

void clrbuf()
{
	AscIn=AscOut=0;
}

void rts_on()
{
	outp( com_MCR, 0x02 );
}

void rts_off()
{
	outp( com_MCR, 0 );
}

/*===========================*/
/* read char from COM  port */
/*===========================*/
int com_in( int len, int msec )
{
    int ch, i;
    clock_t cstart;

    cstart = clock();

    if( debug )
		printf("\nrcvd: ");

    i = 0;

    do
    {
		if( AscIn != AscOut )
		{
	    	cmd_response[i++] = *(Buffer + AscOut);
	    	AscOut++;
	    	AscOut &= BUFSIZE;
	    	
			if( debug) 
				printf("%c", cmd_response[i-1]);

			cstart = clock();
			msec = 100;
		}

    } while( ( (clock()-cstart) < msec ) && ( i < len ) );

	cmd_response[i] = 0;

	return(i);
}


/*=================================*/
/* transmit specified char to COM */
/*=================================*/
com_out(char ch)
{
    while ((inp(com_LSR) & 0x20) == 0); // wait for transmitted buffer empty
	while ((inp(com_MSR) & 0x10) == 0); // wait fot CTS
    outp(com_DATA, ch);

	if( debug )
		putchar( ch );
}

com_outs( char *str )
{
	char chr;

	if( debug )
		printf("\nsend: ");

	while( chr = *str++ )
		com_out( chr );
}

void send_char( unsigned char chr )
{
	_asm
	{
		mov     dx, com_LSR

	wait2send:
		in      al, dx
		test    al, 0x20
		jz      wait2send

		mov     dx, com_MSR
	waitCTS:
		in      al, dx
		test    al, 0x10
		jz      waitCTS

		mov		dx, com_DATA
		mov     al, chr
		out     dx, al
	}
}

int send_block( unsigned char *pbuf, int len )
{
	int i;
	unsigned char chr;
	unsigned int  sum = 0;

	for( i=len; i; i-- )
	{
		send_char( chr = *pbuf++ );
		sum += chr;
	}

	send_char((unsigned char)(sum >> 8));
	send_char((unsigned char)(sum & 0xff));
}


/*=======================*/
/* interrupt handler...  */
/*=======================*/
void interrupt far
handler(es, ds, di, si, bp, sp, bx, dx, cx, ax, ip, cs, flags)
 int    es, ds, di, si, bp, sp, bx, dx, cx, ax, ip, cs, flags;
{
    *(Buffer + AscIn) = inp(com_DATA);   /* read ch from serial port */
    AscIn++;                               /* incr ptr */

    AscIn = AscIn & BUFSIZE;
    _enable();                              /* issue sti */
    outp(PIC_EOI2, 0x20);                    /* 8259 #1 eoi */
    outp(PIC_EOI1, 0x20);                    /* 8259 #1 eoi */
}

int to_off(char *hexds)
{
    int     i;
    int     off = 0;
    char    chr;

    for (i = 0; i < 3; i++) {
	chr = *hexds++;
	if (isdigit(chr))
	    chr -= '0';
	else if (isxdigit(chr))
	    chr = (chr | ('a' - 'A')) - 'a' + 10;
	else
	    return -1;
	off = (off << 4) | chr;
    }
    return off;
}

void device_info()
{
	printf("\n\tType of Display  = %c", cmd_response[3] );
	printf("\n\tFirmware version = %c%c", cmd_response[5], cmd_response[6] );
	printf("\n\tCharacter set    = %c", cmd_response[8] );
	printf("\n\tNumber of lines  = %c", cmd_response[10] );
	printf("\n\tCharacters/line  = %c%c",  cmd_response[12], cmd_response[13] );
}

main( int argc, char *argv[] )
{
    unsigned char cc;
    int addr, mask, intr, baud;
    int p1, p2;
	int blk_no;
	int len;
	int     i;
	int remain, offset;
	char *ptr;

	skip  = debug = 0;
	addr  = COM3_ADR;
	mask  = COM3_MSK;
	intr  = COM3_INT;
	baud  = BAUD9600;
	strcpy( filename, "LCD52.BIN" );


	for( i=1; i<argc; i++ )
	{
		if( argv[i][0] != '/' )
			continue;

		switch( argv[i][1] )
		{

			case 'C':
			case 'c':
				p1 = atoi( argv[i] + 3 );
    			switch(p1)
    			{
					case 1:
	    				addr = COM1_ADR;
	    				mask = COM1_MSK;
	    				intr = COM1_INT;
	    				break;

					case 2:
	    				addr = COM2_ADR;
	    				mask = COM2_MSK;
	    				intr = COM2_INT;
	    				break;

					case 3:
	    				addr = COM3_ADR;
	    				mask = COM3_MSK;
	    				intr = COM3_INT;
	    				break;

					case 4:
	    				addr = COM4_ADR;
	    				mask = COM4_MSK;
	    				intr = COM4_INT;
	    				break;

					default:
	    				printf("\nInvalid port number\n");
	    				exit(0);
    			}
				break;

			case 'B':
			case 'b':
				p1 = atoi( argv[i] + 3 );

    			switch(p1)
    			{
					case 2400:
	    				baud = BAUD2400;
	    				break;

					case 9600:
	    				baud = BAUD9600;
	    				break;

					case 19200:
	    				baud = BAUD19200;
	    				break;

					default:
	    				printf("\nInvalid baud rate\n");
	    				exit(0);
    			}

			case 'F':
			case 'f':
				strcpy( filename, argv[i] + 3 );
				break;

			case 'D':
			case 'd':
				debug = 1;
				break;

			case 'X':
			case 'x':
				skip = 1;
				break;				

			case '?':
				printf("\nUsage: Loadpgm /C=com /B=baud /F=filename /Debug \n\n");
				exit(0);

		}
	}

    printf("\nLOADPGM ver 1.0");

	if( (fp = fopen( filename, "rb" )) == NULL )
	{
		printf("\nCannot open %s", filename );
		exit( 1 );
	}

	clrbuf();

    com_init( addr, mask, intr );
	set_baud( BAUD9600 );
    async_en();         

	dlysec(1);
	clrbuf();
	
	printf("\n\n> Get Device ID: ");
	com_outs("");               // Get device ID

	rts_on();
	if( com_in( 15, 5000 ) == 0 )
	{
		rts_off();
		error_exit( 1 );
	}

	device_info();

	clrbuf();
	if( (cmd_response[5] != '0' || cmd_response[6] != '0') && skip == 0 )
	{
		printf("\n\n> Go to EPROM mode");
    	com_outs("#0P");
    	com_outs("#4P");
    	com_outs("#7P");
    	com_outs("#2P");
    	com_outs("%0G");           	// Go to EPROM mode

		dlysec(1);

		printf("\n\n> Waiting for device initialisation ");

		for( i=0; i<15; i++ )
		{
			if( AscIn != AscOut )
				break;

			dlysec(1);
			putchar('.');
		}

		if( i == 15 )
		{
			printf("\n## Timeout waiting for device initialization");
			//error_exit(1);
		}
		else
		{
			com_in(15,1000);
			device_info();
		}
	}

	rts_off();
	clrbuf();

	for( blk_no = 0; blk_no < BLOCK_NUM; blk_no++ )
	{
		len = fread( xmit_buffer, 1, BUF_SIZE, fp );
		if( len == 0 )
			break;

		dlysec(1);

		printf("\n\n> BLOCK #%d", blk_no);

		set_baud( BAUD9600 );

		com_outs("#0P");
		com_outs("#4P");
		com_outs("#7P");
		com_outs("#2P");

		if( blk_no % 16 == 0 )
		{
			printf("\n>> Erasing ...");

			cmd_erase[2] = (blk_no / 16) + '0';
			if(cmd_erase[2] > '9')
				cmd_erase[2] += 'A' - '0';

			clrbuf();
			rts_on();
			com_outs( cmd_erase );
			if( com_in( 6, 5000 ) != 6 )
			{
				printf("\n## received timeout: %s", cmd_response);
				error_exit(1);
			}
            else if( !strcmp(cmd_response, "&E-OK") )
            printf(" OK" );
			else
			{
				printf("\n## erase FAIL: %s\n", cmd_response);
				error_exit(1);
			}
		}
		rts_off();
		
		printf("\n>> Programming blk %d ... ", blk_no);

		sprintf(cmd, "$A%05lX", blk_no * 0x1000L);
		com_outs(cmd);                      // Program Address

		sprintf(cmd, "$L%03X", len-1);
		com_outs(cmd);                      // Program range

		dlymsec( 20 );
		set_baud( BAUD28800 );

		offset = 0;

		rts_off();

		for( i=0; i<RETRIES; i++ )
		{
			clrbuf();
			rts_on();
			if( com_in( 6, 5000 ) == 0 )
			{
				printf("\n## Receive timeout: Data Req Cmd: previous offset=%04X", offset);
				error_exit(1);
			}
			rts_off();

			if( isxdigit( cmd_response[2] ) )
			{
				offset = to_off( cmd_response + 2 );

				if( offset == -1 )
				{
					printf("\n## Transmit error: %s", cmd_response );
					break;
				}
			}
			else if( strcmp(cmd_response, "&R-OK") == 0 )
				break;
			else if( strcmp(cmd_response, "&FAIL") == 0 )
				break;

			remain = len - offset;
			send_block( xmit_buffer + offset, (remain > 256) ? 256 : remain );
		}

		if( i == RETRIES ) 
		{
			printf("\n## Too more errors, program aborted\n");
			break;
		}

		if( strcmp(cmd_response, "&R-OK") ) 
		{
			printf("\n## Without expected receive OK (%s)\n", cmd_response);
			break;
		}

		clrbuf();
		rts_on();
		if( com_in( 6, 5000 ) != 6 ) 
		{
			printf("\n## Receive time out: expect program OK!\n");
			error_exit(2);
		}
		rts_off();

		if( strcmp(cmd_response, "&P-OK") == 0 ) 
			printf( " OK" );
		else
		{
			printf("\n## Program FAIL (%s)\n", cmd_response);
			error_exit(2);
		}
    }
	rts_off();
    set_baud( BAUD9600 );

   //	dlysec( 1 );

	rts_on();
	clrbuf();
	printf("\n\n> Execute from Flash.");
   	com_outs("#0P");
   	com_outs("#4P");
   	com_outs("#7P");
   	com_outs("#2P");
   	com_outs("%1G");           	// Go to FLASH mode

	dlysec(1);

	printf("\n\n> Waiting for device initialisation ");

	for( i=0; i<15; i++ )
	{
		if( AscIn != AscOut )
			break;

		dlysec(1);
		putchar('.');
	}

	if( i == 15 )
	{
		printf("\n## Timeout waiting for device initialization");
		//error_exit(1);
	}
 
	com_in(11000);
 	rts_off();

	device_info();
 	printf("\n\n");

    async_dis();
    fclose(fp);
}

⌨️ 快捷键说明

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