V2Protocol.c 12.1 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/*
             LUFA Library
     Copyright (C) Dean Camera, 2009.
              
  dean [at] fourwalledcubicle [dot] com
      www.fourwalledcubicle.com
*/

/*
  Copyright 2009  Dean Camera (dean [at] fourwalledcubicle [dot] com)

  Permission to use, copy, modify, and distribute this software
  and its documentation for any purpose and without fee is hereby
  granted, provided that the above copyright notice appear in all
  copies and that both that the copyright notice and this
  permission notice and warranty disclaimer appear in supporting
  documentation, and that the name of the author not be used in
  advertising or publicity pertaining to distribution of the
  software without specific, written prior permission.

  The author disclaim all warranties with regard to this
  software, including all implied warranties of merchantability
  and fitness.  In no event shall the author be liable for any
  special, indirect or consequential damages or any damages
  whatsoever resulting from loss of use, data or profits, whether
  in an action of contract, negligence or other tortious action,
  arising out of or in connection with the use or performance of
  this software.
*/

/** \file
 *
 *  V2Protocol handler, to process V2 Protocol commands used in Atmel programmer devices.
 */

36
#define  INCLUDE_FROM_V2PROTOCOL_C
37
#include "V2Protocol.h"
38

39
40
41
uint32_t CurrentAddress;


42
/* Table of masks for SPI_Init() from a given PARAM_SCK_DURATION value */
43
static const uint8_t SPIMaskFromSCKDuration[] =
44
45
46
47
48
49
50
51
52
53
54
	{
		#if (F_CPU == 8000000)
		SPI_SPEED_FCPU_DIV_2,
		#endif
		SPI_SPEED_FCPU_DIV_2, SPI_SPEED_FCPU_DIV_4, SPI_SPEED_FCPU_DIV_8,
		SPI_SPEED_FCPU_DIV_16, SPI_SPEED_FCPU_DIV_32, SPI_SPEED_FCPU_DIV_64
		#if (F_CPU == 16000000)										
		, SPI_SPEED_FCPU_DIV_128
		#endif
	};

55
static uint8_t V2Protocol_GetSPIPrescalerMask(void)
56
{
57
	uint8_t SCKDuration = V2Params_GetParameterValue(PARAM_SCK_DURATION);
58

59
60
	if (SCKDuration >= sizeof(SPIMaskFromSCKDuration))
	  SCKDuration = (sizeof(SPIMaskFromSCKDuration) - 1);
61
	  
62
	return SPIMaskFromSCKDuration[SCKDuration];
63
}
64
65
66
67
68
69
70

static void V2Protocol_ChangeTargetResetLine(bool ResetTarget)
{
	if (ResetTarget)
	{
		RESET_LINE_DDR  |= RESET_LINE_MASK;
		
71
		if (!(V2Params_GetParameterValue(PARAM_RESET_POLARITY)))
72
73
74
75
76
77
78
79
		  RESET_LINE_PORT |= RESET_LINE_MASK;
	}
	else
	{
		RESET_LINE_PORT &= ~RESET_LINE_MASK;	
		RESET_LINE_DDR  &= ~RESET_LINE_MASK;
	}
}
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108

static void V2Protocol_DelayMS(uint8_t MS)
{
	while (MS--)
	  _delay_ms(1);
}

static uint8_t V2Protocol_WaitWhileTargetBusy(void)
{
	uint8_t TimeoutMS = TARGET_BUST_TIMEOUT_MS;
	uint8_t ResponseByte;
	
	do
	{
		V2Protocol_DelayMS(1);
	
		SPI_SendByte(0xF0);
		SPI_SendByte(0x00);

		SPI_SendByte(0x00);
		ResponseByte = SPI_ReceiveByte();
	}
	while ((ResponseByte & 0x01) && (TimeoutMS--));

	if (!(TimeoutMS))
	  return STATUS_CMD_TOUT;
	else
	  return STATUS_CMD_OK;
}
109
110
111
112

