Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | SVN | RSS feed
#include "DownloadState.h"static HexFile * hf;//static CSerial * serial;static SerialConnection * serial;static HANDLE hRunMutex; // "Keep Running" mutexvoid downloadState(void *pMyID);typedef enum { SEND_START, WAIT_ACK, SEND_PGM_DATA, WAIT_OWN_PACKET, WAIT_PGM_ACK, RESEND_ADDR, WAIT_DONE, SEND_DONE, DONE, WAIT_ADDR_ACK,DEBUG_STATE1,DEBUG_STATE2 } dState;void downloadState(void *pMyID){long lLastError = 0;dState pgs = SEND_START;DWORD t = 0;CanProtoMessage * outCm = (CanProtoMessage *)malloc(sizeof(CanProtoMessage));CanProtoMessage * cm = (CanProtoMessage *)malloc(sizeof(CanProtoMessage));unsigned char data[8];unsigned char byteSent = 0;unsigned long currentAddress = 0;unsigned char bytesToWrite[PACKET_LENGTH];while ( WaitForSingleObject( hRunMutex, 75L ) == WAIT_TIMEOUT ){bool hasMessage = serial->getMessage(cm);if (hasMessage){unsigned char *dtmp = cm->getData();for(int i=0;i<8;i++) data[i]=dtmp[i];printf("[%ld] Has message\n",GetTickCount());}switch(pgs){case SEND_START:// Send boot start packet to target.// and wait for ack.currentAddress = hf->getAddrLower();data[RID_INDEX] = TARGET_ID;data[ADDRU_INDEX] = (unsigned char)((currentAddress & 0xFF0000) >> 16);data[ADDRH_INDEX] = (unsigned char)((currentAddress & 0xFF00) >> 8);data[ADDRL_INDEX] = (unsigned char)(currentAddress & 0xFF);outCm = &CanProtoMessage::CanProtoMessage(FUNCT_BOOTLOADER, FUNCC_BOOT_INIT, MY_NID, MY_ID, 8, data);outCm->getBytes(bytesToWrite);serial->write(bytesToWrite,PACKET_LENGTH);t = GetTickCount();pgs = WAIT_ACK;break;case WAIT_ACK:// Check for timeout, resend start packet in that case..if ((GetTickCount() - t) > TIMEOUT_MS){pgs = SEND_START;}// If received ack.if (hasMessage && cm->getFunct() == FUNCT_BOOTLOADER && cm->getFuncc() == FUNCC_BOOT_ACK && cm->getNid() == MY_NID && cm->getSid() == TARGET_ID){// If no errorif (data[ERR_INDEX] == ERR_NO_ERROR){// Start sending program data..byteSent = 0;pgs = SEND_PGM_DATA;}else{// else resend start..pgs = SEND_START;}}break;case SEND_PGM_DATA:// Send program data.for (int i = 0; i < 8; i++){// Populate data.data[i] = hf->getByte(currentAddress + i + byteSent);}outCm = &CanProtoMessage::CanProtoMessage(FUNCT_BOOTLOADER, (unsigned int)((unsigned int)((unsigned int)(floor(((double)byteSent/8.0)))<<2) + (FUNCC_BOOT_PGM)), MY_NID, MY_ID, 8, data);outCm->getBytes(bytesToWrite);serial->write(bytesToWrite,PACKET_LENGTH);t = GetTickCount();pgs = WAIT_OWN_PACKET;break;case WAIT_OWN_PACKET:// Wait reciving own packet, if timeout, resend last.if ((GetTickCount() - t) > TIMEOUT_MS){//pgs = dState.SEND_PGM_DATA;pgs = RESEND_ADDR;}// If received own packet..if (hasMessage && outCm->equals(cm)){byteSent += 8;// Check if 64 bytes sent or not..if (byteSent == 64){// Yes, wait for ack.t = GetTickCount();pgs = WAIT_PGM_ACK;}else{// No, send more.pgs = SEND_PGM_DATA;}}break;case WAIT_PGM_ACK:// Wait for pgm ack.if ((GetTickCount() - t) > 2*TIMEOUT_MS){// Woops, error. Resend address and start over.pgs = RESEND_ADDR;}// If received ack.if (hasMessage && cm->getFunct() == FUNCT_BOOTLOADER && cm->getFuncc() == FUNCC_BOOT_ACK && cm->getNid() == MY_NID && cm->getSid() == TARGET_ID){// If no errorif (data[ERR_INDEX] == ERR_NO_ERROR){currentAddress += 64;// Check if end.if (currentAddress > hf->getAddrUpper()){// Yes, we are done, send done.pgs = SEND_DONE;}else{// More to write.byteSent = 0;pgs = SEND_PGM_DATA;}}else{// else resend start..pgs = RESEND_ADDR;}}break;case SEND_DONE:// Send doneoutCm = &CanProtoMessage::CanProtoMessage(FUNCT_BOOTLOADER, FUNCC_BOOT_DONE, MY_NID, MY_ID, 8, data);outCm->getBytes(bytesToWrite);serial->write(bytesToWrite,PACKET_LENGTH);t = GetTickCount();pgs = WAIT_DONE;break;case RESEND_ADDR:// Resend addr.data[RID_INDEX] = TARGET_ID;data[ADDRU_INDEX] = (byte)((currentAddress & 0xFF0000) >> 16);data[ADDRH_INDEX] = (byte)((currentAddress & 0xFF00) >> 8);data[ADDRL_INDEX] = (byte)(currentAddress & 0xFF);outCm = &CanProtoMessage::CanProtoMessage(FUNCT_BOOTLOADER, FUNCC_BOOT_ADDR, MY_NID, MY_ID, 8, data);outCm->getBytes(bytesToWrite);serial->write(bytesToWrite,PACKET_LENGTH);t = GetTickCount();pgs = WAIT_ADDR_ACK;break;case WAIT_ADDR_ACK:// Check for timeout, resend addr packet in that case..if ((GetTickCount() - t) > TIMEOUT_MS){pgs = RESEND_ADDR;}// If received ack.if (hasMessage && cm->getFunct() == FUNCT_BOOTLOADER && cm->getFuncc() == FUNCC_BOOT_ACK && cm->getNid() == MY_NID && cm->getSid() == TARGET_ID){// If no errorif (data[ERR_INDEX] == ERR_NO_ERROR){// Start sending program data..byteSent = 0;pgs = SEND_PGM_DATA;}else{// else resend addr..pgs = RESEND_ADDR;}}break;case WAIT_DONE:// Check for timeout, resend done packet in that case..if ((GetTickCount() - t) > TIMEOUT_MS){pgs = SEND_DONE;}// If received ack.if (hasMessage && cm->getFunct() == FUNCT_BOOTLOADER && cm->getFuncc() == FUNCC_BOOT_ACK && cm->getNid() == MY_NID && cm->getSid() == TARGET_ID){// If no errorif (data[ERR_INDEX] == ERR_NO_ERROR){// Start sending program data..byteSent = 0;pgs = DONE;}else{// else resend addr..pgs = RESEND_ADDR;}}break;case DONE:downloadStop();printf("DONE!\n");break;}}return;}void downloadStart(SerialConnection * ser,HexFile *hex){hf = hex;serial = ser;hRunMutex = CreateMutex( NULL, TRUE, NULL ); // Set_beginthread( downloadState, 0, 0 );}void downloadStop( void ){ReleaseMutex( hRunMutex );CloseHandle( hRunMutex );}