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 * ISP Protocol handler, to process V2 Protocol wrapped ISP commands used in Atmel programmer devices.
36 #include "ISPProtocol.h"
38 /** Handler for the CMD_ENTER_PROGMODE_ISP command, which attempts to enter programming mode on
39 * the attached device, returning success or failure back to the host.
41 void ISPProtocol_EnterISPMode(void)
46 uint8_t PinStabDelayMS
;
47 uint8_t ExecutionDelayMS
;
52 uint8_t EnterProgBytes
[4];
55 Endpoint_Read_Stream_LE(&Enter_ISP_Params
, sizeof(Enter_ISP_Params
));
58 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
60 uint8_t ResponseStatus
= STATUS_CMD_FAILED
;
64 V2Protocol_DelayMS(Enter_ISP_Params
.ExecutionDelayMS
);
65 SPI_Init(ISPTarget_GetSPIPrescalerMask() | SPI_SCK_LEAD_RISING
| SPI_SAMPLE_LEADING
| SPI_MODE_MASTER
);
67 while (Enter_ISP_Params
.SynchLoops
-- && (ResponseStatus
== STATUS_CMD_FAILED
))
69 uint8_t ResponseBytes
[4];
71 ISPTarget_ChangeTargetResetLine(true);
72 V2Protocol_DelayMS(Enter_ISP_Params
.PinStabDelayMS
);
74 for (uint8_t RByte
= 0; RByte
< sizeof(ResponseBytes
); RByte
++)
76 V2Protocol_DelayMS(Enter_ISP_Params
.ByteDelay
);
77 ResponseBytes
[RByte
] = SPI_TransferByte(Enter_ISP_Params
.EnterProgBytes
[RByte
]);
80 /* Check if polling disabled, or if the polled value matches the expected value */
81 if (!(Enter_ISP_Params
.PollIndex
) || (ResponseBytes
[Enter_ISP_Params
.PollIndex
- 1] == Enter_ISP_Params
.PollValue
))
83 ResponseStatus
= STATUS_CMD_OK
;
87 ISPTarget_ChangeTargetResetLine(false);
88 V2Protocol_DelayMS(Enter_ISP_Params
.PinStabDelayMS
);
92 Endpoint_Write_Byte(CMD_ENTER_PROGMODE_ISP
);
93 Endpoint_Write_Byte(ResponseStatus
);
97 /** Handler for the CMD_LEAVE_ISP command, which releases the target from programming mode. */
98 void ISPProtocol_LeaveISPMode(void)
106 Endpoint_Read_Stream_LE(&Leave_ISP_Params
, sizeof(Leave_ISP_Params
));
109 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
111 V2Protocol_DelayMS(Leave_ISP_Params
.PreDelayMS
);
112 ISPTarget_ChangeTargetResetLine(false);
114 V2Protocol_DelayMS(Leave_ISP_Params
.PostDelayMS
);
116 Endpoint_Write_Byte(CMD_LEAVE_PROGMODE_ISP
);
117 Endpoint_Write_Byte(STATUS_CMD_OK
);
121 /** Handler for the CMD_PROGRAM_FLASH_ISP and CMD_PROGRAM_EEPROM_ISP commands, writing out bytes,
122 * words or pages of data to the attached device.
124 * \param[in] V2Command Issued V2 Protocol command byte from the host
126 void ISPProtocol_ProgramMemory(uint8_t V2Command
)
130 uint16_t BytesToWrite
;
131 uint8_t ProgrammingMode
;
133 uint8_t ProgrammingCommands
[3];
136 uint8_t ProgData
[256]; // Note, the Jungo driver has a very short ACK timeout period, need to buffer the
137 } Write_Memory_Params
; // whole page and ACK the packet as fast as possible to prevent it from aborting
139 Endpoint_Read_Stream_LE(&Write_Memory_Params
, (sizeof(Write_Memory_Params
) -
140 sizeof(Write_Memory_Params
.ProgData
)));
143 Write_Memory_Params
.BytesToWrite
= SwapEndian_16(Write_Memory_Params
.BytesToWrite
);
145 if (Write_Memory_Params
.BytesToWrite
> sizeof(Write_Memory_Params
.ProgData
))
148 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
150 Endpoint_Write_Byte(V2Command
);
151 Endpoint_Write_Byte(STATUS_CMD_FAILED
);
156 Endpoint_Read_Stream_LE(&Write_Memory_Params
.ProgData
, Write_Memory_Params
.BytesToWrite
);
159 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
161 uint8_t ProgrammingStatus
= STATUS_CMD_OK
;
162 uint16_t PollAddress
= 0;
163 uint8_t PollValue
= (V2Command
== CMD_PROGRAM_FLASH_ISP
) ? Write_Memory_Params
.PollValue1
:
164 Write_Memory_Params
.PollValue2
;
165 uint8_t* NextWriteByte
= Write_Memory_Params
.ProgData
;
169 if (CurrentAddress
& (1UL << 31))
170 ISPTarget_LoadExtendedAddress();
172 MustSetAddress
= false;
175 if (Write_Memory_Params
.ProgrammingMode
& PROG_MODE_PAGED_WRITES_MASK
)
177 uint16_t StartAddress
= (CurrentAddress
& 0xFFFF);
179 /* Paged mode memory programming */
180 for (uint16_t CurrentByte
= 0; CurrentByte
< Write_Memory_Params
.BytesToWrite
; CurrentByte
++)
182 bool IsOddByte
= (CurrentByte
& 0x01);
183 uint8_t ByteToWrite
= *(NextWriteByte
++);
185 if (IsOddByte
&& (V2Command
== CMD_PROGRAM_FLASH_ISP
))
186 Write_Memory_Params
.ProgrammingCommands
[0] |= READ_WRITE_HIGH_BYTE_MASK
;
188 Write_Memory_Params
.ProgrammingCommands
[0] &= ~READ_WRITE_HIGH_BYTE_MASK
;
190 SPI_SendByte(Write_Memory_Params
.ProgrammingCommands
[0]);
191 SPI_SendByte(CurrentAddress
>> 8);
192 SPI_SendByte(CurrentAddress
& 0xFF);
193 SPI_SendByte(ByteToWrite
);
195 if (!(PollAddress
) && (ByteToWrite
!= PollValue
))
197 if (IsOddByte
&& (V2Command
== CMD_PROGRAM_FLASH_ISP
))
198 Write_Memory_Params
.ProgrammingCommands
[2] |= READ_WRITE_HIGH_BYTE_MASK
;
200 PollAddress
= (CurrentAddress
& 0xFFFF);
203 if (IsOddByte
|| (V2Command
== CMD_PROGRAM_EEPROM_ISP
))
207 /* If the current page must be committed, send the PROGRAM PAGE command to the target */
208 if (Write_Memory_Params
.ProgrammingMode
& PROG_MODE_COMMIT_PAGE_MASK
)
210 SPI_SendByte(Write_Memory_Params
.ProgrammingCommands
[1]);
211 SPI_SendByte(StartAddress
>> 8);
212 SPI_SendByte(StartAddress
& 0xFF);
215 /* Check if polling is possible, if not switch to timed delay mode */
218 Write_Memory_Params
.ProgrammingMode
&= ~PROG_MODE_PAGED_VALUE_MASK
;
219 Write_Memory_Params
.ProgrammingMode
|= PROG_MODE_PAGED_TIMEDELAY_MASK
;
222 ProgrammingStatus
= ISPTarget_WaitForProgComplete(Write_Memory_Params
.ProgrammingMode
, PollAddress
, PollValue
,
223 Write_Memory_Params
.DelayMS
, Write_Memory_Params
.ProgrammingCommands
[2]);
228 /* Word/byte mode memory programming */
229 for (uint16_t CurrentByte
= 0; CurrentByte
< Write_Memory_Params
.BytesToWrite
; CurrentByte
++)
231 bool IsOddByte
= (CurrentByte
& 0x01);
232 uint8_t ByteToWrite
= *(NextWriteByte
++);
234 if (IsOddByte
&& (V2Command
== CMD_READ_FLASH_ISP
))
235 Write_Memory_Params
.ProgrammingCommands
[0] |= READ_WRITE_HIGH_BYTE_MASK
;
237 Write_Memory_Params
.ProgrammingCommands
[0] &= ~READ_WRITE_HIGH_BYTE_MASK
;
239 SPI_SendByte(Write_Memory_Params
.ProgrammingCommands
[0]);
240 SPI_SendByte(CurrentAddress
>> 8);
241 SPI_SendByte(CurrentAddress
& 0xFF);
242 SPI_SendByte(ByteToWrite
);
244 if (ByteToWrite
!= PollValue
)
246 if (IsOddByte
&& (V2Command
== CMD_PROGRAM_FLASH_ISP
))
247 Write_Memory_Params
.ProgrammingCommands
[2] |= READ_WRITE_HIGH_BYTE_MASK
;
249 PollAddress
= (CurrentAddress
& 0xFFFF);
252 if (IsOddByte
|| (V2Command
== CMD_PROGRAM_EEPROM_ISP
))
255 ProgrammingStatus
= ISPTarget_WaitForProgComplete(Write_Memory_Params
.ProgrammingMode
, PollAddress
, PollValue
,
256 Write_Memory_Params
.DelayMS
, Write_Memory_Params
.ProgrammingCommands
[2]);
258 if (ProgrammingStatus
!= STATUS_CMD_OK
)
263 Endpoint_Write_Byte(V2Command
);
264 Endpoint_Write_Byte(ProgrammingStatus
);
268 /** Handler for the CMD_READ_FLASH_ISP and CMD_READ_EEPROM_ISP commands, reading in bytes,
269 * words or pages of data from the attached device.
271 * \param[in] V2Command Issued V2 Protocol command byte from the host
273 void ISPProtocol_ReadMemory(uint8_t V2Command
)
277 uint16_t BytesToRead
;
278 uint8_t ReadMemoryCommand
;
279 } Read_Memory_Params
;
281 Endpoint_Read_Stream_LE(&Read_Memory_Params
, sizeof(Read_Memory_Params
));
282 Read_Memory_Params
.BytesToRead
= SwapEndian_16(Read_Memory_Params
.BytesToRead
);
285 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
287 Endpoint_Write_Byte(V2Command
);
288 Endpoint_Write_Byte(STATUS_CMD_OK
);
292 if (CurrentAddress
& (1UL << 31))
293 ISPTarget_LoadExtendedAddress();
295 MustSetAddress
= false;
298 for (uint16_t CurrentByte
= 0; CurrentByte
< Read_Memory_Params
.BytesToRead
; CurrentByte
++)
300 bool IsOddByte
= (CurrentByte
& 0x01);
302 if (IsOddByte
&& (V2Command
== CMD_READ_FLASH_ISP
))
303 Read_Memory_Params
.ReadMemoryCommand
|= READ_WRITE_HIGH_BYTE_MASK
;
305 Read_Memory_Params
.ReadMemoryCommand
&= ~READ_WRITE_HIGH_BYTE_MASK
;
307 SPI_SendByte(Read_Memory_Params
.ReadMemoryCommand
);
308 SPI_SendByte(CurrentAddress
>> 8);
309 SPI_SendByte(CurrentAddress
& 0xFF);
310 Endpoint_Write_Byte(SPI_ReceiveByte());
312 /* Check if the endpoint bank is currently full */
313 if (!(Endpoint_IsReadWriteAllowed()))
316 Endpoint_WaitUntilReady();
319 if ((IsOddByte
&& (V2Command
== CMD_READ_FLASH_ISP
)) || (V2Command
== CMD_READ_EEPROM_ISP
))
323 Endpoint_Write_Byte(STATUS_CMD_OK
);
325 bool IsEndpointFull
= !(Endpoint_IsReadWriteAllowed());
328 /* Ensure last packet is a short packet to terminate the transfer */
331 Endpoint_WaitUntilReady();
333 Endpoint_WaitUntilReady();
337 /** Handler for the CMD_CHI_ERASE_ISP command, clearing the target's FLASH memory. */
338 void ISPProtocol_ChipErase(void)
342 uint8_t EraseDelayMS
;
344 uint8_t EraseCommandBytes
[4];
347 Endpoint_Read_Stream_LE(&Erase_Chip_Params
, sizeof(Erase_Chip_Params
));
350 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
352 uint8_t ResponseStatus
= STATUS_CMD_OK
;
354 for (uint8_t SByte
= 0; SByte
< sizeof(Erase_Chip_Params
.EraseCommandBytes
); SByte
++)
355 SPI_SendByte(Erase_Chip_Params
.EraseCommandBytes
[SByte
]);
357 if (!(Erase_Chip_Params
.PollMethod
))
358 V2Protocol_DelayMS(Erase_Chip_Params
.EraseDelayMS
);
360 ResponseStatus
= ISPTarget_WaitWhileTargetBusy();
362 Endpoint_Write_Byte(CMD_CHIP_ERASE_ISP
);
363 Endpoint_Write_Byte(ResponseStatus
);
367 /** Handler for the CMD_READ_FUSE_ISP, CMD_READ_LOCK_ISP, CMD_READ_SIGNATURE_ISP and CMD_READ_OSCCAL commands,
368 * reading the requested configuration byte from the device.
370 * \param[in] V2Command Issued V2 Protocol command byte from the host
372 void ISPProtocol_ReadFuseLockSigOSCCAL(uint8_t V2Command
)
377 uint8_t ReadCommandBytes
[4];
378 } Read_FuseLockSigOSCCAL_Params
;
380 Endpoint_Read_Stream_LE(&Read_FuseLockSigOSCCAL_Params
, sizeof(Read_FuseLockSigOSCCAL_Params
));
383 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
385 uint8_t ResponseBytes
[4];
387 for (uint8_t RByte
= 0; RByte
< sizeof(ResponseBytes
); RByte
++)
388 ResponseBytes
[RByte
] = SPI_TransferByte(Read_FuseLockSigOSCCAL_Params
.ReadCommandBytes
[RByte
]);
390 Endpoint_Write_Byte(V2Command
);
391 Endpoint_Write_Byte(STATUS_CMD_OK
);
392 Endpoint_Write_Byte(ResponseBytes
[Read_FuseLockSigOSCCAL_Params
.RetByte
- 1]);
393 Endpoint_Write_Byte(STATUS_CMD_OK
);
397 /** Handler for the CMD_WRITE_FUSE_ISP and CMD_WRITE_LOCK_ISP commands, writing the requested configuration
398 * byte to the device.
400 * \param[in] V2Command Issued V2 Protocol command byte from the host
402 void ISPProtocol_WriteFuseLock(uint8_t V2Command
)
406 uint8_t WriteCommandBytes
[4];
407 } Write_FuseLockSig_Params
;
409 Endpoint_Read_Stream_LE(&Write_FuseLockSig_Params
, sizeof(Write_FuseLockSig_Params
));
412 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
414 for (uint8_t SByte
= 0; SByte
< sizeof(Write_FuseLockSig_Params
.WriteCommandBytes
); SByte
++)
415 SPI_SendByte(Write_FuseLockSig_Params
.WriteCommandBytes
[SByte
]);
417 Endpoint_Write_Byte(V2Command
);
418 Endpoint_Write_Byte(STATUS_CMD_OK
);
419 Endpoint_Write_Byte(STATUS_CMD_OK
);
423 /** Handler for the CMD_SPI_MULTI command, writing and reading arbitrary SPI data to and from the attached device. */
424 void ISPProtocol_SPIMulti(void)
434 Endpoint_Read_Stream_LE(&SPI_Multi_Params
, sizeof(SPI_Multi_Params
) - sizeof(SPI_Multi_Params
.TxData
));
435 Endpoint_Read_Stream_LE(&SPI_Multi_Params
.TxData
, SPI_Multi_Params
.TxBytes
);
438 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
440 Endpoint_Write_Byte(CMD_SPI_MULTI
);
441 Endpoint_Write_Byte(STATUS_CMD_OK
);
443 uint8_t CurrTxPos
= 0;
444 uint8_t CurrRxPos
= 0;
446 /* Write out bytes to transmit until the start of the bytes to receive is met */
447 while (CurrTxPos
< SPI_Multi_Params
.RxStartAddr
)
449 if (CurrTxPos
< SPI_Multi_Params
.TxBytes
)
450 SPI_SendByte(SPI_Multi_Params
.TxData
[CurrTxPos
]);
457 /* Transmit remaining bytes with padding as needed, read in response bytes */
458 while (CurrRxPos
< SPI_Multi_Params
.RxBytes
)
460 if (CurrTxPos
< SPI_Multi_Params
.TxBytes
)
461 Endpoint_Write_Byte(SPI_TransferByte(SPI_Multi_Params
.TxData
[CurrTxPos
++]));
463 Endpoint_Write_Byte(SPI_ReceiveByte());
468 Endpoint_Write_Byte(STATUS_CMD_OK
);