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 uint32_t CurrentAddress
;
42 /* Table of masks for SPI_Init() from a given PARAM_SCK_DURATION value */
43 static const uint8_t SPIMaskFromSCKDuration
[] =
45 #if (F_CPU == 8000000)
48 SPI_SPEED_FCPU_DIV_2
, SPI_SPEED_FCPU_DIV_4
, SPI_SPEED_FCPU_DIV_8
,
49 SPI_SPEED_FCPU_DIV_16
, SPI_SPEED_FCPU_DIV_32
, SPI_SPEED_FCPU_DIV_64
50 #if (F_CPU == 16000000)
51 , SPI_SPEED_FCPU_DIV_128
55 static uint8_t V2Protocol_GetSPIPrescalerMask(void)
57 uint8_t SCKDuration
= V2Params_GetParameterValue(PARAM_SCK_DURATION
);
59 if (SCKDuration
>= sizeof(SPIMaskFromSCKDuration
))
60 SCKDuration
= (sizeof(SPIMaskFromSCKDuration
) - 1);
62 return SPIMaskFromSCKDuration
[SCKDuration
];
65 static void V2Protocol_ChangeTargetResetLine(bool ResetTarget
)
69 RESET_LINE_DDR
|= RESET_LINE_MASK
;
71 if (!(V2Params_GetParameterValue(PARAM_RESET_POLARITY
)))
72 RESET_LINE_PORT
|= RESET_LINE_MASK
;
76 RESET_LINE_PORT
&= ~RESET_LINE_MASK
;
77 RESET_LINE_DDR
&= ~RESET_LINE_MASK
;
81 static void V2Protocol_DelayMS(uint8_t MS
)
87 static uint8_t V2Protocol_WaitWhileTargetBusy(void)
89 uint8_t TimeoutMS
= TARGET_BUST_TIMEOUT_MS
;
94 V2Protocol_DelayMS(1);
100 ResponseByte
= SPI_ReceiveByte();
102 while ((ResponseByte
& 0x01) && (TimeoutMS
--));
105 return STATUS_CMD_TOUT
;
107 return STATUS_CMD_OK
;
110 void V2Protocol_ProcessCommand(void)
112 uint8_t V2Command
= Endpoint_Read_Byte();
117 V2Protocol_Command_SignOn();
119 case CMD_SET_PARAMETER
:
120 case CMD_GET_PARAMETER
:
121 V2Protocol_Command_GetSetParam(V2Command
);
123 case CMD_LOAD_ADDRESS
:
124 V2Protocol_Command_LoadAddress();
126 case CMD_ENTER_PROGMODE_ISP
:
127 V2Protocol_Command_EnterISPMode();
129 case CMD_LEAVE_PROGMODE_ISP
:
130 V2Protocol_Command_LeaveISPMode();
132 case CMD_CHIP_ERASE_ISP
:
133 V2Protocol_Command_ChipErase();
135 case CMD_READ_FUSE_ISP
:
136 case CMD_READ_LOCK_ISP
:
137 case CMD_READ_SIGNATURE_ISP
:
138 case CMD_READ_OSCCAL_ISP
:
139 V2Protocol_Command_ReadFuseLockSigOSCCAL(V2Command
);
141 case CMD_PROGRAM_FUSE_ISP
:
142 case CMD_PROGRAM_LOCK_ISP
:
143 V2Protocol_Command_WriteFuseLock(V2Command
);
146 V2Protocol_Command_SPIMulti();
149 V2Protocol_Command_Unknown(V2Command
);
153 Endpoint_WaitUntilReady();
154 Endpoint_SetEndpointDirection(ENDPOINT_DIR_OUT
);
157 static void V2Protocol_Command_Unknown(uint8_t V2Command
)
159 /* Discard all incomming data */
160 while (Endpoint_BytesInEndpoint() == AVRISP_DATA_EPSIZE
)
163 Endpoint_WaitUntilReady();
167 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
169 Endpoint_Write_Byte(V2Command
);
170 Endpoint_Write_Byte(STATUS_CMD_UNKNOWN
);
174 static void V2Protocol_Command_SignOn(void)
177 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
179 Endpoint_Write_Byte(CMD_SIGN_ON
);
180 Endpoint_Write_Byte(STATUS_CMD_OK
);
181 Endpoint_Write_Byte(sizeof(PROGRAMMER_ID
) - 1);
182 Endpoint_Write_Stream_LE(PROGRAMMER_ID
, (sizeof(PROGRAMMER_ID
) - 1));
186 static void V2Protocol_Command_GetSetParam(uint8_t V2Command
)
188 uint8_t ParamID
= Endpoint_Read_Byte();
191 if (V2Command
== CMD_SET_PARAMETER
)
192 ParamValue
= Endpoint_Read_Byte();
195 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
197 Endpoint_Write_Byte(V2Command
);
199 uint8_t ParamPrivs
= V2Params_GetParameterPrivellages(ParamID
);
201 if ((V2Command
== CMD_SET_PARAMETER
) && (ParamPrivs
& PARAM_PRIV_WRITE
))
203 Endpoint_Write_Byte(STATUS_CMD_OK
);
204 V2Params_SetParameterValue(ParamID
, ParamValue
);
206 else if ((V2Command
== CMD_GET_PARAMETER
) && (ParamPrivs
& PARAM_PRIV_READ
))
208 Endpoint_Write_Byte(STATUS_CMD_OK
);
209 Endpoint_Write_Byte(V2Params_GetParameterValue(ParamID
));
213 Endpoint_Write_Byte(STATUS_CMD_FAILED
);
219 static void V2Protocol_Command_LoadAddress(void)
221 Endpoint_Read_Stream_LE(&CurrentAddress
, sizeof(CurrentAddress
));
224 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
226 // TODO: Check for extended address
228 Endpoint_Write_Byte(CMD_LOAD_ADDRESS
);
229 Endpoint_Write_Byte(STATUS_CMD_OK
);
233 static void V2Protocol_Command_EnterISPMode(void)
238 uint8_t PinStabDelayMS
;
239 uint8_t ExecutionDelayMS
;
244 uint8_t EnterProgBytes
[4];
247 Endpoint_Read_Stream_LE(&Enter_ISP_Params
, sizeof(Enter_ISP_Params
));
250 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
252 uint8_t ResponseStatus
= STATUS_CMD_FAILED
;
256 V2Protocol_DelayMS(Enter_ISP_Params
.ExecutionDelayMS
);
257 SPI_Init(V2Protocol_GetSPIPrescalerMask() | SPI_SCK_LEAD_RISING
| SPI_SAMPLE_LEADING
| SPI_MODE_MASTER
);
258 V2Protocol_ChangeTargetResetLine(true);
259 V2Protocol_DelayMS(Enter_ISP_Params
.PinStabDelayMS
);
261 while (Enter_ISP_Params
.SynchLoops
-- && (ResponseStatus
== STATUS_CMD_FAILED
))
263 uint8_t ResponseBytes
[4];
265 for (uint8_t RByte
= 0; RByte
< sizeof(ResponseBytes
); RByte
++)
267 V2Protocol_DelayMS(Enter_ISP_Params
.ByteDelay
);
268 ResponseBytes
[RByte
] = SPI_TransferByte(Enter_ISP_Params
.EnterProgBytes
[RByte
]);
271 /* Check if polling disabled, or if the polled value matches the expected value */
272 if (!Enter_ISP_Params
.PollIndex
|| (ResponseBytes
[Enter_ISP_Params
.PollIndex
- 1] == Enter_ISP_Params
.PollValue
))
273 ResponseStatus
= STATUS_CMD_OK
;
276 Endpoint_Write_Byte(CMD_ENTER_PROGMODE_ISP
);
277 Endpoint_Write_Byte(ResponseStatus
);
281 static void V2Protocol_Command_LeaveISPMode(void)
289 Endpoint_Read_Stream_LE(&Leave_ISP_Params
, sizeof(Leave_ISP_Params
));
292 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
294 V2Protocol_DelayMS(Leave_ISP_Params
.PreDelayMS
);
295 V2Protocol_ChangeTargetResetLine(false);
297 V2Protocol_DelayMS(Leave_ISP_Params
.PostDelayMS
);
299 Endpoint_Write_Byte(CMD_LEAVE_PROGMODE_ISP
);
300 Endpoint_Write_Byte(STATUS_CMD_OK
);
304 static void V2Protocol_Command_ChipErase(void)
308 uint8_t EraseDelayMS
;
310 uint8_t EraseCommandBytes
[4];
313 Endpoint_Read_Stream_LE(&Erase_Chip_Params
, sizeof(Erase_Chip_Params
));
316 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
318 uint8_t ResponseStatus
= STATUS_CMD_OK
;
320 for (uint8_t SByte
= 0; SByte
< sizeof(Erase_Chip_Params
.EraseCommandBytes
); SByte
++)
321 SPI_SendByte(Erase_Chip_Params
.EraseCommandBytes
[SByte
]);
323 if (Erase_Chip_Params
.PollMethod
== 0)
324 V2Protocol_DelayMS(Erase_Chip_Params
.EraseDelayMS
);
326 ResponseStatus
= V2Protocol_WaitWhileTargetBusy();
328 Endpoint_Write_Byte(CMD_CHIP_ERASE_ISP
);
329 Endpoint_Write_Byte(ResponseStatus
);
333 static void V2Protocol_Command_ReadFuseLockSigOSCCAL(uint8_t V2Command
)
338 uint8_t ReadCommandBytes
[4];
339 } Read_FuseLockSigOSCCAL_Params
;
341 Endpoint_Read_Stream_LE(&Read_FuseLockSigOSCCAL_Params
, sizeof(Read_FuseLockSigOSCCAL_Params
));
344 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
346 uint8_t ResponseBytes
[4];
348 for (uint8_t RByte
= 0; RByte
< sizeof(ResponseBytes
); RByte
++)
349 ResponseBytes
[RByte
] = SPI_TransferByte(Read_FuseLockSigOSCCAL_Params
.ReadCommandBytes
[RByte
]);
351 Endpoint_Write_Byte(V2Command
);
352 Endpoint_Write_Byte(STATUS_CMD_OK
);
353 Endpoint_Write_Byte(ResponseBytes
[Read_FuseLockSigOSCCAL_Params
.RetByte
]);
354 Endpoint_Write_Byte(STATUS_CMD_OK
);
358 static void V2Protocol_Command_WriteFuseLock(uint8_t V2Command
)
362 uint8_t WriteCommandBytes
[4];
363 } Write_FuseLockSig_Params
;
365 Endpoint_Read_Stream_LE(&Write_FuseLockSig_Params
, sizeof(Write_FuseLockSig_Params
));
368 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
370 for (uint8_t SByte
= 0; SByte
< sizeof(Write_FuseLockSig_Params
.WriteCommandBytes
); SByte
++)
371 SPI_SendByte(Write_FuseLockSig_Params
.WriteCommandBytes
[SByte
]);
373 Endpoint_Write_Byte(V2Command
);
374 Endpoint_Write_Byte(STATUS_CMD_OK
);
375 Endpoint_Write_Byte(STATUS_CMD_OK
);
379 static void V2Protocol_Command_SPIMulti(void)
389 Endpoint_Read_Stream_LE(&SPI_Multi_Params
, sizeof(SPI_Multi_Params
) -
390 sizeof(SPI_Multi_Params
.TxData
));
391 Endpoint_Read_Stream_LE(&SPI_Multi_Params
.TxData
, SPI_Multi_Params
.TxBytes
);
394 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
396 Endpoint_Write_Byte(CMD_SPI_MULTI
);
397 Endpoint_Write_Byte(STATUS_CMD_OK
);
399 uint8_t CurrTxPos
= 0;
400 uint8_t CurrRxPos
= 0;
402 /* Write out bytes to transmit until the start of the bytes to receive is met */
403 while (CurrTxPos
< SPI_Multi_Params
.RxStartAddr
)
405 if (CurrTxPos
< SPI_Multi_Params
.TxBytes
)
406 SPI_SendByte(SPI_Multi_Params
.TxData
[CurrTxPos
]);
413 /* Transmit remaining bytes with padding as needed, read in response bytes */
414 while (CurrRxPos
< SPI_Multi_Params
.RxBytes
)
416 if (CurrTxPos
< SPI_Multi_Params
.TxBytes
)
417 Endpoint_Write_Byte(SPI_TransferByte(SPI_Multi_Params
.TxData
[CurrTxPos
++]));
419 Endpoint_Write_Byte(SPI_ReceiveByte());
424 Endpoint_Write_Byte(STATUS_CMD_OK
);