void V2Protocol_ProcessCommand(void)
{
	uint8_t V2Command = Endpoint_Read_Byte();
113
		  
114
115
116
	switch (V2Command)
	{
		case CMD_SIGN_ON:
117
			V2Protocol_Command_SignOn();
118
119
120
			break;
		case CMD_SET_PARAMETER:
		case CMD_GET_PARAMETER:
121
			V2Protocol_Command_GetSetParam(V2Command);
122
			break;
123
124
125
		case CMD_LOAD_ADDRESS:
			V2Protocol_Command_LoadAddress();
			break;
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
		case CMD_ENTER_PROGMODE_ISP:
			V2Protocol_Command_EnterISPMode();
			break;
		case CMD_LEAVE_PROGMODE_ISP:
			V2Protocol_Command_LeaveISPMode();
			break;
		case CMD_CHIP_ERASE_ISP:
			V2Protocol_Command_ChipErase();
			break;
		case CMD_READ_FUSE_ISP:
		case CMD_READ_LOCK_ISP:
		case CMD_READ_SIGNATURE_ISP:
		case CMD_READ_OSCCAL_ISP:
			V2Protocol_Command_ReadFuseLockSigOSCCAL(V2Command);
			break;
		case CMD_PROGRAM_FUSE_ISP:
		case CMD_PROGRAM_LOCK_ISP:
			V2Protocol_Command_WriteFuseLock(V2Command);
			break;
145
		case CMD_SPI_MULTI:
146
			V2Protocol_Command_SPIMulti();
147
			break;
148
		default:
149
			V2Protocol_Command_Unknown(V2Command);
150
			break;
151
152
	}
	
153
154
	printf("COMMAND 0x%02x\r\n", V2Command);

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
169

	Endpoint_ClearOUT();
	Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
170
	Endpoint_WaitUntilReady();
171
172
173
174
175

	Endpoint_Write_Byte(V2Command);
	Endpoint_Write_Byte(STATUS_CMD_UNKNOWN);
	Endpoint_ClearIN();
}
176

177
static void V2Protocol_Command_SignOn(void)
178
179
180
{
	Endpoint_ClearOUT();
	Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
181
182
	Endpoint_WaitUntilReady();

183
184
	Endpoint_Write_Byte(CMD_SIGN_ON);
	Endpoint_Write_Byte(STATUS_CMD_OK);
185
186
	Endpoint_Write_Byte(sizeof(PROGRAMMER_ID) - 1);
	Endpoint_Write_Stream_LE(PROGRAMMER_ID, (sizeof(PROGRAMMER_ID) - 1));
187
188
189
	Endpoint_ClearIN();
}

190
static void V2Protocol_Command_GetSetParam(uint8_t V2Command)
191
{
192
193
194
195
196
197
198
	struct
	{
		uint8_t ParamID;
		uint8_t ParamValue;
	} Get_Set_Param_Params;
	
	Endpoint_Read_Stream_LE(&Get_Set_Param_Params, sizeof(Get_Set_Param_Params));
199
200
201

	Endpoint_ClearOUT();
	Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
202
203
	Endpoint_WaitUntilReady();
	
204
	uint8_t ParamPrivs = V2Params_GetParameterPrivellages(Get_Set_Param_Params.ParamID);
205
	
206
	Endpoint_Write_Byte(V2Command);
207
208
209
210
	
	if ((V2Command == CMD_SET_PARAMETER) && (ParamPrivs & PARAM_PRIV_WRITE))
	{
		Endpoint_Write_Byte(STATUS_CMD_OK);
211
		V2Params_SetParameterValue(Get_Set_Param_Params.ParamID, Get_Set_Param_Params.ParamValue);
212
213
214
215
	}
	else if ((V2Command == CMD_GET_PARAMETER) && (ParamPrivs & PARAM_PRIV_READ))
	{
		Endpoint_Write_Byte(STATUS_CMD_OK);
216
		Endpoint_Write_Byte(V2Params_GetParameterValue(Get_Set_Param_Params.ParamID));
217
	}
218
	else
219
220
221
	{	
		Endpoint_Write_Byte(STATUS_CMD_FAILED);
	}
222

223
	Endpoint_ClearIN();
224
}
225

226
227
static void V2Protocol_Command_LoadAddress(void)
{
228
	Endpoint_Read_Stream_LE(&CurrentAddress, sizeof(CurrentAddress));
229
230
231
232

	Endpoint_ClearOUT();
	Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
	Endpoint_WaitUntilReady();
233
234
	
	// TODO: Check for extended address
235
236
237
238
239
240

	Endpoint_Write_Byte(CMD_LOAD_ADDRESS);
	Endpoint_Write_Byte(STATUS_CMD_OK);
	Endpoint_ClearIN();
}

