Fix references to the renamed AVRISP-MKII project folder.
[pub/USBasp.git] / Projects / AVRISP-MKII / Lib / XPROG / XPROGProtocol.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 * XPROG Protocol handler, to process V2 Protocol wrapped XPROG commands used in Atmel programmer devices.
34 */
35
36 #define INCLUDE_FROM_XPROGPROTOCOL_C
37 #include "XPROGProtocol.h"
38
39 #if defined(ENABLE_XPROG_PROTOCOL) || defined(__DOXYGEN__)
40 /** Base absolute address for the target's NVM controller */
41 uint32_t XPROG_Param_NVMBase = 0x010001C0;
42
43 /** Size in bytes of the target's EEPROM page */
44 uint32_t XPROG_Param_EEPageSize;
45
46 /** Currently selected XPROG programming protocol */
47 uint8_t XPROG_SelectedProtocol = XPRG_PROTOCOL_PDI;
48
49 /** Handler for the CMD_XPROG_SETMODE command, which sets the programmer-to-target protocol used for PDI/TPI
50 * programming.
51 */
52 void XPROGProtocol_SetMode(void)
53 {
54 struct
55 {
56 uint8_t Protocol;
57 } SetMode_XPROG_Params;
58
59 Endpoint_Read_Stream_LE(&SetMode_XPROG_Params, sizeof(SetMode_XPROG_Params));
60
61 Endpoint_ClearOUT();
62 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
63
64 XPROG_SelectedProtocol = SetMode_XPROG_Params.Protocol;
65
66 Endpoint_Write_Byte(CMD_XPROG_SETMODE);
67 Endpoint_Write_Byte((SetMode_XPROG_Params.Protocol != XPRG_PROTOCOL_JTAG) ? STATUS_CMD_OK : STATUS_CMD_FAILED);
68 Endpoint_ClearIN();
69 }
70
71 /** Handler for the CMD_XPROG command, which wraps up XPROG commands in a V2 wrapper which need to be
72 * removed and processed so that the underlying XPROG command can be handled.
73 */
74 void XPROGProtocol_Command(void)
75 {
76 uint8_t XPROGCommand = Endpoint_Read_Byte();
77
78 switch (XPROGCommand)
79 {
80 case XPRG_CMD_ENTER_PROGMODE:
81 XPROGProtocol_EnterXPROGMode();
82 break;
83 case XPRG_CMD_LEAVE_PROGMODE:
84 XPROGProtocol_LeaveXPROGMode();
85 break;
86 case XPRG_CMD_ERASE:
87 XPROGProtocol_Erase();
88 break;
89 case XPRG_CMD_WRITE_MEM:
90 XPROGProtocol_WriteMemory();
91 break;
92 case XPRG_CMD_READ_MEM:
93 XPROGProtocol_ReadMemory();
94 break;
95 case XPRG_CMD_CRC:
96 XPROGProtocol_ReadCRC();
97 break;
98 case XPRG_CMD_SET_PARAM:
99 XPROGProtocol_SetParam();
100 break;
101 }
102 }
103
104 /** Handler for the XPROG ENTER_PROGMODE command to establish a connection with the attached device. */
105 static void XPROGProtocol_EnterXPROGMode(void)
106 {
107 Endpoint_ClearOUT();
108 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
109
110 bool NVMBusEnabled;
111
112 if (XPROG_SelectedProtocol == XPRG_PROTOCOL_PDI)
113 {
114 /* Enable PDI programming mode with the attached target */
115 XPROGTarget_EnableTargetPDI();
116
117 /* Store the RESET key into the RESET PDI register to keep the XMEGA in reset */
118 XPROGTarget_SendByte(PDI_CMD_STCS | PDI_RESET_REG);
119 XPROGTarget_SendByte(PDI_RESET_KEY);
120
121 /* Enable access to the XPROG NVM bus by sending the documented NVM access key to the device */
122 XPROGTarget_SendByte(PDI_CMD_KEY);
123 for (uint8_t i = sizeof(PDI_NVMENABLE_KEY); i > 0; i--)
124 XPROGTarget_SendByte(PDI_NVMENABLE_KEY[i - 1]);
125
126 /* Wait until the NVM bus becomes active */
127 NVMBusEnabled = XMEGANVM_WaitWhileNVMBusBusy();
128 }
129 else
130 {
131 /* Enable TPI programming mode with the attached target */
132 XPROGTarget_EnableTargetTPI();
133
134 /* Enable access to the XPROG NVM bus by sending the documented NVM access key to the device */
135 XPROGTarget_SendByte(TPI_CMD_SKEY);
136 for (uint8_t i = sizeof(TPI_NVMENABLE_KEY); i > 0; i--)
137 XPROGTarget_SendByte(TPI_NVMENABLE_KEY[i - 1]);
138
139 /* Wait until the NVM bus becomes active */
140 NVMBusEnabled = TINYNVM_WaitWhileNVMBusBusy();
141 }
142
143 Endpoint_Write_Byte(CMD_XPROG);
144 Endpoint_Write_Byte(XPRG_CMD_ENTER_PROGMODE);
145 Endpoint_Write_Byte(NVMBusEnabled ? XPRG_ERR_OK : XPRG_ERR_FAILED);
146 Endpoint_ClearIN();
147 }
148
149 /** Handler for the XPROG LEAVE_PROGMODE command to terminate the PDI programming connection with
150 * the attached device.
151 */
152 static void XPROGProtocol_LeaveXPROGMode(void)
153 {
154 Endpoint_ClearOUT();
155 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
156
157 if (XPROG_SelectedProtocol == XPRG_PROTOCOL_PDI)
158 {
159 /* Clear the RESET key in the RESET PDI register to allow the XMEGA to run */
160 XPROGTarget_SendByte(PDI_CMD_STCS | PDI_RESET_REG);
161 XPROGTarget_SendByte(0x00);
162
163 XPROGTarget_DisableTargetPDI();
164 }
165 else
166 {
167 /* Clear the NVMEN bit in the TPI CONTROL register to disable TPI mode */
168 XPROGTarget_SendByte(TPI_CMD_SSTCS | TPI_CTRL_REG);
169 XPROGTarget_SendByte(0x00);
170
171 XPROGTarget_DisableTargetTPI();
172 }
173
174 Endpoint_Write_Byte(CMD_XPROG);
175 Endpoint_Write_Byte(XPRG_CMD_LEAVE_PROGMODE);
176 Endpoint_Write_Byte(XPRG_ERR_OK);
177 Endpoint_ClearIN();
178 }
179
180 /** Handler for the XPRG ERASE command to erase a specific memory address space in the attached device. */
181 static void XPROGProtocol_Erase(void)
182 {
183 uint8_t ReturnStatus = XPRG_ERR_OK;
184
185 struct
186 {
187 uint8_t MemoryType;
188 uint32_t Address;
189 } Erase_XPROG_Params;
190
191 Endpoint_Read_Stream_LE(&Erase_XPROG_Params, sizeof(Erase_XPROG_Params));
192 Erase_XPROG_Params.Address = SwapEndian_32(Erase_XPROG_Params.Address);
193
194 Endpoint_ClearOUT();
195 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
196
197 uint8_t EraseCommand = XMEGA_NVM_CMD_NOOP;
198
199 if (XPROG_SelectedProtocol == XPRG_PROTOCOL_PDI)
200 {
201 /* Determine which NVM command to send to the device depending on the memory to erase */
202 if (Erase_XPROG_Params.MemoryType == XPRG_ERASE_CHIP)
203 EraseCommand = XMEGA_NVM_CMD_CHIPERASE;
204 else if (Erase_XPROG_Params.MemoryType == XPRG_ERASE_APP)
205 EraseCommand = XMEGA_NVM_CMD_ERASEAPPSEC;
206 else if (Erase_XPROG_Params.MemoryType == XPRG_ERASE_BOOT)
207 EraseCommand = XMEGA_NVM_CMD_ERASEBOOTSEC;
208 else if (Erase_XPROG_Params.MemoryType == XPRG_ERASE_EEPROM)
209 EraseCommand = XMEGA_NVM_CMD_ERASEEEPROM;
210 else if (Erase_XPROG_Params.MemoryType == XPRG_ERASE_APP_PAGE)
211 EraseCommand = XMEGA_NVM_CMD_ERASEAPPSECPAGE;
212 else if (Erase_XPROG_Params.MemoryType == XPRG_ERASE_BOOT_PAGE)
213 EraseCommand = XMEGA_NVM_CMD_ERASEBOOTSECPAGE;
214 else if (Erase_XPROG_Params.MemoryType == XPRG_ERASE_EEPROM_PAGE)
215 EraseCommand = XMEGA_NVM_CMD_ERASEEEPROMPAGE;
216 else if (Erase_XPROG_Params.MemoryType == XPRG_ERASE_USERSIG)
217 EraseCommand = XMEGA_NVM_CMD_ERASEUSERSIG;
218
219 /* Erase the target memory, indicate timeout if ocurred */
220 if (!(XMEGANVM_EraseMemory(EraseCommand, Erase_XPROG_Params.Address)))
221 ReturnStatus = XPRG_ERR_TIMEOUT;
222 }
223 else
224 {
225 // TODO
226 }
227
228 Endpoint_Write_Byte(CMD_XPROG);
229 Endpoint_Write_Byte(XPRG_CMD_ERASE);
230 Endpoint_Write_Byte(ReturnStatus);
231 Endpoint_ClearIN();
232 }
233
234 /** Handler for the XPROG WRITE_MEMORY command to write to a specific memory space within the attached device. */
235 static void XPROGProtocol_WriteMemory(void)
236 {
237 uint8_t ReturnStatus = XPRG_ERR_OK;
238
239 struct
240 {
241 uint8_t MemoryType;
242 uint8_t PageMode;
243 uint32_t Address;
244 uint16_t Length;
245 uint8_t ProgData[256];
246 } WriteMemory_XPROG_Params;
247
248 Endpoint_Read_Stream_LE(&WriteMemory_XPROG_Params, (sizeof(WriteMemory_XPROG_Params) -
249 sizeof(WriteMemory_XPROG_Params).ProgData));
250 WriteMemory_XPROG_Params.Address = SwapEndian_32(WriteMemory_XPROG_Params.Address);
251 WriteMemory_XPROG_Params.Length = SwapEndian_16(WriteMemory_XPROG_Params.Length);
252 Endpoint_Read_Stream_LE(&WriteMemory_XPROG_Params.ProgData, WriteMemory_XPROG_Params.Length);
253
254 Endpoint_ClearOUT();
255 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
256
257 /* Assume FLASH page programming by default, as it is the common case */
258 uint8_t WriteCommand = XMEGA_NVM_CMD_WRITEFLASHPAGE;
259 uint8_t WriteBuffCommand = XMEGA_NVM_CMD_LOADFLASHPAGEBUFF;
260 uint8_t EraseBuffCommand = XMEGA_NVM_CMD_ERASEFLASHPAGEBUFF;
261 bool PagedMemory = true;
262
263 if (XPROG_SelectedProtocol == XPRG_PROTOCOL_PDI)
264 {
265 if (WriteMemory_XPROG_Params.MemoryType == XPRG_MEM_TYPE_APPL)
266 {
267 WriteCommand = XMEGA_NVM_CMD_WRITEAPPSECPAGE;
268 }
269 else if (WriteMemory_XPROG_Params.MemoryType == XPRG_MEM_TYPE_BOOT)
270 {
271 WriteCommand = XMEGA_NVM_CMD_WRITEBOOTSECPAGE;
272 }
273 else if (WriteMemory_XPROG_Params.MemoryType == XPRG_MEM_TYPE_EEPROM)
274 {
275 WriteCommand = XMEGA_NVM_CMD_WRITEEEPROMPAGE;
276 WriteBuffCommand = XMEGA_NVM_CMD_LOADEEPROMPAGEBUFF;
277 EraseBuffCommand = XMEGA_NVM_CMD_ERASEEEPROMPAGEBUFF;
278 }
279 else if (WriteMemory_XPROG_Params.MemoryType == XPRG_MEM_TYPE_USERSIG)
280 {
281 /* User signature is paged, but needs us to manually indicate the mode bits since the host doesn't set them */
282 WriteMemory_XPROG_Params.PageMode = (XPRG_PAGEMODE_ERASE | XPRG_PAGEMODE_WRITE);
283 WriteCommand = XMEGA_NVM_CMD_WRITEUSERSIG;
284 }
285 else if (WriteMemory_XPROG_Params.MemoryType == XPRG_MEM_TYPE_FUSE)
286 {
287 WriteCommand = XMEGA_NVM_CMD_WRITEFUSE;
288 PagedMemory = false;
289 }
290 else if (WriteMemory_XPROG_Params.MemoryType == XPRG_MEM_TYPE_LOCKBITS)
291 {
292 WriteCommand = XMEGA_NVM_CMD_WRITELOCK;
293 PagedMemory = false;
294 }
295
296 /* Send the appropriate memory write commands to the device, indicate timeout if occurred */
297 if ((PagedMemory && !XMEGANVM_WritePageMemory(WriteBuffCommand, EraseBuffCommand, WriteCommand,
298 WriteMemory_XPROG_Params.PageMode, WriteMemory_XPROG_Params.Address,
299 WriteMemory_XPROG_Params.ProgData, WriteMemory_XPROG_Params.Length)) ||
300 (!PagedMemory && !XMEGANVM_WriteByteMemory(WriteCommand, WriteMemory_XPROG_Params.Address,
301 WriteMemory_XPROG_Params.ProgData)))
302 {
303 ReturnStatus = XPRG_ERR_TIMEOUT;
304 }
305 }
306 else
307 {
308 // TODO
309 }
310
311 Endpoint_Write_Byte(CMD_XPROG);
312 Endpoint_Write_Byte(XPRG_CMD_WRITE_MEM);
313 Endpoint_Write_Byte(ReturnStatus);
314 Endpoint_ClearIN();
315 }
316
317 /** Handler for the XPROG READ_MEMORY command to read data from a specific address space within the
318 * attached device.
319 */
320 static void XPROGProtocol_ReadMemory(void)
321 {
322 uint8_t ReturnStatus = XPRG_ERR_OK;
323
324 struct
325 {
326 uint8_t MemoryType;
327 uint32_t Address;
328 uint16_t Length;
329 } ReadMemory_XPROG_Params;
330
331 Endpoint_Read_Stream_LE(&ReadMemory_XPROG_Params, sizeof(ReadMemory_XPROG_Params));
332 ReadMemory_XPROG_Params.Address = SwapEndian_32(ReadMemory_XPROG_Params.Address);
333 ReadMemory_XPROG_Params.Length = SwapEndian_16(ReadMemory_XPROG_Params.Length);
334
335 Endpoint_ClearOUT();
336 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
337
338 uint8_t ReadBuffer[256];
339
340 if (XPROG_SelectedProtocol == XPRG_PROTOCOL_PDI)
341 {
342 /* Read the target's memory, indicate timeout if occurred */
343 if (!(XMEGANVM_ReadMemory(ReadMemory_XPROG_Params.Address, ReadBuffer, ReadMemory_XPROG_Params.Length)))
344 ReturnStatus = XPRG_ERR_TIMEOUT;
345 }
346 else
347 {
348 // TODO
349 }
350
351 Endpoint_Write_Byte(CMD_XPROG);
352 Endpoint_Write_Byte(XPRG_CMD_READ_MEM);
353 Endpoint_Write_Byte(ReturnStatus);
354
355 if (ReturnStatus == XPRG_ERR_OK)
356 Endpoint_Write_Stream_LE(ReadBuffer, ReadMemory_XPROG_Params.Length);
357
358 Endpoint_ClearIN();
359 }
360
361 /** Handler for the XPROG CRC command to read a specific memory space's CRC value for comparison between the
362 * attached device's memory and a data set on the host.
363 */
364 static void XPROGProtocol_ReadCRC(void)
365 {
366 uint8_t ReturnStatus = XPRG_ERR_OK;
367
368 struct
369 {
370 uint8_t CRCType;
371 } ReadCRC_XPROG_Params;
372
373 Endpoint_Read_Stream_LE(&ReadCRC_XPROG_Params, sizeof(ReadCRC_XPROG_Params));
374 Endpoint_ClearOUT();
375 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
376
377 uint8_t CRCCommand = XMEGA_NVM_CMD_NOOP;
378 uint32_t MemoryCRC;
379
380 if (XPROG_SelectedProtocol == XPRG_PROTOCOL_PDI)
381 {
382 /* Determine which NVM command to send to the device depending on the memory to CRC */
383 if (ReadCRC_XPROG_Params.CRCType == XPRG_CRC_APP)
384 CRCCommand = XMEGA_NVM_CMD_APPCRC;
385 else if (ReadCRC_XPROG_Params.CRCType == XPRG_CRC_BOOT)
386 CRCCommand = XMEGA_NVM_CMD_BOOTCRC;
387 else
388 CRCCommand = XMEGA_NVM_CMD_FLASHCRC;
389
390 /* Perform and retrieve the memory CRC, indicate timeout if occurred */
391 if (!(XMEGANVM_GetMemoryCRC(CRCCommand, &MemoryCRC)))
392 ReturnStatus = XPRG_ERR_TIMEOUT;
393 }
394 else
395 {
396 /* TPI does not support memory CRC */
397 ReturnStatus = XPRG_ERR_FAILED;
398 }
399
400 Endpoint_Write_Byte(CMD_XPROG);
401 Endpoint_Write_Byte(XPRG_CMD_CRC);
402 Endpoint_Write_Byte(ReturnStatus);
403
404 if (ReturnStatus == XPRG_ERR_OK)
405 {
406 Endpoint_Write_Byte(MemoryCRC >> 16);
407 Endpoint_Write_Word_LE(MemoryCRC & 0xFFFF);
408 }
409
410 Endpoint_ClearIN();
411 }
412
413 /** Handler for the XPROG SET_PARAM command to set a XPROG parameter for use when communicating with the
414 * attached device.
415 */
416 static void XPROGProtocol_SetParam(void)
417 {
418 uint8_t ReturnStatus = XPRG_ERR_OK;
419
420 uint8_t XPROGParam = Endpoint_Read_Byte();
421
422 /* Determine which parameter is being set, store the new parameter value */
423 if (XPROGParam == XPRG_PARAM_NVMBASE)
424 XPROG_Param_NVMBase = Endpoint_Read_DWord_BE();
425 else if (XPROGParam == XPRG_PARAM_EEPPAGESIZE)
426 XPROG_Param_EEPageSize = Endpoint_Read_Word_BE();
427 else
428 ReturnStatus = XPRG_ERR_FAILED;
429
430 Endpoint_ClearOUT();
431 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
432
433 Endpoint_Write_Byte(CMD_XPROG);
434 Endpoint_Write_Byte(XPRG_CMD_SET_PARAM);
435 Endpoint_Write_Byte(ReturnStatus);
436 Endpoint_ClearIN();
437 }
438
439 #endif