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 uint8_t ProgData
[256];
274 } Write_Memory_Params
;
276 uint8_t* NextWriteByte
= Write_Memory_Params
.ProgData
;
278 Endpoint_Read_Stream_LE(&Write_Memory_Params
, sizeof(Write_Memory_Params
) - sizeof(Write_Memory_Params
.ProgData
));
279 Write_Memory_Params
.BytesToWrite
= SwapEndian_16(Write_Memory_Params
.BytesToWrite
);
280 Endpoint_Read_Stream_LE(&Write_Memory_Params
.ProgData
, Write_Memory_Params
.BytesToWrite
);
283 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
285 uint8_t ProgrammingStatus
= STATUS_CMD_OK
;
286 uint16_t PollAddress
= 0;
287 uint8_t PollValue
= (V2Command
== CMD_PROGRAM_FLASH_ISP
) ? Write_Memory_Params
.PollValue1
:
288 Write_Memory_Params
.PollValue2
;
289 if (Write_Memory_Params
.ProgrammingMode
& PROG_MODE_PAGED_WRITES_MASK
)
291 uint16_t StartAddress
= (CurrentAddress
& 0xFFFF);
293 /* Paged mode memory programming */
294 for (uint16_t CurrentByte
= 0; CurrentByte
< Write_Memory_Params
.BytesToWrite
; CurrentByte
++)
296 bool IsOddByte
= (CurrentByte
& 0x01);
297 uint8_t ByteToWrite
= *(NextWriteByte
++);
299 if (IsOddByte
&& (V2Command
== CMD_PROGRAM_FLASH_ISP
))
300 Write_Memory_Params
.ProgrammingCommands
[0] |= READ_WRITE_HIGH_BYTE_MASK
;
302 Write_Memory_Params
.ProgrammingCommands
[0] &= ~READ_WRITE_HIGH_BYTE_MASK
;
304 SPI_SendByte(Write_Memory_Params
.ProgrammingCommands
[0]);
305 SPI_SendByte(CurrentAddress
>> 8);
306 SPI_SendByte(CurrentAddress
& 0xFF);
307 SPI_SendByte(ByteToWrite
);
309 if (!(PollAddress
) && (ByteToWrite
!= PollValue
))
311 if (IsOddByte
&& (V2Command
== CMD_PROGRAM_FLASH_ISP
))
312 Write_Memory_Params
.ProgrammingCommands
[2] |= READ_WRITE_HIGH_BYTE_MASK
;
314 PollAddress
= (CurrentAddress
& 0xFFFF);
317 if (IsOddByte
|| (V2Command
== CMD_PROGRAM_EEPROM_ISP
))
321 /* If the current page must be committed, send the PROGRAM PAGE command to the target */
322 if (Write_Memory_Params
.ProgrammingMode
& PROG_MODE_COMMIT_PAGE_MASK
)
324 SPI_SendByte(Write_Memory_Params
.ProgrammingCommands
[1]);
325 SPI_SendByte(StartAddress
>> 8);
326 SPI_SendByte(StartAddress
& 0xFF);
329 /* Check if polling is possible, if not switch to timed delay mode */
332 Write_Memory_Params
.ProgrammingMode
&= ~PROG_MODE_PAGED_VALUE_MASK
;
333 Write_Memory_Params
.ProgrammingMode
|= PROG_MODE_PAGED_TIMEDELAY_MASK
;
336 ProgrammingStatus
= V2Protocol_WaitForProgComplete(Write_Memory_Params
.ProgrammingMode
, PollAddress
, PollValue
,
337 Write_Memory_Params
.DelayMS
, Write_Memory_Params
.ProgrammingCommands
[2]);
342 /* Word/byte mode memory programming */
343 for (uint16_t CurrentByte
= 0; CurrentByte
< Write_Memory_Params
.BytesToWrite
; CurrentByte
++)
345 bool IsOddByte
= (CurrentByte
& 0x01);
346 uint8_t ByteToWrite
= *(NextWriteByte
++);
348 if (IsOddByte
&& (V2Command
== CMD_READ_FLASH_ISP
))
349 Write_Memory_Params
.ProgrammingCommands
[0] |= READ_WRITE_HIGH_BYTE_MASK
;
351 Write_Memory_Params
.ProgrammingCommands
[0] &= ~READ_WRITE_HIGH_BYTE_MASK
;
353 SPI_SendByte(Write_Memory_Params
.ProgrammingCommands
[0]);
354 SPI_SendByte(CurrentAddress
>> 8);
355 SPI_SendByte(CurrentAddress
& 0xFF);
356 SPI_SendByte(ByteToWrite
);
358 if (ByteToWrite
!= PollValue
)
360 if (IsOddByte
&& (V2Command
== CMD_PROGRAM_FLASH_ISP
))
361 Write_Memory_Params
.ProgrammingCommands
[2] |= READ_WRITE_HIGH_BYTE_MASK
;
363 PollAddress
= (CurrentAddress
& 0xFFFF);
366 if (IsOddByte
|| (V2Command
== CMD_PROGRAM_EEPROM_ISP
))
369 ProgrammingStatus
= V2Protocol_WaitForProgComplete(Write_Memory_Params
.ProgrammingMode
, PollAddress
, PollValue
,
370 Write_Memory_Params
.DelayMS
, Write_Memory_Params
.ProgrammingCommands
[2]);
372 if (ProgrammingStatus
!= STATUS_CMD_OK
)
377 Endpoint_Write_Byte(V2Command
);
378 Endpoint_Write_Byte(ProgrammingStatus
);
383 static void V2Protocol_Command_ReadMemory(uint8_t V2Command
)
387 uint16_t BytesToRead
;
388 uint8_t ReadMemoryCommand
;
389 } Read_Memory_Params
;
391 Endpoint_Read_Stream_LE(&Read_Memory_Params
, sizeof(Read_Memory_Params
));
392 Read_Memory_Params
.BytesToRead
= SwapEndian_16(Read_Memory_Params
.BytesToRead
);
395 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
397 Endpoint_Write_Byte(V2Command
);
398 Endpoint_Write_Byte(STATUS_CMD_OK
);
400 for (uint16_t CurrentByte
= 0; CurrentByte
< Read_Memory_Params
.BytesToRead
; CurrentByte
++)
402 bool IsOddByte
= (CurrentByte
& 0x01);
404 if (IsOddByte
&& (V2Command
== CMD_READ_FLASH_ISP
))
405 Read_Memory_Params
.ReadMemoryCommand
|= READ_WRITE_HIGH_BYTE_MASK
;
407 Read_Memory_Params
.ReadMemoryCommand
&= ~READ_WRITE_HIGH_BYTE_MASK
;
409 SPI_SendByte(Read_Memory_Params
.ReadMemoryCommand
);
410 SPI_SendByte(CurrentAddress
>> 8);
411 SPI_SendByte(CurrentAddress
& 0xFF);
412 Endpoint_Write_Byte(SPI_ReceiveByte());
414 /* Check if the endpoint bank is currently full */
415 if (!(Endpoint_IsReadWriteAllowed()))
418 Endpoint_WaitUntilReady();
421 if ((IsOddByte
&& (V2Command
== CMD_READ_FLASH_ISP
)) || (V2Command
== CMD_READ_EEPROM_ISP
))
425 Endpoint_Write_Byte(STATUS_CMD_OK
);
427 bool IsEndpointFull
= !(Endpoint_IsReadWriteAllowed());
430 /* Ensure last packet is a short packet to terminate the transfer */
433 Endpoint_WaitUntilReady();
435 Endpoint_WaitUntilReady();
439 static void V2Protocol_Command_ChipErase(void)
443 uint8_t EraseDelayMS
;
445 uint8_t EraseCommandBytes
[4];
448 Endpoint_Read_Stream_LE(&Erase_Chip_Params
, sizeof(Erase_Chip_Params
));
451 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
453 uint8_t ResponseStatus
= STATUS_CMD_OK
;
455 for (uint8_t SByte
= 0; SByte
< sizeof(Erase_Chip_Params
.EraseCommandBytes
); SByte
++)
456 SPI_SendByte(Erase_Chip_Params
.EraseCommandBytes
[SByte
]);
458 if (!(Erase_Chip_Params
.PollMethod
))
459 V2Protocol_DelayMS(Erase_Chip_Params
.EraseDelayMS
);
461 ResponseStatus
= V2Protocol_WaitWhileTargetBusy();
463 Endpoint_Write_Byte(CMD_CHIP_ERASE_ISP
);
464 Endpoint_Write_Byte(ResponseStatus
);
468 static void V2Protocol_Command_ReadFuseLockSigOSCCAL(uint8_t V2Command
)
473 uint8_t ReadCommandBytes
[4];
474 } Read_FuseLockSigOSCCAL_Params
;
476 Endpoint_Read_Stream_LE(&Read_FuseLockSigOSCCAL_Params
, sizeof(Read_FuseLockSigOSCCAL_Params
));
479 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
481 uint8_t ResponseBytes
[4];
483 for (uint8_t RByte
= 0; RByte
< sizeof(ResponseBytes
); RByte
++)
484 ResponseBytes
[RByte
] = SPI_TransferByte(Read_FuseLockSigOSCCAL_Params
.ReadCommandBytes
[RByte
]);
486 Endpoint_Write_Byte(V2Command
);
487 Endpoint_Write_Byte(STATUS_CMD_OK
);
488 Endpoint_Write_Byte(ResponseBytes
[Read_FuseLockSigOSCCAL_Params
.RetByte
- 1]);
489 Endpoint_Write_Byte(STATUS_CMD_OK
);
493 static void V2Protocol_Command_WriteFuseLock(uint8_t V2Command
)
497 uint8_t WriteCommandBytes
[4];
498 } Write_FuseLockSig_Params
;
500 Endpoint_Read_Stream_LE(&Write_FuseLockSig_Params
, sizeof(Write_FuseLockSig_Params
));
503 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
505 for (uint8_t SByte
= 0; SByte
< sizeof(Write_FuseLockSig_Params
.WriteCommandBytes
); SByte
++)
506 SPI_SendByte(Write_FuseLockSig_Params
.WriteCommandBytes
[SByte
]);
508 Endpoint_Write_Byte(V2Command
);
509 Endpoint_Write_Byte(STATUS_CMD_OK
);
510 Endpoint_Write_Byte(STATUS_CMD_OK
);
514 static void V2Protocol_Command_SPIMulti(void)
524 Endpoint_Read_Stream_LE(&SPI_Multi_Params
, sizeof(SPI_Multi_Params
) - sizeof(SPI_Multi_Params
.TxData
));
525 Endpoint_Read_Stream_LE(&SPI_Multi_Params
.TxData
, SPI_Multi_Params
.TxBytes
);
528 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
530 Endpoint_Write_Byte(CMD_SPI_MULTI
);
531 Endpoint_Write_Byte(STATUS_CMD_OK
);
533 uint8_t CurrTxPos
= 0;
534 uint8_t CurrRxPos
= 0;
536 /* Write out bytes to transmit until the start of the bytes to receive is met */
537 while (CurrTxPos
< SPI_Multi_Params
.RxStartAddr
)
539 if (CurrTxPos
< SPI_Multi_Params
.TxBytes
)
540 SPI_SendByte(SPI_Multi_Params
.TxData
[CurrTxPos
]);
547 /* Transmit remaining bytes with padding as needed, read in response bytes */
548 while (CurrRxPos
< SPI_Multi_Params
.RxBytes
)
550 if (CurrTxPos
< SPI_Multi_Params
.TxBytes
)
551 Endpoint_Write_Byte(SPI_TransferByte(SPI_Multi_Params
.TxData
[CurrTxPos
++]));
553 Endpoint_Write_Byte(SPI_ReceiveByte());
558 Endpoint_Write_Byte(STATUS_CMD_OK
);