2feefc8db5272f0dab636d1d3704caf0f75f0d76
[pub/USBasp.git] / Projects / Incomplete / AVRISP / Lib / V2Protocol.c
1 /*
2 LUFA Library
3 Copyright (C) Dean Camera, 2009.
4
5 dean [at] fourwalledcubicle [dot] com
6 www.fourwalledcubicle.com
7 */
8
9 /*
10 Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)
11
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.
20
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
28 this software.
29 */
30
31 /** \file
32 *
33 * V2Protocol handler, to process V2 Protocol commands used in Atmel programmer devices.
34 */
35
36 #define INCLUDE_FROM_V2PROTOCOL_C
37 #include "V2Protocol.h"
38
39 void V2Protocol_ProcessCommand(void)
40 {
41 uint8_t V2Command = Endpoint_Read_Byte();
42
43 switch (V2Command)
44 {
45 case CMD_SIGN_ON:
46 V2Protocol_Command_SignOn();
47 break;
48 case CMD_SET_PARAMETER:
49 case CMD_GET_PARAMETER:
50 V2Protocol_Command_GetSetParam(V2Command);
51 break;
52 case CMD_LOAD_ADDRESS:
53 V2Protocol_Command_LoadAddress();
54 break;
55 case CMD_ENTER_PROGMODE_ISP:
56 V2Protocol_Command_EnterISPMode();
57 break;
58 case CMD_LEAVE_PROGMODE_ISP:
59 V2Protocol_Command_LeaveISPMode();
60 break;
61 case CMD_CHIP_ERASE_ISP:
62 V2Protocol_Command_ChipErase();
63 break;
64 case CMD_READ_FUSE_ISP:
65 case CMD_READ_LOCK_ISP:
66 case CMD_READ_SIGNATURE_ISP:
67 case CMD_READ_OSCCAL_ISP:
68 V2Protocol_Command_ReadFuseLockSigOSCCAL(V2Command);
69 break;
70 case CMD_PROGRAM_FUSE_ISP:
71 case CMD_PROGRAM_LOCK_ISP:
72 V2Protocol_Command_WriteFuseLock(V2Command);
73 break;
74 case CMD_SPI_MULTI:
75 V2Protocol_Command_SPIMulti();
76 break;
77 default:
78 V2Protocol_Command_Unknown(V2Command);
79 break;
80 }
81
82 Endpoint_WaitUntilReady();
83 Endpoint_SetEndpointDirection(ENDPOINT_DIR_OUT);
84 }
85
86 static void V2Protocol_Command_Unknown(uint8_t V2Command)
87 {
88 /* Discard all incomming data */
89 while (Endpoint_BytesInEndpoint() == AVRISP_DATA_EPSIZE)
90 {
91 Endpoint_ClearOUT();
92 Endpoint_WaitUntilReady();
93 }
94
95 Endpoint_ClearOUT();
96 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
97
98 Endpoint_Write_Byte(V2Command);
99 Endpoint_Write_Byte(STATUS_CMD_UNKNOWN);
100 Endpoint_ClearIN();
101 }
102
103 static void V2Protocol_Command_SignOn(void)
104 {
105 Endpoint_ClearOUT();
106 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
107
108 Endpoint_Write_Byte(CMD_SIGN_ON);
109 Endpoint_Write_Byte(STATUS_CMD_OK);
110 Endpoint_Write_Byte(sizeof(PROGRAMMER_ID) - 1);
111 Endpoint_Write_Stream_LE(PROGRAMMER_ID, (sizeof(PROGRAMMER_ID) - 1));
112 Endpoint_ClearIN();
113 }
114
115 static void V2Protocol_Command_GetSetParam(uint8_t V2Command)
116 {
117 uint8_t ParamID = Endpoint_Read_Byte();
118 uint8_t ParamValue;
119
120 if (V2Command == CMD_SET_PARAMETER)
121 ParamValue = Endpoint_Read_Byte();
122
123 Endpoint_ClearOUT();
124 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
125
126 Endpoint_Write_Byte(V2Command);
127
128 uint8_t ParamPrivs = V2Params_GetParameterPrivellages(ParamID);
129
130 if ((V2Command == CMD_SET_PARAMETER) && (ParamPrivs & PARAM_PRIV_WRITE))
131 {
132 Endpoint_Write_Byte(STATUS_CMD_OK);
133 V2Params_SetParameterValue(ParamID, ParamValue);
134 }
135 else if ((V2Command == CMD_GET_PARAMETER) && (ParamPrivs & PARAM_PRIV_READ))
136 {
137 Endpoint_Write_Byte(STATUS_CMD_OK);
138 Endpoint_Write_Byte(V2Params_GetParameterValue(ParamID));
139 }
140 else
141 {
142 Endpoint_Write_Byte(STATUS_CMD_FAILED);
143 }
144
145 Endpoint_ClearIN();
146 }
147
148 static void V2Protocol_Command_LoadAddress(void)
149 {
150 Endpoint_Read_Stream_LE(&CurrentAddress, sizeof(CurrentAddress));
151
152 Endpoint_ClearOUT();
153 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
154
155 if (CurrentAddress & (1UL << 31))
156 V2Protocol_LoadExtendedAddress();
157
158 Endpoint_Write_Byte(CMD_LOAD_ADDRESS);
159 Endpoint_Write_Byte(STATUS_CMD_OK);
160 Endpoint_ClearIN();
161 }
162
163 static void V2Protocol_Command_EnterISPMode(void)
164 {
165 struct
166 {
167 uint8_t TimeoutMS;
168 uint8_t PinStabDelayMS;
169 uint8_t ExecutionDelayMS;
170 uint8_t SynchLoops;
171 uint8_t ByteDelay;
172 uint8_t PollValue;
173 uint8_t PollIndex;
174 uint8_t EnterProgBytes[4];
175 } Enter_ISP_Params;
176
177 Endpoint_Read_Stream_LE(&Enter_ISP_Params, sizeof(Enter_ISP_Params));
178
179 Endpoint_ClearOUT();
180 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
181
182 uint8_t ResponseStatus = STATUS_CMD_FAILED;
183
184 CurrentAddress = 0;
185
186 V2Protocol_DelayMS(Enter_ISP_Params.ExecutionDelayMS);
187 SPI_Init(V2Protocol_GetSPIPrescalerMask() | SPI_SCK_LEAD_RISING | SPI_SAMPLE_LEADING | SPI_MODE_MASTER);
188 V2Protocol_ChangeTargetResetLine(true);
189 V2Protocol_DelayMS(Enter_ISP_Params.PinStabDelayMS);
190
191 while (Enter_ISP_Params.SynchLoops-- && (ResponseStatus == STATUS_CMD_FAILED))
192 {
193 uint8_t ResponseBytes[4];
194
195 for (uint8_t RByte = 0; RByte < sizeof(ResponseBytes); RByte++)
196 {
197 V2Protocol_DelayMS(Enter_ISP_Params.ByteDelay);
198 ResponseBytes[RByte] = SPI_TransferByte(Enter_ISP_Params.EnterProgBytes[RByte]);
199 }
200
201 /* Check if polling disabled, or if the polled value matches the expected value */
202 if (!Enter_ISP_Params.PollIndex || (ResponseBytes[Enter_ISP_Params.PollIndex - 1] == Enter_ISP_Params.PollValue))
203 ResponseStatus = STATUS_CMD_OK;
204 }
205
206 Endpoint_Write_Byte(CMD_ENTER_PROGMODE_ISP);
207 Endpoint_Write_Byte(ResponseStatus);
208 Endpoint_ClearIN();
209 }
210
211 static void V2Protocol_Command_LeaveISPMode(void)
212 {
213 struct
214 {
215 uint8_t PreDelayMS;
216 uint8_t PostDelayMS;
217 } Leave_ISP_Params;
218
219 Endpoint_Read_Stream_LE(&Leave_ISP_Params, sizeof(Leave_ISP_Params));
220
221 Endpoint_ClearOUT();
222 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
223
224 V2Protocol_DelayMS(Leave_ISP_Params.PreDelayMS);
225 V2Protocol_ChangeTargetResetLine(false);
226 SPI_ShutDown();
227 V2Protocol_DelayMS(Leave_ISP_Params.PostDelayMS);
228
229 Endpoint_Write_Byte(CMD_LEAVE_PROGMODE_ISP);
230 Endpoint_Write_Byte(STATUS_CMD_OK);
231 Endpoint_ClearIN();
232 }
233
234 static void V2Protocol_Command_ChipErase(void)
235 {
236 struct
237 {
238 uint8_t EraseDelayMS;
239 uint8_t PollMethod;
240 uint8_t EraseCommandBytes[4];
241 } Erase_Chip_Params;
242
243 Endpoint_Read_Stream_LE(&Erase_Chip_Params, sizeof(Erase_Chip_Params));
244
245 Endpoint_ClearOUT();
246 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
247
248 uint8_t ResponseStatus = STATUS_CMD_OK;
249
250 for (uint8_t SByte = 0; SByte < sizeof(Erase_Chip_Params.EraseCommandBytes); SByte++)
251 SPI_SendByte(Erase_Chip_Params.EraseCommandBytes[SByte]);
252
253 if (Erase_Chip_Params.PollMethod == 0)
254 V2Protocol_DelayMS(Erase_Chip_Params.EraseDelayMS);
255 else
256 ResponseStatus = V2Protocol_WaitWhileTargetBusy();
257
258 Endpoint_Write_Byte(CMD_CHIP_ERASE_ISP);
259 Endpoint_Write_Byte(ResponseStatus);
260 Endpoint_ClearIN();
261 }
262
263 static void V2Protocol_Command_ReadFuseLockSigOSCCAL(uint8_t V2Command)
264 {
265 struct
266 {
267 uint8_t RetByte;
268 uint8_t ReadCommandBytes[4];
269 } Read_FuseLockSigOSCCAL_Params;
270
271 Endpoint_Read_Stream_LE(&Read_FuseLockSigOSCCAL_Params, sizeof(Read_FuseLockSigOSCCAL_Params));
272
273 Endpoint_ClearOUT();
274 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
275
276 uint8_t ResponseBytes[4];
277
278 for (uint8_t RByte = 0; RByte < sizeof(ResponseBytes); RByte++)
279 ResponseBytes[RByte] = SPI_TransferByte(Read_FuseLockSigOSCCAL_Params.ReadCommandBytes[RByte]);
280
281 Endpoint_Write_Byte(V2Command);
282 Endpoint_Write_Byte(STATUS_CMD_OK);
283 Endpoint_Write_Byte(ResponseBytes[Read_FuseLockSigOSCCAL_Params.RetByte]);
284 Endpoint_Write_Byte(STATUS_CMD_OK);
285 Endpoint_ClearIN();
286 }
287
288 static void V2Protocol_Command_WriteFuseLock(uint8_t V2Command)
289 {
290 struct
291 {
292 uint8_t WriteCommandBytes[4];
293 } Write_FuseLockSig_Params;
294
295 Endpoint_Read_Stream_LE(&Write_FuseLockSig_Params, sizeof(Write_FuseLockSig_Params));
296
297 Endpoint_ClearOUT();
298 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
299
300 for (uint8_t SByte = 0; SByte < sizeof(Write_FuseLockSig_Params.WriteCommandBytes); SByte++)
301 SPI_SendByte(Write_FuseLockSig_Params.WriteCommandBytes[SByte]);
302
303 Endpoint_Write_Byte(V2Command);
304 Endpoint_Write_Byte(STATUS_CMD_OK);
305 Endpoint_Write_Byte(STATUS_CMD_OK);
306 Endpoint_ClearIN();
307 }
308
309 static void V2Protocol_Command_SPIMulti(void)
310 {
311 struct
312 {
313 uint8_t TxBytes;
314 uint8_t RxBytes;
315 uint8_t RxStartAddr;
316 uint8_t TxData[255];
317 } SPI_Multi_Params;
318
319 Endpoint_Read_Stream_LE(&SPI_Multi_Params, sizeof(SPI_Multi_Params) -
320 sizeof(SPI_Multi_Params.TxData));
321 Endpoint_Read_Stream_LE(&SPI_Multi_Params.TxData, SPI_Multi_Params.TxBytes);
322
323 Endpoint_ClearOUT();
324 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
325
326 Endpoint_Write_Byte(CMD_SPI_MULTI);
327 Endpoint_Write_Byte(STATUS_CMD_OK);
328
329 uint8_t CurrTxPos = 0;
330 uint8_t CurrRxPos = 0;
331
332 /* Write out bytes to transmit until the start of the bytes to receive is met */
333 while (CurrTxPos < SPI_Multi_Params.RxStartAddr)
334 {
335 if (CurrTxPos < SPI_Multi_Params.TxBytes)
336 SPI_SendByte(SPI_Multi_Params.TxData[CurrTxPos]);
337 else
338 SPI_SendByte(0);
339
340 CurrTxPos++;
341 }
342
343 /* Transmit remaining bytes with padding as needed, read in response bytes */
344 while (CurrRxPos < SPI_Multi_Params.RxBytes)
345 {
346 if (CurrTxPos < SPI_Multi_Params.TxBytes)
347 Endpoint_Write_Byte(SPI_TransferByte(SPI_Multi_Params.TxData[CurrTxPos++]));
348 else
349 Endpoint_Write_Byte(SPI_ReceiveByte());
350
351 CurrRxPos++;
352 }
353
354 Endpoint_Write_Byte(STATUS_CMD_OK);
355 Endpoint_ClearIN();
356 }