Fixed AVRISP programmer demo -- can now connect to a target and read/write Sig/Lock...
[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 Endpoint_WaitUntilReady();
154 Endpoint_SetEndpointDirection(ENDPOINT_DIR_OUT);
155 }
156
157 static void V2Protocol_Command_Unknown(uint8_t V2Command)
158 {
159 /* Discard all incomming data */
160 while (Endpoint_BytesInEndpoint() == AVRISP_DATA_EPSIZE)
161 {
162 Endpoint_ClearOUT();
163 Endpoint_WaitUntilReady();
164 }
165
166 Endpoint_ClearOUT();
167 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
168
169 Endpoint_Write_Byte(V2Command);
170 Endpoint_Write_Byte(STATUS_CMD_UNKNOWN);
171 Endpoint_ClearIN();
172 }
173
174 static void V2Protocol_Command_SignOn(void)
175 {
176 Endpoint_ClearOUT();
177 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
178
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));
183 Endpoint_ClearIN();
184 }
185
186 static void V2Protocol_Command_GetSetParam(uint8_t V2Command)
187 {
188 uint8_t ParamID = Endpoint_Read_Byte();
189 uint8_t ParamValue;
190
191 if (V2Command == CMD_SET_PARAMETER)
192 ParamValue = Endpoint_Read_Byte();
193
194 Endpoint_ClearOUT();
195 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
196
197 Endpoint_Write_Byte(V2Command);
198
199 uint8_t ParamPrivs = V2Params_GetParameterPrivellages(ParamID);
200
201 if ((V2Command == CMD_SET_PARAMETER) && (ParamPrivs & PARAM_PRIV_WRITE))
202 {
203 Endpoint_Write_Byte(STATUS_CMD_OK);
204 V2Params_SetParameterValue(ParamID, ParamValue);
205 }
206 else if ((V2Command == CMD_GET_PARAMETER) && (ParamPrivs & PARAM_PRIV_READ))
207 {
208 Endpoint_Write_Byte(STATUS_CMD_OK);
209 Endpoint_Write_Byte(V2Params_GetParameterValue(ParamID));
210 }
211 else
212 {
213 Endpoint_Write_Byte(STATUS_CMD_FAILED);
214 }
215
216 Endpoint_ClearIN();
217 }
218
219 static void V2Protocol_Command_LoadAddress(void)
220 {
221 Endpoint_Read_Stream_LE(&CurrentAddress, sizeof(CurrentAddress));
222
223 Endpoint_ClearOUT();
224 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
225
226 // TODO: Check for extended address
227
228 Endpoint_Write_Byte(CMD_LOAD_ADDRESS);
229 Endpoint_Write_Byte(STATUS_CMD_OK);
230 Endpoint_ClearIN();
231 }
232
233 static void V2Protocol_Command_EnterISPMode(void)
234 {
235 struct
236 {
237 uint8_t TimeoutMS;
238 uint8_t PinStabDelayMS;
239 uint8_t ExecutionDelayMS;
240 uint8_t SynchLoops;
241 uint8_t ByteDelay;
242 uint8_t PollValue;
243 uint8_t PollIndex;
244 uint8_t EnterProgBytes[4];
245 } Enter_ISP_Params;
246
247 Endpoint_Read_Stream_LE(&Enter_ISP_Params, sizeof(Enter_ISP_Params));
248
249 Endpoint_ClearOUT();
250 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
251
252 uint8_t ResponseStatus = STATUS_CMD_FAILED;
253
254 CurrentAddress = 0;
255
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);
260
261 while (Enter_ISP_Params.SynchLoops-- && (ResponseStatus == STATUS_CMD_FAILED))
262 {
263 uint8_t ResponseBytes[4];
264
265 for (uint8_t RByte = 0; RByte < sizeof(ResponseBytes); RByte++)
266 {
267 V2Protocol_DelayMS(Enter_ISP_Params.ByteDelay);
268 ResponseBytes[RByte] = SPI_TransferByte(Enter_ISP_Params.EnterProgBytes[RByte]);
269 }
270
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;
274 }
275
276 Endpoint_Write_Byte(CMD_ENTER_PROGMODE_ISP);
277 Endpoint_Write_Byte(ResponseStatus);
278 Endpoint_ClearIN();
279 }
280
281 static void V2Protocol_Command_LeaveISPMode(void)
282 {
283 struct
284 {
285 uint8_t PreDelayMS;
286 uint8_t PostDelayMS;
287 } Leave_ISP_Params;
288
289 Endpoint_Read_Stream_LE(&Leave_ISP_Params, sizeof(Leave_ISP_Params));
290
291 Endpoint_ClearOUT();
292 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
293
294 V2Protocol_DelayMS(Leave_ISP_Params.PreDelayMS);
295 V2Protocol_ChangeTargetResetLine(false);
296 SPI_ShutDown();
297 V2Protocol_DelayMS(Leave_ISP_Params.PostDelayMS);
298
299 Endpoint_Write_Byte(CMD_LEAVE_PROGMODE_ISP);
300 Endpoint_Write_Byte(STATUS_CMD_OK);
301 Endpoint_ClearIN();
302 }
303
304 static void V2Protocol_Command_ChipErase(void)
305 {
306 struct
307 {
308 uint8_t EraseDelayMS;
309 uint8_t PollMethod;
310 uint8_t EraseCommandBytes[4];
311 } Erase_Chip_Params;
312
313 Endpoint_Read_Stream_LE(&Erase_Chip_Params, sizeof(Erase_Chip_Params));
314
315 Endpoint_ClearOUT();
316 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
317
318 uint8_t ResponseStatus = STATUS_CMD_OK;
319
320 for (uint8_t SByte = 0; SByte < sizeof(Erase_Chip_Params.EraseCommandBytes); SByte++)
321 SPI_SendByte(Erase_Chip_Params.EraseCommandBytes[SByte]);
322
323 if (Erase_Chip_Params.PollMethod == 0)
324 V2Protocol_DelayMS(Erase_Chip_Params.EraseDelayMS);
325 else
326 ResponseStatus = V2Protocol_WaitWhileTargetBusy();
327
328 Endpoint_Write_Byte(CMD_CHIP_ERASE_ISP);
329 Endpoint_Write_Byte(ResponseStatus);
330 Endpoint_ClearIN();
331 }
332
333 static void V2Protocol_Command_ReadFuseLockSigOSCCAL(uint8_t V2Command)
334 {
335 struct
336 {
337 uint8_t RetByte;
338 uint8_t ReadCommandBytes[4];
339 } Read_FuseLockSigOSCCAL_Params;
340
341 Endpoint_Read_Stream_LE(&Read_FuseLockSigOSCCAL_Params, sizeof(Read_FuseLockSigOSCCAL_Params));
342
343 Endpoint_ClearOUT();
344 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
345
346 uint8_t ResponseBytes[4];
347
348 for (uint8_t RByte = 0; RByte < sizeof(ResponseBytes); RByte++)
349 ResponseBytes[RByte] = SPI_TransferByte(Read_FuseLockSigOSCCAL_Params.ReadCommandBytes[RByte]);
350
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);
355 Endpoint_ClearIN();
356 }
357
358 static void V2Protocol_Command_WriteFuseLock(uint8_t V2Command)
359 {
360 struct
361 {
362 uint8_t WriteCommandBytes[4];
363 } Write_FuseLockSig_Params;
364
365 Endpoint_Read_Stream_LE(&Write_FuseLockSig_Params, sizeof(Write_FuseLockSig_Params));
366
367 Endpoint_ClearOUT();
368 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
369
370 for (uint8_t SByte = 0; SByte < sizeof(Write_FuseLockSig_Params.WriteCommandBytes); SByte++)
371 SPI_SendByte(Write_FuseLockSig_Params.WriteCommandBytes[SByte]);
372
373 Endpoint_Write_Byte(V2Command);
374 Endpoint_Write_Byte(STATUS_CMD_OK);
375 Endpoint_Write_Byte(STATUS_CMD_OK);
376 Endpoint_ClearIN();
377 }
378
379 static void V2Protocol_Command_SPIMulti(void)
380 {
381 struct
382 {
383 uint8_t TxBytes;
384 uint8_t RxBytes;
385 uint8_t RxStartAddr;
386 uint8_t TxData[255];
387 } SPI_Multi_Params;
388
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);
392
393 Endpoint_ClearOUT();
394 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
395
396 Endpoint_Write_Byte(CMD_SPI_MULTI);
397 Endpoint_Write_Byte(STATUS_CMD_OK);
398
399 uint8_t CurrTxPos = 0;
400 uint8_t CurrRxPos = 0;
401
402 /* Write out bytes to transmit until the start of the bytes to receive is met */
403 while (CurrTxPos < SPI_Multi_Params.RxStartAddr)
404 {
405 if (CurrTxPos < SPI_Multi_Params.TxBytes)
406 SPI_SendByte(SPI_Multi_Params.TxData[CurrTxPos]);
407 else
408 SPI_SendByte(0);
409
410 CurrTxPos++;
411 }
412
413 /* Transmit remaining bytes with padding as needed, read in response bytes */
414 while (CurrRxPos < SPI_Multi_Params.RxBytes)
415 {
416 if (CurrTxPos < SPI_Multi_Params.TxBytes)
417 Endpoint_Write_Byte(SPI_TransferByte(SPI_Multi_Params.TxData[CurrTxPos++]));
418 else
419 Endpoint_Write_Byte(SPI_ReceiveByte());
420
421 CurrRxPos++;
422 }
423
424 Endpoint_Write_Byte(STATUS_CMD_OK);
425 Endpoint_ClearIN();
426 }