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

📄 picboot.c

📁 P1618QP bootloader code
💻 C
字号:

/******************************************************************************\
*	PIC16/18 Bootloader Communications Handler
*	by Ross M. Fosler
*	Microchip Technology Incorporated
\******************************************************************************/

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

    PROGRAM:	P1618BOOT.c

    PURPOSE:	The purpose of this DLL is to provide a communications base for 
				quick and easy higher level development.

    FUNCTIONS:	HANDLE APIENTRY OpenPIC(LPSTR, DWORD, DWORD)
				INT APIENTRY ClosePIC(HANDLE)
				INT APIENTRY GetPacket(HANDLE, BYTE *, WORD)
				INT APIENTRY SendPacket(HANDLE, BYTE *, WORD)
				INT APIENTRY SendGetPacket(HANDLE, BYTE *, WORD, WORD, WORD)
				DWORD APIENTRY WritePIC(HANDLE, PIC *, BYTE *)
				DWORD APIENTRY ReadPIC(HANDLE, PIC *, BYTE *)     

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

#include "windows.h"
#include "PICBOOT.h"



/****************************************************************************
   FUNCTION: DllMain(HANDLE, DWORD, LPVOID)

   PURPOSE:  DllMain is called by Windows when
             the DLL is initialized, Thread Attached, and other times.
             Refer to SDK documentation, as to the different ways this
             may be called.
             
             The DllMain function should perform additional initialization
             tasks required by the DLL.  In this example, no initialization
             tasks are required.  DllMain should return a value of 1 if
             the initialization is successful.
           
*******************************************************************************/
BOOL APIENTRY DllMain(HANDLE hInst, DWORD ul_reason_being_called, LPVOID lpReserved)
{
    return 1;
        UNREFERENCED_PARAMETER(hInst);
        UNREFERENCED_PARAMETER(ul_reason_being_called);
        UNREFERENCED_PARAMETER(lpReserved);
}


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

    FUNCTION:	OpenPIC

    PURPOSE:	This function is provided to open communications to the
				PIC through a serial port. The function returns a handle 
				to the opened port or returns a negative number on an error.

****************************************************************************/
HANDLE APIENTRY OpenPIC(LPSTR ComPort, DWORD BitRate, DWORD ReadTimeOut)
{
	HANDLE hComm;
	DCB dcb = {0};
	COMMTIMEOUTS CommTmOut = {0};
	
	// Get a handle to the port.
	hComm = CreateFile( ComPort,  
                       GENERIC_READ | GENERIC_WRITE, 
                       0, 
                       NULL, 
                       OPEN_EXISTING,
                       FILE_ATTRIBUTE_NORMAL,
                       0);
	if (hComm == INVALID_HANDLE_VALUE)
		return INVALID_HANDLE_VALUE;

	// Get the current state of the port
	FillMemory(&dcb, sizeof(dcb), 0);

	if (!GetCommState(hComm, &dcb)){
		return INVALID_HANDLE_VALUE;
	}
	else{
		dcb.BaudRate = BitRate;
		dcb.Parity = NOPARITY;
		dcb.StopBits = ONESTOPBIT;
		dcb.fDtrControl = DTR_CONTROL_DISABLE;
		dcb.fRtsControl = RTS_CONTROL_DISABLE;
		dcb.fOutX = FALSE;
		dcb.fInX = FALSE;
		dcb.fOutxCtsFlow = FALSE;
		dcb.fOutxDsrFlow = FALSE;
		dcb.ByteSize = 8;
	}
		
	if (!SetCommState(hComm, &dcb))
		return INVALID_HANDLE_VALUE;


	//Set the timeout conditions
	if (!GetCommTimeouts(hComm, &CommTmOut)){
		return INVALID_HANDLE_VALUE;
	}
	else{
		CommTmOut.ReadIntervalTimeout = MAXDWORD;
		CommTmOut.ReadTotalTimeoutMultiplier = MAXDWORD;
		CommTmOut.ReadTotalTimeoutConstant = ReadTimeOut;
	}

	if (!SetCommTimeouts(hComm, &CommTmOut))
		return INVALID_HANDLE_VALUE;

	return hComm;
}



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

    FUNCTION:	ClosePIC

    PURPOSE: 

****************************************************************************/
INT APIENTRY ClosePIC(HANDLE hComPort)
{
	return CloseHandle(hComPort);
}








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

    FUNCTION:	GetPacket

    PURPOSE:	This function captures data from the opened source and 
				strips out special control characters. The length of the 
				packet is returned.

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

