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 receieved 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 V2Command Issued V2 Protocol command byte from the host
106 static void V2Protocol_Command_Unknown(uint8_t V2Command
)
108 /* Discard all incomming 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 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_GetParameterPrivellages(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 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
[512];
305 } Write_Memory_Params
;
307 uint8_t* NextWriteByte
= Write_Memory_Params
.ProgData
;
309 Endpoint_Read_Stream_LE(&Write_Memory_Params
, sizeof(Write_Memory_Params
) - sizeof(Write_Memory_Params
.ProgData
));
310 Write_Memory_Params
.BytesToWrite
= SwapEndian_16(Write_Memory_Params
.BytesToWrite
);
311 Endpoint_Read_Stream_LE(&Write_Memory_Params
.ProgData
, Write_Memory_Params
.BytesToWrite
);
314 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
316 uint8_t ProgrammingStatus
= STATUS_CMD_OK
;
317 uint16_t PollAddress
= 0;
318 uint8_t PollValue
= (V2Command
== CMD_PROGRAM_FLASH_ISP
) ? Write_Memory_Params
.PollValue1
:
319 Write_Memory_Params
.PollValue2
;
320 if (Write_Memory_Params
.ProgrammingMode
& PROG_MODE_PAGED_WRITES_MASK
)
322 uint16_t StartAddress
= (CurrentAddress
& 0xFFFF);
324 /* Paged mode memory programming */
325 for (uint16_t CurrentByte
= 0; CurrentByte
< Write_Memory_Params
.BytesToWrite
; CurrentByte
++)
327 bool IsOddByte
= (CurrentByte
& 0x01);
328 uint8_t ByteToWrite
= *(NextWriteByte
++);
330 if (IsOddByte
&& (V2Command
== CMD_PROGRAM_FLASH_ISP
))
331 Write_Memory_Params
.ProgrammingCommands
[0] |= READ_WRITE_HIGH_BYTE_MASK
;
333 Write_Memory_Params
.ProgrammingCommands
[0] &= ~READ_WRITE_HIGH_BYTE_MASK
;
335 SPI_SendByte(Write_Memory_Params
.ProgrammingCommands
[0]);
336 SPI_SendByte(CurrentAddress
>> 8);
337 SPI_SendByte(CurrentAddress
& 0xFF);
338 SPI_SendByte(ByteToWrite
);
340 if (!(PollAddress
) && (ByteToWrite
!= PollValue
))
342 if (IsOddByte
&& (V2Command
== CMD_PROGRAM_FLASH_ISP
))
343 Write_Memory_Params
.ProgrammingCommands
[2] |= READ_WRITE_HIGH_BYTE_MASK
;
345 PollAddress
= (CurrentAddress
& 0xFFFF);
348 if (IsOddByte
|| (V2Command
== CMD_PROGRAM_EEPROM_ISP
))
352 /* If the current page must be committed, send the PROGRAM PAGE command to the target */
353 if (Write_Memory_Params
.ProgrammingMode
& PROG_MODE_COMMIT_PAGE_MASK
)
355 SPI_SendByte(Write_Memory_Params
.ProgrammingCommands
[1]);
356 SPI_SendByte(StartAddress
>> 8);
357 SPI_SendByte(StartAddress
& 0xFF);
360 /* Check if polling is possible, if not switch to timed delay mode */
363 Write_Memory_Params
.ProgrammingMode
&= ~PROG_MODE_PAGED_VALUE_MASK
;
364 Write_Memory_Params
.ProgrammingMode
|= PROG_MODE_PAGED_TIMEDELAY_MASK
;
367 ProgrammingStatus
= V2Protocol_WaitForProgComplete(Write_Memory_Params
.ProgrammingMode
, PollAddress
, PollValue
,
368 Write_Memory_Params
.DelayMS
, Write_Memory_Params
.ProgrammingCommands
[2]);
373 /* Word/byte mode memory programming */
374 for (uint16_t CurrentByte
= 0; CurrentByte
< Write_Memory_Params
.BytesToWrite
; CurrentByte
++)
376 bool IsOddByte
= (CurrentByte
& 0x01);
377 uint8_t ByteToWrite
= *(NextWriteByte
++);
379 if (IsOddByte
&& (V2Command
== CMD_READ_FLASH_ISP
))
380 Write_Memory_Params
.ProgrammingCommands
[0] |= READ_WRITE_HIGH_BYTE_MASK
;
382 Write_Memory_Params
.ProgrammingCommands
[0] &= ~READ_WRITE_HIGH_BYTE_MASK
;
384 SPI_SendByte(Write_Memory_Params
.ProgrammingCommands
[0]);
385 SPI_SendByte(CurrentAddress
>> 8);
386 SPI_SendByte(CurrentAddress
& 0xFF);
387 SPI_SendByte(ByteToWrite
);
389 if (ByteToWrite
!= PollValue
)
391 if (IsOddByte
&& (V2Command
== CMD_PROGRAM_FLASH_ISP
))
392 Write_Memory_Params
.ProgrammingCommands
[2] |= READ_WRITE_HIGH_BYTE_MASK
;
394 PollAddress
= (CurrentAddress
& 0xFFFF);
397 if (IsOddByte
|| (V2Command
== CMD_PROGRAM_EEPROM_ISP
))
400 ProgrammingStatus
= V2Protocol_WaitForProgComplete(Write_Memory_Params
.ProgrammingMode
, PollAddress
, PollValue
,
401 Write_Memory_Params
.DelayMS
, Write_Memory_Params
.ProgrammingCommands
[2]);
403 if (ProgrammingStatus
!= STATUS_CMD_OK
)
408 Endpoint_Write_Byte(V2Command
);
409 Endpoint_Write_Byte(ProgrammingStatus
);
414 /** Handler for the CMD_READ_FLASH_ISP and CMD_READ_EEPROM_ISP commands, reading in bytes,
415 * words or pages of data from the attached device.
417 * \param V2Command Issued V2 Protocol command byte from the host
419 static void V2Protocol_Command_ReadMemory(uint8_t V2Command
)
423 uint16_t BytesToRead
;
424 uint8_t ReadMemoryCommand
;
425 } Read_Memory_Params
;
427 Endpoint_Read_Stream_LE(&Read_Memory_Params
, sizeof(Read_Memory_Params
));
428 Read_Memory_Params
.BytesToRead
= SwapEndian_16(Read_Memory_Params
.BytesToRead
);
431 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
433 Endpoint_Write_Byte(V2Command
);
434 Endpoint_Write_Byte(STATUS_CMD_OK
);
436 for (uint16_t CurrentByte
= 0; CurrentByte
< Read_Memory_Params
.BytesToRead
; CurrentByte
++)
438 bool IsOddByte
= (CurrentByte
& 0x01);
440 if (IsOddByte
&& (V2Command
== CMD_READ_FLASH_ISP
))
441 Read_Memory_Params
.ReadMemoryCommand
|= READ_WRITE_HIGH_BYTE_MASK
;
443 Read_Memory_Params
.ReadMemoryCommand
&= ~READ_WRITE_HIGH_BYTE_MASK
;
445 SPI_SendByte(Read_Memory_Params
.ReadMemoryCommand
);
446 SPI_SendByte(CurrentAddress
>> 8);
447 SPI_SendByte(CurrentAddress
& 0xFF);
448 Endpoint_Write_Byte(SPI_ReceiveByte());
450 /* Check if the endpoint bank is currently full */
451 if (!(Endpoint_IsReadWriteAllowed()))
454 Endpoint_WaitUntilReady();
457 if ((IsOddByte
&& (V2Command
== CMD_READ_FLASH_ISP
)) || (V2Command
== CMD_READ_EEPROM_ISP
))
461 Endpoint_Write_Byte(STATUS_CMD_OK
);
463 bool IsEndpointFull
= !(Endpoint_IsReadWriteAllowed());
466 /* Ensure last packet is a short packet to terminate the transfer */
469 Endpoint_WaitUntilReady();
471 Endpoint_WaitUntilReady();
475 /** Handler for the CMD_CHI_ERASE_ISP command, clearing the target's FLASH memory. */
476 static void V2Protocol_Command_ChipErase(void)
480 uint8_t EraseDelayMS
;
482 uint8_t EraseCommandBytes
[4];
485 Endpoint_Read_Stream_LE(&Erase_Chip_Params
, sizeof(Erase_Chip_Params
));
488 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
490 uint8_t ResponseStatus
= STATUS_CMD_OK
;
492 for (uint8_t SByte
= 0; SByte
< sizeof(Erase_Chip_Params
.EraseCommandBytes
); SByte
++)
493 SPI_SendByte(Erase_Chip_Params
.EraseCommandBytes
[SByte
]);
495 if (!(Erase_Chip_Params
.PollMethod
))
496 V2Protocol_DelayMS(Erase_Chip_Params
.EraseDelayMS
);
498 ResponseStatus
= V2Protocol_WaitWhileTargetBusy();
500 Endpoint_Write_Byte(CMD_CHIP_ERASE_ISP
);
501 Endpoint_Write_Byte(ResponseStatus
);
505 /** Handler for the CMD_READ_FUSE_ISP, CMD_READ_LOCK_ISP, CMD_READ_SIGNATURE_ISP and CMD_READ_OSCCAL commands,
506 * reading the requested configuration byte from the device.
508 * \param V2Command Issued V2 Protocol command byte from the host
510 static void V2Protocol_Command_ReadFuseLockSigOSCCAL(uint8_t V2Command
)
515 uint8_t ReadCommandBytes
[4];
516 } Read_FuseLockSigOSCCAL_Params
;
518 Endpoint_Read_Stream_LE(&Read_FuseLockSigOSCCAL_Params
, sizeof(Read_FuseLockSigOSCCAL_Params
));
521 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
523 uint8_t ResponseBytes
[4];
525 for (uint8_t RByte
= 0; RByte
< sizeof(ResponseBytes
); RByte
++)
526 ResponseBytes
[RByte
] = SPI_TransferByte(Read_FuseLockSigOSCCAL_Params
.ReadCommandBytes
[RByte
]);
528 Endpoint_Write_Byte(V2Command
);
529 Endpoint_Write_Byte(STATUS_CMD_OK
);
530 Endpoint_Write_Byte(ResponseBytes
[Read_FuseLockSigOSCCAL_Params
.RetByte
- 1]);
531 Endpoint_Write_Byte(STATUS_CMD_OK
);
535 /** Handler for the CMD_WRITE_FUSE_ISP and CMD_WRITE_LOCK_ISP commands, writing the requested configuration
536 * byte to the device.
538 * \param V2Command Issued V2 Protocol command byte from the host
540 static void V2Protocol_Command_WriteFuseLock(uint8_t V2Command
)
544 uint8_t WriteCommandBytes
[4];
545 } Write_FuseLockSig_Params
;
547 Endpoint_Read_Stream_LE(&Write_FuseLockSig_Params
, sizeof(Write_FuseLockSig_Params
));
550 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
552 for (uint8_t SByte
= 0; SByte
< sizeof(Write_FuseLockSig_Params
.WriteCommandBytes
); SByte
++)
553 SPI_SendByte(Write_FuseLockSig_Params
.WriteCommandBytes
[SByte
]);
555 Endpoint_Write_Byte(V2Command
);
556 Endpoint_Write_Byte(STATUS_CMD_OK
);
557 Endpoint_Write_Byte(STATUS_CMD_OK
);
561 /** Handler for the CMD_SPI_MULTI command, writing and reading arbitrary SPI data to and from the attached device. */
562 static void V2Protocol_Command_SPIMulti(void)
572 Endpoint_Read_Stream_LE(&SPI_Multi_Params
, sizeof(SPI_Multi_Params
) - sizeof(SPI_Multi_Params
.TxData
));
573 Endpoint_Read_Stream_LE(&SPI_Multi_Params
.TxData
, SPI_Multi_Params
.TxBytes
);
576 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
578 Endpoint_Write_Byte(CMD_SPI_MULTI
);
579 Endpoint_Write_Byte(STATUS_CMD_OK
);
581 uint8_t CurrTxPos
= 0;
582 uint8_t CurrRxPos
= 0;
584 /* Write out bytes to transmit until the start of the bytes to receive is met */
585 while (CurrTxPos
< SPI_Multi_Params
.RxStartAddr
)
587 if (CurrTxPos
< SPI_Multi_Params
.TxBytes
)
588 SPI_SendByte(SPI_Multi_Params
.TxData
[CurrTxPos
]);
595 /* Transmit remaining bytes with padding as needed, read in response bytes */
596 while (CurrRxPos
< SPI_Multi_Params
.RxBytes
)
598 if (CurrTxPos
< SPI_Multi_Params
.TxBytes
)
599 Endpoint_Write_Byte(SPI_TransferByte(SPI_Multi_Params
.TxData
[CurrTxPos
++]));
601 Endpoint_Write_Byte(SPI_ReceiveByte());
606 Endpoint_Write_Byte(STATUS_CMD_OK
);