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....: 2007-07-23
11 PC2 SCK speed option. GND -> slow (8khz SCK),
12 open -> fast (375kHz SCK)
16 #include <avr/interrupt.h>
17 #include <avr/pgmspace.h>
24 #define USBASP_FUNC_CONNECT 1
25 #define USBASP_FUNC_DISCONNECT 2
26 #define USBASP_FUNC_TRANSMIT 3
27 #define USBASP_FUNC_READFLASH 4
28 #define USBASP_FUNC_ENABLEPROG 5
29 #define USBASP_FUNC_WRITEFLASH 6
30 #define USBASP_FUNC_READEEPROM 7
31 #define USBASP_FUNC_WRITEEEPROM 8
32 #define USBASP_FUNC_SETLONGADDRESS 9
34 #define PROG_STATE_IDLE 0
35 #define PROG_STATE_WRITEFLASH 1
36 #define PROG_STATE_READFLASH 2
37 #define PROG_STATE_READEEPROM 3
38 #define PROG_STATE_WRITEEEPROM 4
40 #define PROG_BLOCKFLAG_FIRST 1
41 #define PROG_BLOCKFLAG_LAST 2
43 #define ledRedOn() PORTC &= ~(1 << PC1)
44 #define ledRedOff() PORTC |= (1 << PC1)
45 #define ledGreenOn() PORTC &= ~(1 << PC0)
46 #define ledGreenOff() PORTC |= (1 << PC0)
48 static uchar replyBuffer
[8];
50 static uchar prog_state
= PROG_STATE_IDLE
;
52 static uchar prog_address_newmode
= 0;
53 static unsigned long prog_address
;
54 static unsigned int prog_nbytes
= 0;
55 static unsigned int prog_pagesize
;
56 static uchar prog_blockflags
;
57 static uchar prog_pagecounter
;
60 uchar
usbFunctionSetup(uchar data
[8]) {
64 if(data
[1] == USBASP_FUNC_CONNECT
){
67 if ((PINC
& (1 << PC2
)) == 0) {
68 ispSetSCKOption(ISP_SCK_SLOW
);
70 ispSetSCKOption(ISP_SCK_FAST
);
73 /* set compatibility mode of address delivering */
74 prog_address_newmode
= 0;
79 } else if (data
[1] == USBASP_FUNC_DISCONNECT
) {
83 } else if (data
[1] == USBASP_FUNC_TRANSMIT
) {
84 replyBuffer
[0] = ispTransmit(data
[2]);
85 replyBuffer
[1] = ispTransmit(data
[3]);
86 replyBuffer
[2] = ispTransmit(data
[4]);
87 replyBuffer
[3] = ispTransmit(data
[5]);
90 } else if (data
[1] == USBASP_FUNC_READFLASH
) {
92 if (!prog_address_newmode
)
93 prog_address
= (data
[3] << 8) | data
[2];
95 prog_nbytes
= (data
[7] << 8) | data
[6];
96 prog_state
= PROG_STATE_READFLASH
;
97 len
= 0xff; /* multiple in */
99 } else if (data
[1] == USBASP_FUNC_READEEPROM
) {
101 if (!prog_address_newmode
)
102 prog_address
= (data
[3] << 8) | data
[2];
104 prog_nbytes
= (data
[7] << 8) | data
[6];
105 prog_state
= PROG_STATE_READEEPROM
;
106 len
= 0xff; /* multiple in */
108 } else if (data
[1] == USBASP_FUNC_ENABLEPROG
) {
109 replyBuffer
[0] = ispEnterProgrammingMode();;
112 } else if (data
[1] == USBASP_FUNC_WRITEFLASH
) {
114 if (!prog_address_newmode
)
115 prog_address
= (data
[3] << 8) | data
[2];
117 prog_pagesize
= data
[4];
118 prog_blockflags
= data
[5] & 0x0F;
119 prog_pagesize
+= (((unsigned int)data
[5] & 0xF0)<<4);
120 if (prog_blockflags
& PROG_BLOCKFLAG_FIRST
) {
121 prog_pagecounter
= prog_pagesize
;
123 prog_nbytes
= (data
[7] << 8) | data
[6];
124 prog_state
= PROG_STATE_WRITEFLASH
;
125 len
= 0xff; /* multiple out */
127 } else if (data
[1] == USBASP_FUNC_WRITEEEPROM
) {
129 if (!prog_address_newmode
)
130 prog_address
= (data
[3] << 8) | data
[2];
134 prog_nbytes
= (data
[7] << 8) | data
[6];
135 prog_state
= PROG_STATE_WRITEEEPROM
;
136 len
= 0xff; /* multiple out */
138 } else if(data
[1] == USBASP_FUNC_SETLONGADDRESS
) {
140 /* set new mode of address delivering (ignore address delivered in commands) */
141 prog_address_newmode
= 1;
142 /* set new address */
143 prog_address
= *((unsigned long*)&data
[2]);
146 usbMsgPtr
= replyBuffer
;
152 uchar
usbFunctionRead(uchar
*data
, uchar len
) {
156 /* check if programmer is in correct read state */
157 if ((prog_state
!= PROG_STATE_READFLASH
) &&
158 (prog_state
!= PROG_STATE_READEEPROM
)) {
163 for (i
= 0; i
< len
; i
++) {
164 if (prog_state
== PROG_STATE_READFLASH
) {
165 data
[i
] = ispReadFlash(prog_address
);
167 data
[i
] = ispReadEEPROM(prog_address
);
174 prog_state
= PROG_STATE_IDLE
;
181 uchar
usbFunctionWrite(uchar
*data
, uchar len
) {
186 /* check if programmer is in correct write state */
187 if ((prog_state
!= PROG_STATE_WRITEFLASH
) &&
188 (prog_state
!= PROG_STATE_WRITEEEPROM
)) {
193 for (i
= 0; i
< len
; i
++) {
195 if (prog_state
== PROG_STATE_WRITEFLASH
) {
198 if (prog_pagesize
== 0) {
200 ispWriteFlash(prog_address
, data
[i
], 1);
203 ispWriteFlash(prog_address
, data
[i
], 0);
205 if (prog_pagecounter
== 0) {
206 ispFlushPage(prog_address
, data
[i
]);
207 prog_pagecounter
= prog_pagesize
;
213 ispWriteEEPROM(prog_address
, data
[i
]);
218 if (prog_nbytes
== 0) {
219 prog_state
= PROG_STATE_IDLE
;
220 if ((prog_blockflags
& PROG_BLOCKFLAG_LAST
) &&
221 (prog_pagecounter
!= prog_pagesize
)) {
223 /* last block and page flush pending, so flush it now */
224 ispFlushPage(prog_address
, data
[i
]);
227 retVal
= 1; // Need to return 1 when no more data is to be received
242 PORTB
= 0; /* no pullups on USB and ISP pins */
243 DDRD
= ~(1 << 2); /* all outputs except PD2 = INT0 */
245 DDRB
= ~0; /* output SE0 for USB reset */
247 while(--j
){ /* USB Reset by device only required on Watchdog Reset */
249 while(--i
); /* delay >10ms for USB reset */
251 DDRB
= 0; /* all USB and ISP pins inputs */
253 DDRC
= 0x03; /* all inputs except PC0, PC1 */
256 clockInit(); /* init timer */
258 ispSetSCKOption(ISP_SCK_FAST
);
262 for(;;){ /* main event loop */