INT APIENTRY GetPacket(HANDLE hComPort, BYTE PacketData[], WORD ByteLimit)
{
	WORD PacketCount;
	DWORD Checksum = 0;
	DWORD BytesRead;
	BYTE DataByte;
	BYTE Flags = 2;

	//Scan for a start condition
StartOfPacket:
	while (Flags){

		BytesRead = 0;
		if (!ReadFile(hComPort, &DataByte, 1, &BytesRead, NULL)) return ERROR_GEN_READWRITE;
		if (!BytesRead) return ERROR_READ_TIMEOUT;

		if (DataByte == STX) Flags--;
		else Flags = 2;
	}

	//Get the data and unstuff when necessary
	PacketCount = 0;
	Flags = 1;
	while (Flags){

		BytesRead = 0;
		if (!ReadFile(hComPort, &DataByte, 1, &BytesRead, NULL)) return ERROR_GEN_READWRITE;
		if (!BytesRead) return ERROR_READ_TIMEOUT;

		switch (DataByte){
			case STX: 
			{
				goto StartOfPacket;
			}
			case ETX: 
			{
				Flags = 0;
				continue;
			}
			case DLE: 
			{
				BytesRead = 0;
				if (!ReadFile(hComPort, &DataByte, 1, &BytesRead, NULL)) return ERROR_GEN_READWRITE;
				if (!BytesRead) return ERROR_READ_TIMEOUT;
			}
			default:
			{
				if (PacketCount > ByteLimit) return ERROR_READ_LIMIT;
				PacketData[PacketCount] = DataByte;
				Checksum = Checksum + (DWORD)DataByte;
				PacketCount++;
			}
		}
	}

	//Test the checksum
	DataByte =  (BYTE)(((~(Checksum)) + 1) & 255);
	if (DataByte) return ERROR_BAD_CHKSUM;
	
	return PacketCount;
}






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

    FUNCTION:	SendPacket

    PURPOSE:	This function translates and transmitts a packet of data to 
				communicate with the bootloader firmware on the PIC
				microcontroller.

****************************************************************************/
INT APIENTRY SendPacket(HANDLE hComPort, 
						BYTE PacketData[],  
						WORD NumOfBytes)
{
	UINT PacketCount;
	DWORD Checksum = 0;
	DWORD BytesWritten;
	BYTE DataByte;
	
	//Send the start condition
	DataByte = STX;
	for(PacketCount = 0; PacketCount < 2; PacketCount++){
		if (!WriteFile(hComPort, &DataByte, 1, &BytesWritten, NULL)){
			return ERROR_GEN_READWRITE;
		}
	}

	//Send the packet data and stuff byte if necessary
	for(PacketCount = 0; PacketCount < NumOfBytes; PacketCount++)
	{
		switch (PacketData[PacketCount])
		{
			case STX:
			case ETX:
			case DLE:
			{
				DataByte = DLE;
				if (!WriteFile(hComPort, &DataByte, 1, &BytesWritten, NULL)) return ERROR_GEN_READWRITE;
				break;
			}
		}
		
		DataByte = PacketData[PacketCount]; 
		Checksum = Checksum + (DWORD)DataByte; 
		if (!WriteFile(hComPort, &DataByte, 1, &BytesWritten, NULL)) return ERROR_GEN_READWRITE;
	}
	
	//Send the checksum
	DataByte =  (BYTE)(((~(Checksum)) + 1) & 255);
	switch (DataByte)
	{
		case STX:
		case ETX:
		case DLE:
		{
			DataByte = DLE;
			if (!WriteFile(hComPort, &DataByte, 1, &BytesWritten, NULL)) return ERROR_GEN_READWRITE;
			break;
		}
	}
	DataByte =  (BYTE)(((~(Checksum)) + 1) & 255);
	if (!WriteFile(hComPort, &DataByte, 1, &BytesWritten, NULL)) return ERROR_GEN_READWRITE;


	//Send the stop condition
	DataByte = ETX;
	if (!WriteFile(hComPort, &DataByte, 1, &BytesWritten, NULL)) return ERROR_GEN_READWRITE;

	return	PacketCount;
}






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

    FUNCTION:	SendGetPacket

    PURPOSE:	This function is a combined function of the SendPacket and
				GetPacket functions. A retry option has been added to allow
				retransmission and reception in the event of normal 
				communications failure. 

****************************************************************************/
INT APIENTRY SendGetPacket(HANDLE hComPort, 
							BYTE PacketData[],
							WORD SendNumOfBytes,
							WORD RecvByteLimit,
							WORD NumOfRetrys)
{
	INT RetStatus;
	INT RetryCount;

	RetryCount = NumOfRetrys;

	while (TRUE){
		if(!RetryCount) return ERROR_RETRY_LIMIT;
		RetryCount--;

		RetStatus = SendPacket(hComPort, PacketData, SendNumOfBytes);
		if(RetStatus < 0) return RetStatus;

		RetStatus = GetPacket(hComPort, PacketData, RecvByteLimit);
		switch (RetStatus){
			case	ERROR_READ_TIMEOUT:
			case	ERROR_BAD_CHKSUM:
				continue;

			default: return RetStatus;
		}
		
		break;
	}

	return RetStatus;
}





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

    FUNCTION:	ReadPIC

    PURPOSE:	This is a simple read function. 

