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 /* Check if the endpoint bank is currently empty */
291 if (!(Endpoint_IsReadWriteAllowed()))
294 Endpoint_WaitUntilReady();
297 bool IsOddByte
= (CurrentByte
& 0x01);
298 uint8_t ByteToWrite
= Endpoint_Read_Byte();
300 if (IsOddByte
&& (V2Command
== CMD_PROGRAM_FLASH_ISP
))
301 Write_Memory_Params
.ProgrammingCommands
[0] |= READ_WRITE_HIGH_BYTE_MASK
;
303 Write_Memory_Params
.ProgrammingCommands
[0] &= ~READ_WRITE_HIGH_BYTE_MASK
;
305 SPI_SendByte(Write_Memory_Params
.ProgrammingCommands
[0]);
306 SPI_SendByte(CurrentAddress
>> 8);
307 SPI_SendByte(CurrentAddress
& 0xFF);
308 SPI_SendByte(ByteToWrite
);
310 if (!(PollAddress
) && (ByteToWrite
!= PollValue
))
312 if (IsOddByte
&& (V2Command
== CMD_PROGRAM_FLASH_ISP
))
313 Write_Memory_Params
.ProgrammingCommands
[2] |= READ_WRITE_HIGH_BYTE_MASK
;
315 PollAddress
= (CurrentAddress
& 0xFFFF);
318 if (IsOddByte
|| (V2Command
== CMD_PROGRAM_EEPROM_ISP
))
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
)
325 SPI_SendByte(Write_Memory_Params
.ProgrammingCommands
[1]);
326 SPI_SendByte(StartAddress
>> 8);
327 SPI_SendByte(StartAddress
& 0xFF);
330 /* Check if polling is possible, if not switch to timed delay mode */
333 Write_Memory_Params
.ProgrammingMode
&= ~PROG_MODE_PAGED_VALUE_MASK
;
334 Write_Memory_Params
.ProgrammingMode
&= ~PROG_MODE_PAGED_TIMEDELAY_MASK
;
337 ProgrammingStatus
= V2Protocol_WaitForProgComplete(Write_Memory_Params
.ProgrammingMode
, PollAddress
, PollValue
,
338 Write_Memory_Params
.DelayMS
, Write_Memory_Params
.ProgrammingCommands
[2]);
343 /* Word/byte mode memory programming */
344 for (uint16_t CurrentByte
= 0; CurrentByte
< Write_Memory_Params
.BytesToWrite
; CurrentByte
++)
346 /* Check if the endpoint bank is currently empty */
347 if (!(Endpoint_IsReadWriteAllowed()))
350 Endpoint_WaitUntilReady();
353 bool IsOddByte
= (CurrentByte
& 0x01);
354 uint8_t ByteToWrite
= Endpoint_Read_Byte();
356 if (IsOddByte
&& (V2Command
== CMD_READ_FLASH_ISP
))
357 Write_Memory_Params
.ProgrammingCommands
[0] |= READ_WRITE_HIGH_BYTE_MASK
;
359 Write_Memory_Params
.ProgrammingCommands
[0] &= ~READ_WRITE_HIGH_BYTE_MASK
;
361 SPI_SendByte(Write_Memory_Params
.ProgrammingCommands
[0]);
362 SPI_SendByte(CurrentAddress
>> 8);
363 SPI_SendByte(CurrentAddress
& 0xFF);
364 SPI_SendByte(ByteToWrite
);
366 if (ByteToWrite
!= PollValue
)
368 if (IsOddByte
&& (V2Command
== CMD_PROGRAM_FLASH_ISP
))
369 Write_Memory_Params
.ProgrammingCommands
[2] |= READ_WRITE_HIGH_BYTE_MASK
;
371 PollAddress
= (CurrentAddress
& 0xFFFF);
374 if (IsOddByte
|| (V2Command
== CMD_PROGRAM_EEPROM_ISP
))
377 ProgrammingStatus
= V2Protocol_WaitForProgComplete(Write_Memory_Params
.ProgrammingMode
, PollAddress
, PollValue
,
378 Write_Memory_Params
.DelayMS
, Write_Memory_Params
.ProgrammingCommands
[2]);
380 if (ProgrammingStatus
!= STATUS_CMD_OK
)
386 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
388 Endpoint_Write_Byte(V2Command
);
389 Endpoint_Write_Byte(ProgrammingStatus
);
394 static void V2Protocol_Command_ReadMemory(uint8_t V2Command
)
398 uint16_t BytesToRead
;
399 uint8_t ReadMemoryCommand
;
400 } Read_Memory_Params
;
402 Endpoint_Read_Stream_LE(&Read_Memory_Params
, sizeof(Read_Memory_Params
));
403 Read_Memory_Params
.BytesToRead
= SwapEndian_16(Read_Memory_Params
.BytesToRead
);
406 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
408 Endpoint_Write_Byte(V2Command
);
409 Endpoint_Write_Byte(STATUS_CMD_OK
);
411 for (uint16_t CurrentByte
= 0; CurrentByte
< Read_Memory_Params
.BytesToRead
; CurrentByte
++)
413 bool IsOddByte
= (CurrentByte
& 0x01);
415 if (IsOddByte
&& (V2Command
== CMD_READ_FLASH_ISP
))
416 Read_Memory_Params
.ReadMemoryCommand
|= READ_WRITE_HIGH_BYTE_MASK
;
418 Read_Memory_Params
.ReadMemoryCommand
&= ~READ_WRITE_HIGH_BYTE_MASK
;
420 SPI_SendByte(Read_Memory_Params
.ReadMemoryCommand
);
421 SPI_SendByte(CurrentAddress
>> 8);
422 SPI_SendByte(CurrentAddress
& 0xFF);
423 Endpoint_Write_Byte(SPI_ReceiveByte());
425 /* Check if the endpoint bank is currently full */
426 if (!(Endpoint_IsReadWriteAllowed()))
429 Endpoint_WaitUntilReady();
432 if ((IsOddByte
&& (V2Command
== CMD_READ_FLASH_ISP
)) || (V2Command
== CMD_READ_EEPROM_ISP
))
436 Endpoint_Write_Byte(STATUS_CMD_OK
);
438 bool IsEndpointFull
= !(Endpoint_IsReadWriteAllowed());
441 /* Ensure last packet is a short packet to terminate the transfer */
444 Endpoint_WaitUntilReady();
446 Endpoint_WaitUntilReady();
450 static void V2Protocol_Command_ChipErase(void)
454 uint8_t EraseDelayMS
;
456 uint8_t EraseCommandBytes
[4];
459 Endpoint_Read_Stream_LE(&Erase_Chip_Params
, sizeof(Erase_Chip_Params
));
462 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
464 uint8_t ResponseStatus
= STATUS_CMD_OK
;
466 for (uint8_t SByte
= 0; SByte
< sizeof(Erase_Chip_Params
.EraseCommandBytes
); SByte
++)
467 SPI_SendByte(Erase_Chip_Params
.EraseCommandBytes
[SByte
]);
469 if (!(Erase_Chip_Params
.PollMethod
))
470 V2Protocol_DelayMS(Erase_Chip_Params
.EraseDelayMS
);
472 ResponseStatus
= V2Protocol_WaitWhileTargetBusy();
474 Endpoint_Write_Byte(CMD_CHIP_ERASE_ISP
);
475 Endpoint_Write_Byte(ResponseStatus
);
479 static void V2Protocol_Command_ReadFuseLockSigOSCCAL(uint8_t V2Command
)
484 uint8_t ReadCommandBytes
[4];
485 } Read_FuseLockSigOSCCAL_Params
;
487 Endpoint_Read_Stream_LE(&Read_FuseLockSigOSCCAL_Params
, sizeof(Read_FuseLockSigOSCCAL_Params
));
490 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
492 uint8_t ResponseBytes
[4];
494 for (uint8_t RByte
= 0; RByte
< sizeof(ResponseBytes
); RByte
++)
495 ResponseBytes
[RByte
] = SPI_TransferByte(Read_FuseLockSigOSCCAL_Params
.ReadCommandBytes
[RByte
]);
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
);
504 static void V2Protocol_Command_WriteFuseLock(uint8_t V2Command
)
508 uint8_t WriteCommandBytes
[4];
509 } Write_FuseLockSig_Params
;
511 Endpoint_Read_Stream_LE(&Write_FuseLockSig_Params
, sizeof(Write_FuseLockSig_Params
));
514 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
516 for (uint8_t SByte
= 0; SByte
< sizeof(Write_FuseLockSig_Params
.WriteCommandBytes
); SByte
++)
517 SPI_SendByte(Write_FuseLockSig_Params
.WriteCommandBytes
[SByte
]);
519 Endpoint_Write_Byte(V2Command
);
520 Endpoint_Write_Byte(STATUS_CMD_OK
);
521 Endpoint_Write_Byte(STATUS_CMD_OK
);
525 static void V2Protocol_Command_SPIMulti(void)
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
);
540 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
542 Endpoint_Write_Byte(CMD_SPI_MULTI
);
543 Endpoint_Write_Byte(STATUS_CMD_OK
);
545 uint8_t CurrTxPos
= 0;
546 uint8_t CurrRxPos
= 0;
548 /* Write out bytes to transmit until the start of the bytes to receive is met */
549 while (CurrTxPos
< SPI_Multi_Params
.RxStartAddr
)
551 if (CurrTxPos
< SPI_Multi_Params
.TxBytes
)
552 SPI_SendByte(SPI_Multi_Params
.TxData
[CurrTxPos
]);
559 /* Transmit remaining bytes with padding as needed, read in response bytes */
560 while (CurrRxPos
< SPI_Multi_Params
.RxBytes
)
562 if (CurrTxPos
< SPI_Multi_Params
.TxBytes
)
563 Endpoint_Write_Byte(SPI_TransferByte(SPI_Multi_Params
.TxData
[CurrTxPos
++]));
565 Endpoint_Write_Byte(SPI_ReceiveByte());
570 Endpoint_Write_Byte(STATUS_CMD_OK
);