241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
static void V2Protocol_Command_EnterISPMode(void)
{
	struct
	{
		uint8_t TimeoutMS;
		uint8_t PinStabDelayMS;
		uint8_t ExecutionDelayMS;
		uint8_t SynchLoops;
		uint8_t ByteDelay;
		uint8_t PollValue;
		uint8_t PollIndex;
		uint8_t EnterProgBytes[4];
	} Enter_ISP_Params;
	
	Endpoint_Read_Stream_LE(&Enter_ISP_Params, sizeof(Enter_ISP_Params));

	Endpoint_ClearOUT();
	Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
	Endpoint_WaitUntilReady();

	uint8_t SCKDuration = V2Params_GetParameterValue(PARAM_SCK_DURATION);
	uint8_t ResponseStatus = STATUS_CMD_FAILED;

	Enter_ISP_Params.TimeoutMS -= Enter_ISP_Params.ExecutionDelayMS +
	                              Enter_ISP_Params.PinStabDelayMS;
	
	CurrentAddress = 0;

	if (SCKDuration >= sizeof(SPIMaskFromSCKDuration))
	  SCKDuration = (sizeof(SPIMaskFromSCKDuration) - 1);

	V2Protocol_DelayMS(Enter_ISP_Params.ExecutionDelayMS);	  
	SPI_Init(SPIMaskFromSCKDuration[SCKDuration], true);
	V2Protocol_ChangeTargetResetLine(true);
	V2Protocol_DelayMS(Enter_ISP_Params.PinStabDelayMS);
		
	while (Enter_ISP_Params.SynchLoops-- && (ResponseStatus == STATUS_CMD_FAILED))
	{
		uint8_t ResponseBytes[4];
		
		for (uint8_t RByte = 0; RByte < sizeof(ResponseBytes); RByte++)
		{
			ResponseBytes[RByte] = SPI_TransferByte(Enter_ISP_Params.EnterProgBytes[RByte]);
			V2Protocol_DelayMS(Enter_ISP_Params.ByteDelay);
			
			if (Enter_ISP_Params.TimeoutMS >= Enter_ISP_Params.ByteDelay)
			  Enter_ISP_Params.TimeoutMS -= Enter_ISP_Params.ByteDelay;
			else
			  ResponseStatus = STATUS_CMD_TOUT;
		}
		
		if (ResponseBytes[Enter_ISP_Params.PollIndex] == Enter_ISP_Params.PollValue)
		  ResponseStatus = STATUS_CMD_OK;
	}

	Endpoint_Write_Byte(CMD_ENTER_PROGMODE_ISP);
	Endpoint_Write_Byte(ResponseStatus);
	Endpoint_ClearIN();
}

static void V2Protocol_Command_LeaveISPMode(void)
{
	struct
	{
		uint8_t PreDelayMS;
		uint8_t PostDelayMS;
	} Leave_ISP_Params;

	Endpoint_Read_Stream_LE(&Leave_ISP_Params, sizeof(Leave_ISP_Params));
	
	Endpoint_ClearOUT();
	Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
	Endpoint_WaitUntilReady();

	V2Protocol_DelayMS(Leave_ISP_Params.PreDelayMS);
	V2Protocol_ChangeTargetResetLine(false);
	SPI_ShutDown();
	V2Protocol_DelayMS(Leave_ISP_Params.PostDelayMS);

	Endpoint_Write_Byte(CMD_LEAVE_PROGMODE_ISP);
	Endpoint_Write_Byte(STATUS_CMD_OK);
	Endpoint_ClearIN();
}

static void V2Protocol_Command_ChipErase(void)
{
	struct
	{
		uint8_t EraseDelayMS;
		uint8_t PollMethod;
		uint8_t EraseCommandBytes[4];
	} Erase_Chip_Params;
	
	Endpoint_Read_Stream_LE(&Erase_Chip_Params, sizeof(Erase_Chip_Params));
	
	Endpoint_ClearOUT();
	Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
	Endpoint_WaitUntilReady();
	
	uint8_t ResponseStatus = STATUS_CMD_OK;
	
	for (uint8_t SByte = 0; SByte < sizeof(Erase_Chip_Params.EraseCommandBytes); SByte++)
	  SPI_SendByte(Erase_Chip_Params.EraseCommandBytes[SByte]);

	if (Erase_Chip_Params.PollMethod == 0)
	  V2Protocol_DelayMS(Erase_Chip_Params.EraseDelayMS);
	else
	  ResponseStatus = V2Protocol_WaitWhileTargetBusy();
	  
	Endpoint_Write_Byte(CMD_CHIP_ERASE_ISP);
	Endpoint_Write_Byte(ResponseStatus);
	Endpoint_ClearIN();
}