****************************************************************************/
INT APIENTRY ReadPIC(HANDLE hComPort, PIC *pic, BYTE PacketData[])
{
	BYTE InData[MAX_PACKET];		//Allocate for one packet
	INT RetStatus;
	INT DatCount;
	INT DatCount2 = 0;

	switch (pic->BootCmd){
		case COMMAND_READPM: 
		case COMMAND_READEE: 
		case COMMAND_READCFG: 
			break;
		default: return ERROR_INVALID_COMMAND;
	}
	
	//Limit to 1 or 2 bytes per addr
	if(!pic->BytesPerAddr) return ERROR_BPA_TOO_SMALL;
	if(pic->BytesPerAddr > 2) return ERROR_BPA_TOO_BIG;

	if(pic->BytesPerBlock < pic->BytesPerAddr) return ERROR_BLOCK_TOO_SMALL;
	if(pic->BootDatLen > MAX_PACKET - 6) return ERROR_PACKET_TOO_BIG;

	//Build header
	InData[0] = pic->BootCmd;
	InData[1] = pic->BootDatLen / pic->BytesPerAddr;
	InData[2] = (BYTE)(pic->BootAddr & 0xFF);
	InData[3] = (BYTE)((pic->BootAddr & 0xFF00) / 0x100);
	InData[4] = (BYTE)((pic->BootAddr & 0xFF0000) / 0x10000);

	RetStatus = SendGetPacket(hComPort, InData, 5, MAX_PACKET, pic->MaxRetrys);

	if(RetStatus < 0) return RetStatus;

	for (DatCount = 5; DatCount < RetStatus - 1; DatCount++){
		PacketData[DatCount2] = InData[DatCount];
		DatCount2++;
	}
	
	return DatCount2;
}



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

    FUNCTION:	

    PURPOSE: 

****************************************************************************/
INT APIENTRY WritePIC(HANDLE hComPort, PIC *pic, BYTE PacketData[])
{
	BYTE OutData[MAX_PACKET];		//Allocate for one packet
	INT RetStatus;
	INT DatCount;
	INT DatCount2;

	switch (pic->BootCmd){
		case COMMAND_WRITEPM: 
		case COMMAND_WRITEEE: 
		case COMMAND_WRITECFG: 
			break;
		default: return ERROR_INVALID_COMMAND;
	}

	//Limit to 1 or 2 bytes per addr
	if(!pic->BytesPerAddr) return ERROR_BPA_TOO_SMALL;
	if(pic->BytesPerAddr > 2) return ERROR_BPA_TOO_BIG;

	if(pic->BytesPerBlock < pic->BytesPerAddr) return ERROR_BLOCK_TOO_SMALL;
	if(pic->BootDatLen > MAX_PACKET - 6) return ERROR_PACKET_TOO_BIG;

	if(pic->BootAddr % pic->BytesPerBlock) return ERROR_OFF_BOUNDRY;
	if(pic->BootDatLen % pic->BytesPerBlock) return ERROR_OFF_BOUNDRY;

	//Build header
	OutData[0] = pic->BootCmd;
	OutData[1] = pic->BootDatLen / pic->BytesPerBlock;
	OutData[2] = (BYTE)(pic->BootAddr & 0xFF);
	OutData[3] = (BYTE)((pic->BootAddr & 0xFF00) / 0x100);
	OutData[4] = (BYTE)((pic->BootAddr & 0xFF0000) / 0x10000);

	DatCount = 5;
	for (DatCount2 = 0; DatCount2 < pic->BootDatLen; DatCount2++){
		OutData[DatCount] = PacketData[DatCount2];
		DatCount++;
	}

	RetStatus = SendGetPacket(hComPort, OutData, (BYTE)DatCount, MAX_PACKET, pic->MaxRetrys);

	if(RetStatus < 0) return RetStatus;

	return DatCount2;
}








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

    FUNCTION:	ErasePIC

    PURPOSE:	Simple erase function.

****************************************************************************/
INT APIENTRY ErasePIC(HANDLE hComPort, DWORD PICAddr, BYTE nBlock, BYTE nRetry)
{
	BYTE InData[MAX_PACKET];		//Allocate for one packet
	INT RetStatus;
	
		
	//Build header
	InData[0] = COMMAND_ERASEPM;
	InData[1] = nBlock;
	InData[2] = (BYTE)(PICAddr & 0xFF);
	InData[3] = (BYTE)((PICAddr & 0xFF00) / 0x100);
	InData[4] = (BYTE)((PICAddr & 0xFF0000) / 0x10000);

	RetStatus = SendGetPacket(hComPort, InData, 5, MAX_PACKET, nRetry);

	if(RetStatus < 0) return RetStatus;

	return InData[1];
}













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

    FUNCTION:	

    PURPOSE: 

****************************************************************************/
INT APIENTRY VerifyPIC(HANDLE hComPort, PIC *pic, BYTE PacketData[]){
	INT RetStatus;
	BYTE InData[MAX_PACKET];
	INT i;

	switch (pic->BootCmd){
		case COMMAND_READPM: 
		case COMMAND_READEE: 
		case COMMAND_READCFG: 
			break;
		default: return ERROR_INVALID_COMMAND;
	}
	
	RetStatus = ReadPIC(hComPort, pic, InData);
	if(RetStatus < 0) return RetStatus;

	for(i = 0; i < RetStatus; i++){
		if(PacketData[i] != InData[i]) return ERROR_VERIFY_FAILED;
	}

	return i;
}



⌨️ 快捷键说明

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