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_BE(&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 uint16_t StartAddress
= (CurrentAddress
& 0xFFFF);
287 /* Paged mode memory programming */
288 for (uint16_t CurrentByte
= 0; CurrentByte
< Write_Memory_Params
.BytesToWrite
; CurrentByte
++)
290 bool IsOddByte
= (CurrentByte
& 0x01);
291 uint8_t ByteToWrite
= Endpoint_Read_Byte();
293 if (IsOddByte
&& (V2Command
== CMD_PROGRAM_FLASH_ISP
))
294 Write_Memory_Params
.ProgrammingCommands
[0] ^= READ_WRITE_HIGH_BYTE_MASK
;
296 SPI_SendByte(Write_Memory_Params
.ProgrammingCommands
[0]);
297 SPI_SendByte(CurrentAddress
>> 8);
298 SPI_SendByte(CurrentAddress
& 0xFF);
299 SPI_SendByte(ByteToWrite
);
301 if (!(PollAddress
) && (ByteToWrite
!= PollValue
))
303 if (IsOddByte
&& (V2Command
== CMD_PROGRAM_FLASH_ISP
))
304 Write_Memory_Params
.ProgrammingCommands
[2] |= READ_WRITE_HIGH_BYTE_MASK
;
306 PollAddress
= (CurrentAddress
& 0xFFFF);
309 /* Check if the endpoint bank is currently empty */
310 if (!(Endpoint_IsReadWriteAllowed()))
313 Endpoint_WaitUntilReady();
316 if (IsOddByte
|| (V2Command
== CMD_PROGRAM_EEPROM_ISP
))
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
)
323 SPI_SendByte(Write_Memory_Params
.ProgrammingCommands
[1]);
324 SPI_SendByte(StartAddress
>> 8);
325 SPI_SendByte(StartAddress
& 0xFF);
328 /* Check if polling is possible, if not switch to timed delay mode */
331 Write_Memory_Params
.ProgrammingMode
&= ~PROG_MODE_PAGED_VALUE_MASK
;
332 Write_Memory_Params
.ProgrammingMode
&= ~PROG_MODE_PAGED_TIMEDELAY_MASK
;
335 ProgrammingStatus
= V2Protocol_WaitForProgComplete(Write_Memory_Params
.ProgrammingMode
, PollAddress
, PollValue
,
336 Write_Memory_Params
.DelayMS
, Write_Memory_Params
.ProgrammingCommands
[2]);
341 /* Word/byte mode memory programming */
342 for (uint16_t CurrentByte
= 0; CurrentByte
< Write_Memory_Params
.BytesToWrite
; CurrentByte
++)
344 bool IsOddByte
= (CurrentByte
& 0x01);
345 uint8_t ByteToWrite
= Endpoint_Read_Byte();
347 if (IsOddByte
&& (V2Command
== CMD_READ_FLASH_ISP
))
348 Write_Memory_Params
.ProgrammingCommands
[0] ^= READ_WRITE_HIGH_BYTE_MASK
;
350 SPI_SendByte(Write_Memory_Params
.ProgrammingCommands
[0]);
351 SPI_SendByte(CurrentAddress
>> 8);
352 SPI_SendByte(CurrentAddress
& 0xFF);
353 SPI_SendByte(ByteToWrite
);
355 if (ByteToWrite
!= PollValue
)
357 if (IsOddByte
&& (V2Command
== CMD_PROGRAM_FLASH_ISP
))
358 Write_Memory_Params
.ProgrammingCommands
[2] |= READ_WRITE_HIGH_BYTE_MASK
;
360 PollAddress
= (CurrentAddress
& 0xFFFF);
363 /* Check if the endpoint bank is currently empty */
364 if (!(Endpoint_IsReadWriteAllowed()))
367 Endpoint_WaitUntilReady();
370 if (IsOddByte
|| (V2Command
== CMD_PROGRAM_EEPROM_ISP
))
373 ProgrammingStatus
= V2Protocol_WaitForProgComplete(Write_Memory_Params
.ProgrammingMode
, PollAddress
, PollValue
,
374 Write_Memory_Params
.DelayMS
, Write_Memory_Params
.ProgrammingCommands
[2]);
376 if (ProgrammingStatus
!= STATUS_CMD_OK
)
382 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
384 Endpoint_Write_Byte(V2Command
);
385 Endpoint_Write_Byte(ProgrammingStatus
);
390 static void V2Protocol_Command_ReadMemory(uint8_t V2Command
)
394 uint16_t BytesToRead
;
395 uint8_t ReadMemoryCommand
;
396 } Read_Memory_Params
;
398 Endpoint_Read_Stream_LE(&Read_Memory_Params
, sizeof(Read_Memory_Params
));
399 Read_Memory_Params
.BytesToRead
= SwapEndian_16(Read_Memory_Params
.BytesToRead
);
402 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
404 Endpoint_Write_Byte(V2Command
);
405 Endpoint_Write_Byte(STATUS_CMD_OK
);
407 for (uint16_t CurrentByte
= 0; CurrentByte
< Read_Memory_Params
.BytesToRead
; CurrentByte
++)
409 if ((V2Command
== CMD_READ_FLASH_ISP
) && (CurrentByte
& 0x01))
410 Read_Memory_Params
.ReadMemoryCommand
^= READ_WRITE_HIGH_BYTE_MASK
;
412 SPI_SendByte(Read_Memory_Params
.ReadMemoryCommand
);
413 SPI_SendByte(CurrentAddress
>> 8);
414 SPI_SendByte(CurrentAddress
& 0xFF);
415 Endpoint_Write_Byte(SPI_ReceiveByte());
417 /* Check if the endpoint bank is currently full */
418 if (!(Endpoint_IsReadWriteAllowed()))
421 Endpoint_WaitUntilReady();
424 if (((V2Command
== CMD_READ_FLASH_ISP
) && (CurrentByte
& 0x01)) || (V2Command
== CMD_READ_EEPROM_ISP
))
428 Endpoint_Write_Byte(STATUS_CMD_OK
);
430 bool IsEndpointFull
= !(Endpoint_IsReadWriteAllowed());
433 /* Ensure last packet is a short packet to terminate the transfer */
436 Endpoint_WaitUntilReady();
438 Endpoint_WaitUntilReady();
442 static void V2Protocol_Command_ChipErase(void)
446 uint8_t EraseDelayMS
;
448 uint8_t EraseCommandBytes
[4];
451 Endpoint_Read_Stream_LE(&Erase_Chip_Params
, sizeof(Erase_Chip_Params
));
454 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
456 uint8_t ResponseStatus
= STATUS_CMD_OK
;
458 for (uint8_t SByte
= 0; SByte
< sizeof(Erase_Chip_Params
.EraseCommandBytes
); SByte
++)
459 SPI_SendByte(Erase_Chip_Params
.EraseCommandBytes
[SByte
]);
461 if (!(Erase_Chip_Params
.PollMethod
))
462 V2Protocol_DelayMS(Erase_Chip_Params
.EraseDelayMS
);
464 ResponseStatus
= V2Protocol_WaitWhileTargetBusy();
466 Endpoint_Write_Byte(CMD_CHIP_ERASE_ISP
);
467 Endpoint_Write_Byte(ResponseStatus
);
471 static void V2Protocol_Command_ReadFuseLockSigOSCCAL(uint8_t V2Command
)
476 uint8_t ReadCommandBytes
[4];
477 } Read_FuseLockSigOSCCAL_Params
;
479 Endpoint_Read_Stream_LE(&Read_FuseLockSigOSCCAL_Params
, sizeof(Read_FuseLockSigOSCCAL_Params
));
482 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
484 uint8_t ResponseBytes
[4];
486 for (uint8_t RByte
= 0; RByte
< sizeof(ResponseBytes
); RByte
++)
487 ResponseBytes
[RByte
] = SPI_TransferByte(Read_FuseLockSigOSCCAL_Params
.ReadCommandBytes
[RByte
]);
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
);
496 static void V2Protocol_Command_WriteFuseLock(uint8_t V2Command
)
500 uint8_t WriteCommandBytes
[4];
501 } Write_FuseLockSig_Params
;
503 Endpoint_Read_Stream_LE(&Write_FuseLockSig_Params
, sizeof(Write_FuseLockSig_Params
));
506 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
508 for (uint8_t SByte
= 0; SByte
< sizeof(Write_FuseLockSig_Params
.WriteCommandBytes
); SByte
++)
509 SPI_SendByte(Write_FuseLockSig_Params
.WriteCommandBytes
[SByte
]);
511 Endpoint_Write_Byte(V2Command
);
512 Endpoint_Write_Byte(STATUS_CMD_OK
);
513 Endpoint_Write_Byte(STATUS_CMD_OK
);
517 static void V2Protocol_Command_SPIMulti(void)
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
);
532 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
534 Endpoint_Write_Byte(CMD_SPI_MULTI
);
535 Endpoint_Write_Byte(STATUS_CMD_OK
);
537 uint8_t CurrTxPos
= 0;
538 uint8_t CurrRxPos
= 0;
540 /* Write out bytes to transmit until the start of the bytes to receive is met */
541 while (CurrTxPos
< SPI_Multi_Params
.RxStartAddr
)
543 if (CurrTxPos
< SPI_Multi_Params
.TxBytes
)
544 SPI_SendByte(SPI_Multi_Params
.TxData
[CurrTxPos
]);
551 /* Transmit remaining bytes with padding as needed, read in response bytes */
552 while (CurrRxPos
< SPI_Multi_Params
.RxBytes
)
554 if (CurrTxPos
< SPI_Multi_Params
.TxBytes
)
555 Endpoint_Write_Byte(SPI_TransferByte(SPI_Multi_Params
.TxData
[CurrTxPos
++]));
557 Endpoint_Write_Byte(SPI_ReceiveByte());
562 Endpoint_Write_Byte(STATUS_CMD_OK
);