8d1480269f6a0957f36883f04488a13afa20460d
[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 } Write_Memory_Params;
274
275 Endpoint_Read_Stream_LE(&Write_Memory_Params, sizeof(Write_Memory_Params));
276 Write_Memory_Params.BytesToWrite = SwapEndian_16(Write_Memory_Params.BytesToWrite);
277
278 uint8_t ProgrammingStatus = STATUS_CMD_OK;
279 uint16_t PollAddress = 0;
280 uint8_t PollValue = (V2Command == CMD_PROGRAM_FLASH_ISP) ? Write_Memory_Params.PollValue1 :
281 Write_Memory_Params.PollValue2;
282
283 if (Write_Memory_Params.ProgrammingMode & PROG_MODE_PAGED_WRITES_MASK)
284 {
285 uint16_t StartAddress = (CurrentAddress & 0xFFFF);
286
287 /* Paged mode memory programming */
288 for (uint16_t CurrentByte = 0; CurrentByte < Write_Memory_Params.BytesToWrite; CurrentByte++)
289 {
290 bool IsOddByte = (CurrentByte & 0x01);
291 uint8_t ByteToWrite = Endpoint_Read_Byte();
292
293 if (IsOddByte && (V2Command == CMD_PROGRAM_FLASH_ISP))
294 Write_Memory_Params.ProgrammingCommands[0] ^= READ_WRITE_HIGH_BYTE_MASK;
295
296 SPI_SendByte(Write_Memory_Params.ProgrammingCommands[0]);
297 SPI_SendByte(CurrentAddress >> 8);
298 SPI_SendByte(CurrentAddress & 0xFF);
299 SPI_SendByte(ByteToWrite);
300
301 if (!(PollAddress) && (ByteToWrite != PollValue))
302 {
303 if (IsOddByte && (V2Command == CMD_PROGRAM_FLASH_ISP))
304 Write_Memory_Params.ProgrammingCommands[2] |= READ_WRITE_HIGH_BYTE_MASK;
305
306 PollAddress = (CurrentAddress & 0xFFFF);
307 }
308
309 /* Check if the endpoint bank is currently empty */
310 if (!(Endpoint_IsReadWriteAllowed()))
311 {
312 Endpoint_ClearOUT();
313 Endpoint_WaitUntilReady();
314 }
315
316 if (IsOddByte || (V2Command == CMD_PROGRAM_EEPROM_ISP))
317 CurrentAddress++;
318 }
319
320 /* If the current page must be committed, send the PROGRAM PAGE command to the target */
321 if (Write_Memory_Params.ProgrammingMode & PROG_MODE_COMMIT_PAGE_MASK)
322 {
323 SPI_SendByte(Write_Memory_Params.ProgrammingCommands[1]);
324 SPI_SendByte(StartAddress >> 8);
325 SPI_SendByte(StartAddress & 0xFF);
326 SPI_SendByte(0x00);
327
328 /* Check if polling is possible, if not switch to timed delay mode */
329 if (!(PollAddress))
330 {
331 Write_Memory_Params.ProgrammingMode &= ~PROG_MODE_PAGED_VALUE_MASK;
332 Write_Memory_Params.ProgrammingMode &= ~PROG_MODE_PAGED_TIMEDELAY_MASK;
333 }
334
335 ProgrammingStatus = V2Protocol_WaitForProgComplete(Write_Memory_Params.ProgrammingMode, PollAddress, PollValue,
336 Write_Memory_Params.DelayMS, Write_Memory_Params.ProgrammingCommands[2]);
337 }
338 }
339 else
340 {
341 /* Word/byte mode memory programming */
342 for (uint16_t CurrentByte = 0; CurrentByte < Write_Memory_Params.BytesToWrite; CurrentByte++)
343 {
344 bool IsOddByte = (CurrentByte & 0x01);
345 uint8_t ByteToWrite = Endpoint_Read_Byte();
346
347 if (IsOddByte && (V2Command == CMD_READ_FLASH_ISP))
348 Write_Memory_Params.ProgrammingCommands[0] ^= READ_WRITE_HIGH_BYTE_MASK;
349
350 SPI_SendByte(Write_Memory_Params.ProgrammingCommands[0]);
351 SPI_SendByte(CurrentAddress >> 8);
352 SPI_SendByte(CurrentAddress & 0xFF);
353 SPI_SendByte(ByteToWrite);
354
355 if (ByteToWrite != PollValue)
356 {
357 if (IsOddByte && (V2Command == CMD_PROGRAM_FLASH_ISP))
358 Write_Memory_Params.ProgrammingCommands[2] |= READ_WRITE_HIGH_BYTE_MASK;
359
360 PollAddress = (CurrentAddress & 0xFFFF);
361 }
362
363 /* Check if the endpoint bank is currently empty */
364 if (!(Endpoint_IsReadWriteAllowed()))
365 {
366 Endpoint_ClearOUT();
367 Endpoint_WaitUntilReady();
368 }
369
370 if (IsOddByte || (V2Command == CMD_PROGRAM_EEPROM_ISP))
371 CurrentAddress++;
372
373 ProgrammingStatus = V2Protocol_WaitForProgComplete(Write_Memory_Params.ProgrammingMode, PollAddress, PollValue,
374 Write_Memory_Params.DelayMS, Write_Memory_Params.ProgrammingCommands[2]);
375
376 if (ProgrammingStatus != STATUS_CMD_OK)
377 break;
378 }
379 }
380
381 Endpoint_ClearOUT();
382 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
383
384 Endpoint_Write_Byte(V2Command);
385 Endpoint_Write_Byte(ProgrammingStatus);
386
387 Endpoint_ClearIN();
388 }
389
390 static void V2Protocol_Command_ReadMemory(uint8_t V2Command)
391 {
392 struct
393 {
394 uint16_t BytesToRead;
395 uint8_t ReadMemoryCommand;
396 } Read_Memory_Params;
397
398 Endpoint_Read_Stream_LE(&Read_Memory_Params, sizeof(Read_Memory_Params));
399 Read_Memory_Params.BytesToRead = SwapEndian_16(Read_Memory_Params.BytesToRead);
400
401 Endpoint_ClearOUT();
402 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
403
404 Endpoint_Write_Byte(V2Command);
405 Endpoint_Write_Byte(STATUS_CMD_OK);
406
407 for (uint16_t CurrentByte = 0; CurrentByte < Read_Memory_Params.BytesToRead; CurrentByte++)
408 {
409 if ((V2Command == CMD_READ_FLASH_ISP) && (CurrentByte & 0x01))
410 Read_Memory_Params.ReadMemoryCommand ^= READ_WRITE_HIGH_BYTE_MASK;
411
412 SPI_SendByte(Read_Memory_Params.ReadMemoryCommand);
413 SPI_SendByte(CurrentAddress >> 8);
414 SPI_SendByte(CurrentAddress & 0xFF);
415 Endpoint_Write_Byte(SPI_ReceiveByte());
416
417 /* Check if the endpoint bank is currently full */
418 if (!(Endpoint_IsReadWriteAllowed()))
419 {
420 Endpoint_ClearIN();
421 Endpoint_WaitUntilReady();
422 }
423
424 if (((V2Command == CMD_READ_FLASH_ISP) && (CurrentByte & 0x01)) || (V2Command == CMD_READ_EEPROM_ISP))
425 CurrentAddress++;
426 }
427
428 Endpoint_Write_Byte(STATUS_CMD_OK);
429
430 bool IsEndpointFull = !(Endpoint_IsReadWriteAllowed());
431 Endpoint_ClearIN();
432
433 /* Ensure last packet is a short packet to terminate the transfer */
434 if (IsEndpointFull)
435 {
436 Endpoint_WaitUntilReady();
437 Endpoint_ClearIN();
438 Endpoint_WaitUntilReady();
439 }
440 }
441
442 static void V2Protocol_Command_ChipErase(void)
443 {
444 struct
445 {
446 uint8_t EraseDelayMS;
447 uint8_t PollMethod;
448 uint8_t EraseCommandBytes[4];
449 } Erase_Chip_Params;
450
451 Endpoint_Read_Stream_LE(&Erase_Chip_Params, sizeof(Erase_Chip_Params));
452
453 Endpoint_ClearOUT();
454 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
455
456 uint8_t ResponseStatus = STATUS_CMD_OK;
457
458 for (uint8_t SByte = 0; SByte < sizeof(Erase_Chip_Params.EraseCommandBytes); SByte++)
459 SPI_SendByte(Erase_Chip_Params.EraseCommandBytes[SByte]);
460
461 if (!(Erase_Chip_Params.PollMethod))
462 V2Protocol_DelayMS(Erase_Chip_Params.EraseDelayMS);
463 else
464 ResponseStatus = V2Protocol_WaitWhileTargetBusy();
465
466 Endpoint_Write_Byte(CMD_CHIP_ERASE_ISP);
467 Endpoint_Write_Byte(ResponseStatus);
468 Endpoint_ClearIN();
469 }
470
471 static void V2Protocol_Command_ReadFuseLockSigOSCCAL(uint8_t V2Command)
472 {
473 struct
474 {
475 uint8_t RetByte;
476 uint8_t ReadCommandBytes[4];
477 } Read_FuseLockSigOSCCAL_Params;
478
479 Endpoint_Read_Stream_LE(&Read_FuseLockSigOSCCAL_Params, sizeof(Read_FuseLockSigOSCCAL_Params));
480
481 Endpoint_ClearOUT();
482 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
483
484 uint8_t ResponseBytes[4];
485
486 for (uint8_t RByte = 0; RByte < sizeof(ResponseBytes); RByte++)
487 ResponseBytes[RByte] = SPI_TransferByte(Read_FuseLockSigOSCCAL_Params.ReadCommandBytes[RByte]);
488
489 Endpoint_Write_Byte(V2Command);
490 Endpoint_Write_Byte(STATUS_CMD_OK);
491 Endpoint_Write_Byte(ResponseBytes[Read_FuseLockSigOSCCAL_Params.RetByte - 1]);
492 Endpoint_Write_Byte(STATUS_CMD_OK);
493 Endpoint_ClearIN();
494 }
495
496 static void V2Protocol_Command_WriteFuseLock(uint8_t V2Command)
497 {
498 struct
499 {
500 uint8_t WriteCommandBytes[4];
501 } Write_FuseLockSig_Params;
502
503 Endpoint_Read_Stream_LE(&Write_FuseLockSig_Params, sizeof(Write_FuseLockSig_Params));
504
505 Endpoint_ClearOUT();
506 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
507
508 for (uint8_t SByte = 0; SByte < sizeof(Write_FuseLockSig_Params.WriteCommandBytes); SByte++)
509 SPI_SendByte(Write_FuseLockSig_Params.WriteCommandBytes[SByte]);
510
511 Endpoint_Write_Byte(V2Command);
512 Endpoint_Write_Byte(STATUS_CMD_OK);
513 Endpoint_Write_Byte(STATUS_CMD_OK);
514 Endpoint_ClearIN();
515 }
516
517 static void V2Protocol_Command_SPIMulti(void)
518 {
519 struct
520 {
521 uint8_t TxBytes;
522 uint8_t RxBytes;
523 uint8_t RxStartAddr;
524 uint8_t TxData[255];
525 } SPI_Multi_Params;
526
527 Endpoint_Read_Stream_LE(&SPI_Multi_Params, sizeof(SPI_Multi_Params) -
528 sizeof(SPI_Multi_Params.TxData));
529 Endpoint_Read_Stream_LE(&SPI_Multi_Params.TxData, SPI_Multi_Params.TxBytes);
530
531 Endpoint_ClearOUT();
532 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
533
534 Endpoint_Write_Byte(CMD_SPI_MULTI);
535 Endpoint_Write_Byte(STATUS_CMD_OK);
536
537 uint8_t CurrTxPos = 0;
538 uint8_t CurrRxPos = 0;
539
540 /* Write out bytes to transmit until the start of the bytes to receive is met */
541 while (CurrTxPos < SPI_Multi_Params.RxStartAddr)
542 {
543 if (CurrTxPos < SPI_Multi_Params.TxBytes)
544 SPI_SendByte(SPI_Multi_Params.TxData[CurrTxPos]);
545 else
546 SPI_SendByte(0);
547
548 CurrTxPos++;
549 }
550
551 /* Transmit remaining bytes with padding as needed, read in response bytes */
552 while (CurrRxPos < SPI_Multi_Params.RxBytes)
553 {
554 if (CurrTxPos < SPI_Multi_Params.TxBytes)
555 Endpoint_Write_Byte(SPI_TransferByte(SPI_Multi_Params.TxData[CurrTxPos++]));
556 else
557 Endpoint_Write_Byte(SPI_ReceiveByte());
558
559 CurrRxPos++;
560 }
561
562 Endpoint_Write_Byte(STATUS_CMD_OK);
563 Endpoint_ClearIN();
564 }