2 USBasp - USB in-circuit programmer for Atmel AVR controllers
4 Thomas Fischl <tfischl@gmx.de>
7 The project is built with AVR USB driver by Objective Development, which is
8 published under an own licence based on the GNU General Public License (GPL).
9 USBasp is also distributed under this enhanced licence. See Documentation.
11 Target.........: ATMega8 at 12 MHz
12 Creation Date..: 2005-02-20
13 Last change....: 2006-12-29
15 PC2 SCK speed option. GND -> slow (8khz SCK),
16 open -> fast (375kHz SCK)
20 #include <avr/interrupt.h>
21 #include <avr/pgmspace.h>
28 #define USBASP_FUNC_CONNECT 1
29 #define USBASP_FUNC_DISCONNECT 2
30 #define USBASP_FUNC_TRANSMIT 3
31 #define USBASP_FUNC_READFLASH 4
32 #define USBASP_FUNC_ENABLEPROG 5
33 #define USBASP_FUNC_WRITEFLASH 6
34 #define USBASP_FUNC_READEEPROM 7
35 #define USBASP_FUNC_WRITEEEPROM 8
37 #define PROG_STATE_IDLE 0
38 #define PROG_STATE_WRITEFLASH 1
39 #define PROG_STATE_READFLASH 2
40 #define PROG_STATE_READEEPROM 3
41 #define PROG_STATE_WRITEEEPROM 4
43 #define PROG_BLOCKFLAG_FIRST 1
44 #define PROG_BLOCKFLAG_LAST 2
46 #define ledRedOn() PORTC &= ~(1 << PC1)
47 #define ledRedOff() PORTC |= (1 << PC1)
48 #define ledGreenOn() PORTC &= ~(1 << PC0)
49 #define ledGreenOff() PORTC |= (1 << PC0)
51 static uchar replyBuffer
[8];
53 static uchar prog_state
= PROG_STATE_IDLE
;
55 static unsigned int prog_address
;
56 static unsigned int prog_nbytes
= 0;
57 static unsigned int prog_pagesize
; //TP: Mega128 fix
58 static uchar prog_blockflags
;
59 static uchar prog_pagecounter
;
62 uchar
usbFunctionSetup(uchar data
[8]) {
66 if(data
[1] == USBASP_FUNC_CONNECT
){
69 if ((PINC
& (1 << PC2
)) == 0) {
70 ispSetSCKOption(ISP_SCK_SLOW
);
72 ispSetSCKOption(ISP_SCK_FAST
);
78 } else if (data
[1] == USBASP_FUNC_DISCONNECT
) {
82 } else if (data
[1] == USBASP_FUNC_TRANSMIT
) {
83 replyBuffer
[0] = ispTransmit(data
[2]);
84 replyBuffer
[1] = ispTransmit(data
[3]);
85 replyBuffer
[2] = ispTransmit(data
[4]);
86 replyBuffer
[3] = ispTransmit(data
[5]);
89 } else if (data
[1] == USBASP_FUNC_READFLASH
) {
90 prog_address
= (data
[3] << 8) | data
[2];
91 prog_nbytes
= (data
[7] << 8) | data
[6];
92 prog_state
= PROG_STATE_READFLASH
;
93 len
= 0xff; /* multiple in */
95 } else if (data
[1] == USBASP_FUNC_READEEPROM
) {
96 prog_address
= (data
[3] << 8) | data
[2];
97 prog_nbytes
= (data
[7] << 8) | data
[6];
98 prog_state
= PROG_STATE_READEEPROM
;
99 len
= 0xff; /* multiple in */
101 } else if (data
[1] == USBASP_FUNC_ENABLEPROG
) {
102 replyBuffer
[0] = ispEnterProgrammingMode();;
105 } else if (data
[1] == USBASP_FUNC_WRITEFLASH
) {
106 prog_address
= (data
[3] << 8) | data
[2];
107 prog_pagesize
= data
[4];
108 prog_blockflags
= data
[5] & 0x0F;
109 prog_pagesize
+= (((unsigned int)data
[5] & 0xF0)<<4); //TP: Mega128 fix
110 if (prog_blockflags
& PROG_BLOCKFLAG_FIRST
) {
111 prog_pagecounter
= prog_pagesize
;
113 prog_nbytes
= (data
[7] << 8) | data
[6];
114 prog_state
= PROG_STATE_WRITEFLASH
;
115 len
= 0xff; /* multiple out */
117 } else if (data
[1] == USBASP_FUNC_WRITEEEPROM
) {
118 prog_address
= (data
[3] << 8) | data
[2];
121 prog_nbytes
= (data
[7] << 8) | data
[6];
122 prog_state
= PROG_STATE_WRITEEEPROM
;
123 len
= 0xff; /* multiple out */
126 usbMsgPtr
= replyBuffer
;
132 uchar
usbFunctionRead(uchar
*data
, uchar len
) {
136 /* check if programmer is in correct read state */
137 if ((prog_state
!= PROG_STATE_READFLASH
) &&
138 (prog_state
!= PROG_STATE_READEEPROM
)) {
143 for (i
= 0; i
< len
; i
++) {
144 if (prog_state
== PROG_STATE_READFLASH
) {
145 data
[i
] = ispReadFlash(prog_address
);
147 data
[i
] = ispReadEEPROM(prog_address
);
154 prog_state
= PROG_STATE_IDLE
;
161 uchar
usbFunctionWrite(uchar
*data
, uchar len
) {
166 /* check if programmer is in correct write state */
167 if ((prog_state
!= PROG_STATE_WRITEFLASH
) &&
168 (prog_state
!= PROG_STATE_WRITEEEPROM
)) {
173 for (i
= 0; i
< len
; i
++) {
175 if (prog_state
== PROG_STATE_WRITEFLASH
) {
178 if (prog_pagesize
== 0) {
180 ispWriteFlash(prog_address
, data
[i
], 1);
183 ispWriteFlash(prog_address
, data
[i
], 0);
185 if (prog_pagecounter
== 0) {
186 ispFlushPage(prog_address
, data
[i
]);
187 prog_pagecounter
= prog_pagesize
;
193 ispWriteEEPROM(prog_address
, data
[i
]);
198 if (prog_nbytes
== 0) {
199 prog_state
= PROG_STATE_IDLE
;
200 if ((prog_blockflags
& PROG_BLOCKFLAG_LAST
) &&
201 (prog_pagecounter
!= prog_pagesize
)) {
203 /* last block and page flush pending, so flush it now */
204 ispFlushPage(prog_address
, data
[i
]);
207 retVal
= 1; // Need to return 1 when no more data is to be received
222 PORTB
= 0; /* no pullups on USB and ISP pins */
223 DDRD
= ~(1 << 2); /* all outputs except PD2 = INT0 */
225 DDRB
= ~0; /* output SE0 for USB reset */
227 while(--j
){ /* USB Reset by device only required on Watchdog Reset */
229 while(--i
); /* delay >10ms for USB reset */
231 DDRB
= 0; /* all USB and ISP pins inputs */
233 DDRC
= 0x03; /* all inputs except PC0, PC1 */
236 clockInit(); /* init timer */
238 ispSetSCKOption(ISP_SCK_FAST
);
242 for(;;){ /* main event loop */