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 /** Master V2 Protocol packet handler, for received V2 Protocol packets from a connected host.
40 * This routine decodes the issued command and passes off the handling of the command to the
41 * appropriate function.
43 void V2Protocol_ProcessCommand(void)
45 uint8_t V2Command
= Endpoint_Read_Byte();
50 V2Protocol_Command_SignOn();
52 case CMD_SET_PARAMETER
:
53 case CMD_GET_PARAMETER
:
54 V2Protocol_Command_GetSetParam(V2Command
);
56 case CMD_LOAD_ADDRESS
:
57 V2Protocol_Command_LoadAddress();
59 case CMD_RESET_PROTECTION
:
60 V2Protocol_Command_ResetProtection();
62 case CMD_ENTER_PROGMODE_ISP
:
63 V2Protocol_Command_EnterISPMode();
65 case CMD_LEAVE_PROGMODE_ISP
:
66 V2Protocol_Command_LeaveISPMode();
68 case CMD_PROGRAM_FLASH_ISP
:
69 case CMD_PROGRAM_EEPROM_ISP
:
70 V2Protocol_Command_ProgramMemory(V2Command
);
72 case CMD_READ_FLASH_ISP
:
73 case CMD_READ_EEPROM_ISP
:
74 V2Protocol_Command_ReadMemory(V2Command
);
76 case CMD_CHIP_ERASE_ISP
:
77 V2Protocol_Command_ChipErase();
79 case CMD_READ_FUSE_ISP
:
80 case CMD_READ_LOCK_ISP
:
81 case CMD_READ_SIGNATURE_ISP
:
82 case CMD_READ_OSCCAL_ISP
:
83 V2Protocol_Command_ReadFuseLockSigOSCCAL(V2Command
);
85 case CMD_PROGRAM_FUSE_ISP
:
86 case CMD_PROGRAM_LOCK_ISP
:
87 V2Protocol_Command_WriteFuseLock(V2Command
);
90 V2Protocol_Command_SPIMulti();
93 V2Protocol_Command_Unknown(V2Command
);
97 Endpoint_WaitUntilReady();
98 Endpoint_SetEndpointDirection(ENDPOINT_DIR_OUT
);
101 /** Handler for unknown V2 protocol commands. This discards all sent data and returns a
102 * STATUS_CMD_UNKNOWN status back to the host.
104 * \param[in] V2Command Issued V2 Protocol command byte from the host
106 static void V2Protocol_Command_Unknown(uint8_t V2Command
)
108 /* Discard all incoming data */
109 while (Endpoint_BytesInEndpoint() == AVRISP_DATA_EPSIZE
)
112 Endpoint_WaitUntilReady();
116 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
118 Endpoint_Write_Byte(V2Command
);
119 Endpoint_Write_Byte(STATUS_CMD_UNKNOWN
);
123 /** Handler for the CMD_SIGN_ON command, returning the programmer ID string to the host. */
124 static void V2Protocol_Command_SignOn(void)
127 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
129 Endpoint_Write_Byte(CMD_SIGN_ON
);
130 Endpoint_Write_Byte(STATUS_CMD_OK
);
131 Endpoint_Write_Byte(sizeof(PROGRAMMER_ID
) - 1);
132 Endpoint_Write_Stream_LE(PROGRAMMER_ID
, (sizeof(PROGRAMMER_ID
) - 1));
136 /** Handler for the CMD_SET_PARAMETER and CMD_GET_PARAMETER commands from the host, setting or
137 * getting a device parameter's value from the parameter table.
139 * \param[in] V2Command Issued V2 Protocol command byte from the host
141 static void V2Protocol_Command_GetSetParam(uint8_t V2Command
)
143 uint8_t ParamID
= Endpoint_Read_Byte();
146 if (V2Command
== CMD_SET_PARAMETER
)
147 ParamValue
= Endpoint_Read_Byte();
150 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
152 Endpoint_Write_Byte(V2Command
);
154 uint8_t ParamPrivs
= V2Params_GetParameterPrivileges(ParamID
);
156 if ((V2Command
== CMD_SET_PARAMETER
) && (ParamPrivs
& PARAM_PRIV_WRITE
))
158 Endpoint_Write_Byte(STATUS_CMD_OK
);
159 V2Params_SetParameterValue(ParamID
, ParamValue
);
161 else if ((V2Command
== CMD_GET_PARAMETER
) && (ParamPrivs
& PARAM_PRIV_READ
))
163 Endpoint_Write_Byte(STATUS_CMD_OK
);
164 Endpoint_Write_Byte(V2Params_GetParameterValue(ParamID
));
168 Endpoint_Write_Byte(STATUS_CMD_FAILED
);
174 /** Handler for the CMD_LOAD_ADDRESS command, loading the given device address into a
175 * global storage variable for later use, and issuing LOAD EXTENDED ADDRESS commands
176 * to the attached device as required.
178 static void V2Protocol_Command_LoadAddress(void)
180 Endpoint_Read_Stream_BE(&CurrentAddress
, sizeof(CurrentAddress
));
183 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
185 if (CurrentAddress
& (1UL << 31))
186 V2Protocol_LoadExtendedAddress();
188 Endpoint_Write_Byte(CMD_LOAD_ADDRESS
);
189 Endpoint_Write_Byte(STATUS_CMD_OK
);
193 /** Handler for the CMD_RESET_PROTECTION command, currently implemented as a dummy ACK function
194 * as no ISP short-circuit protection is currently implemented.
196 static void V2Protocol_Command_ResetProtection(void)
199 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
201 Endpoint_Write_Byte(CMD_RESET_PROTECTION
);
202 Endpoint_Write_Byte(STATUS_CMD_OK
);
206 /** Handler for the CMD_ENTER_PROGMODE_ISP command, which attempts to enter programming mode on
207 * the attached device, returning success or failure back to the host.
209 static void V2Protocol_Command_EnterISPMode(void)
214 uint8_t PinStabDelayMS
;
215 uint8_t ExecutionDelayMS
;
220 uint8_t EnterProgBytes
[4];
223 Endpoint_Read_Stream_LE(&Enter_ISP_Params
, sizeof(Enter_ISP_Params
));
226 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
228 uint8_t ResponseStatus
= STATUS_CMD_FAILED
;
232 V2Protocol_DelayMS(Enter_ISP_Params
.ExecutionDelayMS
);
233 SPI_Init(V2Protocol_GetSPIPrescalerMask() | SPI_SCK_LEAD_RISING
| SPI_SAMPLE_LEADING
| SPI_MODE_MASTER
);
235 while (Enter_ISP_Params
.SynchLoops
-- && (ResponseStatus
== STATUS_CMD_FAILED
))
237 uint8_t ResponseBytes
[4];
239 V2Protocol_ChangeTargetResetLine(true);
240 V2Protocol_DelayMS(Enter_ISP_Params
.PinStabDelayMS
);
242 for (uint8_t RByte
= 0; RByte
< sizeof(ResponseBytes
); RByte
++)
244 V2Protocol_DelayMS(Enter_ISP_Params
.ByteDelay
);
245 ResponseBytes
[RByte
] = SPI_TransferByte(Enter_ISP_Params
.EnterProgBytes
[RByte
]);
248 /* Check if polling disabled, or if the polled value matches the expected value */
249 if (!(Enter_ISP_Params
.PollIndex
) || (ResponseBytes
[Enter_ISP_Params
.PollIndex
- 1] == Enter_ISP_Params
.PollValue
))
251 ResponseStatus
= STATUS_CMD_OK
;
255 V2Protocol_ChangeTargetResetLine(false);
256 V2Protocol_DelayMS(Enter_ISP_Params
.PinStabDelayMS
);
260 Endpoint_Write_Byte(CMD_ENTER_PROGMODE_ISP
);
261 Endpoint_Write_Byte(ResponseStatus
);
265 /** Handler for the CMD_LEAVE_ISP command, which releases the target from programming mode. */
266 static void V2Protocol_Command_LeaveISPMode(void)
274 Endpoint_Read_Stream_LE(&Leave_ISP_Params
, sizeof(Leave_ISP_Params
));
277 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
279 V2Protocol_DelayMS(Leave_ISP_Params
.PreDelayMS
);
280 V2Protocol_ChangeTargetResetLine(false);
282 V2Protocol_DelayMS(Leave_ISP_Params
.PostDelayMS
);
284 Endpoint_Write_Byte(CMD_LEAVE_PROGMODE_ISP
);
285 Endpoint_Write_Byte(STATUS_CMD_OK
);
289 /** Handler for the CMD_PROGRAM_FLASH_ISP and CMD_PROGRAM_EEPROM_ISP commands, writing out bytes,
290 * words or pages of data to the attached device.
292 * \param[in] V2Command Issued V2 Protocol command byte from the host
294 static void V2Protocol_Command_ProgramMemory(uint8_t V2Command
)
298 uint16_t BytesToWrite
;
299 uint8_t ProgrammingMode
;
301 uint8_t ProgrammingCommands
[3];
304 uint8_t ProgData
[256]; // Note, the Jungo driver has a very short ACK timeout period, need to buffer the
305 } Write_Memory_Params
; // whole page and ACK the packet as fast as possible to prevent it from aborting
307 Endpoint_Read_Stream_LE(&Write_Memory_Params
, sizeof(Write_Memory_Params
) - sizeof(Write_Memory_Params
.ProgData
));
308 Write_Memory_Params
.BytesToWrite
= SwapEndian_16(Write_Memory_Params
.BytesToWrite
);
310 if (Write_Memory_Params
.BytesToWrite
> sizeof(Write_Memory_Params
.ProgData
))
313 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
315 Endpoint_Write_Byte(V2Command
);
316 Endpoint_Write_Byte(STATUS_CMD_FAILED
);
321 Endpoint_Read_Stream_LE(&Write_Memory_Params
.ProgData
, Write_Memory_Params
.BytesToWrite
);
324 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
326 uint8_t ProgrammingStatus
= STATUS_CMD_OK
;
327 uint16_t PollAddress
= 0;
328 uint8_t PollValue
= (V2Command
== CMD_PROGRAM_FLASH_ISP
) ? Write_Memory_Params
.PollValue1
:
329 Write_Memory_Params
.PollValue2
;
330 uint8_t* NextWriteByte
= Write_Memory_Params
.ProgData
;
332 if (Write_Memory_Params
.ProgrammingMode
& PROG_MODE_PAGED_WRITES_MASK
)
334 uint16_t StartAddress
= (CurrentAddress
& 0xFFFF);
336 /* Paged mode memory programming */
337 for (uint16_t CurrentByte
= 0; CurrentByte
< Write_Memory_Params
.BytesToWrite
; CurrentByte
++)
339 bool IsOddByte
= (CurrentByte
& 0x01);
340 uint8_t ByteToWrite
= *(NextWriteByte
++);
342 if (IsOddByte
&& (V2Command
== CMD_PROGRAM_FLASH_ISP
))
343 Write_Memory_Params
.ProgrammingCommands
[0] |= READ_WRITE_HIGH_BYTE_MASK
;
345 Write_Memory_Params
.ProgrammingCommands
[0] &= ~READ_WRITE_HIGH_BYTE_MASK
;
347 SPI_SendByte(Write_Memory_Params
.ProgrammingCommands
[0]);
348 SPI_SendByte(CurrentAddress
>> 8);
349 SPI_SendByte(CurrentAddress
& 0xFF);
350 SPI_SendByte(ByteToWrite
);
352 if (!(PollAddress
) && (ByteToWrite
!= PollValue
))
354 if (IsOddByte
&& (V2Command
== CMD_PROGRAM_FLASH_ISP
))
355 Write_Memory_Params
.ProgrammingCommands
[2] |= READ_WRITE_HIGH_BYTE_MASK
;
357 PollAddress
= (CurrentAddress
& 0xFFFF);
360 if (IsOddByte
|| (V2Command
== CMD_PROGRAM_EEPROM_ISP
))
364 /* If the current page must be committed, send the PROGRAM PAGE command to the target */
365 if (Write_Memory_Params
.ProgrammingMode
& PROG_MODE_COMMIT_PAGE_MASK
)
367 SPI_SendByte(Write_Memory_Params
.ProgrammingCommands
[1]);
368 SPI_SendByte(StartAddress
>> 8);
369 SPI_SendByte(StartAddress
& 0xFF);
372 /* Check if polling is possible, if not switch to timed delay mode */
375 Write_Memory_Params
.ProgrammingMode
&= ~PROG_MODE_PAGED_VALUE_MASK
;
376 Write_Memory_Params
.ProgrammingMode
|= PROG_MODE_PAGED_TIMEDELAY_MASK
;
379 ProgrammingStatus
= V2Protocol_WaitForProgComplete(Write_Memory_Params
.ProgrammingMode
, PollAddress
, PollValue
,
380 Write_Memory_Params
.DelayMS
, Write_Memory_Params
.ProgrammingCommands
[2]);
385 /* Word/byte mode memory programming */
386 for (uint16_t CurrentByte
= 0; CurrentByte
< Write_Memory_Params
.BytesToWrite
; CurrentByte
++)
388 bool IsOddByte
= (CurrentByte
& 0x01);
389 uint8_t ByteToWrite
= *(NextWriteByte
++);
391 if (IsOddByte
&& (V2Command
== CMD_READ_FLASH_ISP
))
392 Write_Memory_Params
.ProgrammingCommands
[0] |= READ_WRITE_HIGH_BYTE_MASK
;
394 Write_Memory_Params
.ProgrammingCommands
[0] &= ~READ_WRITE_HIGH_BYTE_MASK
;
396 SPI_SendByte(Write_Memory_Params
.ProgrammingCommands
[0]);
397 SPI_SendByte(CurrentAddress
>> 8);
398 SPI_SendByte(CurrentAddress
& 0xFF);
399 SPI_SendByte(ByteToWrite
);
401 if (ByteToWrite
!= PollValue
)
403 if (IsOddByte
&& (V2Command
== CMD_PROGRAM_FLASH_ISP
))
404 Write_Memory_Params
.ProgrammingCommands
[2] |= READ_WRITE_HIGH_BYTE_MASK
;
406 PollAddress
= (CurrentAddress
& 0xFFFF);
409 if (IsOddByte
|| (V2Command
== CMD_PROGRAM_EEPROM_ISP
))
412 ProgrammingStatus
= V2Protocol_WaitForProgComplete(Write_Memory_Params
.ProgrammingMode
, PollAddress
, PollValue
,
413 Write_Memory_Params
.DelayMS
, Write_Memory_Params
.ProgrammingCommands
[2]);
415 if (ProgrammingStatus
!= STATUS_CMD_OK
)
420 Endpoint_Write_Byte(V2Command
);
421 Endpoint_Write_Byte(ProgrammingStatus
);
425 /** Handler for the CMD_READ_FLASH_ISP and CMD_READ_EEPROM_ISP commands, reading in bytes,
426 * words or pages of data from the attached device.
428 * \param[in] V2Command Issued V2 Protocol command byte from the host
430 static void V2Protocol_Command_ReadMemory(uint8_t V2Command
)
434 uint16_t BytesToRead
;
435 uint8_t ReadMemoryCommand
;
436 } Read_Memory_Params
;
438 Endpoint_Read_Stream_LE(&Read_Memory_Params
, sizeof(Read_Memory_Params
));
439 Read_Memory_Params
.BytesToRead
= SwapEndian_16(Read_Memory_Params
.BytesToRead
);
442 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
444 Endpoint_Write_Byte(V2Command
);
445 Endpoint_Write_Byte(STATUS_CMD_OK
);
447 for (uint16_t CurrentByte
= 0; CurrentByte
< Read_Memory_Params
.BytesToRead
; CurrentByte
++)
449 bool IsOddByte
= (CurrentByte
& 0x01);
451 if (IsOddByte
&& (V2Command
== CMD_READ_FLASH_ISP
))
452 Read_Memory_Params
.ReadMemoryCommand
|= READ_WRITE_HIGH_BYTE_MASK
;
454 Read_Memory_Params
.ReadMemoryCommand
&= ~READ_WRITE_HIGH_BYTE_MASK
;
456 SPI_SendByte(Read_Memory_Params
.ReadMemoryCommand
);
457 SPI_SendByte(CurrentAddress
>> 8);
458 SPI_SendByte(CurrentAddress
& 0xFF);
459 Endpoint_Write_Byte(SPI_ReceiveByte());
461 /* Check if the endpoint bank is currently full */
462 if (!(Endpoint_IsReadWriteAllowed()))
465 Endpoint_WaitUntilReady();
468 if ((IsOddByte
&& (V2Command
== CMD_READ_FLASH_ISP
)) || (V2Command
== CMD_READ_EEPROM_ISP
))
472 Endpoint_Write_Byte(STATUS_CMD_OK
);
474 bool IsEndpointFull
= !(Endpoint_IsReadWriteAllowed());
477 /* Ensure last packet is a short packet to terminate the transfer */
480 Endpoint_WaitUntilReady();
482 Endpoint_WaitUntilReady();
486 /** Handler for the CMD_CHI_ERASE_ISP command, clearing the target's FLASH memory. */
487 static void V2Protocol_Command_ChipErase(void)
491 uint8_t EraseDelayMS
;
493 uint8_t EraseCommandBytes
[4];
496 Endpoint_Read_Stream_LE(&Erase_Chip_Params
, sizeof(Erase_Chip_Params
));
499 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
501 uint8_t ResponseStatus
= STATUS_CMD_OK
;
503 for (uint8_t SByte
= 0; SByte
< sizeof(Erase_Chip_Params
.EraseCommandBytes
); SByte
++)
504 SPI_SendByte(Erase_Chip_Params
.EraseCommandBytes
[SByte
]);
506 if (!(Erase_Chip_Params
.PollMethod
))
507 V2Protocol_DelayMS(Erase_Chip_Params
.EraseDelayMS
);
509 ResponseStatus
= V2Protocol_WaitWhileTargetBusy();
511 Endpoint_Write_Byte(CMD_CHIP_ERASE_ISP
);
512 Endpoint_Write_Byte(ResponseStatus
);
516 /** Handler for the CMD_READ_FUSE_ISP, CMD_READ_LOCK_ISP, CMD_READ_SIGNATURE_ISP and CMD_READ_OSCCAL commands,
517 * reading the requested configuration byte from the device.
519 * \param[in] V2Command Issued V2 Protocol command byte from the host
521 static void V2Protocol_Command_ReadFuseLockSigOSCCAL(uint8_t V2Command
)
526 uint8_t ReadCommandBytes
[4];
527 } Read_FuseLockSigOSCCAL_Params
;
529 Endpoint_Read_Stream_LE(&Read_FuseLockSigOSCCAL_Params
, sizeof(Read_FuseLockSigOSCCAL_Params
));
532 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
534 uint8_t ResponseBytes
[4];
536 for (uint8_t RByte
= 0; RByte
< sizeof(ResponseBytes
); RByte
++)
537 ResponseBytes
[RByte
] = SPI_TransferByte(Read_FuseLockSigOSCCAL_Params
.ReadCommandBytes
[RByte
]);
539 Endpoint_Write_Byte(V2Command
);
540 Endpoint_Write_Byte(STATUS_CMD_OK
);
541 Endpoint_Write_Byte(ResponseBytes
[Read_FuseLockSigOSCCAL_Params
.RetByte
- 1]);
542 Endpoint_Write_Byte(STATUS_CMD_OK
);
546 /** Handler for the CMD_WRITE_FUSE_ISP and CMD_WRITE_LOCK_ISP commands, writing the requested configuration
547 * byte to the device.
549 * \param[in] V2Command Issued V2 Protocol command byte from the host
551 static void V2Protocol_Command_WriteFuseLock(uint8_t V2Command
)
555 uint8_t WriteCommandBytes
[4];
556 } Write_FuseLockSig_Params
;
558 Endpoint_Read_Stream_LE(&Write_FuseLockSig_Params
, sizeof(Write_FuseLockSig_Params
));
561 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
563 for (uint8_t SByte
= 0; SByte
< sizeof(Write_FuseLockSig_Params
.WriteCommandBytes
); SByte
++)
564 SPI_SendByte(Write_FuseLockSig_Params
.WriteCommandBytes
[SByte
]);
566 Endpoint_Write_Byte(V2Command
);
567 Endpoint_Write_Byte(STATUS_CMD_OK
);
568 Endpoint_Write_Byte(STATUS_CMD_OK
);
572 /** Handler for the CMD_SPI_MULTI command, writing and reading arbitrary SPI data to and from the attached device. */
573 static void V2Protocol_Command_SPIMulti(void)
583 Endpoint_Read_Stream_LE(&SPI_Multi_Params
, sizeof(SPI_Multi_Params
) - sizeof(SPI_Multi_Params
.TxData
));
584 Endpoint_Read_Stream_LE(&SPI_Multi_Params
.TxData
, SPI_Multi_Params
.TxBytes
);
587 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
589 Endpoint_Write_Byte(CMD_SPI_MULTI
);
590 Endpoint_Write_Byte(STATUS_CMD_OK
);
592 uint8_t CurrTxPos
= 0;
593 uint8_t CurrRxPos
= 0;
595 /* Write out bytes to transmit until the start of the bytes to receive is met */
596 while (CurrTxPos
< SPI_Multi_Params
.RxStartAddr
)
598 if (CurrTxPos
< SPI_Multi_Params
.TxBytes
)
599 SPI_SendByte(SPI_Multi_Params
.TxData
[CurrTxPos
]);
606 /* Transmit remaining bytes with padding as needed, read in response bytes */
607 while (CurrRxPos
< SPI_Multi_Params
.RxBytes
)
609 if (CurrTxPos
< SPI_Multi_Params
.TxBytes
)
610 Endpoint_Write_Byte(SPI_TransferByte(SPI_Multi_Params
.TxData
[CurrTxPos
++]));
612 Endpoint_Write_Byte(SPI_ReceiveByte());
617 Endpoint_Write_Byte(STATUS_CMD_OK
);