ChaloupeLora/ChaloupeLora.X/Source/BootloaderProtocol.c
2022-04-27 16:08:20 -04:00

427 lines
9.4 KiB
C
Raw Permalink Blame History

/**********************************************************************
Project: Automatic cat feeder
Date: march 19 2006
Author: Jean-Fran<61>ois Martel
Target: PIC 18F252
Compiler: Microchip mcc18
Filename: Protocol.c
File description: Communication protocol implementation.
jean-francois.martel@polymtl.ca
**********************************************************************/
#include "define.h"
#include <string.h>
#include "ProtocolDefs.h"
#include "BootloaderProtocol.h"
#include "BootloaderInterface.h"
#include "WiFiCtrl.h"
#include "checksum.h"
//test
unsigned int BootloaderHeader = 0;
unsigned int BootloaderDataSize = 0;
unsigned int BootloaderDataCtr = 0;
unsigned int BootloaderBufPtr = 0;
unsigned int BootloaderCRC = 0;
unsigned int BtldrComputedCRC = CRC_START_32;
unsigned char *BootloaderRxPtr;
unsigned char BootloaderCommand = 0;
unsigned char BootloaderState = RxHeader1;
const unsigned char *BootloaderDataStartPtr = &BootloaderBuffer[9];
static char MyDeviceID = ID_SPRINKLER_DEVICE;
void BootloaderProtocolInit(void)
{
BootloaderProtocolResetStateMachine();
}
void BootloaderProtocolStateMachine(unsigned char Data)
{
switch(BootloaderState)
{
case Initialization: //Reset all pointers and data...
{
BootloaderDataSize = 0;
BootloaderBufPtr = 0;
BootloaderCommand = 0;
BootloaderCRC = 0;
BootloaderState = RxHeader1;
BtldrComputedCRC = CRC_START_32;
break;
}
case RxHeader1: //Wait for data header...
{
BootloaderHeader <<= 8;
BootloaderHeader += Data; //0xDE
BtldrComputedCRC = update_crc_32(BtldrComputedCRC,Data);
if(Data == BOOTLOADER_FRAME_HEADER_1)
{
BootloaderState = RxHeader2;
}
else
{
BootloaderProtocolResetStateMachine();
}
break;
}
case RxHeader2: //Wait for data header...
{
BootloaderHeader <<= 8;
BootloaderHeader += Data; //0xAD
BtldrComputedCRC = update_crc_32(BtldrComputedCRC,Data);
if(Data == BOOTLOADER_FRAME_HEADER_2)
{
BootloaderState = RxHeader3;
}
else
{
BootloaderProtocolResetStateMachine();
}
break;
}
case RxHeader3: //Wait for data header...
{
BootloaderHeader <<= 8;
BootloaderHeader += Data; //0xBE
BtldrComputedCRC = update_crc_32(BtldrComputedCRC,Data);
if(Data == BOOTLOADER_FRAME_HEADER_3)
{
BootloaderState = RxHeader4;
}
else
{
BootloaderProtocolResetStateMachine();
}
break;
}
case RxHeader4: //Wait for data header...
{
BootloaderHeader <<= 8;
BootloaderHeader += Data; //0xEF
BtldrComputedCRC = update_crc_32(BtldrComputedCRC,Data);
if(BootloaderHeader != BOOTLOADER_FRAME_HEADER)
{
//TODO, send NACK?
BootloaderProtocolResetStateMachine();
break;
}
else
{
BootloaderState = RxCmd;
}
break;
}
case RxCmd:
{
BootloaderCommand = Data;
BootloaderState = RxPayloadSize1;
BtldrComputedCRC = update_crc_32(BtldrComputedCRC,Data);
break;
}
case RxPayloadSize1:
{
BootloaderDataSize = Data;
BootloaderState = RxPayloadSize2;
BtldrComputedCRC = update_crc_32(BtldrComputedCRC,Data);
break;
}
case RxPayloadSize2:
{
BootloaderDataSize <<= 8;
BootloaderDataSize += Data;
BtldrComputedCRC = update_crc_32(BtldrComputedCRC,Data);
BootloaderState = RxPayloadSize3;
break;
}
case RxPayloadSize3:
{
BootloaderDataSize <<= 8;
BootloaderDataSize += Data;
BtldrComputedCRC = update_crc_32(BtldrComputedCRC,Data);
BootloaderState = RxPayloadSize4;
break;
}
case RxPayloadSize4:
{
BootloaderDataSize <<= 8;
BootloaderDataSize += Data;
BtldrComputedCRC = update_crc_32(BtldrComputedCRC,Data);
if(BootloaderDataSize > MAX_BOOTLOADER_PAYLOAD_SIZE+8) //+8 bytes for the size and index data
{
//TODO, send NACK?
BootloaderProtocolResetStateMachine();
break;
}
if(BootloaderDataSize == 0)
{
BootloaderState = RxCRC1;
}
else
{
BootloaderState = RxPayload;
}
break;
}
case RxPayload: //Data size
{
*BootloaderRxPtr = Data;
BootloaderRxPtr++;
BootloaderDataCtr++;
BtldrComputedCRC = update_crc_32(BtldrComputedCRC,Data);
if(BootloaderDataCtr == BootloaderDataSize)
{
BootloaderState = RxCRC1;
break;
}
break;
}
case RxCRC1: //Data size
{
BootloaderCRC = Data;
BootloaderState = RxCRC2;
break;
}
case RxCRC2: //Data size
{
BootloaderCRC <<= 8;
BootloaderCRC += Data;
BootloaderState = RxCRC3;
break;
}
case RxCRC3: //Data size
{
BootloaderCRC <<= 8;
BootloaderCRC += Data;
BootloaderState = RxCRC4;
break;
}
case RxCRC4: //Data size
{
BootloaderCRC <<= 8;
BootloaderCRC += Data;
//TODO: Compute and Compare CRC.
BtldrComputedCRC ^= 0xffffffffL;
//if(BootloaderCRC != 0xBAADCAFE)
if(BootloaderCRC != BtldrComputedCRC)
{
BootloaderExecuteCmd(BootloaderCommand,0);
BootloaderProtocolResetStateMachine();
return;
}
BootloaderExecuteCmd(BootloaderCommand,1);
BootloaderProtocolResetStateMachine();
break;
}
default:
{
BootloaderProtocolResetStateMachine();
break;
}
}
}
void BootloaderProtocolProtocolAnalyzeNewData(unsigned char *DataBuf, int size)
{
int i;
for(i = 0; i < size; i++)
{
BootloaderProtocolStateMachine(*DataBuf++);
}
}
void BootloaderProtocolResetStateMachine()
{
BootloaderDataSize = 0;
BootloaderHeader = 0;
BootloaderBufPtr = 0;
BootloaderCommand = 0;
BootloaderCRC = 0;
BootloaderState = RxHeader1;
BootloaderDataCtr = 0;
BtldrComputedCRC = CRC_START_32;
BootloaderRxPtr = &BootloaderBuffer[0];
}
void BootloaderProtocolSendFrame(unsigned char Cmd, int Size)
{
//Header
BootloaderBuffer[0] = BOOTLOADER_FRAME_HEADER_1; //Header
BootloaderBuffer[1] = BOOTLOADER_FRAME_HEADER_2;
BootloaderBuffer[2] = BOOTLOADER_FRAME_HEADER_3;
BootloaderBuffer[3] = BOOTLOADER_FRAME_HEADER_4;
BootloaderBuffer[4] = Cmd;
char nibble = (char)((Size >> 24) &0x000000FF);
BootloaderBuffer[5] = nibble;
nibble = (char)((Size >> 16) &0x000000FF);
BootloaderBuffer[6] = nibble;
nibble = (char)((Size >> 8) &0x000000FF);
BootloaderBuffer[7] = nibble;
nibble = (char)(Size &0x000000FF);
BootloaderBuffer[8] = nibble;
unsigned int CRC = CRC_START_32;
CRC = crc_32((const unsigned char*)BootloaderBuffer,Size+9);
unsigned char* CRCPtr = (unsigned char*)BootloaderDataStartPtr + Size;
nibble = (char)((CRC >> 24) &0x000000FF);
*CRCPtr++ = nibble;
nibble = (char)((CRC >> 16) &0x000000FF);
*CRCPtr++ = nibble;
nibble = (char)((CRC >> 8) &0x000000FF);
*CRCPtr++ = nibble;
nibble = (char)(CRC &0x000000FF);
*CRCPtr++ = nibble;
// *CRCPtr++ = 0xBA;
// *CRCPtr++ = 0xAD;
// *CRCPtr++ = 0xCA;
// *CRCPtr++ = 0xFE;
SendBootloaderData(&BootloaderBuffer[0],Size + PROTOCOL_INFO_DATA_SIZE);
}
unsigned char *BootloaderProtocolGetDataBufferPtr()
{
return (unsigned char*)BootloaderDataStartPtr;
}
void BootloaderProtocolSendHeartbeat()
{
*BootloaderProtocolGetDataBufferPtr() = BOOTLOADER_ACK;
BootloaderProtocolSendFrame(BOOTLOADER_HEARTBEAT_RESPONSE,1);
}
void BootloaderProtocolSendACK(unsigned char Cmd)
{
*BootloaderProtocolGetDataBufferPtr() = BOOTLOADER_ACK;
BootloaderProtocolSendFrame(Cmd,1);
}
void BootloaderProtocolSendNACK(unsigned char Cmd)
{
*BootloaderProtocolGetDataBufferPtr() = 0;
BootloaderProtocolSendFrame(Cmd,1);
}
void BootloaderProtocolSendInitUploadResponse(char result)
{
int MaxSize = MAX_BOOTLOADER_PAYLOAD_SIZE;
char* DataPtr = BootloaderProtocolGetDataBufferPtr();
*DataPtr++ = result;
if(result == 1)
{
char nibble = (char)((MaxSize >> 24) &0x000000FF);
*DataPtr++ = nibble;
nibble = (char)((MaxSize >> 16) &0x000000FF);
*DataPtr++ = nibble;
nibble = (char)((MaxSize >> 8) &0x000000FF);
*DataPtr++ = nibble;
nibble = (char)(MaxSize &0x000000FF);
*DataPtr++ = nibble;
}
else
{
*DataPtr++ = 0;
*DataPtr++ = 0;
*DataPtr++ = 0;
*DataPtr++ = 0;
}
BootloaderProtocolSendFrame(BOOTLOADER_INIT_UPLOAD_RESPONSE,5);
}
void BootloaderProtocolSendDataChunkResult(char ErrorCode, int ChunkValue)
{
char* DataPtr = BootloaderProtocolGetDataBufferPtr();
*DataPtr++ = ErrorCode;
char nibble = (char)((ChunkValue >> 24) &0x000000FF);
*DataPtr++ = nibble;
nibble = (char)((ChunkValue >> 16) &0x000000FF);
*DataPtr++ = nibble;
nibble = (char)((ChunkValue >> 8) &0x000000FF);
*DataPtr++ = nibble;
nibble = (char)(ChunkValue &0x000000FF);
*DataPtr++ = nibble;
BootloaderProtocolSendFrame(BOOTLOADER_SEND_DATA_CHUNK_RESPONSE,5);
}
void BootloaderProtocolSendBootloaderState(char State)
{
char* DataPtr = BootloaderProtocolGetDataBufferPtr();
*DataPtr++ = State;
BootloaderProtocolSendFrame(BOOTLOADER_GET_STATE_RESPONSE,1);
}
void BootloaderProtocolSendFirmwareUploadResult(char Result)
{
char* DataPtr = BootloaderProtocolGetDataBufferPtr();
*DataPtr++ = Result;
BootloaderProtocolSendFrame(BOOTLOADER_UPLOAD_FINISHED_RESPONSE,1);
}
void BootloaderProtocolSendFlashCheckResult(char Result)
{
char* DataPtr = BootloaderProtocolGetDataBufferPtr();
*DataPtr++ = Result;
BootloaderProtocolSendFrame(BOOTLOADER_CHECK_FLASH_FIRMW_INTEGRITY_RESPONSE,1);
}
void BootloaderProtocolSendStoredFirmwareInfoResponse(unsigned char* FirmwareData, int size)
{
char* DataPtr = BootloaderProtocolGetDataBufferPtr();
int i = 0;
for(i = 0; i < size; i++)
{
*DataPtr++ = *FirmwareData++;
}
BootloaderProtocolSendFrame(BOOTLOADER_GET_STORED_FIRMWARE_INFO_RESPONSE,size);
}