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