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();
52 case CMD_SET_PARAMETER
:
53 case CMD_GET_PARAMETER
:
54 V2Protocol_GetSetParam(V2Command
);
56 case CMD_LOAD_ADDRESS
:
57 V2Protocol_LoadAddress();
59 case CMD_RESET_PROTECTION
:
60 V2Protocol_ResetProtection();
62 case CMD_ENTER_PROGMODE_ISP
:
63 V2Protocol_ISP_EnterISPMode();
65 case CMD_LEAVE_PROGMODE_ISP
:
66 V2Protocol_ISP_LeaveISPMode();
68 case CMD_PROGRAM_FLASH_ISP
:
69 case CMD_PROGRAM_EEPROM_ISP
:
70 V2Protocol_ISP_ProgramMemory(V2Command
);
72 case CMD_READ_FLASH_ISP
:
73 case CMD_READ_EEPROM_ISP
:
74 V2Protocol_ISP_ReadMemory(V2Command
);
76 case CMD_CHIP_ERASE_ISP
:
77 V2Protocol_ISP_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_ISP_ReadFuseLockSigOSCCAL(V2Command
);
85 case CMD_PROGRAM_FUSE_ISP
:
86 case CMD_PROGRAM_LOCK_ISP
:
87 V2Protocol_ISP_WriteFuseLock(V2Command
);
90 V2Protocol_ISP_SPIMulti();
93 V2Protocol_UnknownCommand(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_UnknownCommand(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_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_RESET_PROTECTION command, currently implemented as a dummy ACK function
137 * as no ISP short-circuit protection is currently implemented.
139 static void V2Protocol_ResetProtection(void)
142 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
144 Endpoint_Write_Byte(CMD_RESET_PROTECTION
);
145 Endpoint_Write_Byte(STATUS_CMD_OK
);
150 /** Handler for the CMD_SET_PARAMETER and CMD_GET_PARAMETER commands from the host, setting or
151 * getting a device parameter's value from the parameter table.
153 * \param[in] V2Command Issued V2 Protocol command byte from the host
155 static void V2Protocol_GetSetParam(uint8_t V2Command
)
157 uint8_t ParamID
= Endpoint_Read_Byte();
160 if (V2Command
== CMD_SET_PARAMETER
)
161 ParamValue
= Endpoint_Read_Byte();
164 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
166 Endpoint_Write_Byte(V2Command
);
168 uint8_t ParamPrivs
= V2Params_GetParameterPrivileges(ParamID
);
170 if ((V2Command
== CMD_SET_PARAMETER
) && (ParamPrivs
& PARAM_PRIV_WRITE
))
172 Endpoint_Write_Byte(STATUS_CMD_OK
);
173 V2Params_SetParameterValue(ParamID
, ParamValue
);
175 else if ((V2Command
== CMD_GET_PARAMETER
) && (ParamPrivs
& PARAM_PRIV_READ
))
177 Endpoint_Write_Byte(STATUS_CMD_OK
);
178 Endpoint_Write_Byte(V2Params_GetParameterValue(ParamID
));
182 Endpoint_Write_Byte(STATUS_CMD_FAILED
);
188 /** Handler for the CMD_LOAD_ADDRESS command, loading the given device address into a
189 * global storage variable for later use, and issuing LOAD EXTENDED ADDRESS commands
190 * to the attached device as required.
192 static void V2Protocol_LoadAddress(void)
194 Endpoint_Read_Stream_BE(&CurrentAddress
, sizeof(CurrentAddress
));
197 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
199 if (CurrentAddress
& (1UL << 31))
200 V2Protocol_LoadExtendedAddress();
202 Endpoint_Write_Byte(CMD_LOAD_ADDRESS
);
203 Endpoint_Write_Byte(STATUS_CMD_OK
);
207 /** Handler for the CMD_ENTER_PROGMODE_ISP command, which attempts to enter programming mode on
208 * the attached device, returning success or failure back to the host.
210 static void V2Protocol_ISP_EnterISPMode(void)
215 uint8_t PinStabDelayMS
;
216 uint8_t ExecutionDelayMS
;
221 uint8_t EnterProgBytes
[4];
224 Endpoint_Read_Stream_LE(&Enter_ISP_Params
, sizeof(Enter_ISP_Params
));
227 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
229 uint8_t ResponseStatus
= STATUS_CMD_FAILED
;
233 V2Protocol_DelayMS(Enter_ISP_Params
.ExecutionDelayMS
);
234 SPI_Init(V2Protocol_GetSPIPrescalerMask() | SPI_SCK_LEAD_RISING
| SPI_SAMPLE_LEADING
| SPI_MODE_MASTER
);
236 while (Enter_ISP_Params
.SynchLoops
-- && (ResponseStatus
== STATUS_CMD_FAILED
))
238 uint8_t ResponseBytes
[4];
240 V2Protocol_ChangeTargetResetLine(true);
241 V2Protocol_DelayMS(Enter_ISP_Params
.PinStabDelayMS
);
243 for (uint8_t RByte
= 0; RByte
< sizeof(ResponseBytes
); RByte
++)
245 V2Protocol_DelayMS(Enter_ISP_Params
.ByteDelay
);
246 ResponseBytes
[RByte
] = SPI_TransferByte(Enter_ISP_Params
.EnterProgBytes
[RByte
]);
249 /* Check if polling disabled, or if the polled value matches the expected value */
250 if (!(Enter_ISP_Params
.PollIndex
) || (ResponseBytes
[Enter_ISP_Params
.PollIndex
- 1] == Enter_ISP_Params
.PollValue
))
252 ResponseStatus
= STATUS_CMD_OK
;
256 V2Protocol_ChangeTargetResetLine(false);
257 V2Protocol_DelayMS(Enter_ISP_Params
.PinStabDelayMS
);
261 Endpoint_Write_Byte(CMD_ENTER_PROGMODE_ISP
);
262 Endpoint_Write_Byte(ResponseStatus
);
266 /** Handler for the CMD_LEAVE_ISP command, which releases the target from programming mode. */
267 static void V2Protocol_ISP_LeaveISPMode(void)
275 Endpoint_Read_Stream_LE(&Leave_ISP_Params
, sizeof(Leave_ISP_Params
));
278 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
280 V2Protocol_DelayMS(Leave_ISP_Params
.PreDelayMS
);
281 V2Protocol_ChangeTargetResetLine(false);
283 V2Protocol_DelayMS(Leave_ISP_Params
.PostDelayMS
);
285 Endpoint_Write_Byte(CMD_LEAVE_PROGMODE_ISP
);
286 Endpoint_Write_Byte(STATUS_CMD_OK
);
290 /** Handler for the CMD_PROGRAM_FLASH_ISP and CMD_PROGRAM_EEPROM_ISP commands, writing out bytes,
291 * words or pages of data to the attached device.
293 * \param[in] V2Command Issued V2 Protocol command byte from the host
295 static void V2Protocol_ISP_ProgramMemory(uint8_t V2Command
)
299 uint16_t BytesToWrite
;
300 uint8_t ProgrammingMode
;
302 uint8_t ProgrammingCommands
[3];
305 uint8_t ProgData
[256]; // Note, the Jungo driver has a very short ACK timeout period, need to buffer the
306 } Write_Memory_Params
; // whole page and ACK the packet as fast as possible to prevent it from aborting
308 Endpoint_Read_Stream_LE(&Write_Memory_Params
, sizeof(Write_Memory_Params
) - sizeof(Write_Memory_Params
.ProgData
));
309 Write_Memory_Params
.BytesToWrite
= SwapEndian_16(Write_Memory_Params
.BytesToWrite
);
311 if (Write_Memory_Params
.BytesToWrite
> sizeof(Write_Memory_Params
.ProgData
))
314 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
316 Endpoint_Write_Byte(V2Command
);
317 Endpoint_Write_Byte(STATUS_CMD_FAILED
);
322 Endpoint_Read_Stream_LE(&Write_Memory_Params
.ProgData
, Write_Memory_Params
.BytesToWrite
);
325 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
327 uint8_t ProgrammingStatus
= STATUS_CMD_OK
;
328 uint16_t PollAddress
= 0;
329 uint8_t PollValue
= (V2Command
== CMD_PROGRAM_FLASH_ISP
) ? Write_Memory_Params
.PollValue1
:
330 Write_Memory_Params
.PollValue2
;
331 uint8_t* NextWriteByte
= Write_Memory_Params
.ProgData
;
333 if (Write_Memory_Params
.ProgrammingMode
& PROG_MODE_PAGED_WRITES_MASK
)
335 uint16_t StartAddress
= (CurrentAddress
& 0xFFFF);
337 /* Paged mode memory programming */
338 for (uint16_t CurrentByte
= 0; CurrentByte
< Write_Memory_Params
.BytesToWrite
; CurrentByte
++)
340 bool IsOddByte
= (CurrentByte
& 0x01);
341 uint8_t ByteToWrite
= *(NextWriteByte
++);
343 if (IsOddByte
&& (V2Command
== CMD_PROGRAM_FLASH_ISP
))
344 Write_Memory_Params
.ProgrammingCommands
[0] |= READ_WRITE_HIGH_BYTE_MASK
;
346 Write_Memory_Params
.ProgrammingCommands
[0] &= ~READ_WRITE_HIGH_BYTE_MASK
;
348 SPI_SendByte(Write_Memory_Params
.ProgrammingCommands
[0]);
349 SPI_SendByte(CurrentAddress
>> 8);
350 SPI_SendByte(CurrentAddress
& 0xFF);
351 SPI_SendByte(ByteToWrite
);
353 if (!(PollAddress
) && (ByteToWrite
!= PollValue
))
355 if (IsOddByte
&& (V2Command
== CMD_PROGRAM_FLASH_ISP
))
356 Write_Memory_Params
.ProgrammingCommands
[2] |= READ_WRITE_HIGH_BYTE_MASK
;
358 PollAddress
= (CurrentAddress
& 0xFFFF);
361 if (IsOddByte
|| (V2Command
== CMD_PROGRAM_EEPROM_ISP
))
365 /* If the current page must be committed, send the PROGRAM PAGE command to the target */
366 if (Write_Memory_Params
.ProgrammingMode
& PROG_MODE_COMMIT_PAGE_MASK
)
368 SPI_SendByte(Write_Memory_Params
.ProgrammingCommands
[1]);
369 SPI_SendByte(StartAddress
>> 8);
370 SPI_SendByte(StartAddress
& 0xFF);
373 /* Check if polling is possible, if not switch to timed delay mode */
376 Write_Memory_Params
.ProgrammingMode
&= ~PROG_MODE_PAGED_VALUE_MASK
;
377 Write_Memory_Params
.ProgrammingMode
|= PROG_MODE_PAGED_TIMEDELAY_MASK
;
380 ProgrammingStatus
= V2Protocol_WaitForProgComplete(Write_Memory_Params
.ProgrammingMode
, PollAddress
, PollValue
,
381 Write_Memory_Params
.DelayMS
, Write_Memory_Params
.ProgrammingCommands
[2]);
386 /* Word/byte mode memory programming */
387 for (uint16_t CurrentByte
= 0; CurrentByte
< Write_Memory_Params
.BytesToWrite
; CurrentByte
++)
389 bool IsOddByte
= (CurrentByte
& 0x01);
390 uint8_t ByteToWrite
= *(NextWriteByte
++);
392 if (IsOddByte
&& (V2Command
== CMD_READ_FLASH_ISP
))
393 Write_Memory_Params
.ProgrammingCommands
[0] |= READ_WRITE_HIGH_BYTE_MASK
;
395 Write_Memory_Params
.ProgrammingCommands
[0] &= ~READ_WRITE_HIGH_BYTE_MASK
;
397 SPI_SendByte(Write_Memory_Params
.ProgrammingCommands
[0]);
398 SPI_SendByte(CurrentAddress
>> 8);
399 SPI_SendByte(CurrentAddress
& 0xFF);
400 SPI_SendByte(ByteToWrite
);
402 if (ByteToWrite
!= PollValue
)
404 if (IsOddByte
&& (V2Command
== CMD_PROGRAM_FLASH_ISP
))
405 Write_Memory_Params
.ProgrammingCommands
[2] |= READ_WRITE_HIGH_BYTE_MASK
;
407 PollAddress
= (CurrentAddress
& 0xFFFF);
410 if (IsOddByte
|| (V2Command
== CMD_PROGRAM_EEPROM_ISP
))
413 ProgrammingStatus
= V2Protocol_WaitForProgComplete(Write_Memory_Params
.ProgrammingMode
, PollAddress
, PollValue
,
414 Write_Memory_Params
.DelayMS
, Write_Memory_Params
.ProgrammingCommands
[2]);
416 if (ProgrammingStatus
!= STATUS_CMD_OK
)
421 Endpoint_Write_Byte(V2Command
);
422 Endpoint_Write_Byte(ProgrammingStatus
);
426 /** Handler for the CMD_READ_FLASH_ISP and CMD_READ_EEPROM_ISP commands, reading in bytes,
427 * words or pages of data from the attached device.
429 * \param[in] V2Command Issued V2 Protocol command byte from the host
431 static void V2Protocol_ISP_ReadMemory(uint8_t V2Command
)
435 uint16_t BytesToRead
;
436 uint8_t ReadMemoryCommand
;
437 } Read_Memory_Params
;
439 Endpoint_Read_Stream_LE(&Read_Memory_Params
, sizeof(Read_Memory_Params
));
440 Read_Memory_Params
.BytesToRead
= SwapEndian_16(Read_Memory_Params
.BytesToRead
);
443 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
445 Endpoint_Write_Byte(V2Command
);
446 Endpoint_Write_Byte(STATUS_CMD_OK
);
448 for (uint16_t CurrentByte
= 0; CurrentByte
< Read_Memory_Params
.BytesToRead
; CurrentByte
++)
450 bool IsOddByte
= (CurrentByte
& 0x01);
452 if (IsOddByte
&& (V2Command
== CMD_READ_FLASH_ISP
))
453 Read_Memory_Params
.ReadMemoryCommand
|= READ_WRITE_HIGH_BYTE_MASK
;
455 Read_Memory_Params
.ReadMemoryCommand
&= ~READ_WRITE_HIGH_BYTE_MASK
;
457 SPI_SendByte(Read_Memory_Params
.ReadMemoryCommand
);
458 SPI_SendByte(CurrentAddress
>> 8);
459 SPI_SendByte(CurrentAddress
& 0xFF);
460 Endpoint_Write_Byte(SPI_ReceiveByte());
462 /* Check if the endpoint bank is currently full */
463 if (!(Endpoint_IsReadWriteAllowed()))
466 Endpoint_WaitUntilReady();
469 if ((IsOddByte
&& (V2Command
== CMD_READ_FLASH_ISP
)) || (V2Command
== CMD_READ_EEPROM_ISP
))
473 Endpoint_Write_Byte(STATUS_CMD_OK
);
475 bool IsEndpointFull
= !(Endpoint_IsReadWriteAllowed());
478 /* Ensure last packet is a short packet to terminate the transfer */
481 Endpoint_WaitUntilReady();
483 Endpoint_WaitUntilReady();
487 /** Handler for the CMD_CHI_ERASE_ISP command, clearing the target's FLASH memory. */
488 static void V2Protocol_ISP_ChipErase(void)
492 uint8_t EraseDelayMS
;
494 uint8_t EraseCommandBytes
[4];
497 Endpoint_Read_Stream_LE(&Erase_Chip_Params
, sizeof(Erase_Chip_Params
));
500 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
502 uint8_t ResponseStatus
= STATUS_CMD_OK
;
504 for (uint8_t SByte
= 0; SByte
< sizeof(Erase_Chip_Params
.EraseCommandBytes
); SByte
++)
505 SPI_SendByte(Erase_Chip_Params
.EraseCommandBytes
[SByte
]);
507 if (!(Erase_Chip_Params
.PollMethod
))
508 V2Protocol_DelayMS(Erase_Chip_Params
.EraseDelayMS
);
510 ResponseStatus
= V2Protocol_WaitWhileTargetBusy();
512 Endpoint_Write_Byte(CMD_CHIP_ERASE_ISP
);
513 Endpoint_Write_Byte(ResponseStatus
);
517 /** Handler for the CMD_READ_FUSE_ISP, CMD_READ_LOCK_ISP, CMD_READ_SIGNATURE_ISP and CMD_READ_OSCCAL commands,
518 * reading the requested configuration byte from the device.
520 * \param[in] V2Command Issued V2 Protocol command byte from the host
522 static void V2Protocol_ISP_ReadFuseLockSigOSCCAL(uint8_t V2Command
)
527 uint8_t ReadCommandBytes
[4];
528 } Read_FuseLockSigOSCCAL_Params
;
530 Endpoint_Read_Stream_LE(&Read_FuseLockSigOSCCAL_Params
, sizeof(Read_FuseLockSigOSCCAL_Params
));
533 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
535 uint8_t ResponseBytes
[4];
537 for (uint8_t RByte
= 0; RByte
< sizeof(ResponseBytes
); RByte
++)
538 ResponseBytes
[RByte
] = SPI_TransferByte(Read_FuseLockSigOSCCAL_Params
.ReadCommandBytes
[RByte
]);
540 Endpoint_Write_Byte(V2Command
);
541 Endpoint_Write_Byte(STATUS_CMD_OK
);
542 Endpoint_Write_Byte(ResponseBytes
[Read_FuseLockSigOSCCAL_Params
.RetByte
- 1]);
543 Endpoint_Write_Byte(STATUS_CMD_OK
);
547 /** Handler for the CMD_WRITE_FUSE_ISP and CMD_WRITE_LOCK_ISP commands, writing the requested configuration
548 * byte to the device.
550 * \param[in] V2Command Issued V2 Protocol command byte from the host
552 static void V2Protocol_ISP_WriteFuseLock(uint8_t V2Command
)
556 uint8_t WriteCommandBytes
[4];
557 } Write_FuseLockSig_Params
;
559 Endpoint_Read_Stream_LE(&Write_FuseLockSig_Params
, sizeof(Write_FuseLockSig_Params
));
562 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
564 for (uint8_t SByte
= 0; SByte
< sizeof(Write_FuseLockSig_Params
.WriteCommandBytes
); SByte
++)
565 SPI_SendByte(Write_FuseLockSig_Params
.WriteCommandBytes
[SByte
]);
567 Endpoint_Write_Byte(V2Command
);
568 Endpoint_Write_Byte(STATUS_CMD_OK
);
569 Endpoint_Write_Byte(STATUS_CMD_OK
);
573 /** Handler for the CMD_SPI_MULTI command, writing and reading arbitrary SPI data to and from the attached device. */
574 static void V2Protocol_ISP_SPIMulti(void)
584 Endpoint_Read_Stream_LE(&SPI_Multi_Params
, sizeof(SPI_Multi_Params
) - sizeof(SPI_Multi_Params
.TxData
));
585 Endpoint_Read_Stream_LE(&SPI_Multi_Params
.TxData
, SPI_Multi_Params
.TxBytes
);
588 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
590 Endpoint_Write_Byte(CMD_SPI_MULTI
);
591 Endpoint_Write_Byte(STATUS_CMD_OK
);
593 uint8_t CurrTxPos
= 0;
594 uint8_t CurrRxPos
= 0;
596 /* Write out bytes to transmit until the start of the bytes to receive is met */
597 while (CurrTxPos
< SPI_Multi_Params
.RxStartAddr
)
599 if (CurrTxPos
< SPI_Multi_Params
.TxBytes
)
600 SPI_SendByte(SPI_Multi_Params
.TxData
[CurrTxPos
]);
607 /* Transmit remaining bytes with padding as needed, read in response bytes */
608 while (CurrRxPos
< SPI_Multi_Params
.RxBytes
)
610 if (CurrTxPos
< SPI_Multi_Params
.TxBytes
)
611 Endpoint_Write_Byte(SPI_TransferByte(SPI_Multi_Params
.TxData
[CurrTxPos
++]));
613 Endpoint_Write_Byte(SPI_ReceiveByte());
618 Endpoint_Write_Byte(STATUS_CMD_OK
);