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
) - sizeof(Write_Memory_Params
.ProgData
));
140 Write_Memory_Params
.BytesToWrite
= SwapEndian_16(Write_Memory_Params
.BytesToWrite
);
142 if (Write_Memory_Params
.BytesToWrite
> sizeof(Write_Memory_Params
.ProgData
))
145 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
147 Endpoint_Write_Byte(V2Command
);
148 Endpoint_Write_Byte(STATUS_CMD_FAILED
);
153 Endpoint_Read_Stream_LE(&Write_Memory_Params
.ProgData
, Write_Memory_Params
.BytesToWrite
);
156 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
158 uint8_t ProgrammingStatus
= STATUS_CMD_OK
;
159 uint16_t PollAddress
= 0;
160 uint8_t PollValue
= (V2Command
== CMD_PROGRAM_FLASH_ISP
) ? Write_Memory_Params
.PollValue1
:
161 Write_Memory_Params
.PollValue2
;
162 uint8_t* NextWriteByte
= Write_Memory_Params
.ProgData
;
166 if (CurrentAddress
& (1UL << 31))
167 ISPTarget_LoadExtendedAddress();
169 MustSetAddress
= false;
172 if (Write_Memory_Params
.ProgrammingMode
& PROG_MODE_PAGED_WRITES_MASK
)
174 uint16_t StartAddress
= (CurrentAddress
& 0xFFFF);
176 /* Paged mode memory programming */
177 for (uint16_t CurrentByte
= 0; CurrentByte
< Write_Memory_Params
.BytesToWrite
; CurrentByte
++)
179 bool IsOddByte
= (CurrentByte
& 0x01);
180 uint8_t ByteToWrite
= *(NextWriteByte
++);
182 if (IsOddByte
&& (V2Command
== CMD_PROGRAM_FLASH_ISP
))
183 Write_Memory_Params
.ProgrammingCommands
[0] |= READ_WRITE_HIGH_BYTE_MASK
;
185 Write_Memory_Params
.ProgrammingCommands
[0] &= ~READ_WRITE_HIGH_BYTE_MASK
;
187 SPI_SendByte(Write_Memory_Params
.ProgrammingCommands
[0]);
188 SPI_SendByte(CurrentAddress
>> 8);
189 SPI_SendByte(CurrentAddress
& 0xFF);
190 SPI_SendByte(ByteToWrite
);
192 if (!(PollAddress
) && (ByteToWrite
!= PollValue
))
194 if (IsOddByte
&& (V2Command
== CMD_PROGRAM_FLASH_ISP
))
195 Write_Memory_Params
.ProgrammingCommands
[2] |= READ_WRITE_HIGH_BYTE_MASK
;
197 PollAddress
= (CurrentAddress
& 0xFFFF);
200 if (IsOddByte
|| (V2Command
== CMD_PROGRAM_EEPROM_ISP
))
204 /* If the current page must be committed, send the PROGRAM PAGE command to the target */
205 if (Write_Memory_Params
.ProgrammingMode
& PROG_MODE_COMMIT_PAGE_MASK
)
207 SPI_SendByte(Write_Memory_Params
.ProgrammingCommands
[1]);
208 SPI_SendByte(StartAddress
>> 8);
209 SPI_SendByte(StartAddress
& 0xFF);
212 /* Check if polling is possible, if not switch to timed delay mode */
215 Write_Memory_Params
.ProgrammingMode
&= ~PROG_MODE_PAGED_VALUE_MASK
;
216 Write_Memory_Params
.ProgrammingMode
|= PROG_MODE_PAGED_TIMEDELAY_MASK
;
219 ProgrammingStatus
= ISPTarget_WaitForProgComplete(Write_Memory_Params
.ProgrammingMode
, PollAddress
, PollValue
,
220 Write_Memory_Params
.DelayMS
, Write_Memory_Params
.ProgrammingCommands
[2]);
225 /* Word/byte mode memory programming */
226 for (uint16_t CurrentByte
= 0; CurrentByte
< Write_Memory_Params
.BytesToWrite
; CurrentByte
++)
228 bool IsOddByte
= (CurrentByte
& 0x01);
229 uint8_t ByteToWrite
= *(NextWriteByte
++);
231 if (IsOddByte
&& (V2Command
== CMD_READ_FLASH_ISP
))
232 Write_Memory_Params
.ProgrammingCommands
[0] |= READ_WRITE_HIGH_BYTE_MASK
;
234 Write_Memory_Params
.ProgrammingCommands
[0] &= ~READ_WRITE_HIGH_BYTE_MASK
;
236 SPI_SendByte(Write_Memory_Params
.ProgrammingCommands
[0]);
237 SPI_SendByte(CurrentAddress
>> 8);
238 SPI_SendByte(CurrentAddress
& 0xFF);
239 SPI_SendByte(ByteToWrite
);
241 if (ByteToWrite
!= PollValue
)
243 if (IsOddByte
&& (V2Command
== CMD_PROGRAM_FLASH_ISP
))
244 Write_Memory_Params
.ProgrammingCommands
[2] |= READ_WRITE_HIGH_BYTE_MASK
;
246 PollAddress
= (CurrentAddress
& 0xFFFF);
249 if (IsOddByte
|| (V2Command
== CMD_PROGRAM_EEPROM_ISP
))
252 ProgrammingStatus
= ISPTarget_WaitForProgComplete(Write_Memory_Params
.ProgrammingMode
, PollAddress
, PollValue
,
253 Write_Memory_Params
.DelayMS
, Write_Memory_Params
.ProgrammingCommands
[2]);
255 if (ProgrammingStatus
!= STATUS_CMD_OK
)
260 Endpoint_Write_Byte(V2Command
);
261 Endpoint_Write_Byte(ProgrammingStatus
);
265 /** Handler for the CMD_READ_FLASH_ISP and CMD_READ_EEPROM_ISP commands, reading in bytes,
266 * words or pages of data from the attached device.
268 * \param[in] V2Command Issued V2 Protocol command byte from the host
270 void ISPProtocol_ReadMemory(uint8_t V2Command
)
274 uint16_t BytesToRead
;
275 uint8_t ReadMemoryCommand
;
276 } Read_Memory_Params
;
278 Endpoint_Read_Stream_LE(&Read_Memory_Params
, sizeof(Read_Memory_Params
));
279 Read_Memory_Params
.BytesToRead
= SwapEndian_16(Read_Memory_Params
.BytesToRead
);
282 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
284 Endpoint_Write_Byte(V2Command
);
285 Endpoint_Write_Byte(STATUS_CMD_OK
);
289 if (CurrentAddress
& (1UL << 31))
290 ISPTarget_LoadExtendedAddress();
292 MustSetAddress
= false;
295 for (uint16_t CurrentByte
= 0; CurrentByte
< Read_Memory_Params
.BytesToRead
; CurrentByte
++)
297 bool IsOddByte
= (CurrentByte
& 0x01);
299 if (IsOddByte
&& (V2Command
== CMD_READ_FLASH_ISP
))
300 Read_Memory_Params
.ReadMemoryCommand
|= READ_WRITE_HIGH_BYTE_MASK
;
302 Read_Memory_Params
.ReadMemoryCommand
&= ~READ_WRITE_HIGH_BYTE_MASK
;
304 SPI_SendByte(Read_Memory_Params
.ReadMemoryCommand
);
305 SPI_SendByte(CurrentAddress
>> 8);
306 SPI_SendByte(CurrentAddress
& 0xFF);
307 Endpoint_Write_Byte(SPI_ReceiveByte());
309 /* Check if the endpoint bank is currently full */
310 if (!(Endpoint_IsReadWriteAllowed()))
313 Endpoint_WaitUntilReady();
316 if ((IsOddByte
&& (V2Command
== CMD_READ_FLASH_ISP
)) || (V2Command
== CMD_READ_EEPROM_ISP
))
320 Endpoint_Write_Byte(STATUS_CMD_OK
);
322 bool IsEndpointFull
= !(Endpoint_IsReadWriteAllowed());
325 /* Ensure last packet is a short packet to terminate the transfer */
328 Endpoint_WaitUntilReady();
330 Endpoint_WaitUntilReady();
334 /** Handler for the CMD_CHI_ERASE_ISP command, clearing the target's FLASH memory. */
335 void ISPProtocol_ChipErase(void)
339 uint8_t EraseDelayMS
;
341 uint8_t EraseCommandBytes
[4];
344 Endpoint_Read_Stream_LE(&Erase_Chip_Params
, sizeof(Erase_Chip_Params
));
347 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
349 uint8_t ResponseStatus
= STATUS_CMD_OK
;
351 for (uint8_t SByte
= 0; SByte
< sizeof(Erase_Chip_Params
.EraseCommandBytes
); SByte
++)
352 SPI_SendByte(Erase_Chip_Params
.EraseCommandBytes
[SByte
]);
354 if (!(Erase_Chip_Params
.PollMethod
))
355 V2Protocol_DelayMS(Erase_Chip_Params
.EraseDelayMS
);
357 ResponseStatus
= ISPTarget_WaitWhileTargetBusy();
359 Endpoint_Write_Byte(CMD_CHIP_ERASE_ISP
);
360 Endpoint_Write_Byte(ResponseStatus
);
364 /** Handler for the CMD_READ_FUSE_ISP, CMD_READ_LOCK_ISP, CMD_READ_SIGNATURE_ISP and CMD_READ_OSCCAL commands,
365 * reading the requested configuration byte from the device.
367 * \param[in] V2Command Issued V2 Protocol command byte from the host
369 void ISPProtocol_ReadFuseLockSigOSCCAL(uint8_t V2Command
)
374 uint8_t ReadCommandBytes
[4];
375 } Read_FuseLockSigOSCCAL_Params
;
377 Endpoint_Read_Stream_LE(&Read_FuseLockSigOSCCAL_Params
, sizeof(Read_FuseLockSigOSCCAL_Params
));
380 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
382 uint8_t ResponseBytes
[4];
384 for (uint8_t RByte
= 0; RByte
< sizeof(ResponseBytes
); RByte
++)
385 ResponseBytes
[RByte
] = SPI_TransferByte(Read_FuseLockSigOSCCAL_Params
.ReadCommandBytes
[RByte
]);
387 Endpoint_Write_Byte(V2Command
);
388 Endpoint_Write_Byte(STATUS_CMD_OK
);
389 Endpoint_Write_Byte(ResponseBytes
[Read_FuseLockSigOSCCAL_Params
.RetByte
- 1]);
390 Endpoint_Write_Byte(STATUS_CMD_OK
);
394 /** Handler for the CMD_WRITE_FUSE_ISP and CMD_WRITE_LOCK_ISP commands, writing the requested configuration
395 * byte to the device.
397 * \param[in] V2Command Issued V2 Protocol command byte from the host
399 void ISPProtocol_WriteFuseLock(uint8_t V2Command
)
403 uint8_t WriteCommandBytes
[4];
404 } Write_FuseLockSig_Params
;
406 Endpoint_Read_Stream_LE(&Write_FuseLockSig_Params
, sizeof(Write_FuseLockSig_Params
));
409 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
411 for (uint8_t SByte
= 0; SByte
< sizeof(Write_FuseLockSig_Params
.WriteCommandBytes
); SByte
++)
412 SPI_SendByte(Write_FuseLockSig_Params
.WriteCommandBytes
[SByte
]);
414 Endpoint_Write_Byte(V2Command
);
415 Endpoint_Write_Byte(STATUS_CMD_OK
);
416 Endpoint_Write_Byte(STATUS_CMD_OK
);
420 /** Handler for the CMD_SPI_MULTI command, writing and reading arbitrary SPI data to and from the attached device. */
421 void ISPProtocol_SPIMulti(void)
431 Endpoint_Read_Stream_LE(&SPI_Multi_Params
, sizeof(SPI_Multi_Params
) - sizeof(SPI_Multi_Params
.TxData
));
432 Endpoint_Read_Stream_LE(&SPI_Multi_Params
.TxData
, SPI_Multi_Params
.TxBytes
);
435 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
437 Endpoint_Write_Byte(CMD_SPI_MULTI
);
438 Endpoint_Write_Byte(STATUS_CMD_OK
);
440 uint8_t CurrTxPos
= 0;
441 uint8_t CurrRxPos
= 0;
443 /* Write out bytes to transmit until the start of the bytes to receive is met */
444 while (CurrTxPos
< SPI_Multi_Params
.RxStartAddr
)
446 if (CurrTxPos
< SPI_Multi_Params
.TxBytes
)
447 SPI_SendByte(SPI_Multi_Params
.TxData
[CurrTxPos
]);
454 /* Transmit remaining bytes with padding as needed, read in response bytes */
455 while (CurrRxPos
< SPI_Multi_Params
.RxBytes
)
457 if (CurrTxPos
< SPI_Multi_Params
.TxBytes
)
458 Endpoint_Write_Byte(SPI_TransferByte(SPI_Multi_Params
.TxData
[CurrTxPos
++]));
460 Endpoint_Write_Byte(SPI_ReceiveByte());
465 Endpoint_Write_Byte(STATUS_CMD_OK
);