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