3 Copyright (C) Dean Camera, 2009.
5 dean [at] fourwalledcubicle [dot] com
6 www.fourwalledcubicle.com
10 Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)
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.
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
33 * XPROG Protocol handler, to process V2 Protocol wrapped XPROG commands used in Atmel programmer devices.
36 #define INCLUDE_FROM_XPROGPROTOCOL_C
37 #include "XPROGProtocol.h"
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;
43 /** Size in bytes of the target's EEPROM page */
44 uint32_t XPROG_Param_EEPageSize
;
46 /** Currently selected XPROG programming protocol */
47 uint8_t XPROG_SelectedProtocol
= XPRG_PROTOCOL_PDI
;
49 /** Handler for the CMD_XPROG_SETMODE command, which sets the programmer-to-target protocol used for PDI/TPI
52 void XPROGProtocol_SetMode(void)
57 } SetMode_XPROG_Params
;
59 Endpoint_Read_Stream_LE(&SetMode_XPROG_Params
, sizeof(SetMode_XPROG_Params
));
62 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
64 XPROG_SelectedProtocol
= SetMode_XPROG_Params
.Protocol
;
66 Endpoint_Write_Byte(CMD_XPROG_SETMODE
);
67 Endpoint_Write_Byte((SetMode_XPROG_Params
.Protocol
!= XPRG_PROTOCOL_JTAG
) ? STATUS_CMD_OK
: STATUS_CMD_FAILED
);
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.
74 void XPROGProtocol_Command(void)
76 uint8_t XPROGCommand
= Endpoint_Read_Byte();
80 case XPRG_CMD_ENTER_PROGMODE
:
81 XPROGProtocol_EnterXPROGMode();
83 case XPRG_CMD_LEAVE_PROGMODE
:
84 XPROGProtocol_LeaveXPROGMode();
87 XPROGProtocol_Erase();
89 case XPRG_CMD_WRITE_MEM
:
90 XPROGProtocol_WriteMemory();
92 case XPRG_CMD_READ_MEM
:
93 XPROGProtocol_ReadMemory();
96 XPROGProtocol_ReadCRC();
98 case XPRG_CMD_SET_PARAM
:
99 XPROGProtocol_SetParam();
104 /** Handler for the XPROG ENTER_PROGMODE command to establish a connection with the attached device. */
105 static void XPROGProtocol_EnterXPROGMode(void)
108 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
112 if (XPROG_SelectedProtocol
== XPRG_PROTOCOL_PDI
)
114 /* Enable PDI programming mode with the attached target */
115 XPROGTarget_EnableTargetPDI();
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
);
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]);
126 /* Wait until the NVM bus becomes active */
127 NVMBusEnabled
= XMEGANVM_WaitWhileNVMBusBusy();
131 /* Enable TPI programming mode with the attached target */
132 XPROGTarget_EnableTargetTPI();
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]);
139 /* Wait until the NVM bus becomes active */
140 NVMBusEnabled
= TINYNVM_WaitWhileNVMBusBusy();
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
);
149 /** Handler for the XPROG LEAVE_PROGMODE command to terminate the PDI programming connection with
150 * the attached device.
152 static void XPROGProtocol_LeaveXPROGMode(void)
155 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
157 if (XPROG_SelectedProtocol
== XPRG_PROTOCOL_PDI
)
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);
163 XPROGTarget_DisableTargetPDI();
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);
171 XPROGTarget_DisableTargetTPI();
174 Endpoint_Write_Byte(CMD_XPROG
);
175 Endpoint_Write_Byte(XPRG_CMD_LEAVE_PROGMODE
);
176 Endpoint_Write_Byte(XPRG_ERR_OK
);
180 /** Handler for the XPRG ERASE command to erase a specific memory address space in the attached device. */
181 static void XPROGProtocol_Erase(void)
183 uint8_t ReturnStatus
= XPRG_ERR_OK
;
189 } Erase_XPROG_Params
;
191 Endpoint_Read_Stream_LE(&Erase_XPROG_Params
, sizeof(Erase_XPROG_Params
));
192 Erase_XPROG_Params
.Address
= SwapEndian_32(Erase_XPROG_Params
.Address
);
195 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
197 uint8_t EraseCommand
= XMEGA_NVM_CMD_NOOP
;
199 if (XPROG_SelectedProtocol
== XPRG_PROTOCOL_PDI
)
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
;
219 /* Erase the target memory, indicate timeout if ocurred */
220 if (!(XMEGANVM_EraseMemory(EraseCommand
, Erase_XPROG_Params
.Address
)))
221 ReturnStatus
= XPRG_ERR_TIMEOUT
;
228 Endpoint_Write_Byte(CMD_XPROG
);
229 Endpoint_Write_Byte(XPRG_CMD_ERASE
);
230 Endpoint_Write_Byte(ReturnStatus
);
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)
237 uint8_t ReturnStatus
= XPRG_ERR_OK
;
245 uint8_t ProgData
[256];
246 } WriteMemory_XPROG_Params
;
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
);
255 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
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;
263 if (XPROG_SelectedProtocol
== XPRG_PROTOCOL_PDI
)
265 if (WriteMemory_XPROG_Params
.MemoryType
== XPRG_MEM_TYPE_APPL
)
267 WriteCommand
= XMEGA_NVM_CMD_WRITEAPPSECPAGE
;
269 else if (WriteMemory_XPROG_Params
.MemoryType
== XPRG_MEM_TYPE_BOOT
)
271 WriteCommand
= XMEGA_NVM_CMD_WRITEBOOTSECPAGE
;
273 else if (WriteMemory_XPROG_Params
.MemoryType
== XPRG_MEM_TYPE_EEPROM
)
275 WriteCommand
= XMEGA_NVM_CMD_WRITEEEPROMPAGE
;
276 WriteBuffCommand
= XMEGA_NVM_CMD_LOADEEPROMPAGEBUFF
;
277 EraseBuffCommand
= XMEGA_NVM_CMD_ERASEEEPROMPAGEBUFF
;
279 else if (WriteMemory_XPROG_Params
.MemoryType
== XPRG_MEM_TYPE_USERSIG
)
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
;
285 else if (WriteMemory_XPROG_Params
.MemoryType
== XPRG_MEM_TYPE_FUSE
)
287 WriteCommand
= XMEGA_NVM_CMD_WRITEFUSE
;
290 else if (WriteMemory_XPROG_Params
.MemoryType
== XPRG_MEM_TYPE_LOCKBITS
)
292 WriteCommand
= XMEGA_NVM_CMD_WRITELOCK
;
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
)))
303 ReturnStatus
= XPRG_ERR_TIMEOUT
;
311 Endpoint_Write_Byte(CMD_XPROG
);
312 Endpoint_Write_Byte(XPRG_CMD_WRITE_MEM
);
313 Endpoint_Write_Byte(ReturnStatus
);
317 /** Handler for the XPROG READ_MEMORY command to read data from a specific address space within the
320 static void XPROGProtocol_ReadMemory(void)
322 uint8_t ReturnStatus
= XPRG_ERR_OK
;
329 } ReadMemory_XPROG_Params
;
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
);
336 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
338 uint8_t ReadBuffer
[256];
340 if (XPROG_SelectedProtocol
== XPRG_PROTOCOL_PDI
)
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
;
351 Endpoint_Write_Byte(CMD_XPROG
);
352 Endpoint_Write_Byte(XPRG_CMD_READ_MEM
);
353 Endpoint_Write_Byte(ReturnStatus
);
355 if (ReturnStatus
== XPRG_ERR_OK
)
356 Endpoint_Write_Stream_LE(ReadBuffer
, ReadMemory_XPROG_Params
.Length
);
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.
364 static void XPROGProtocol_ReadCRC(void)
366 uint8_t ReturnStatus
= XPRG_ERR_OK
;
371 } ReadCRC_XPROG_Params
;
373 Endpoint_Read_Stream_LE(&ReadCRC_XPROG_Params
, sizeof(ReadCRC_XPROG_Params
));
375 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
377 uint8_t CRCCommand
= XMEGA_NVM_CMD_NOOP
;
380 if (XPROG_SelectedProtocol
== XPRG_PROTOCOL_PDI
)
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
;
388 CRCCommand
= XMEGA_NVM_CMD_FLASHCRC
;
390 /* Perform and retrieve the memory CRC, indicate timeout if occurred */
391 if (!(XMEGANVM_GetMemoryCRC(CRCCommand
, &MemoryCRC
)))
392 ReturnStatus
= XPRG_ERR_TIMEOUT
;
396 /* TPI does not support memory CRC */
397 ReturnStatus
= XPRG_ERR_FAILED
;
400 Endpoint_Write_Byte(CMD_XPROG
);
401 Endpoint_Write_Byte(XPRG_CMD_CRC
);
402 Endpoint_Write_Byte(ReturnStatus
);
404 if (ReturnStatus
== XPRG_ERR_OK
)
406 Endpoint_Write_Byte(MemoryCRC
>> 16);
407 Endpoint_Write_Word_LE(MemoryCRC
& 0xFFFF);
413 /** Handler for the XPROG SET_PARAM command to set a XPROG parameter for use when communicating with the
416 static void XPROGProtocol_SetParam(void)
418 uint8_t ReturnStatus
= XPRG_ERR_OK
;
420 uint8_t XPROGParam
= Endpoint_Read_Byte();
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();
428 ReturnStatus
= XPRG_ERR_FAILED
;
431 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN
);
433 Endpoint_Write_Byte(CMD_XPROG
);
434 Endpoint_Write_Byte(XPRG_CMD_SET_PARAM
);
435 Endpoint_Write_Byte(ReturnStatus
);