2 * isp.c - part of USBasp
4 * Autor..........: Thomas Fischl <tfischl@gmx.de>
5 * Description....: Provides functions for communication/programming
7 * Licence........: GNU GPL v2 (see Readme.txt)
8 * Creation Date..: 2005-02-23
9 * Last change....: 2010-01-19
17 #define spiHWdisable() SPCR = 0
20 uchar sck_sw_delay_loops
;
30 void ispSetSCKOption(uchar option
) {
32 if (option
== USBASP_ISP_SCK_AUTO
)
33 option
= USBASP_ISP_SCK_375
;
35 if (((F_CPU
<= 12000000) && (option
>= USBASP_ISP_SCK_93_75
))
36 || ((F_CPU
> 12000000) && (option
>= USBASP_ISP_SCK_187_5
))) {
37 ispTransmit
= ispTransmit_hw
;
39 sck_sw_delay
= 1; /* force RST#/SCK pulse for 320us */
40 sck_sw_delay_loops
= 1;
44 case USBASP_ISP_SCK_1500
:
45 # if (F_CPU <= 12000000)
46 /* enable SPI, master, 1.5MHz, XTAL/8 */
47 sck_spcr
= (1 << SPE
) | (1 << MSTR
) | (1 << SPR0
);
48 sck_spsr
= (1 << SPI2X
);
50 /* enable SPI, master, ~1.1MHz, XTAL/16 */
51 sck_spcr
= (1 << SPE
) | (1 << MSTR
) | (1 << SPR0
);
54 case USBASP_ISP_SCK_750
:
55 # if (F_CPU <= 12000000)
56 /* enable SPI, master, 750kHz, XTAL/16 */
57 sck_spcr
= (1 << SPE
) | (1 << MSTR
) | (1 << SPR0
);
59 /* enable SPI, master, ~531kHz, XTAL/32 */
60 sck_spcr
= (1 << SPE
) | (1 << MSTR
) | (1 << SPR1
);
61 sck_spsr
= (1 << SPI2X
);
64 case USBASP_ISP_SCK_375
:
66 # if (F_CPU <= 12000000)
67 /* enable SPI, master, 375kHz, XTAL/32 (default) */
68 sck_spcr
= (1 << SPE
) | (1 << MSTR
) | (1 << SPR1
);
69 sck_spsr
= (1 << SPI2X
);
71 /* enable SPI, master, ~265.6kHz XTAL/64 (default) */
72 sck_spcr
= (1 << SPE
) | (1 << MSTR
) | (1 << SPR1
);
75 case USBASP_ISP_SCK_187_5
:
76 # if (F_CPU <= 12000000)
77 /* enable SPI, master, 187.5kHz XTAL/64 */
78 sck_spcr
= (1 << SPE
) | (1 << MSTR
) | (1 << SPR1
);
80 /* enable SPI, master, ~132.81kHz XTAL/128 */
81 sck_spcr
= (1 << SPE
) | (1 << MSTR
) | (1 << SPR1
) | (1 << SPR0
);
84 # if (F_CPU <= 12000000)
85 case USBASP_ISP_SCK_93_75
:
86 /* enable SPI, master, 93.75kHz XTAL/128 */
87 sck_spcr
= (1 << SPE
) | (1 << MSTR
) | (1 << SPR1
) | (1 << SPR0
);
93 ispTransmit
= ispTransmit_sw
;
94 sck_sw_delay_loops
= 1;
98 # if (F_CPU > 12000000)
99 case USBASP_ISP_SCK_93_75
:
104 case USBASP_ISP_SCK_32
:
105 sck_sw_delay
= ((3 * (F_CPU
/1000000L) + 11) / 12);
108 case USBASP_ISP_SCK_16
:
109 sck_sw_delay
= ((6 * (F_CPU
/1000000L) + 11) / 12);
112 case USBASP_ISP_SCK_8
:
113 sck_sw_delay
= ((12 * (F_CPU
/1000000L) + 11) / 12);
116 case USBASP_ISP_SCK_4
:
117 sck_sw_delay
= ((24 * (F_CPU
/1000000L) + 11) / 12);
120 case USBASP_ISP_SCK_2
:
121 sck_sw_delay
= ((48 * (F_CPU
/1000000L) + 11) / 12);
124 case USBASP_ISP_SCK_1
:
125 sck_sw_delay
= ((96 * (F_CPU
/1000000L) + 11) / 12);
128 case USBASP_ISP_SCK_0_5
:
129 sck_sw_delay
= ((96 * (F_CPU
/1000000L) + 11) / 12);
130 sck_sw_delay_loops
= 2;
139 uint8_t starttime
= TIMERVALUE
;
140 uint8_t loops
= sck_sw_delay_loops
;
143 while ((uint8_t) (TIMERVALUE
- starttime
) < sck_sw_delay
) {
150 /* all ISP pins are inputs before */
151 /* now set output pins */
152 ISP_DDR
|= (1 << ISP_RST
) | (1 << ISP_SCK
) | (1 << ISP_MOSI
);
155 ISP_OUT
&= ~(1 << ISP_RST
); /* RST low */
156 ISP_OUT
&= ~(1 << ISP_SCK
); /* SCK low */
158 /* positive reset pulse > 2 SCK (target) */
160 ISP_OUT
|= (1 << ISP_RST
); /* RST high */
162 ISP_OUT
&= ~(1 << ISP_RST
); /* RST low */
164 if (ispTransmit
== ispTransmit_hw
) {
168 /* Initial extended address value */
172 void ispDisconnect() {
174 /* set all ISP pins inputs */
175 ISP_DDR
&= ~((1 << ISP_RST
) | (1 << ISP_SCK
) | (1 << ISP_MOSI
));
176 /* switch pullups off */
177 ISP_OUT
&= ~((1 << ISP_RST
) | (1 << ISP_SCK
) | (1 << ISP_MOSI
));
179 /* disable hardware SPI */
183 uchar
ispTransmit_sw(uchar send_byte
) {
187 for (i
= 0; i
< 8; i
++) {
189 /* set MSB to MOSI-pin */
190 if ((send_byte
& 0x80) != 0) {
191 ISP_OUT
|= (1 << ISP_MOSI
); /* MOSI high */
193 ISP_OUT
&= ~(1 << ISP_MOSI
); /* MOSI low */
195 /* shift to next bit */
196 send_byte
= send_byte
<< 1;
199 rec_byte
= rec_byte
<< 1;
200 if ((ISP_IN
& (1 << ISP_MISO
)) != 0) {
205 ISP_OUT
|= (1 << ISP_SCK
); /* SCK high */
207 ISP_OUT
&= ~(1 << ISP_SCK
); /* SCK low */
214 uchar
ispTransmit_hw(uchar send_byte
) {
217 while (!(SPSR
& (1 << SPIF
)))
222 uchar
ispEnterProgrammingMode() {
229 check
= ispTransmit(0);
240 ISP_OUT
|= (1 << ISP_RST
); /* RST high */
242 ISP_OUT
&= ~(1 << ISP_RST
); /* RST low */
245 if (ispTransmit
== ispTransmit_hw
) {
251 return 1; /* error: device dosn't answer */
254 static void ispUpdateExtended(unsigned long address
)
258 curr_hiaddr
= (address
>> 17);
260 /* check if extended address byte is changed */
261 if(isp_hiaddr
!= curr_hiaddr
)
263 isp_hiaddr
= curr_hiaddr
;
264 /* Load Extended Address byte */
267 ispTransmit(isp_hiaddr
);
272 uchar
ispReadFlash(unsigned long address
) {
274 ispUpdateExtended(address
);
276 ispTransmit(0x20 | ((address
& 1) << 3));
277 ispTransmit(address
>> 9);
278 ispTransmit(address
>> 1);
279 return ispTransmit(0);
282 uchar
ispWriteFlash(unsigned long address
, uchar data
, uchar pollmode
) {
284 /* 0xFF is value after chip erase, so skip programming
290 ispUpdateExtended(address
);
292 ispTransmit(0x40 | ((address
& 1) << 3));
293 ispTransmit(address
>> 9);
294 ispTransmit(address
>> 1);
301 clockWait(15); /* wait 4,8 ms */
307 uint8_t starttime
= TIMERVALUE
;
308 while (retries
!= 0) {
309 if (ispReadFlash(address
) != 0x7F) {
313 if ((uint8_t) (TIMERVALUE
- starttime
) > CLOCK_T_320us
) {
314 starttime
= TIMERVALUE
;
319 return 1; /* error */
324 uchar
ispFlushPage(unsigned long address
, uchar pollvalue
) {
326 ispUpdateExtended(address
);
329 ispTransmit(address
>> 9);
330 ispTransmit(address
>> 1);
333 if (pollvalue
== 0xFF) {
340 uint8_t starttime
= TIMERVALUE
;
342 while (retries
!= 0) {
343 if (ispReadFlash(address
) != 0xFF) {
347 if ((uint8_t) (TIMERVALUE
- starttime
) > CLOCK_T_320us
) {
348 starttime
= TIMERVALUE
;
354 return 1; /* error */
359 uchar
ispReadEEPROM(unsigned int address
) {
361 ispTransmit(address
>> 8);
362 ispTransmit(address
);
363 return ispTransmit(0);
366 uchar
ispWriteEEPROM(unsigned int address
, uchar data
) {
369 ispTransmit(address
>> 8);
370 ispTransmit(address
);
373 clockWait(30); // wait 9,6 ms