Started implementing the low level PDI protocol in the AVRISP project, for XMEGA...
[pub/USBasp.git] / Projects / AVRISP / Lib / PDIProtocol.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 #if defined(ENABLE_XPROG_PROTOCOL)
32
33 /** \file
34 *
35 * PDI Protocol handler, to process V2 Protocol wrapped PDI commands used in Atmel programmer devices.
36 */
37
38 #define INCLUDE_FROM_PDIPROTOCOL_C
39 #include "PDIProtocol.h"
40
41 uint32_t XPROG_Param_NVMBase;
42 uint32_t XPROG_Param_EEPageSize;
43
44 /** Handler for the CMD_XPROG_SETMODE command, which sets the programmer-to-target protocol used for PDI
45 * XMEGA programming (either PDI or JTAG). Only PDI programming is supported.
46 */
47 void PDIProtocol_XPROG_SetMode(void)
48 {
49 struct
50 {
51 uint8_t Protocol;
52 } SetMode_XPROG_Params;
53
54 Endpoint_Read_Stream_LE(&SetMode_XPROG_Params, sizeof(SetMode_XPROG_Params));
55
56 Endpoint_ClearOUT();
57 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
58
59 Endpoint_Write_Byte(CMD_XPROG_SETMODE);
60 Endpoint_Write_Byte(SetMode_XPROG_Params.Protocol ? STATUS_CMD_FAILED : STATUS_CMD_OK);
61 Endpoint_ClearIN();
62 }
63
64 void PDIProtocol_XPROG_Command(void)
65 {
66 uint8_t XPROGCommand = Endpoint_Read_Byte();
67
68 switch (XPROGCommand)
69 {
70 case XPRG_CMD_ENTER_PROGMODE:
71 PDIProtocol_EnterXPROGMode();
72 break;
73 case XPRG_CMD_LEAVE_PROGMODE:
74 PDIProtocol_LeaveXPROGMode();
75 break;
76 case XPRG_CMD_ERASE:
77 PDIProtocol_EraseChip();
78 break;
79 case XPRG_CMD_WRITE_MEM:
80 PDIProtocol_WriteMemory();
81 break;
82 case XPRG_CMD_READ_MEM:
83 PDIProtocol_ReadMemory();
84 break;
85 case XPRG_CMD_CRC:
86 PDIProtocol_ReadCRC();
87 break;
88 case XPRG_CMD_SET_PARAM:
89 PDIProtocol_SetParam();
90 break;
91 }
92 }
93
94 static void PDIProtocol_EnterXPROGMode(void)
95 {
96 uint8_t ReturnStatus = XPRG_ERR_OK;
97
98 Endpoint_ClearOUT();
99 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
100
101 PDIDATA_LINE_DDR |= PDIDATA_LINE_MASK;
102 PDICLOCK_LINE_DDR |= PDICLOCK_LINE_MASK;
103
104 PDIDATA_LINE_PORT |= PDIDATA_LINE_MASK;
105
106 _delay_us(1);
107
108 for (uint8_t i = 0; i < 16; i++)
109 {
110 PDICLOCK_LINE_PORT ^= PDICLOCK_LINE_MASK;
111 PDICLOCK_LINE_PORT ^= PDICLOCK_LINE_MASK;
112 }
113
114 static const uint8_t NVMKey[8] = {0x12, 0x89, 0xAB, 0x45, 0xCD, 0xD8, 0x88, 0xFF};
115
116 PDITarget_SendByte(PDI_CMD_KEY);
117 for (uint8_t i = 0; i < 8; i++)
118 PDITarget_SendByte(NVMKey[i]);
119
120 PDITarget_SendByte(PDI_CMD_LDCS | PD_STATUS_REG);
121 if (!(PDITarget_ReceiveByte() & PDI_STATUS_NVM))
122 ReturnStatus = XPRG_ERR_FAILED;
123
124 Endpoint_Write_Byte(CMD_XPROG);
125 Endpoint_Write_Byte(XPRG_CMD_ENTER_PROGMODE);
126 Endpoint_Write_Byte(ReturnStatus);
127 Endpoint_ClearIN();
128 }
129
130 static void PDIProtocol_LeaveXPROGMode(void)
131 {
132 Endpoint_ClearOUT();
133 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
134
135 PDIDATA_LINE_DDR &= ~PDIDATA_LINE_MASK;
136 PDICLOCK_LINE_DDR &= ~PDICLOCK_LINE_MASK;
137
138 PDIDATA_LINE_PORT &= ~PDIDATA_LINE_MASK;
139 PDICLOCK_LINE_PORT &= ~PDICLOCK_LINE_MASK;
140
141 Endpoint_Write_Byte(CMD_XPROG);
142 Endpoint_Write_Byte(XPRG_CMD_LEAVE_PROGMODE);
143 Endpoint_Write_Byte(XPRG_ERR_OK);
144 Endpoint_ClearIN();
145 }
146
147 static void PDIProtocol_EraseChip(void)
148 {
149 uint8_t ReturnStatus = XPRG_ERR_OK;
150
151 struct
152 {
153 uint8_t MemoryType;
154 uint32_t Address;
155 } Erase_XPROG_Params;
156
157 Endpoint_Read_Stream_LE(&Erase_XPROG_Params, sizeof(Erase_XPROG_Params));
158
159 Endpoint_ClearOUT();
160 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
161
162 // TODO: Send erase command here via PDI protocol
163
164 Endpoint_Write_Byte(CMD_XPROG);
165 Endpoint_Write_Byte(XPRG_CMD_ERASE);
166 Endpoint_Write_Byte(ReturnStatus);
167 Endpoint_ClearIN();
168 }
169
170 static void PDIProtocol_WriteMemory(void)
171 {
172 uint8_t ReturnStatus = XPRG_ERR_OK;
173
174 struct
175 {
176 uint8_t MemoryType;
177 uint32_t Address;
178 uint16_t Length;
179 uint8_t ProgData[256];
180 } WriteMemory_XPROG_Params;
181
182 Endpoint_Read_Stream_LE(&WriteMemory_XPROG_Params, (sizeof(WriteMemory_XPROG_Params) -
183 sizeof(WriteMemory_XPROG_Params).ProgData));
184 WriteMemory_XPROG_Params.Address = SwapEndian_32(WriteMemory_XPROG_Params.Address);
185 WriteMemory_XPROG_Params.Length = SwapEndian_16(WriteMemory_XPROG_Params.Length);
186 Endpoint_Read_Stream_LE(&WriteMemory_XPROG_Params.ProgData, WriteMemory_XPROG_Params.Length);
187
188 Endpoint_ClearOUT();
189 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
190
191 // TODO: Send program command here via PDI protocol
192
193 Endpoint_Write_Byte(CMD_XPROG);
194 Endpoint_Write_Byte(XPRG_CMD_READ_MEM);
195 Endpoint_Write_Byte(ReturnStatus);
196 Endpoint_ClearIN();
197 }
198
199 static void PDIProtocol_ReadMemory(void)
200 {
201 uint8_t ReturnStatus = XPRG_ERR_OK;
202
203 struct
204 {
205 uint8_t MemoryType;
206 uint32_t Address;
207 uint16_t Length;
208 } ReadMemory_XPROG_Params;
209
210 Endpoint_Read_Stream_LE(&ReadMemory_XPROG_Params, sizeof(ReadMemory_XPROG_Params));
211 ReadMemory_XPROG_Params.Address = SwapEndian_32(ReadMemory_XPROG_Params.Address);
212 ReadMemory_XPROG_Params.Length = SwapEndian_16(ReadMemory_XPROG_Params.Length);
213
214 Endpoint_ClearOUT();
215 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
216
217 // TODO: Send read command here via PDI protocol
218
219 Endpoint_Write_Byte(CMD_XPROG);
220 Endpoint_Write_Byte(XPRG_CMD_READ_MEM);
221 Endpoint_Write_Byte(ReturnStatus);
222
223 // START TEMP
224 uint8_t ProgData[256];
225 for (uint16_t i = 0; i < ReadMemory_XPROG_Params.Length; i++)
226 ProgData[i] = i;
227 Endpoint_Write_Stream_LE(ProgData, ReadMemory_XPROG_Params.Length);
228
229 if (!Endpoint_IsReadWriteAllowed())
230 {
231 Endpoint_ClearIN();
232 while(!(Endpoint_IsReadWriteAllowed()));
233 }
234 // END TEMP
235
236 Endpoint_ClearIN();
237 }
238
239 static void PDIProtocol_ReadCRC(void)
240 {
241 uint8_t ReturnStatus = XPRG_ERR_OK;
242
243 uint8_t CRCType = Endpoint_Read_Byte();
244
245 Endpoint_ClearOUT();
246 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
247
248 uint32_t MemoryCRC = 0;
249
250 // TODO: Read device CRC for desired memory via PDI protocol
251
252 Endpoint_Write_Byte(CMD_XPROG);
253 Endpoint_Write_Byte(XPRG_CMD_CRC);
254 Endpoint_Write_Byte(ReturnStatus);
255
256 if (ReturnStatus == XPRG_ERR_OK)
257 {
258 Endpoint_Write_Byte(MemoryCRC >> 16);
259 Endpoint_Write_Word_LE(MemoryCRC & 0xFFFF);
260 }
261
262 Endpoint_ClearIN();
263 }
264
265 static void PDIProtocol_SetParam(void)
266 {
267 uint8_t ReturnStatus = XPRG_ERR_OK;
268
269 uint8_t XPROGParam = Endpoint_Read_Byte();
270
271 if (XPROGParam == XPRG_PARAM_NVMBASE)
272 XPROG_Param_NVMBase = Endpoint_Read_DWord_LE();
273 else if (XPROGParam == XPRG_PARAM_EEPPAGESIZE)
274 XPROG_Param_EEPageSize = Endpoint_Read_Word_LE();
275 else
276 ReturnStatus = XPRG_ERR_FAILED;
277
278 Endpoint_ClearOUT();
279 Endpoint_SetEndpointDirection(ENDPOINT_DIR_IN);
280
281 Endpoint_Write_Byte(CMD_XPROG);
282 Endpoint_Write_Byte(XPRG_CMD_SET_PARAM);
283 Endpoint_Write_Byte(ReturnStatus);
284 Endpoint_ClearIN();
285 }
286
287 #endif