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 printf("COMMAND 0x%02x\r\n", V2Command
);
155 Endpoint_WaitUntilReady();
156 Endpoint_SetEndpointDirection(ENDPOINT_DIR_OUT
);
159 static void V2Protocol_Command_Unknown(uint8_t V2Command
)
161 /* Discard all incomming data */
162 while (Endpoint_BytesInEndpoint() == AVRISP_DATA_EPSIZE
)
165 Endpoint_WaitUntilReady();
169 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
170 Endpoint_WaitUntilReady();
172 Endpoint_Write_Byte(V2Command
);
173 Endpoint_Write_Byte(STATUS_CMD_UNKNOWN
);
177 static void V2Protocol_Command_SignOn(void)
180 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
181 Endpoint_WaitUntilReady();
183 Endpoint_Write_Byte(CMD_SIGN_ON
);
184 Endpoint_Write_Byte(STATUS_CMD_OK
);
185 Endpoint_Write_Byte(sizeof(PROGRAMMER_ID
) - 1);
186 Endpoint_Write_Stream_LE(PROGRAMMER_ID
, (sizeof(PROGRAMMER_ID
) - 1));
190 static void V2Protocol_Command_GetSetParam(uint8_t V2Command
)
196 } Get_Set_Param_Params
;
198 Endpoint_Read_Stream_LE(&Get_Set_Param_Params
, sizeof(Get_Set_Param_Params
));
201 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
202 Endpoint_WaitUntilReady();
204 uint8_t ParamPrivs
= V2Params_GetParameterPrivellages(Get_Set_Param_Params
.ParamID
);
206 Endpoint_Write_Byte(V2Command
);
208 if ((V2Command
== CMD_SET_PARAMETER
) && (ParamPrivs
& PARAM_PRIV_WRITE
))
210 Endpoint_Write_Byte(STATUS_CMD_OK
);
211 V2Params_SetParameterValue(Get_Set_Param_Params
.ParamID
, Get_Set_Param_Params
.ParamValue
);
213 else if ((V2Command
== CMD_GET_PARAMETER
) && (ParamPrivs
& PARAM_PRIV_READ
))
215 Endpoint_Write_Byte(STATUS_CMD_OK
);
216 Endpoint_Write_Byte(V2Params_GetParameterValue(Get_Set_Param_Params
.ParamID
));
220 Endpoint_Write_Byte(STATUS_CMD_FAILED
);
226 static void V2Protocol_Command_LoadAddress(void)
228 Endpoint_Read_Stream_LE(&CurrentAddress
, sizeof(CurrentAddress
));
231 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
232 Endpoint_WaitUntilReady();
234 // TODO: Check for extended address
236 Endpoint_Write_Byte(CMD_LOAD_ADDRESS
);
237 Endpoint_Write_Byte(STATUS_CMD_OK
);
241 static void V2Protocol_Command_EnterISPMode(void)
246 uint8_t PinStabDelayMS
;
247 uint8_t ExecutionDelayMS
;
252 uint8_t EnterProgBytes
[4];
255 Endpoint_Read_Stream_LE(&Enter_ISP_Params
, sizeof(Enter_ISP_Params
));
258 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
259 Endpoint_WaitUntilReady();
261 uint8_t SCKDuration
= V2Params_GetParameterValue(PARAM_SCK_DURATION
);
262 uint8_t ResponseStatus
= STATUS_CMD_FAILED
;
264 Enter_ISP_Params
.TimeoutMS
-= Enter_ISP_Params
.ExecutionDelayMS
+
265 Enter_ISP_Params
.PinStabDelayMS
;
269 if (SCKDuration
>= sizeof(SPIMaskFromSCKDuration
))
270 SCKDuration
= (sizeof(SPIMaskFromSCKDuration
) - 1);
272 V2Protocol_DelayMS(Enter_ISP_Params
.ExecutionDelayMS
);
273 SPI_Init(SPIMaskFromSCKDuration
[SCKDuration
], true);
274 V2Protocol_ChangeTargetResetLine(true);
275 V2Protocol_DelayMS(Enter_ISP_Params
.PinStabDelayMS
);
277 while (Enter_ISP_Params
.SynchLoops
-- && (ResponseStatus
== STATUS_CMD_FAILED
))
279 uint8_t ResponseBytes
[4];
281 for (uint8_t RByte
= 0; RByte
< sizeof(ResponseBytes
); RByte
++)
283 ResponseBytes
[RByte
] = SPI_TransferByte(Enter_ISP_Params
.EnterProgBytes
[RByte
]);
284 V2Protocol_DelayMS(Enter_ISP_Params
.ByteDelay
);
286 if (Enter_ISP_Params
.TimeoutMS
>= Enter_ISP_Params
.ByteDelay
)
287 Enter_ISP_Params
.TimeoutMS
-= Enter_ISP_Params
.ByteDelay
;
289 ResponseStatus
= STATUS_CMD_TOUT
;
292 if (ResponseBytes
[Enter_ISP_Params
.PollIndex
] == Enter_ISP_Params
.PollValue
)
293 ResponseStatus
= STATUS_CMD_OK
;
296 Endpoint_Write_Byte(CMD_ENTER_PROGMODE_ISP
);
297 Endpoint_Write_Byte(ResponseStatus
);
301 static void V2Protocol_Command_LeaveISPMode(void)
309 Endpoint_Read_Stream_LE(&Leave_ISP_Params
, sizeof(Leave_ISP_Params
));
312 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
313 Endpoint_WaitUntilReady();
315 V2Protocol_DelayMS(Leave_ISP_Params
.PreDelayMS
);
316 V2Protocol_ChangeTargetResetLine(false);
318 V2Protocol_DelayMS(Leave_ISP_Params
.PostDelayMS
);
320 Endpoint_Write_Byte(CMD_LEAVE_PROGMODE_ISP
);
321 Endpoint_Write_Byte(STATUS_CMD_OK
);
325 static void V2Protocol_Command_ChipErase(void)
329 uint8_t EraseDelayMS
;
331 uint8_t EraseCommandBytes
[4];
334 Endpoint_Read_Stream_LE(&Erase_Chip_Params
, sizeof(Erase_Chip_Params
));
337 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
338 Endpoint_WaitUntilReady();
340 uint8_t ResponseStatus
= STATUS_CMD_OK
;
342 for (uint8_t SByte
= 0; SByte
< sizeof(Erase_Chip_Params
.EraseCommandBytes
); SByte
++)
343 SPI_SendByte(Erase_Chip_Params
.EraseCommandBytes
[SByte
]);
345 if (Erase_Chip_Params
.PollMethod
== 0)
346 V2Protocol_DelayMS(Erase_Chip_Params
.EraseDelayMS
);
348 ResponseStatus
= V2Protocol_WaitWhileTargetBusy();
350 Endpoint_Write_Byte(CMD_CHIP_ERASE_ISP
);
351 Endpoint_Write_Byte(ResponseStatus
);
355 static void V2Protocol_Command_ReadFuseLockSigOSCCAL(uint8_t V2Command
)
360 uint8_t ReadCommandBytes
[4];
361 } Read_FuseLockSigOSCCAL_Params
;
363 Endpoint_Read_Stream_LE(&Read_FuseLockSigOSCCAL_Params
, sizeof(Read_FuseLockSigOSCCAL_Params
));
366 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
367 Endpoint_WaitUntilReady();
369 uint8_t ResponseBytes
[4];
371 for (uint8_t RByte
= 0; RByte
< sizeof(ResponseBytes
); RByte
++)
372 ResponseBytes
[RByte
] = SPI_TransferByte(Read_FuseLockSigOSCCAL_Params
.ReadCommandBytes
[RByte
]);
374 Endpoint_Write_Byte(V2Command
);
375 Endpoint_Write_Byte(STATUS_CMD_OK
);
376 Endpoint_Write_Byte(ResponseBytes
[Read_FuseLockSigOSCCAL_Params
.RetByte
]);
377 Endpoint_Write_Byte(STATUS_CMD_OK
);
381 static void V2Protocol_Command_WriteFuseLock(uint8_t V2Command
)
385 uint8_t WriteCommandBytes
[4];
386 } Write_FuseLockSig_Params
;
388 Endpoint_Read_Stream_LE(&Write_FuseLockSig_Params
, sizeof(Write_FuseLockSig_Params
));
391 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
392 Endpoint_WaitUntilReady();
394 for (uint8_t SByte
= 0; SByte
< sizeof(Write_FuseLockSig_Params
.WriteCommandBytes
); SByte
++)
395 SPI_SendByte(Write_FuseLockSig_Params
.WriteCommandBytes
[SByte
]);
397 Endpoint_Write_Byte(V2Command
);
398 Endpoint_Write_Byte(STATUS_CMD_OK
);
399 Endpoint_Write_Byte(STATUS_CMD_OK
);
403 static void V2Protocol_Command_SPIMulti(void)
413 Endpoint_Read_Stream_LE(&SPI_Multi_Params
, sizeof(SPI_Multi_Params
) -
414 sizeof(SPI_Multi_Params
.TxData
));
415 Endpoint_Read_Stream_LE(&SPI_Multi_Params
.TxData
, SPI_Multi_Params
.TxBytes
);
418 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
419 Endpoint_WaitUntilReady();
421 Endpoint_Write_Byte(CMD_SPI_MULTI
);
422 Endpoint_Write_Byte(STATUS_CMD_OK
);
424 uint8_t CurrTxPos
= 0;
425 uint8_t CurrRxPos
= 0;
427 /* Write out bytes to transmit until the start of the bytes to receive is met */
428 while (CurrTxPos
< SPI_Multi_Params
.RxStartAddr
)
430 if (CurrTxPos
< SPI_Multi_Params
.TxBytes
)
431 SPI_SendByte(SPI_Multi_Params
.TxData
[CurrTxPos
]);
438 /* Transmit remaining bytes with padding as needed, read in response bytes */
439 while (CurrRxPos
< SPI_Multi_Params
.RxBytes
)
441 if (CurrTxPos
< SPI_Multi_Params
.TxBytes
)
442 Endpoint_Write_Byte(SPI_TransferByte(SPI_Multi_Params
.TxData
[CurrTxPos
++]));
444 Endpoint_Write_Byte(SPI_ReceiveByte());
449 Endpoint_Write_Byte(STATUS_CMD_OK
);