static void V2Protocol_Command_ReadFuseLockSigOSCCAL(uint8_t V2Command)
{
	struct
	{
		uint8_t RetByte;
		uint8_t ReadCommandBytes[4];
	} Read_FuseLockSigOSCCAL_Params;
	
	Endpoint_Read_Stream_LE(&Read_FuseLockSigOSCCAL_Params, sizeof(Read_FuseLockSigOSCCAL_Params));

	Endpoint_ClearOUT();
	Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
	Endpoint_WaitUntilReady();

	uint8_t ResponseBytes[4];
		
	for (uint8_t RByte = 0; RByte < sizeof(ResponseBytes); RByte++)
	  ResponseBytes[RByte] = SPI_TransferByte(Read_FuseLockSigOSCCAL_Params.ReadCommandBytes[RByte]);
		
	Endpoint_Write_Byte(V2Command);
	Endpoint_Write_Byte(STATUS_CMD_OK);
	Endpoint_Write_Byte(ResponseBytes[Read_FuseLockSigOSCCAL_Params.RetByte]);
	Endpoint_Write_Byte(STATUS_CMD_OK);
	Endpoint_ClearIN();
}

static void V2Protocol_Command_WriteFuseLock(uint8_t V2Command)
{
	struct
	{
		uint8_t WriteCommandBytes[4];
	} Write_FuseLockSig_Params;
	
	Endpoint_Read_Stream_LE(&Write_FuseLockSig_Params, sizeof(Write_FuseLockSig_Params));

	Endpoint_ClearOUT();
	Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
	Endpoint_WaitUntilReady();

	for (uint8_t SByte = 0; SByte < sizeof(Write_FuseLockSig_Params.WriteCommandBytes); SByte++)
	  SPI_SendByte(Write_FuseLockSig_Params.WriteCommandBytes[SByte]);
		
	Endpoint_Write_Byte(V2Command);
	Endpoint_Write_Byte(STATUS_CMD_OK);
	Endpoint_Write_Byte(STATUS_CMD_OK);
	Endpoint_ClearIN();
}

403
static void V2Protocol_Command_SPIMulti(void)
404
{
405
406
407
408
409
410
411
	struct
	{
		uint8_t TxBytes;
		uint8_t RxBytes;
		uint8_t RxStartAddr;
		uint8_t TxData[255];
	} SPI_Multi_Params;
412
	
413
414
415
	Endpoint_Read_Stream_LE(&SPI_Multi_Params, sizeof(SPI_Multi_Params) -
	                                           sizeof(SPI_Multi_Params.TxData));
	Endpoint_Read_Stream_LE(&SPI_Multi_Params.TxData, SPI_Multi_Params.TxBytes);
416
417
418
419
420
421
422
423
424
425
426
	
	Endpoint_ClearOUT();
	Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
	Endpoint_WaitUntilReady();
	
	Endpoint_Write_Byte(CMD_SPI_MULTI);
	Endpoint_Write_Byte(STATUS_CMD_OK);

	uint8_t CurrTxPos = 0;
	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)
429
	{
430
431
		if (CurrTxPos < SPI_Multi_Params.TxBytes)
		  SPI_SendByte(SPI_Multi_Params.TxData[CurrTxPos]);
432
433
434
435
436
437
		else
		  SPI_SendByte(0);
		
		CurrTxPos++;
	}

438
	/* Transmit remaining bytes with padding as needed, read in response bytes */
439
	while (CurrRxPos < SPI_Multi_Params.RxBytes)
440
	{
441
442
		if (CurrTxPos < SPI_Multi_Params.TxBytes)
		  Endpoint_Write_Byte(SPI_TransferByte(SPI_Multi_Params.TxData[CurrTxPos++]));
443
		else
444
		  Endpoint_Write_Byte(SPI_ReceiveByte());
445
446
447
448
449
		
		CurrRxPos++;
	}	
	
	Endpoint_Write_Byte(STATUS_CMD_OK);
450
	Endpoint_ClearIN();
451
}