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