08a54e2f1386739ca9ac2e97ad6adb7b9d73f075
[pub/USBasp.git] / Projects / Incomplete / AVRISP / Lib / V2Protocol.c
1 /*
2 LUFA Library
3 Copyright (C) Dean Camera, 2009.
4
5 dean [at] fourwalledcubicle [dot] com
6 www.fourwalledcubicle.com
7 */
8
9 /*
10 Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)
11
12 Permission to use, copy, modify, and distribute this software
13 and its documentation for any purpose and without fee is hereby
14 granted, provided that the above copyright notice appear in all
15 copies and that both that the copyright notice and this
16 permission notice and warranty disclaimer appear in supporting
17 documentation, and that the name of the author not be used in
18 advertising or publicity pertaining to distribution of the
19 software without specific, written prior permission.
20
21 The author disclaim all warranties with regard to this
22 software, including all implied warranties of merchantability
23 and fitness. In no event shall the author be liable for any
24 special, indirect or consequential damages or any damages
25 whatsoever resulting from loss of use, data or profits, whether
26 in an action of contract, negligence or other tortious action,
27 arising out of or in connection with the use or performance of
28 this software.
29 */
30
31 /** \file
32 *
33 * V2Protocol handler, to process V2 Protocol commands used in Atmel programmer devices.
34 */
35
36 #define INCLUDE_FROM_V2PROTOCOL_C
37 #include "V2Protocol.h"
38
39 void V2Protocol_ProcessCommand(void)
40 {
41 uint8_t V2Command = Endpoint_Read_Byte();
42
43 switch (V2Command)
44 {
45 case CMD_SIGN_ON:
46 V2Protocol_Command_SignOn();
47 break;
48 case CMD_SET_PARAMETER:
49 case CMD_GET_PARAMETER:
50 V2Protocol_Command_GetSetParam(V2Command);
51 break;
52 case CMD_LOAD_ADDRESS:
53 V2Protocol_Command_LoadAddress();
54 break;
55 case CMD_RESET_PROTECTION:
56 V2Protocol_Command_ResetProtection();
57 break;
58 case CMD_ENTER_PROGMODE_ISP:
59 V2Protocol_Command_EnterISPMode();
60 break;
61 case CMD_LEAVE_PROGMODE_ISP:
62 V2Protocol_Command_LeaveISPMode();
63 break;
64 case CMD_PROGRAM_FLASH_ISP:
65 case CMD_PROGRAM_EEPROM_ISP:
66 V2Protocol_Command_ProgramMemory(V2Command);
67 break;
68 case CMD_READ_FLASH_ISP:
69 case CMD_READ_EEPROM_ISP:
70 V2Protocol_Command_ReadMemory(V2Command);
71 break;
72 case CMD_CHIP_ERASE_ISP:
73 V2Protocol_Command_ChipErase();
74 break;
75 case CMD_READ_FUSE_ISP:
76 case CMD_READ_LOCK_ISP:
77 case CMD_READ_SIGNATURE_ISP:
78 case CMD_READ_OSCCAL_ISP:
79 V2Protocol_Command_ReadFuseLockSigOSCCAL(V2Command);
80 break;
81 case CMD_PROGRAM_FUSE_ISP:
82 case CMD_PROGRAM_LOCK_ISP:
83 V2Protocol_Command_WriteFuseLock(V2Command);
84 break;
85 case CMD_SPI_MULTI:
86 V2Protocol_Command_SPIMulti();
87 break;
88 default:
89 V2Protocol_Command_Unknown(V2Command);
90 break;
91 }
92
93 Endpoint_WaitUntilReady();
94 Endpoint_SetEndpointDirection(ENDPOINT_DIR_OUT);
95 }
96
97 static void V2Protocol_Command_Unknown(uint8_t V2Command)
98 {
99 /* Discard all incomming data */
100 while (Endpoint_BytesInEndpoint() == AVRISP_DATA_EPSIZE)
101 {
102 Endpoint_ClearOUT();
103 Endpoint_WaitUntilReady();
104 }
105
106 Endpoint_ClearOUT();
107 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
108
109 Endpoint_Write_Byte(V2Command);
110 Endpoint_Write_Byte(STATUS_CMD_UNKNOWN);
111 Endpoint_ClearIN();
112 }
113
114 static void V2Protocol_Command_SignOn(void)
115 {
116 Endpoint_ClearOUT();
117 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
118
119 Endpoint_Write_Byte(CMD_SIGN_ON);
120 Endpoint_Write_Byte(STATUS_CMD_OK);
121 Endpoint_Write_Byte(sizeof(PROGRAMMER_ID) - 1);
122 Endpoint_Write_Stream_LE(PROGRAMMER_ID, (sizeof(PROGRAMMER_ID) - 1));
123 Endpoint_ClearIN();
124 }
125
126 static void V2Protocol_Command_GetSetParam(uint8_t V2Command)
127 {
128 uint8_t ParamID = Endpoint_Read_Byte();
129 uint8_t ParamValue;
130
131 if (V2Command == CMD_SET_PARAMETER)
132 ParamValue = Endpoint_Read_Byte();
133
134 Endpoint_ClearOUT();
135 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
136
137 Endpoint_Write_Byte(V2Command);
138
139 uint8_t ParamPrivs = V2Params_GetParameterPrivellages(ParamID);
140
141 if ((V2Command == CMD_SET_PARAMETER) && (ParamPrivs & PARAM_PRIV_WRITE))
142 {
143 Endpoint_Write_Byte(STATUS_CMD_OK);
144 V2Params_SetParameterValue(ParamID, ParamValue);
145 }
146 else if ((V2Command == CMD_GET_PARAMETER) && (ParamPrivs & PARAM_PRIV_READ))
147 {
148 Endpoint_Write_Byte(STATUS_CMD_OK);
149 Endpoint_Write_Byte(V2Params_GetParameterValue(ParamID));
150 }
151 else
152 {
153 Endpoint_Write_Byte(STATUS_CMD_FAILED);
154 }
155
156 Endpoint_ClearIN();
157 }
158
159 static void V2Protocol_Command_LoadAddress(void)
160 {
161 Endpoint_Read_Stream_BE(&CurrentAddress, sizeof(CurrentAddress));
162
163 Endpoint_ClearOUT();
164 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
165
166 if (CurrentAddress & (1UL << 31))
167 V2Protocol_LoadExtendedAddress();
168
169 Endpoint_Write_Byte(CMD_LOAD_ADDRESS);
170 Endpoint_Write_Byte(STATUS_CMD_OK);
171 Endpoint_ClearIN();
172 }
173
174 static void V2Protocol_Command_ResetProtection(void)
175 {
176 Endpoint_ClearOUT();
177 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
178
179 Endpoint_Write_Byte(CMD_RESET_PROTECTION);
180 Endpoint_Write_Byte(STATUS_CMD_OK);
181 Endpoint_ClearIN();
182 }
183
184 static void V2Protocol_Command_EnterISPMode(void)
185 {
186 struct
187 {
188 uint8_t TimeoutMS;
189 uint8_t PinStabDelayMS;
190 uint8_t ExecutionDelayMS;
191 uint8_t SynchLoops;
192 uint8_t ByteDelay;
193 uint8_t PollValue;
194 uint8_t PollIndex;
195 uint8_t EnterProgBytes[4];
196 } Enter_ISP_Params;
197
198 Endpoint_Read_Stream_LE(&Enter_ISP_Params, sizeof(Enter_ISP_Params));
199
200 Endpoint_ClearOUT();
201 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
202
203 uint8_t ResponseStatus = STATUS_CMD_FAILED;
204
205 CurrentAddress = 0;
206
207 V2Protocol_DelayMS(Enter_ISP_Params.ExecutionDelayMS);
208 SPI_Init(V2Protocol_GetSPIPrescalerMask() | SPI_SCK_LEAD_RISING | SPI_SAMPLE_LEADING | SPI_MODE_MASTER);
209
210 while (Enter_ISP_Params.SynchLoops-- && (ResponseStatus == STATUS_CMD_FAILED))
211 {
212 uint8_t ResponseBytes[4];
213
214 V2Protocol_ChangeTargetResetLine(true);
215 V2Protocol_DelayMS(Enter_ISP_Params.PinStabDelayMS);
216
217 for (uint8_t RByte = 0; RByte < sizeof(ResponseBytes); RByte++)
218 {
219 V2Protocol_DelayMS(Enter_ISP_Params.ByteDelay);
220 ResponseBytes[RByte] = SPI_TransferByte(Enter_ISP_Params.EnterProgBytes[RByte]);
221 }
222
223 /* Check if polling disabled, or if the polled value matches the expected value */
224 if (!(Enter_ISP_Params.PollIndex) || (ResponseBytes[Enter_ISP_Params.PollIndex - 1] == Enter_ISP_Params.PollValue))
225 {
226 ResponseStatus = STATUS_CMD_OK;
227 }
228 else
229 {
230 V2Protocol_ChangeTargetResetLine(false);
231 V2Protocol_DelayMS(Enter_ISP_Params.PinStabDelayMS);
232 }
233 }
234
235 Endpoint_Write_Byte(CMD_ENTER_PROGMODE_ISP);
236 Endpoint_Write_Byte(ResponseStatus);
237 Endpoint_ClearIN();
238 }
239
240 static void V2Protocol_Command_LeaveISPMode(void)
241 {
242 struct
243 {
244 uint8_t PreDelayMS;
245 uint8_t PostDelayMS;
246 } Leave_ISP_Params;
247
248 Endpoint_Read_Stream_LE(&Leave_ISP_Params, sizeof(Leave_ISP_Params));
249
250 Endpoint_ClearOUT();
251 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
252
253 V2Protocol_DelayMS(Leave_ISP_Params.PreDelayMS);
254 V2Protocol_ChangeTargetResetLine(false);
255 SPI_ShutDown();
256 V2Protocol_DelayMS(Leave_ISP_Params.PostDelayMS);
257
258 Endpoint_Write_Byte(CMD_LEAVE_PROGMODE_ISP);
259 Endpoint_Write_Byte(STATUS_CMD_OK);
260 Endpoint_ClearIN();
261 }
262
263 static void V2Protocol_Command_ProgramMemory(uint8_t V2Command)
264 {
265 struct
266 {
267 uint16_t BytesToWrite;
268 uint8_t ProgrammingMode;
269 uint8_t DelayMS;
270 uint8_t ProgrammingCommands[3];
271 uint8_t PollValue1;
272 uint8_t PollValue2;
273 uint8_t ProgData[256];
274 } Write_Memory_Params;
275
276 uint8_t* NextWriteByte = Write_Memory_Params.ProgData;
277
278 Endpoint_Read_Stream_LE(&Write_Memory_Params, sizeof(Write_Memory_Params) - sizeof(Write_Memory_Params.ProgData));
279 Write_Memory_Params.BytesToWrite = SwapEndian_16(Write_Memory_Params.BytesToWrite);
280 Endpoint_Read_Stream_LE(&Write_Memory_Params.ProgData, Write_Memory_Params.BytesToWrite);
281
282 Endpoint_ClearOUT();
283 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
284
285 uint8_t ProgrammingStatus = STATUS_CMD_OK;
286 uint16_t PollAddress = 0;
287 uint8_t PollValue = (V2Command == CMD_PROGRAM_FLASH_ISP) ? Write_Memory_Params.PollValue1 :
288 Write_Memory_Params.PollValue2;
289 if (Write_Memory_Params.ProgrammingMode & PROG_MODE_PAGED_WRITES_MASK)
290 {
291 uint16_t StartAddress = (CurrentAddress & 0xFFFF);
292
293 /* Paged mode memory programming */
294 for (uint16_t CurrentByte = 0; CurrentByte < Write_Memory_Params.BytesToWrite; CurrentByte++)
295 {
296 bool IsOddByte = (CurrentByte & 0x01);
297 uint8_t ByteToWrite = *(NextWriteByte++);
298
299 if (IsOddByte && (V2Command == CMD_PROGRAM_FLASH_ISP))
300 Write_Memory_Params.ProgrammingCommands[0] |= READ_WRITE_HIGH_BYTE_MASK;
301 else
302 Write_Memory_Params.ProgrammingCommands[0] &= ~READ_WRITE_HIGH_BYTE_MASK;
303
304 SPI_SendByte(Write_Memory_Params.ProgrammingCommands[0]);
305 SPI_SendByte(CurrentAddress >> 8);
306 SPI_SendByte(CurrentAddress & 0xFF);
307 SPI_SendByte(ByteToWrite);
308
309 if (!(PollAddress) && (ByteToWrite != PollValue))
310 {
311 if (IsOddByte && (V2Command == CMD_PROGRAM_FLASH_ISP))
312 Write_Memory_Params.ProgrammingCommands[2] |= READ_WRITE_HIGH_BYTE_MASK;
313
314 PollAddress = (CurrentAddress & 0xFFFF);
315 }
316
317 if (IsOddByte || (V2Command == CMD_PROGRAM_EEPROM_ISP))
318 CurrentAddress++;
319 }
320
321 /* If the current page must be committed, send the PROGRAM PAGE command to the target */
322 if (Write_Memory_Params.ProgrammingMode & PROG_MODE_COMMIT_PAGE_MASK)
323 {
324 SPI_SendByte(Write_Memory_Params.ProgrammingCommands[1]);
325 SPI_SendByte(StartAddress >> 8);
326 SPI_SendByte(StartAddress & 0xFF);
327 SPI_SendByte(0x00);
328
329 /* Check if polling is possible, if not switch to timed delay mode */
330 if (!(PollAddress))
331 {
332 Write_Memory_Params.ProgrammingMode &= ~PROG_MODE_PAGED_VALUE_MASK;
333 Write_Memory_Params.ProgrammingMode |= PROG_MODE_PAGED_TIMEDELAY_MASK;
334 }
335
336 ProgrammingStatus = V2Protocol_WaitForProgComplete(Write_Memory_Params.ProgrammingMode, PollAddress, PollValue,
337 Write_Memory_Params.DelayMS, Write_Memory_Params.ProgrammingCommands[2]);
338 }
339 }
340 else
341 {
342 /* Word/byte mode memory programming */
343 for (uint16_t CurrentByte = 0; CurrentByte < Write_Memory_Params.BytesToWrite; CurrentByte++)
344 {
345 bool IsOddByte = (CurrentByte & 0x01);
346 uint8_t ByteToWrite = *(NextWriteByte++);
347
348 if (IsOddByte && (V2Command == CMD_READ_FLASH_ISP))
349 Write_Memory_Params.ProgrammingCommands[0] |= READ_WRITE_HIGH_BYTE_MASK;
350 else
351 Write_Memory_Params.ProgrammingCommands[0] &= ~READ_WRITE_HIGH_BYTE_MASK;
352
353 SPI_SendByte(Write_Memory_Params.ProgrammingCommands[0]);
354 SPI_SendByte(CurrentAddress >> 8);
355 SPI_SendByte(CurrentAddress & 0xFF);
356 SPI_SendByte(ByteToWrite);
357
358 if (ByteToWrite != PollValue)
359 {
360 if (IsOddByte && (V2Command == CMD_PROGRAM_FLASH_ISP))
361 Write_Memory_Params.ProgrammingCommands[2] |= READ_WRITE_HIGH_BYTE_MASK;
362
363 PollAddress = (CurrentAddress & 0xFFFF);
364 }
365
366 if (IsOddByte || (V2Command == CMD_PROGRAM_EEPROM_ISP))
367 CurrentAddress++;
368
369 ProgrammingStatus = V2Protocol_WaitForProgComplete(Write_Memory_Params.ProgrammingMode, PollAddress, PollValue,
370 Write_Memory_Params.DelayMS, Write_Memory_Params.ProgrammingCommands[2]);
371
372 if (ProgrammingStatus != STATUS_CMD_OK)
373 break;
374 }
375 }
376
377 Endpoint_Write_Byte(V2Command);
378 Endpoint_Write_Byte(ProgrammingStatus);
379
380 Endpoint_ClearIN();
381 }
382
383 static void V2Protocol_Command_ReadMemory(uint8_t V2Command)
384 {
385 struct
386 {
387 uint16_t BytesToRead;
388 uint8_t ReadMemoryCommand;
389 } Read_Memory_Params;
390
391 Endpoint_Read_Stream_LE(&Read_Memory_Params, sizeof(Read_Memory_Params));
392 Read_Memory_Params.BytesToRead = SwapEndian_16(Read_Memory_Params.BytesToRead);
393
394 Endpoint_ClearOUT();
395 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
396
397 Endpoint_Write_Byte(V2Command);
398 Endpoint_Write_Byte(STATUS_CMD_OK);
399
400 for (uint16_t CurrentByte = 0; CurrentByte < Read_Memory_Params.BytesToRead; CurrentByte++)
401 {
402 bool IsOddByte = (CurrentByte & 0x01);
403
404 if (IsOddByte && (V2Command == CMD_READ_FLASH_ISP))
405 Read_Memory_Params.ReadMemoryCommand |= READ_WRITE_HIGH_BYTE_MASK;
406 else
407 Read_Memory_Params.ReadMemoryCommand &= ~READ_WRITE_HIGH_BYTE_MASK;
408
409 SPI_SendByte(Read_Memory_Params.ReadMemoryCommand);
410 SPI_SendByte(CurrentAddress >> 8);
411 SPI_SendByte(CurrentAddress & 0xFF);
412 Endpoint_Write_Byte(SPI_ReceiveByte());
413
414 /* Check if the endpoint bank is currently full */
415 if (!(Endpoint_IsReadWriteAllowed()))
416 {
417 Endpoint_ClearIN();
418 Endpoint_WaitUntilReady();
419 }
420
421 if ((IsOddByte && (V2Command == CMD_READ_FLASH_ISP)) || (V2Command == CMD_READ_EEPROM_ISP))
422 CurrentAddress++;
423 }
424
425 Endpoint_Write_Byte(STATUS_CMD_OK);
426
427 bool IsEndpointFull = !(Endpoint_IsReadWriteAllowed());
428 Endpoint_ClearIN();
429
430 /* Ensure last packet is a short packet to terminate the transfer */
431 if (IsEndpointFull)
432 {
433 Endpoint_WaitUntilReady();
434 Endpoint_ClearIN();
435 Endpoint_WaitUntilReady();
436 }
437 }
438
439 static void V2Protocol_Command_ChipErase(void)
440 {
441 struct
442 {
443 uint8_t EraseDelayMS;
444 uint8_t PollMethod;
445 uint8_t EraseCommandBytes[4];
446 } Erase_Chip_Params;
447
448 Endpoint_Read_Stream_LE(&Erase_Chip_Params, sizeof(Erase_Chip_Params));
449
450 Endpoint_ClearOUT();
451 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
452
453 uint8_t ResponseStatus = STATUS_CMD_OK;
454
455 for (uint8_t SByte = 0; SByte < sizeof(Erase_Chip_Params.EraseCommandBytes); SByte++)
456 SPI_SendByte(Erase_Chip_Params.EraseCommandBytes[SByte]);
457
458 if (!(Erase_Chip_Params.PollMethod))
459 V2Protocol_DelayMS(Erase_Chip_Params.EraseDelayMS);
460 else
461 ResponseStatus = V2Protocol_WaitWhileTargetBusy();
462
463 Endpoint_Write_Byte(CMD_CHIP_ERASE_ISP);
464 Endpoint_Write_Byte(ResponseStatus);
465 Endpoint_ClearIN();
466 }
467
468 static void V2Protocol_Command_ReadFuseLockSigOSCCAL(uint8_t V2Command)
469 {
470 struct
471 {
472 uint8_t RetByte;
473 uint8_t ReadCommandBytes[4];
474 } Read_FuseLockSigOSCCAL_Params;
475
476 Endpoint_Read_Stream_LE(&Read_FuseLockSigOSCCAL_Params, sizeof(Read_FuseLockSigOSCCAL_Params));
477
478 Endpoint_ClearOUT();
479 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
480
481 uint8_t ResponseBytes[4];
482
483 for (uint8_t RByte = 0; RByte < sizeof(ResponseBytes); RByte++)
484 ResponseBytes[RByte] = SPI_TransferByte(Read_FuseLockSigOSCCAL_Params.ReadCommandBytes[RByte]);
485
486 Endpoint_Write_Byte(V2Command);
487 Endpoint_Write_Byte(STATUS_CMD_OK);
488 Endpoint_Write_Byte(ResponseBytes[Read_FuseLockSigOSCCAL_Params.RetByte - 1]);
489 Endpoint_Write_Byte(STATUS_CMD_OK);
490 Endpoint_ClearIN();
491 }
492
493 static void V2Protocol_Command_WriteFuseLock(uint8_t V2Command)
494 {
495 struct
496 {
497 uint8_t WriteCommandBytes[4];
498 } Write_FuseLockSig_Params;
499
500 Endpoint_Read_Stream_LE(&Write_FuseLockSig_Params, sizeof(Write_FuseLockSig_Params));
501
502 Endpoint_ClearOUT();
503 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
504
505 for (uint8_t SByte = 0; SByte < sizeof(Write_FuseLockSig_Params.WriteCommandBytes); SByte++)
506 SPI_SendByte(Write_FuseLockSig_Params.WriteCommandBytes[SByte]);
507
508 Endpoint_Write_Byte(V2Command);
509 Endpoint_Write_Byte(STATUS_CMD_OK);
510 Endpoint_Write_Byte(STATUS_CMD_OK);
511 Endpoint_ClearIN();
512 }
513
514 static void V2Protocol_Command_SPIMulti(void)
515 {
516 struct
517 {
518 uint8_t TxBytes;
519 uint8_t RxBytes;
520 uint8_t RxStartAddr;
521 uint8_t TxData[255];
522 } SPI_Multi_Params;
523
524 Endpoint_Read_Stream_LE(&SPI_Multi_Params, sizeof(SPI_Multi_Params) - sizeof(SPI_Multi_Params.TxData));
525 Endpoint_Read_Stream_LE(&SPI_Multi_Params.TxData, SPI_Multi_Params.TxBytes);
526
527 Endpoint_ClearOUT();
528 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
529
530 Endpoint_Write_Byte(CMD_SPI_MULTI);
531 Endpoint_Write_Byte(STATUS_CMD_OK);
532
533 uint8_t CurrTxPos = 0;
534 uint8_t CurrRxPos = 0;
535
536 /* Write out bytes to transmit until the start of the bytes to receive is met */
537 while (CurrTxPos < SPI_Multi_Params.RxStartAddr)
538 {
539 if (CurrTxPos < SPI_Multi_Params.TxBytes)
540 SPI_SendByte(SPI_Multi_Params.TxData[CurrTxPos]);
541 else
542 SPI_SendByte(0);
543
544 CurrTxPos++;
545 }
546
547 /* Transmit remaining bytes with padding as needed, read in response bytes */
548 while (CurrRxPos < SPI_Multi_Params.RxBytes)
549 {
550 if (CurrTxPos < SPI_Multi_Params.TxBytes)
551 Endpoint_Write_Byte(SPI_TransferByte(SPI_Multi_Params.TxData[CurrTxPos++]));
552 else
553 Endpoint_Write_Byte(SPI_ReceiveByte());
554
555 CurrRxPos++;
556 }
557
558 Endpoint_Write_Byte(STATUS_CMD_OK);
559 Endpoint_ClearIN();
560 }