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>
26 static uchar replyBuffer
[8];
28 static uchar prog_state
= PROG_STATE_IDLE
;
29 static uchar prog_sck
= USBASP_ISP_SCK_AUTO
;
31 static uchar prog_address_newmode
= 0;
32 static unsigned long prog_address
;
33 static unsigned int prog_nbytes
= 0;
34 static unsigned int prog_pagesize
;
35 static uchar prog_blockflags
;
36 static uchar prog_pagecounter
;
38 uchar
usbFunctionSetup(uchar data
[8]) {
42 if (data
[1] == USBASP_FUNC_CONNECT
) {
45 if ((PINC
& (1 << PC2
)) == 0) {
46 ispSetSCKOption(USBASP_ISP_SCK_8
);
48 ispSetSCKOption(prog_sck
);
51 /* set compatibility mode of address delivering */
52 prog_address_newmode
= 0;
57 } else if (data
[1] == USBASP_FUNC_DISCONNECT
) {
61 } else if (data
[1] == USBASP_FUNC_TRANSMIT
) {
62 replyBuffer
[0] = ispTransmit(data
[2]);
63 replyBuffer
[1] = ispTransmit(data
[3]);
64 replyBuffer
[2] = ispTransmit(data
[4]);
65 replyBuffer
[3] = ispTransmit(data
[5]);
68 } else if (data
[1] == USBASP_FUNC_READFLASH
) {
70 if (!prog_address_newmode
)
71 prog_address
= (data
[3] << 8) | data
[2];
73 prog_nbytes
= (data
[7] << 8) | data
[6];
74 prog_state
= PROG_STATE_READFLASH
;
75 len
= 0xff; /* multiple in */
77 } else if (data
[1] == USBASP_FUNC_READEEPROM
) {
79 if (!prog_address_newmode
)
80 prog_address
= (data
[3] << 8) | data
[2];
82 prog_nbytes
= (data
[7] << 8) | data
[6];
83 prog_state
= PROG_STATE_READEEPROM
;
84 len
= 0xff; /* multiple in */
86 } else if (data
[1] == USBASP_FUNC_ENABLEPROG
) {
87 replyBuffer
[0] = ispEnterProgrammingMode();
90 } else if (data
[1] == USBASP_FUNC_WRITEFLASH
) {
92 if (!prog_address_newmode
)
93 prog_address
= (data
[3] << 8) | data
[2];
95 prog_pagesize
= data
[4];
96 prog_blockflags
= data
[5] & 0x0F;
97 prog_pagesize
+= (((unsigned int) data
[5] & 0xF0) << 4);
98 if (prog_blockflags
& PROG_BLOCKFLAG_FIRST
) {
99 prog_pagecounter
= prog_pagesize
;
101 prog_nbytes
= (data
[7] << 8) | data
[6];
102 prog_state
= PROG_STATE_WRITEFLASH
;
103 len
= 0xff; /* multiple out */
105 } else if (data
[1] == USBASP_FUNC_WRITEEEPROM
) {
107 if (!prog_address_newmode
)
108 prog_address
= (data
[3] << 8) | data
[2];
112 prog_nbytes
= (data
[7] << 8) | data
[6];
113 prog_state
= PROG_STATE_WRITEEEPROM
;
114 len
= 0xff; /* multiple out */
116 } else if (data
[1] == USBASP_FUNC_SETLONGADDRESS
) {
118 /* set new mode of address delivering (ignore address delivered in commands) */
119 prog_address_newmode
= 1;
120 /* set new address */
121 prog_address
= *((unsigned long*) &data
[2]);
123 } else if (data
[1] == USBASP_FUNC_SETISPSCK
) {
131 usbMsgPtr
= replyBuffer
;
136 uchar
usbFunctionRead(uchar
*data
, uchar len
) {
140 /* check if programmer is in correct read state */
141 if ((prog_state
!= PROG_STATE_READFLASH
) && (prog_state
142 != PROG_STATE_READEEPROM
)) {
147 for (i
= 0; i
< len
; i
++) {
148 if (prog_state
== PROG_STATE_READFLASH
) {
149 data
[i
] = ispReadFlash(prog_address
);
151 data
[i
] = ispReadEEPROM(prog_address
);
158 prog_state
= PROG_STATE_IDLE
;
164 uchar
usbFunctionWrite(uchar
*data
, uchar len
) {
169 /* check if programmer is in correct write state */
170 if ((prog_state
!= PROG_STATE_WRITEFLASH
) && (prog_state
171 != PROG_STATE_WRITEEEPROM
)) {
175 for (i
= 0; i
< len
; i
++) {
177 if (prog_state
== PROG_STATE_WRITEFLASH
) {
180 if (prog_pagesize
== 0) {
182 ispWriteFlash(prog_address
, data
[i
], 1);
185 ispWriteFlash(prog_address
, data
[i
], 0);
187 if (prog_pagecounter
== 0) {
188 ispFlushPage(prog_address
, data
[i
]);
189 prog_pagecounter
= prog_pagesize
;
195 ispWriteEEPROM(prog_address
, data
[i
]);
200 if (prog_nbytes
== 0) {
201 prog_state
= PROG_STATE_IDLE
;
202 if ((prog_blockflags
& PROG_BLOCKFLAG_LAST
) && (prog_pagecounter
205 /* last block and page flush pending, so flush it now */
206 ispFlushPage(prog_address
, data
[i
]);
209 retVal
= 1; // Need to return 1 when no more data is to be received
221 /* no pullups on USB and ISP pins */
224 /* all outputs except PD2 = INT0 */
227 /* output SE0 for USB reset */
230 /* USB Reset by device only required on Watchdog Reset */
233 /* delay >10ms for USB reset */
237 /* all USB and ISP pins inputs */
240 /* all inputs except PC0, PC1 */
247 /* main event loop */