3 Copyright (C) Dean Camera, 2009.
5 dean [at] fourwalledcubicle [dot] com
6 www.fourwalledcubicle.com
10 Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)
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.
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
33 * V2Protocol handler, to process V2 Protocol commands used in Atmel programmer devices.
36 #define INCLUDE_FROM_V2PROTOCOL_C
37 #include "V2Protocol.h"
39 void V2Protocol_ProcessCommand(void)
41 uint8_t V2Command
= Endpoint_Read_Byte();
46 V2Protocol_Command_SignOn();
48 case CMD_SET_PARAMETER
:
49 case CMD_GET_PARAMETER
:
50 V2Protocol_Command_GetSetParam(V2Command
);
52 case CMD_LOAD_ADDRESS
:
53 V2Protocol_Command_LoadAddress();
55 case CMD_RESET_PROTECTION
:
56 V2Protocol_Command_ResetProtection();
58 case CMD_ENTER_PROGMODE_ISP
:
59 V2Protocol_Command_EnterISPMode();
61 case CMD_LEAVE_PROGMODE_ISP
:
62 V2Protocol_Command_LeaveISPMode();
64 case CMD_PROGRAM_FLASH_ISP
:
65 case CMD_PROGRAM_EEPROM_ISP
:
66 V2Protocol_Command_ProgramMemory(V2Command
);
68 case CMD_READ_FLASH_ISP
:
69 case CMD_READ_EEPROM_ISP
:
70 V2Protocol_Command_ReadMemory(V2Command
);
72 case CMD_CHIP_ERASE_ISP
:
73 V2Protocol_Command_ChipErase();
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
);
81 case CMD_PROGRAM_FUSE_ISP
:
82 case CMD_PROGRAM_LOCK_ISP
:
83 V2Protocol_Command_WriteFuseLock(V2Command
);
86 V2Protocol_Command_SPIMulti();
89 V2Protocol_Command_Unknown(V2Command
);
93 Endpoint_WaitUntilReady();
94 Endpoint_SetEndpointDirection(ENDPOINT_DIR_OUT
);
97 static void V2Protocol_Command_Unknown(uint8_t V2Command
)
99 /* Discard all incomming data */
100 while (Endpoint_BytesInEndpoint() == AVRISP_DATA_EPSIZE
)
103 Endpoint_WaitUntilReady();
107 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
109 Endpoint_Write_Byte(V2Command
);
110 Endpoint_Write_Byte(STATUS_CMD_UNKNOWN
);
114 static void V2Protocol_Command_SignOn(void)
117 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
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));
126 static void V2Protocol_Command_GetSetParam(uint8_t V2Command
)
128 uint8_t ParamID
= Endpoint_Read_Byte();
131 if (V2Command
== CMD_SET_PARAMETER
)
132 ParamValue
= Endpoint_Read_Byte();
135 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
137 Endpoint_Write_Byte(V2Command
);
139 uint8_t ParamPrivs
= V2Params_GetParameterPrivellages(ParamID
);
141 if ((V2Command
== CMD_SET_PARAMETER
) && (ParamPrivs
& PARAM_PRIV_WRITE
))
143 Endpoint_Write_Byte(STATUS_CMD_OK
);
144 V2Params_SetParameterValue(ParamID
, ParamValue
);
146 else if ((V2Command
== CMD_GET_PARAMETER
) && (ParamPrivs
& PARAM_PRIV_READ
))
148 Endpoint_Write_Byte(STATUS_CMD_OK
);
149 Endpoint_Write_Byte(V2Params_GetParameterValue(ParamID
));
153 Endpoint_Write_Byte(STATUS_CMD_FAILED
);
159 static void V2Protocol_Command_LoadAddress(void)
161 Endpoint_Read_Stream_LE(&CurrentAddress
, sizeof(CurrentAddress
));
164 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
166 if (CurrentAddress
& (1UL << 31))
167 V2Protocol_LoadExtendedAddress();
169 Endpoint_Write_Byte(CMD_LOAD_ADDRESS
);
170 Endpoint_Write_Byte(STATUS_CMD_OK
);
174 static void V2Protocol_Command_ResetProtection(void)
177 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
179 Endpoint_Write_Byte(CMD_RESET_PROTECTION
);
180 Endpoint_Write_Byte(STATUS_CMD_OK
);
184 static void V2Protocol_Command_EnterISPMode(void)
189 uint8_t PinStabDelayMS
;
190 uint8_t ExecutionDelayMS
;
195 uint8_t EnterProgBytes
[4];
198 Endpoint_Read_Stream_LE(&Enter_ISP_Params
, sizeof(Enter_ISP_Params
));
201 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
203 uint8_t ResponseStatus
= STATUS_CMD_FAILED
;
207 V2Protocol_DelayMS(Enter_ISP_Params
.ExecutionDelayMS
);
208 SPI_Init(V2Protocol_GetSPIPrescalerMask() | SPI_SCK_LEAD_RISING
| SPI_SAMPLE_LEADING
| SPI_MODE_MASTER
);
210 while (Enter_ISP_Params
.SynchLoops
-- && (ResponseStatus
== STATUS_CMD_FAILED
))
212 uint8_t ResponseBytes
[4];
214 V2Protocol_ChangeTargetResetLine(true);
215 V2Protocol_DelayMS(Enter_ISP_Params
.PinStabDelayMS
);
217 for (uint8_t RByte
= 0; RByte
< sizeof(ResponseBytes
); RByte
++)
219 V2Protocol_DelayMS(Enter_ISP_Params
.ByteDelay
);
220 ResponseBytes
[RByte
] = SPI_TransferByte(Enter_ISP_Params
.EnterProgBytes
[RByte
]);
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
))
226 ResponseStatus
= STATUS_CMD_OK
;
230 V2Protocol_ChangeTargetResetLine(false);
231 V2Protocol_DelayMS(Enter_ISP_Params
.PinStabDelayMS
);
235 Endpoint_Write_Byte(CMD_ENTER_PROGMODE_ISP
);
236 Endpoint_Write_Byte(ResponseStatus
);
240 static void V2Protocol_Command_LeaveISPMode(void)
248 Endpoint_Read_Stream_LE(&Leave_ISP_Params
, sizeof(Leave_ISP_Params
));
251 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
253 V2Protocol_DelayMS(Leave_ISP_Params
.PreDelayMS
);
254 V2Protocol_ChangeTargetResetLine(false);
256 V2Protocol_DelayMS(Leave_ISP_Params
.PostDelayMS
);
258 Endpoint_Write_Byte(CMD_LEAVE_PROGMODE_ISP
);
259 Endpoint_Write_Byte(STATUS_CMD_OK
);
263 static void V2Protocol_Command_ProgramMemory(uint8_t V2Command
)
267 uint16_t BytesToWrite
;
268 uint8_t ProgrammingMode
;
270 uint8_t ProgrammingCommands
[3];
273 } Write_Memory_Params
;
275 Endpoint_Read_Stream_LE(&Write_Memory_Params
, sizeof(Write_Memory_Params
));
276 Write_Memory_Params
.BytesToWrite
= SwapEndian_16(Write_Memory_Params
.BytesToWrite
);
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
;
283 if (Write_Memory_Params
.ProgrammingMode
& PROG_MODE_PAGED_WRITES_MASK
)
285 /* Paged mode memory programming */
286 for (uint16_t CurrentByte
= 0; CurrentByte
< Write_Memory_Params
.BytesToWrite
; CurrentByte
++)
288 bool IsOddByte
= (CurrentByte
& 0x01);
289 uint8_t ByteToWrite
= Endpoint_Read_Byte();
291 if ((V2Command
== CMD_READ_FLASH_ISP
) && IsOddByte
)
292 Write_Memory_Params
.ProgrammingCommands
[0] ^= READ_WRITE_ODD_BYTE_MASK
;
294 SPI_SendByte(Write_Memory_Params
.ProgrammingCommands
[0]);
295 SPI_SendByte(CurrentAddress
>> 8);
296 SPI_SendByte(CurrentAddress
& 0xFF);
297 SPI_SendByte(ByteToWrite
);
299 if (!(PollAddress
) && (ByteToWrite
!= PollValue
))
301 if (V2Command
== CMD_PROGRAM_FLASH_ISP
)
302 PollAddress
= (((CurrentAddress
& 0xFFFF) << 1) | IsOddByte
);
304 PollAddress
= (CurrentAddress
& 0xFFFF);
307 if (IsOddByte
|| (V2Command
== CMD_PROGRAM_EEPROM_ISP
))
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
)
314 SPI_SendByte(Write_Memory_Params
.ProgrammingCommands
[1]);
315 SPI_SendByte(CurrentAddress
>> 8);
316 SPI_SendByte(CurrentAddress
& 0xFF);
319 /* Check if polling is possible, if not switch to timed delay mode */
322 Write_Memory_Params
.ProgrammingMode
&= ~PROG_MODE_PAGED_VALUE_MASK
;
323 Write_Memory_Params
.ProgrammingMode
&= ~PROG_MODE_PAGED_TIMEDELAY_MASK
;
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]);
333 /* Word/byte mode memory programming */
334 for (uint16_t CurrentByte
= 0; CurrentByte
< Write_Memory_Params
.BytesToWrite
; CurrentByte
++)
336 bool IsOddByte
= (CurrentByte
& 0x01);
337 uint8_t ByteToWrite
= Endpoint_Read_Byte();
339 if ((V2Command
== CMD_READ_FLASH_ISP
) && IsOddByte
)
340 Write_Memory_Params
.ProgrammingCommands
[0] ^= READ_WRITE_ODD_BYTE_MASK
;
342 SPI_SendByte(Write_Memory_Params
.ProgrammingCommands
[0]);
343 SPI_SendByte(CurrentAddress
>> 8);
344 SPI_SendByte(CurrentAddress
& 0xFF);
345 SPI_SendByte(ByteToWrite
);
347 if (ByteToWrite
!= PollValue
)
349 if (V2Command
== CMD_PROGRAM_FLASH_ISP
)
350 PollAddress
= (((CurrentAddress
& 0xFFFF) << 1) | IsOddByte
);
352 PollAddress
= (CurrentAddress
& 0xFFFF);
355 if (IsOddByte
|| (V2Command
== CMD_PROGRAM_EEPROM_ISP
))
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]);
362 if (ProgrammingStatus
!= STATUS_CMD_OK
)
368 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
370 Endpoint_Write_Byte(V2Command
);
371 Endpoint_Write_Byte(ProgrammingStatus
);
376 static void V2Protocol_Command_ReadMemory(uint8_t V2Command
)
380 uint16_t BytesToRead
;
381 uint8_t ReadMemoryCommand
;
382 } Read_Memory_Params
;
384 Endpoint_Read_Stream_LE(&Read_Memory_Params
, sizeof(Read_Memory_Params
));
385 Read_Memory_Params
.BytesToRead
= SwapEndian_16(Read_Memory_Params
.BytesToRead
);
388 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
390 Endpoint_Write_Byte(V2Command
);
391 Endpoint_Write_Byte(STATUS_CMD_OK
);
393 for (uint16_t CurrentByte
= 0; CurrentByte
< Read_Memory_Params
.BytesToRead
; CurrentByte
++)
395 if ((V2Command
== CMD_READ_FLASH_ISP
) && (CurrentByte
& 0x01))
396 Read_Memory_Params
.ReadMemoryCommand
^= READ_WRITE_ODD_BYTE_MASK
;
398 SPI_SendByte(Read_Memory_Params
.ReadMemoryCommand
);
399 SPI_SendByte(CurrentAddress
>> 8);
400 SPI_SendByte(CurrentAddress
& 0xFF);
401 Endpoint_Write_Byte(SPI_ReceiveByte());
403 /* Check if the endpoint bank is currently full */
404 if (!(Endpoint_IsReadWriteAllowed()))
407 Endpoint_WaitUntilReady();
410 if (((V2Command
== CMD_READ_FLASH_ISP
) && (CurrentByte
& 0x01)) || (V2Command
== CMD_READ_EEPROM_ISP
))
414 Endpoint_Write_Byte(STATUS_CMD_OK
);
416 bool IsEndpointFull
= !(Endpoint_IsReadWriteAllowed());
419 /* Ensure last packet is a short packet to terminate the transfer */
422 Endpoint_WaitUntilReady();
424 Endpoint_WaitUntilReady();
428 static void V2Protocol_Command_ChipErase(void)
432 uint8_t EraseDelayMS
;
434 uint8_t EraseCommandBytes
[4];
437 Endpoint_Read_Stream_LE(&Erase_Chip_Params
, sizeof(Erase_Chip_Params
));
440 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
442 uint8_t ResponseStatus
= STATUS_CMD_OK
;
444 for (uint8_t SByte
= 0; SByte
< sizeof(Erase_Chip_Params
.EraseCommandBytes
); SByte
++)
445 SPI_SendByte(Erase_Chip_Params
.EraseCommandBytes
[SByte
]);
447 if (!(Erase_Chip_Params
.PollMethod
))
448 V2Protocol_DelayMS(Erase_Chip_Params
.EraseDelayMS
);
450 ResponseStatus
= V2Protocol_WaitWhileTargetBusy();
452 Endpoint_Write_Byte(CMD_CHIP_ERASE_ISP
);
453 Endpoint_Write_Byte(ResponseStatus
);
457 static void V2Protocol_Command_ReadFuseLockSigOSCCAL(uint8_t V2Command
)
462 uint8_t ReadCommandBytes
[4];
463 } Read_FuseLockSigOSCCAL_Params
;
465 Endpoint_Read_Stream_LE(&Read_FuseLockSigOSCCAL_Params
, sizeof(Read_FuseLockSigOSCCAL_Params
));
468 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
470 uint8_t ResponseBytes
[4];
472 for (uint8_t RByte
= 0; RByte
< sizeof(ResponseBytes
); RByte
++)
473 ResponseBytes
[RByte
] = SPI_TransferByte(Read_FuseLockSigOSCCAL_Params
.ReadCommandBytes
[RByte
]);
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
);
482 static void V2Protocol_Command_WriteFuseLock(uint8_t V2Command
)
486 uint8_t WriteCommandBytes
[4];
487 } Write_FuseLockSig_Params
;
489 Endpoint_Read_Stream_LE(&Write_FuseLockSig_Params
, sizeof(Write_FuseLockSig_Params
));
492 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
494 for (uint8_t SByte
= 0; SByte
< sizeof(Write_FuseLockSig_Params
.WriteCommandBytes
); SByte
++)
495 SPI_SendByte(Write_FuseLockSig_Params
.WriteCommandBytes
[SByte
]);
497 Endpoint_Write_Byte(V2Command
);
498 Endpoint_Write_Byte(STATUS_CMD_OK
);
499 Endpoint_Write_Byte(STATUS_CMD_OK
);
503 static void V2Protocol_Command_SPIMulti(void)
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
);
518 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
520 Endpoint_Write_Byte(CMD_SPI_MULTI
);
521 Endpoint_Write_Byte(STATUS_CMD_OK
);
523 uint8_t CurrTxPos
= 0;
524 uint8_t CurrRxPos
= 0;
526 /* Write out bytes to transmit until the start of the bytes to receive is met */
527 while (CurrTxPos
< SPI_Multi_Params
.RxStartAddr
)
529 if (CurrTxPos
< SPI_Multi_Params
.TxBytes
)
530 SPI_SendByte(SPI_Multi_Params
.TxData
[CurrTxPos
]);
537 /* Transmit remaining bytes with padding as needed, read in response bytes */
538 while (CurrRxPos
< SPI_Multi_Params
.RxBytes
)
540 if (CurrTxPos
< SPI_Multi_Params
.TxBytes
)
541 Endpoint_Write_Byte(SPI_TransferByte(SPI_Multi_Params
.TxData
[CurrTxPos
++]));
543 Endpoint_Write_Byte(SPI_ReceiveByte());
548 Endpoint_Write_Byte(STATUS_CMD_OK
);