Added V2Protocol handlers to the AVRISP project to enter/exit programming mode, and...
[pub/lufa.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 uint32_t CurrentAddress;
40
41
42 /* Table of masks for SPI_Init() from a given PARAM_SCK_DURATION value */
43 static const uint8_t SPIMaskFromSCKDuration[] =
44 {
45 #if (F_CPU == 8000000)
46 SPI_SPEED_FCPU_DIV_2,
47 #endif
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
52 #endif
53 };
54
55 static uint8_t V2Protocol_GetSPIPrescalerMask(void)
56 {
57 uint8_t SCKDuration = V2Params_GetParameterValue(PARAM_SCK_DURATION);
58
59 if (SCKDuration >= sizeof(SPIMaskFromSCKDuration))
60 SCKDuration = (sizeof(SPIMaskFromSCKDuration) - 1);
61
62 return SPIMaskFromSCKDuration[SCKDuration];
63 }
64
65 static void V2Protocol_ChangeTargetResetLine(bool ResetTarget)
66 {
67 if (ResetTarget)
68 {
69 RESET_LINE_DDR |= RESET_LINE_MASK;
70
71 if (!(V2Params_GetParameterValue(PARAM_RESET_POLARITY)))
72 RESET_LINE_PORT |= RESET_LINE_MASK;
73 }
74 else
75 {
76 RESET_LINE_PORT &= ~RESET_LINE_MASK;
77 RESET_LINE_DDR &= ~RESET_LINE_MASK;
78 }
79 }
80
81 static void V2Protocol_DelayMS(uint8_t MS)
82 {
83 while (MS--)
84 _delay_ms(1);
85 }
86
87 static uint8_t V2Protocol_WaitWhileTargetBusy(void)
88 {
89 uint8_t TimeoutMS = TARGET_BUST_TIMEOUT_MS;
90 uint8_t ResponseByte;
91
92 do
93 {
94 V2Protocol_DelayMS(1);
95
96 SPI_SendByte(0xF0);
97 SPI_SendByte(0x00);
98
99 SPI_SendByte(0x00);
100 ResponseByte = SPI_ReceiveByte();
101 }
102 while ((ResponseByte & 0x01) && (TimeoutMS--));
103
104 if (!(TimeoutMS))
105 return STATUS_CMD_TOUT;
106 else
107 return STATUS_CMD_OK;
108 }
109
110 void V2Protocol_ProcessCommand(void)
111 {
112 uint8_t V2Command = Endpoint_Read_Byte();
113
114 switch (V2Command)
115 {
116 case CMD_SIGN_ON:
117 V2Protocol_Command_SignOn();
118 break;
119 case CMD_SET_PARAMETER:
120 case CMD_GET_PARAMETER:
121 V2Protocol_Command_GetSetParam(V2Command);
122 break;
123 case CMD_LOAD_ADDRESS:
124 V2Protocol_Command_LoadAddress();
125 break;
126 case CMD_ENTER_PROGMODE_ISP:
127 V2Protocol_Command_EnterISPMode();
128 break;
129 case CMD_LEAVE_PROGMODE_ISP:
130 V2Protocol_Command_LeaveISPMode();
131 break;
132 case CMD_CHIP_ERASE_ISP:
133 V2Protocol_Command_ChipErase();
134 break;
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);
140 break;
141 case CMD_PROGRAM_FUSE_ISP:
142 case CMD_PROGRAM_LOCK_ISP:
143 V2Protocol_Command_WriteFuseLock(V2Command);
144 break;
145 case CMD_SPI_MULTI:
146 V2Protocol_Command_SPIMulti();
147 break;
148 default:
149 V2Protocol_Command_Unknown(V2Command);
150 break;
151 }
152
153 printf("COMMAND 0x%02x\r\n", V2Command);
154
155 Endpoint_WaitUntilReady();
156 Endpoint_SetEndpointDirection(ENDPOINT_DIR_OUT);
157 }
158
159 static void V2Protocol_Command_Unknown(uint8_t V2Command)
160 {
161 /* Discard all incomming data */
162 while (Endpoint_BytesInEndpoint() == AVRISP_DATA_EPSIZE)
163 {
164 Endpoint_ClearOUT();
165 Endpoint_WaitUntilReady();
166 }
167
168 Endpoint_ClearOUT();
169 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
170 Endpoint_WaitUntilReady();
171
172 Endpoint_Write_Byte(V2Command);
173 Endpoint_Write_Byte(STATUS_CMD_UNKNOWN);
174 Endpoint_ClearIN();
175 }
176
177 static void V2Protocol_Command_SignOn(void)
178 {
179 Endpoint_ClearOUT();
180 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
181 Endpoint_WaitUntilReady();
182
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));
187 Endpoint_ClearIN();
188 }
189
190 static void V2Protocol_Command_GetSetParam(uint8_t V2Command)
191 {
192 struct
193 {
194 uint8_t ParamID;
195 uint8_t ParamValue;
196 } Get_Set_Param_Params;
197
198 Endpoint_Read_Stream_LE(&Get_Set_Param_Params, sizeof(Get_Set_Param_Params));
199
200 Endpoint_ClearOUT();
201 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
202 Endpoint_WaitUntilReady();
203
204 uint8_t ParamPrivs = V2Params_GetParameterPrivellages(Get_Set_Param_Params.ParamID);
205
206 Endpoint_Write_Byte(V2Command);
207
208 if ((V2Command == CMD_SET_PARAMETER) && (ParamPrivs & PARAM_PRIV_WRITE))
209 {
210 Endpoint_Write_Byte(STATUS_CMD_OK);
211 V2Params_SetParameterValue(Get_Set_Param_Params.ParamID, Get_Set_Param_Params.ParamValue);
212 }
213 else if ((V2Command == CMD_GET_PARAMETER) && (ParamPrivs & PARAM_PRIV_READ))
214 {
215 Endpoint_Write_Byte(STATUS_CMD_OK);
216 Endpoint_Write_Byte(V2Params_GetParameterValue(Get_Set_Param_Params.ParamID));
217 }
218 else
219 {
220 Endpoint_Write_Byte(STATUS_CMD_FAILED);
221 }
222
223 Endpoint_ClearIN();
224 }
225
226 static void V2Protocol_Command_LoadAddress(void)
227 {
228 Endpoint_Read_Stream_LE(&CurrentAddress, sizeof(CurrentAddress));
229
230 Endpoint_ClearOUT();
231 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
232 Endpoint_WaitUntilReady();
233
234 // TODO: Check for extended address
235
236 Endpoint_Write_Byte(CMD_LOAD_ADDRESS);
237 Endpoint_Write_Byte(STATUS_CMD_OK);
238 Endpoint_ClearIN();
239 }
240
241 static void V2Protocol_Command_EnterISPMode(void)
242 {
243 struct
244 {
245 uint8_t TimeoutMS;
246 uint8_t PinStabDelayMS;
247 uint8_t ExecutionDelayMS;
248 uint8_t SynchLoops;
249 uint8_t ByteDelay;
250 uint8_t PollValue;
251 uint8_t PollIndex;
252 uint8_t EnterProgBytes[4];
253 } Enter_ISP_Params;
254
255 Endpoint_Read_Stream_LE(&Enter_ISP_Params, sizeof(Enter_ISP_Params));
256
257 Endpoint_ClearOUT();
258 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
259 Endpoint_WaitUntilReady();
260
261 uint8_t SCKDuration = V2Params_GetParameterValue(PARAM_SCK_DURATION);
262 uint8_t ResponseStatus = STATUS_CMD_FAILED;
263
264 Enter_ISP_Params.TimeoutMS -= Enter_ISP_Params.ExecutionDelayMS +
265 Enter_ISP_Params.PinStabDelayMS;
266
267 CurrentAddress = 0;
268
269 if (SCKDuration >= sizeof(SPIMaskFromSCKDuration))
270 SCKDuration = (sizeof(SPIMaskFromSCKDuration) - 1);
271
272 V2Protocol_DelayMS(Enter_ISP_Params.ExecutionDelayMS);
273 SPI_Init(SPIMaskFromSCKDuration[SCKDuration], true);
274 V2Protocol_ChangeTargetResetLine(true);
275 V2Protocol_DelayMS(Enter_ISP_Params.PinStabDelayMS);
276
277 while (Enter_ISP_Params.SynchLoops-- && (ResponseStatus == STATUS_CMD_FAILED))
278 {
279 uint8_t ResponseBytes[4];
280
281 for (uint8_t RByte = 0; RByte < sizeof(ResponseBytes); RByte++)
282 {
283 ResponseBytes[RByte] = SPI_TransferByte(Enter_ISP_Params.EnterProgBytes[RByte]);
284 V2Protocol_DelayMS(Enter_ISP_Params.ByteDelay);
285
286 if (Enter_ISP_Params.TimeoutMS >= Enter_ISP_Params.ByteDelay)
287 Enter_ISP_Params.TimeoutMS -= Enter_ISP_Params.ByteDelay;
288 else
289 ResponseStatus = STATUS_CMD_TOUT;
290 }
291
292 if (ResponseBytes[Enter_ISP_Params.PollIndex] == Enter_ISP_Params.PollValue)
293 ResponseStatus = STATUS_CMD_OK;
294 }
295
296 Endpoint_Write_Byte(CMD_ENTER_PROGMODE_ISP);
297 Endpoint_Write_Byte(ResponseStatus);
298 Endpoint_ClearIN();
299 }
300
301 static void V2Protocol_Command_LeaveISPMode(void)
302 {
303 struct
304 {
305 uint8_t PreDelayMS;
306 uint8_t PostDelayMS;
307 } Leave_ISP_Params;
308
309 Endpoint_Read_Stream_LE(&Leave_ISP_Params, sizeof(Leave_ISP_Params));
310
311 Endpoint_ClearOUT();
312 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
313 Endpoint_WaitUntilReady();
314
315 V2Protocol_DelayMS(Leave_ISP_Params.PreDelayMS);
316 V2Protocol_ChangeTargetResetLine(false);
317 SPI_ShutDown();
318 V2Protocol_DelayMS(Leave_ISP_Params.PostDelayMS);
319
320 Endpoint_Write_Byte(CMD_LEAVE_PROGMODE_ISP);
321 Endpoint_Write_Byte(STATUS_CMD_OK);
322 Endpoint_ClearIN();
323 }
324
325 static void V2Protocol_Command_ChipErase(void)
326 {
327 struct
328 {
329 uint8_t EraseDelayMS;
330 uint8_t PollMethod;
331 uint8_t EraseCommandBytes[4];
332 } Erase_Chip_Params;
333
334 Endpoint_Read_Stream_LE(&Erase_Chip_Params, sizeof(Erase_Chip_Params));
335
336 Endpoint_ClearOUT();
337 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
338 Endpoint_WaitUntilReady();
339
340 uint8_t ResponseStatus = STATUS_CMD_OK;
341
342 for (uint8_t SByte = 0; SByte < sizeof(Erase_Chip_Params.EraseCommandBytes); SByte++)
343 SPI_SendByte(Erase_Chip_Params.EraseCommandBytes[SByte]);
344
345 if (Erase_Chip_Params.PollMethod == 0)
346 V2Protocol_DelayMS(Erase_Chip_Params.EraseDelayMS);
347 else
348 ResponseStatus = V2Protocol_WaitWhileTargetBusy();
349
350 Endpoint_Write_Byte(CMD_CHIP_ERASE_ISP);
351 Endpoint_Write_Byte(ResponseStatus);
352 Endpoint_ClearIN();
353 }
354
355 static void V2Protocol_Command_ReadFuseLockSigOSCCAL(uint8_t V2Command)
356 {
357 struct
358 {
359 uint8_t RetByte;
360 uint8_t ReadCommandBytes[4];
361 } Read_FuseLockSigOSCCAL_Params;
362
363 Endpoint_Read_Stream_LE(&Read_FuseLockSigOSCCAL_Params, sizeof(Read_FuseLockSigOSCCAL_Params));
364
365 Endpoint_ClearOUT();
366 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
367 Endpoint_WaitUntilReady();
368
369 uint8_t ResponseBytes[4];
370
371 for (uint8_t RByte = 0; RByte < sizeof(ResponseBytes); RByte++)
372 ResponseBytes[RByte] = SPI_TransferByte(Read_FuseLockSigOSCCAL_Params.ReadCommandBytes[RByte]);
373
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);
378 Endpoint_ClearIN();
379 }
380
381 static void V2Protocol_Command_WriteFuseLock(uint8_t V2Command)
382 {
383 struct
384 {
385 uint8_t WriteCommandBytes[4];
386 } Write_FuseLockSig_Params;
387
388 Endpoint_Read_Stream_LE(&Write_FuseLockSig_Params, sizeof(Write_FuseLockSig_Params));
389
390 Endpoint_ClearOUT();
391 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
392 Endpoint_WaitUntilReady();
393
394 for (uint8_t SByte = 0; SByte < sizeof(Write_FuseLockSig_Params.WriteCommandBytes); SByte++)
395 SPI_SendByte(Write_FuseLockSig_Params.WriteCommandBytes[SByte]);
396
397 Endpoint_Write_Byte(V2Command);
398 Endpoint_Write_Byte(STATUS_CMD_OK);
399 Endpoint_Write_Byte(STATUS_CMD_OK);
400 Endpoint_ClearIN();
401 }
402
403 static void V2Protocol_Command_SPIMulti(void)
404 {
405 struct
406 {
407 uint8_t TxBytes;
408 uint8_t RxBytes;
409 uint8_t RxStartAddr;
410 uint8_t TxData[255];
411 } SPI_Multi_Params;
412
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);
416
417 Endpoint_ClearOUT();
418 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
419 Endpoint_WaitUntilReady();
420
421 Endpoint_Write_Byte(CMD_SPI_MULTI);
422 Endpoint_Write_Byte(STATUS_CMD_OK);
423
424 uint8_t CurrTxPos = 0;
425 uint8_t CurrRxPos = 0;
426
427 /* Write out bytes to transmit until the start of the bytes to receive is met */
428 while (CurrTxPos < SPI_Multi_Params.RxStartAddr)
429 {
430 if (CurrTxPos < SPI_Multi_Params.TxBytes)
431 SPI_SendByte(SPI_Multi_Params.TxData[CurrTxPos]);
432 else
433 SPI_SendByte(0);
434
435 CurrTxPos++;
436 }
437
438 /* Transmit remaining bytes with padding as needed, read in response bytes */
439 while (CurrRxPos < SPI_Multi_Params.RxBytes)
440 {
441 if (CurrTxPos < SPI_Multi_Params.TxBytes)
442 Endpoint_Write_Byte(SPI_TransferByte(SPI_Multi_Params.TxData[CurrTxPos++]));
443 else
444 Endpoint_Write_Byte(SPI_ReceiveByte());
445
446 CurrRxPos++;
447 }
448
449 Endpoint_Write_Byte(STATUS_CMD_OK);
450 Endpoint_ClearIN();
451 }