Rev 270 | Details | Compare with Previous | Last modification | View Log | SVN | RSS feed
| Rev | Author | Line No. | Line |
|---|---|---|---|
| 270 | johboh | 1 | #include "DownloadState.h" |
| 2 | |||
| 3 | |||
| 4 | |||
| 5 | static HexFile * hf; |
||
| 6 | //static CSerial * serial; |
||
| 7 | static SerialConnection * serial; |
||
| 8 | |||
| 9 | static HANDLE hRunMutex; // "Keep Running" mutex |
||
| 10 | |||
| 11 | void downloadState(void *pMyID); |
||
| 12 | |||
| 13 | 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; |
||
| 14 | |||
| 15 | |||
| 16 | void downloadState(void *pMyID) |
||
| 17 | { |
||
| 18 | long lLastError = 0; |
||
| 19 | |||
| 20 | dState pgs = SEND_START; |
||
| 21 | DWORD t = 0; |
||
| 22 | CanProtoMessage * outCm = (CanProtoMessage *)malloc(sizeof(CanProtoMessage)); |
||
| 23 | CanProtoMessage * cm = (CanProtoMessage *)malloc(sizeof(CanProtoMessage)); |
||
| 24 | unsigned char data[8]; |
||
| 25 | unsigned char byteSent = 0; |
||
| 26 | unsigned long currentAddress = 0; |
||
| 27 | unsigned char bytesToWrite[PACKET_LENGTH]; |
||
| 28 | |||
| 29 | while ( WaitForSingleObject( hRunMutex, 75L ) == WAIT_TIMEOUT ) |
||
| 30 | { |
||
| 31 | |||
| 32 | bool hasMessage = serial->getMessage(cm); |
||
| 33 | if (hasMessage) |
||
| 34 | { |
||
| 35 | unsigned char *dtmp = cm->getData(); |
||
| 36 | for(int i=0;i<8;i++) data[i]=dtmp[i]; |
||
| 37 | printf("[%ld] Has message\n",GetTickCount()); |
||
| 38 | } |
||
| 39 | |||
| 40 | switch(pgs) |
||
| 41 | { |
||
| 42 | case SEND_START: |
||
| 43 | // Send boot start packet to target. |
||
| 44 | // and wait for ack. |
||
| 45 | currentAddress = hf->getAddrLower(); |
||
| 46 | data[RID_INDEX] = TARGET_ID; |
||
| 47 | data[ADDRU_INDEX] = (unsigned char)((currentAddress & 0xFF0000) >> 16); |
||
| 48 | data[ADDRH_INDEX] = (unsigned char)((currentAddress & 0xFF00) >> 8); |
||
| 49 | data[ADDRL_INDEX] = (unsigned char)(currentAddress & 0xFF); |
||
| 50 | outCm = &CanProtoMessage::CanProtoMessage(FUNCT_BOOTLOADER, FUNCC_BOOT_INIT, MY_NID, MY_ID, 8, data); |
||
| 51 | outCm->getBytes(bytesToWrite); |
||
| 52 | serial->write(bytesToWrite,PACKET_LENGTH); |
||
| 53 | t = GetTickCount(); |
||
| 54 | pgs = WAIT_ACK; |
||
| 55 | break; |
||
| 56 | |||
| 57 | |||
| 58 | case WAIT_ACK: |
||
| 59 | |||
| 60 | // Check for timeout, resend start packet in that case.. |
||
| 61 | if ((GetTickCount() - t) > TIMEOUT_MS) |
||
| 62 | { |
||
| 63 | pgs = SEND_START; |
||
| 64 | } |
||
| 65 | |||
| 66 | // If received ack. |
||
| 67 | if (hasMessage && cm->getFunct() == FUNCT_BOOTLOADER && cm->getFuncc() == FUNCC_BOOT_ACK && cm->getNid() == MY_NID && cm->getSid() == TARGET_ID) |
||
| 68 | { |
||
| 69 | // If no error |
||
| 70 | if (data[ERR_INDEX] == ERR_NO_ERROR) |
||
| 71 | { |
||
| 72 | // Start sending program data.. |
||
| 73 | byteSent = 0; |
||
| 74 | pgs = SEND_PGM_DATA; |
||
| 75 | } |
||
| 76 | else |
||
| 77 | { |
||
| 78 | // else resend start.. |
||
| 79 | pgs = SEND_START; |
||
| 80 | } |
||
| 81 | } |
||
| 82 | break; |
||
| 83 | |||
| 84 | case SEND_PGM_DATA: |
||
| 85 | // Send program data. |
||
| 86 | for (int i = 0; i < 8; i++) |
||
| 87 | { |
||
| 88 | // Populate data. |
||
| 89 | data[i] = hf->getByte(currentAddress + i + byteSent); |
||
| 90 | } |
||
| 91 | 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); |
||
| 92 | outCm->getBytes(bytesToWrite); |
||
| 93 | serial->write(bytesToWrite,PACKET_LENGTH); |
||
| 94 | t = GetTickCount(); |
||
| 95 | pgs = WAIT_OWN_PACKET; |
||
| 96 | break; |
||
| 97 | |||
| 98 | case WAIT_OWN_PACKET: |
||
| 99 | // Wait reciving own packet, if timeout, resend last. |
||
| 100 | if ((GetTickCount() - t) > TIMEOUT_MS) |
||
| 101 | { |
||
| 102 | //pgs = dState.SEND_PGM_DATA; |
||
| 103 | pgs = RESEND_ADDR; |
||
| 104 | } |
||
| 105 | |||
| 106 | // If received own packet.. |
||
| 107 | if (hasMessage && outCm->equals(cm)) |
||
| 108 | { |
||
| 109 | |||
| 110 | byteSent += 8; |
||
| 111 | |||
| 112 | // Check if 64 bytes sent or not.. |
||
| 113 | if (byteSent == 64) |
||
| 114 | { |
||
| 115 | // Yes, wait for ack. |
||
| 116 | t = GetTickCount(); |
||
| 117 | pgs = WAIT_PGM_ACK; |
||
| 118 | } |
||
| 119 | else |
||
| 120 | { |
||
| 121 | // No, send more. |
||
| 122 | pgs = SEND_PGM_DATA; |
||
| 123 | } |
||
| 124 | |||
| 125 | } |
||
| 126 | break; |
||
| 127 | |||
| 128 | |||
| 129 | case WAIT_PGM_ACK: |
||
| 130 | // Wait for pgm ack. |
||
| 131 | if ((GetTickCount() - t) > 2*TIMEOUT_MS) |
||
| 132 | { |
||
| 133 | // Woops, error. Resend address and start over. |
||
| 134 | pgs = RESEND_ADDR; |
||
| 135 | } |
||
| 136 | |||
| 137 | // If received ack. |
||
| 138 | if (hasMessage && cm->getFunct() == FUNCT_BOOTLOADER && cm->getFuncc() == FUNCC_BOOT_ACK && cm->getNid() == MY_NID && cm->getSid() == TARGET_ID) |
||
| 139 | { |
||
| 140 | // If no error |
||
| 141 | if (data[ERR_INDEX] == ERR_NO_ERROR) |
||
| 142 | { |
||
| 143 | currentAddress += 64; |
||
| 144 | // Check if end. |
||
| 145 | if (currentAddress > hf->getAddrUpper()) |
||
| 146 | { |
||
| 147 | // Yes, we are done, send done. |
||
| 148 | pgs = SEND_DONE; |
||
| 149 | } |
||
| 150 | else |
||
| 151 | { |
||
| 152 | // More to write. |
||
| 153 | byteSent = 0; |
||
| 154 | pgs = SEND_PGM_DATA; |
||
| 155 | } |
||
| 156 | } |
||
| 157 | else |
||
| 158 | { |
||
| 159 | // else resend start.. |
||
| 160 | pgs = RESEND_ADDR; |
||
| 161 | } |
||
| 162 | } |
||
| 163 | break; |
||
| 164 | |||
| 165 | |||
| 166 | case SEND_DONE: |
||
| 167 | // Send done |
||
| 168 | outCm = &CanProtoMessage::CanProtoMessage(FUNCT_BOOTLOADER, FUNCC_BOOT_DONE, MY_NID, MY_ID, 8, data); |
||
| 169 | outCm->getBytes(bytesToWrite); |
||
| 170 | serial->write(bytesToWrite,PACKET_LENGTH); |
||
| 171 | t = GetTickCount(); |
||
| 172 | pgs = WAIT_DONE; |
||
| 173 | break; |
||
| 174 | |||
| 175 | case RESEND_ADDR: |
||
| 176 | // Resend addr. |
||
| 177 | data[RID_INDEX] = TARGET_ID; |
||
| 178 | data[ADDRU_INDEX] = (byte)((currentAddress & 0xFF0000) >> 16); |
||
| 179 | data[ADDRH_INDEX] = (byte)((currentAddress & 0xFF00) >> 8); |
||
| 180 | data[ADDRL_INDEX] = (byte)(currentAddress & 0xFF); |
||
| 181 | outCm = &CanProtoMessage::CanProtoMessage(FUNCT_BOOTLOADER, FUNCC_BOOT_ADDR, MY_NID, MY_ID, 8, data); |
||
| 182 | outCm->getBytes(bytesToWrite); |
||
| 183 | serial->write(bytesToWrite,PACKET_LENGTH); |
||
| 184 | t = GetTickCount(); |
||
| 185 | pgs = WAIT_ADDR_ACK; |
||
| 186 | break; |
||
| 187 | |||
| 188 | |||
| 189 | case WAIT_ADDR_ACK: |
||
| 190 | // Check for timeout, resend addr packet in that case.. |
||
| 191 | if ((GetTickCount() - t) > TIMEOUT_MS) |
||
| 192 | { |
||
| 193 | pgs = RESEND_ADDR; |
||
| 194 | } |
||
| 195 | |||
| 196 | // If received ack. |
||
| 197 | if (hasMessage && cm->getFunct() == FUNCT_BOOTLOADER && cm->getFuncc() == FUNCC_BOOT_ACK && cm->getNid() == MY_NID && cm->getSid() == TARGET_ID) |
||
| 198 | { |
||
| 199 | // If no error |
||
| 200 | if (data[ERR_INDEX] == ERR_NO_ERROR) |
||
| 201 | { |
||
| 202 | // Start sending program data.. |
||
| 203 | byteSent = 0; |
||
| 204 | pgs = SEND_PGM_DATA; |
||
| 205 | } |
||
| 206 | else |
||
| 207 | { |
||
| 208 | // else resend addr.. |
||
| 209 | pgs = RESEND_ADDR; |
||
| 210 | } |
||
| 211 | } |
||
| 212 | break; |
||
| 213 | |||
| 214 | case WAIT_DONE: |
||
| 215 | // Check for timeout, resend done packet in that case.. |
||
| 216 | if ((GetTickCount() - t) > TIMEOUT_MS) |
||
| 217 | { |
||
| 218 | pgs = SEND_DONE; |
||
| 219 | } |
||
| 220 | |||
| 221 | // If received ack. |
||
| 222 | if (hasMessage && cm->getFunct() == FUNCT_BOOTLOADER && cm->getFuncc() == FUNCC_BOOT_ACK && cm->getNid() == MY_NID && cm->getSid() == TARGET_ID) |
||
| 223 | { |
||
| 224 | // If no error |
||
| 225 | if (data[ERR_INDEX] == ERR_NO_ERROR) |
||
| 226 | { |
||
| 227 | // Start sending program data.. |
||
| 228 | byteSent = 0; |
||
| 229 | pgs = DONE; |
||
| 230 | } |
||
| 231 | else |
||
| 232 | { |
||
| 233 | // else resend addr.. |
||
| 234 | pgs = RESEND_ADDR; |
||
| 235 | } |
||
| 236 | } |
||
| 237 | break; |
||
| 238 | |||
| 239 | case DONE: |
||
| 240 | downloadStop(); |
||
| 241 | printf("DONE!\n"); |
||
| 242 | break; |
||
| 243 | } |
||
| 244 | } |
||
| 245 | |||
| 246 | return; |
||
| 247 | } |
||
| 248 | |||
| 249 | |||
| 250 | void downloadStart(SerialConnection * ser,HexFile *hex) |
||
| 251 | { |
||
| 252 | hf = hex; |
||
| 253 | serial = ser; |
||
| 254 | hRunMutex = CreateMutex( NULL, TRUE, NULL ); // Set |
||
| 255 | _beginthread( downloadState, 0, 0 ); |
||
| 256 | |||
| 257 | } |
||
| 258 | |||
| 259 | void downloadStop( void ) |
||
| 260 | { |
||
| 261 | ReleaseMutex( hRunMutex ); |
||
| 262 | CloseHandle( hRunMutex ); |
||
| 263 | } |
||
| 264 |