2 * USBasp - USB in-circuit programmer for Atmel AVR controllers
4 * Thomas Fischl <tfischl@gmx.de>
6 * License........: GNU GPL v2 (see Readme.txt)
7 * Target.........: ATMega8 at 12 MHz
8 * Creation Date..: 2005-02-20
9 * Last change....: 2009-02-28
11 * PC2 SCK speed option.
12 * GND -> slow (8khz SCK),
13 * open -> software set speed (default is 375kHz SCK)
17 #include <avr/interrupt.h>
18 #include <avr/pgmspace.h>
28 static uchar replyBuffer
[8];
30 static uchar prog_state
= PROG_STATE_IDLE
;
31 static uchar prog_sck
= USBASP_ISP_SCK_AUTO
;
33 static uchar prog_address_newmode
= 0;
34 static unsigned long prog_address
;
35 static unsigned int prog_nbytes
= 0;
36 static unsigned int prog_pagesize
;
37 static uchar prog_blockflags
;
38 static uchar prog_pagecounter
;
40 uchar
usbFunctionSetup(uchar data
[8]) {
44 if (data
[1] == USBASP_FUNC_CONNECT
) {
47 if ((PINC
& (1 << PC2
)) == 0) {
48 ispSetSCKOption(USBASP_ISP_SCK_8
);
50 ispSetSCKOption(prog_sck
);
53 /* set compatibility mode of address delivering */
54 prog_address_newmode
= 0;
59 } else if (data
[1] == USBASP_FUNC_DISCONNECT
) {
63 } else if (data
[1] == USBASP_FUNC_TRANSMIT
) {
64 replyBuffer
[0] = ispTransmit(data
[2]);
65 replyBuffer
[1] = ispTransmit(data
[3]);
66 replyBuffer
[2] = ispTransmit(data
[4]);
67 replyBuffer
[3] = ispTransmit(data
[5]);
70 } else if (data
[1] == USBASP_FUNC_READFLASH
) {
72 if (!prog_address_newmode
)
73 prog_address
= (data
[3] << 8) | data
[2];
75 prog_nbytes
= (data
[7] << 8) | data
[6];
76 prog_state
= PROG_STATE_READFLASH
;
77 len
= 0xff; /* multiple in */
79 } else if (data
[1] == USBASP_FUNC_READEEPROM
) {
81 if (!prog_address_newmode
)
82 prog_address
= (data
[3] << 8) | data
[2];
84 prog_nbytes
= (data
[7] << 8) | data
[6];
85 prog_state
= PROG_STATE_READEEPROM
;
86 len
= 0xff; /* multiple in */
88 } else if (data
[1] == USBASP_FUNC_ENABLEPROG
) {
89 replyBuffer
[0] = ispEnterProgrammingMode();
92 } else if (data
[1] == USBASP_FUNC_WRITEFLASH
) {
94 if (!prog_address_newmode
)
95 prog_address
= (data
[3] << 8) | data
[2];
97 prog_pagesize
= data
[4];
98 prog_blockflags
= data
[5] & 0x0F;
99 prog_pagesize
+= (((unsigned int) data
[5] & 0xF0) << 4);
100 if (prog_blockflags
& PROG_BLOCKFLAG_FIRST
) {
101 prog_pagecounter
= prog_pagesize
;
103 prog_nbytes
= (data
[7] << 8) | data
[6];
104 prog_state
= PROG_STATE_WRITEFLASH
;
105 len
= 0xff; /* multiple out */
107 } else if (data
[1] == USBASP_FUNC_WRITEEEPROM
) {
109 if (!prog_address_newmode
)
110 prog_address
= (data
[3] << 8) | data
[2];
114 prog_nbytes
= (data
[7] << 8) | data
[6];
115 prog_state
= PROG_STATE_WRITEEEPROM
;
116 len
= 0xff; /* multiple out */
118 } else if (data
[1] == USBASP_FUNC_SETLONGADDRESS
) {
120 /* set new mode of address delivering (ignore address delivered in commands) */
121 prog_address_newmode
= 1;
122 /* set new address */
123 prog_address
= *((unsigned long*) &data
[2]);
125 } else if (data
[1] == USBASP_FUNC_SETISPSCK
) {
132 } else if (data
[1] == USBASP_FUNC_TPI_CONNECT
) {
133 tpi_dly_cnt
= data
[2] | (data
[3] << 8);
136 ISP_OUT
|= (1 << ISP_RST
);
137 ISP_DDR
|= (1 << ISP_RST
);
142 ISP_OUT
&= ~(1 << ISP_RST
);
148 } else if (data
[1] == USBASP_FUNC_TPI_DISCONNECT
) {
150 tpi_send_byte(TPI_OP_SSTCS(TPISR
));
156 ISP_OUT
|= (1 << ISP_RST
);
158 ISP_OUT
&= ~(1 << ISP_RST
);
161 /* set all ISP pins inputs */
162 ISP_DDR
&= ~((1 << ISP_RST
) | (1 << ISP_SCK
) | (1 << ISP_MOSI
));
163 /* switch pullups off */
164 ISP_OUT
&= ~((1 << ISP_RST
) | (1 << ISP_SCK
) | (1 << ISP_MOSI
));
168 } else if (data
[1] == USBASP_FUNC_TPI_RAWREAD
) {
169 replyBuffer
[0] = tpi_recv_byte();
172 } else if (data
[1] == USBASP_FUNC_TPI_RAWWRITE
) {
173 tpi_send_byte(data
[2]);
175 } else if (data
[1] == USBASP_FUNC_TPI_READBLOCK
) {
176 prog_address
= (data
[3] << 8) | data
[2];
177 prog_nbytes
= (data
[7] << 8) | data
[6];
178 prog_state
= PROG_STATE_TPI_READ
;
179 len
= 0xff; /* multiple in */
181 } else if (data
[1] == USBASP_FUNC_TPI_WRITEBLOCK
) {
182 prog_address
= (data
[3] << 8) | data
[2];
183 prog_nbytes
= (data
[7] << 8) | data
[6];
184 prog_state
= PROG_STATE_TPI_WRITE
;
185 len
= 0xff; /* multiple out */
187 } else if (data
[1] == USBASP_FUNC_GETCAPABILITIES
) {
188 replyBuffer
[0] = USBASP_CAP_0_TPI
;
195 usbMsgPtr
= replyBuffer
;
200 uchar
usbFunctionRead(uchar
*data
, uchar len
) {
204 /* check if programmer is in correct read state */
205 if ((prog_state
!= PROG_STATE_READFLASH
) && (prog_state
206 != PROG_STATE_READEEPROM
) && (prog_state
!= PROG_STATE_TPI_READ
)) {
210 /* fill packet TPI mode */
211 if(prog_state
== PROG_STATE_TPI_READ
)
213 tpi_read_block(prog_address
, data
, len
);
218 /* fill packet ISP mode */
219 for (i
= 0; i
< len
; i
++) {
220 if (prog_state
== PROG_STATE_READFLASH
) {
221 data
[i
] = ispReadFlash(prog_address
);
223 data
[i
] = ispReadEEPROM(prog_address
);
230 prog_state
= PROG_STATE_IDLE
;
236 uchar
usbFunctionWrite(uchar
*data
, uchar len
) {
241 /* check if programmer is in correct write state */
242 if ((prog_state
!= PROG_STATE_WRITEFLASH
) && (prog_state
243 != PROG_STATE_WRITEEEPROM
) && (prog_state
!= PROG_STATE_TPI_WRITE
)) {
247 if (prog_state
== PROG_STATE_TPI_WRITE
)
249 tpi_write_block(prog_address
, data
, len
);
254 prog_state
= PROG_STATE_IDLE
;
260 for (i
= 0; i
< len
; i
++) {
262 if (prog_state
== PROG_STATE_WRITEFLASH
) {
265 if (prog_pagesize
== 0) {
267 ispWriteFlash(prog_address
, data
[i
], 1);
270 ispWriteFlash(prog_address
, data
[i
], 0);
272 if (prog_pagecounter
== 0) {
273 ispFlushPage(prog_address
, data
[i
]);
274 prog_pagecounter
= prog_pagesize
;
280 ispWriteEEPROM(prog_address
, data
[i
]);
285 if (prog_nbytes
== 0) {
286 prog_state
= PROG_STATE_IDLE
;
287 if ((prog_blockflags
& PROG_BLOCKFLAG_LAST
) && (prog_pagecounter
290 /* last block and page flush pending, so flush it now */
291 ispFlushPage(prog_address
, data
[i
]);
294 retVal
= 1; // Need to return 1 when no more data is to be received
306 /* no pullups on USB and ISP pins */
309 /* all outputs except PD2 = INT0 */
312 /* output SE0 for USB reset */
315 /* USB Reset by device only required on Watchdog Reset */
318 /* delay >10ms for USB reset */
322 /* all USB and ISP pins inputs */
325 /* all inputs except PC0, PC1 */
332 /* main event loop */