AVR301 - Atmel

AVR301: C Code for Interfacing AVR® to
AT17LVXXX FPGA Configuration Memories
Features
•
•
•
•
C Routines for Software Two-wire Interface (TWI)
Example Circuit for AVR Programming FPGA Configuration Memories
User Programmable Speed
Supports AT17LVXXX and AT24Cxxx Families of EEPROM
Introduction
8-bit
Microcontroller
Application
Note
This application note describes how to In-System-Program (ISP) an Atmel FPGA Configuration memory using an Atmel AVR microcontroller and how to bit bang a Two-wire
Interface (TWI) using port pins on an AT90S8515 AVR microcontroller. The
AT17LVXXX family of FPGA configuration memories, ranging from 512K bits to 1M bit,
uses the 2-wire protocol for In-System Programming.
This application note assumes that the user is familiar with the AT90S8515 and AT17
series EEPROMs data sheets and the application note titled “Programming Specification for Atmel’s AT17 and AT17A series FPGA Configuration EEPROMs”.
This application note is written specifically for the 512K/1M device. C routines to read
and write data are included. The code can easily be recompiled for all AVR controllers
with 256 bytes SRAM or more.
Rev. 1450D–AVR–01/04
Figure 1. Circuit Diagram
VCC
3
2
1
20
19
9
10
11
12
13
18
4
17
5
6 AT17C/LV512/ 16
010
15
7
14
8
NC
GND
NC
NC
NC
CLK
WP1
RESET/OE (RESET OE)
WP2
CE
AT90S8515
4.7K
NC
DATA
NC
VCC
NC
4.7K
NC
SER_EN
READY
CEO
(T0) PB0
(T1) PB1
(AIN0) PB2
(AIN1) PB3
(SS) PB4
(MOSI) PB5
(MISO) PB6
(SCK) PB7
RESET
(RXD) PD0
(TXD) PD1
(INT0) PD2
(INT1) PD3
PD4
(OC1A) PD5
(WR) PD6
(RD) PD7
XTAL2
XTAL1
GND
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
40
39
38
37
36
35
34
33
32
31
30
29
28
27
26
25
24
23
22
21
VCC
PA0 (AD0)
PA1 (AD1)
PA2 (AD2)
PA3 (AD3)
PA4 (AD4)
PA5 (AD5)
PA6 (AD6)
PA7 (AD7)
ICP
ALE
OC1B
PC7 (A15)
PC6 (A14)
PC5 (A13)
PC4 (A12)
PC3 (A11)
PC2 (A10)
PC1 (A9)
PC0 (A8)
Theory of Operation
The TWI is a Two-wire synchronous serial interface consisting of one data (SDA) and
one clock (SCL) line. By using open drain/collector outputs, the TWI supports any fabrication process (CMOS, bipolar and more). The TWI is a multi-master bus where one or
more devices, capable of taking control of the bus, can be connected. When there is
only one Master connected to the bus, the resulting code is much simpler because handling of bus contentions and inter Master access (a Master accessing another Master) is
not necessary. Only master devices can drive both the SCL and SDA lines while a Slave
device is only allowed to issue data on the SDA line. This application note implements a
single Master TWI.
Software Description
The generic TWI routines listed below were compiled with size optimization using IAR’s
C Compiler Version 1.40. These routines implement a single Master TWI implementation. The AT90S8515 used to perform the master function is driven by an external
7.3728 MHz crystal. The routine BitDelay is executed in 15 clock cycles or a 2.03 µs
period and provides the quarter period bit timing necessary to meet the 3.3V timing
specifications found in the above mentioned application note.
This code uses PORTB of the AT90S8515. On power-up, PORTB is initialized to all
inputs with the internal pull-ups turned off, the external pull-ups pull the SDA and SCL
lines high and the PORTB output latch bits SCL and SDA are initialized to zero. Routines WriteSDA and WriteSCL toggle their respective data direction bit depending on the
value of parameter “state”. When state is a “1” the port pin is configured as input (external pull-ups pull high). When state is a “0” the port pin is configured as an output and the
latch drives the pin low. Table 1 lists the generic TWI routines and the amount of code
space used by each routine. WriteSDA and WriteSCL are very simple routines that
could be incorporated into their respective calling routines to further reduce the code
size.
2
AVR301
1450D–AVR–01/04
AVR301
Table 1 lists the number of clock cycles used while implementing the function. Compiler
options were set to generate minimum code.
Table 1. Size and Execution Time for TWI Routines
Routine
Clocks
Bytes
138
22
1050-1054
74
SendStopBit
110
16
BitDelay
15
10
SetSCLHigh
33
38
WriteSCL
12-13
12
WriteSDA
12-13
12
1089-1090
66
SendStartBit
SendByte
GetByte
General Calling
Sequence for the TWI
Routines
Write:
SendStartBit();
/*start* /
SendByte(byte,msbfirst);/*send address MSB first*/
SendByte(byte,lsbfirst);/*send data byte to that*/
/*address LSB first*/
Read:
SendStop():
/*stop*/
SendStartBit();
/*start*/
SendByte(byte,msbfirst);/*send address MSB first*/
byte = GetByte(lastbyte);/*read byte from that*/
/*address last byte = 1
/*for the last byte*/
/*in a serial stream*/
SendStop();
/*stop*/
The routines SendStartBit, SendByte, and GetByte all leave the SCL signal low on exit,
allowing the next routine to write data to SDA (TWI allows changes on SDA only when
SCL is low; Otherwise the TWI device will interpret a start or stop condition). SendByte
returns a flag indicating a successful write to the TWI Slave, 0x01 signals that the Slave
did not acknowledge the transfer and that something is wrong on the TWI bus or with
the Slave. WritePage and ProgramResetPolarity use this flag for data polling. Figure 1
shows TWI start and stop bit conditions.
3
1450D–AVR–01/04
Figure 2. TWI Start and Stop Bits
START Condition
SCL
SDA
STOP Condition
SCL
SDA
The AT17LV512/010 device is programmed/verified on a 128-byte page boundary. During normal FPGA configuration operations the read of the device starts at address 0 and
continues until the FPGA has completed its configuration. The routines WritePage and
ReadPage write and read 128-byte pages from the configuration memory and use the
generic TWI routines to perform this function. WritePage and ReadPage are both called
with the page address to write/read to, and a pointer to a 128-byte page buffer. At the
end of a page write the data polling method is used to determine the end of the internal
page programming cycle. ProgramResetPolarity and VerifyResetPolarity write and read
data from specific memory locations 0x2000H - 0x20003H for 512K/1M in effect setting
and verifying the reset/oe polarity.
Table 2. Code Size and Execution Time for Page Read/Write
Routines
Cycles
Bytes
WritePage
287872
146
ReadPage
145901
126
ProgramResetPolarity
156104
106
VerifyResetPolarity
157269
98
PORTB on the AT90S8515 is used to communicate with the FPGA configuration memory. Bit assignments are as follows:
/*PB0 = SDA*/
/*PB1 = SCL*/
/*PB2 = SER_EN - used to put AT17LV010 in I2C mode*/
/*PB3 = CS*/
/*PB4 = RESET/OE*/
The routine Init.c initializes the AT90S8515 peripherals. Routines Timer0.c and
Timer1.c are general purpose time-out routines. Main is used to call WritePage,
ReadPage, ProgramResetPolarity, and VerifyResetPolarity and serves to illustrate
proper calling conventions for those routines.
4
AVR301
1450D–AVR–01/04
AVR301
Modifications and
Optimizations
Impact on Changing
Crystal Frequency
If the user decides to change oscillator frequencies then the following routines would
have to be modified:
•
BitDelay
•
ProgramResetPolarity
•
SetSCLHigh
•
WritePage
BitDelay uses NOP’s to effect a quarter bus period delay. Add or remove NOP’s to
increase or decrease the delay. In the routines ProgramResetPolarity and WritePage
Timer1 is used to generate a Time-out after 20 milliseconds, the programming operation
should have completed by then. Timer0 is used in SetSCLHigh to generate a Time-out
after 35 microseconds. If the SCL line is not high by then, then something is wrong on
the bus.
References
Programming Specification for Atmel’s Configuration Memory EEPROMS – Atmel
Corporation
AT17LV512/010 FPGA Configuration Memory Datasheets – Atmel Corporation
AT90S8515 Datasheet – Atmel Corporation
5
1450D–AVR–01/04
Codes
Main.c
/* main use the STK200 starter kit and external prototype board to program an Atmel AT17LV512/010 device. LEDs
on PORTC are used as visual status indicators 4.7k ohm pull-up resistors are used on SDA and SCL */
#include "2wi.h"
volatile unsigned char t0_timed_out;
volatile unsigned char t1_timed_out;
tiny unsigned char wrbuf[PAGE_SIZE];
unsigned char rdbuf[PAGE_SIZE];
extern void WritePage(unsigned int address, unsigned char *bufptr);
extern void ReadPage(unsigned int address, unsigned char *bufptr);
void ProgramResetPolarity(unsigned char state);
unsigned char VerifyResetPolarity(void);
extern void Init(void);
void C_task main(void)
{
unsigned int address = 0;
unsigned char i;
Init();
_SEI(); /* enable interrupts */
/* init test buffer */
for (i = 0; i < PAGE_SIZE; i++)
wrbuf[i] = i;
while (1)
{
PORTC = 0x00; /* LEDs off */
for (address = 0; address < MAX_PAGES; address++)
{
WritePage(address,&wrbuf[0]);
PORTC = address; /* LEDs on */
ReadPage(address,&rdbuf[0]);
/* verify programmed page */
for (i = 0; i < PAGE_SIZE; i++)
{
if (wrbuf[i] != rdbuf[i])
{
PORTC = 0xff; /* LEDs on */
}
6
AVR301
1450D–AVR–01/04
AVR301
}
ProgramResetPolarity(0);
if (VerifyResetPolarity())
{
PORTC = 0xaa;
}
ProgramResetPolarity(0xff);
if (!VerifyResetPolarity())
{
PORTC = 0x55;
}
/* clear verify buf */
for (i = 0; i < PAGE_SIZE; i++)
rdbuf[i] = 0;
}
} /* while (1) */
} /* main */
Bitdelay.c
/* BitDelay.c for a 3.3v device min clock pulse width low and high is 4 us generate 2us delay for bit timing
using NOP's 7.3728MHz crystal */
#include "2wi.h"
void BitDelay(void)
{
char delay;
delay = 0x03;
do
{
while(--delay)
;
_NOP();
return;
}
Getbyte.c
/* GetByte.c reads a byte from the TWI Slave, lastbyte is used to tell Slave that the read is over */
#include "2wi.h"
extern void WriteSCL(unsigned char state);
extern void WriteSDA(unsigned char state);
extern void BitDelay(void);
extern unsigned char SetSCLHigh(void);
unsigned char GetByte(unsigned char lastbyte)
{
7
1450D–AVR–01/04
/* lastbyte == 1 for last byte */
unsigned char i, bit;
unsigned char result = 0;
DDRB &= 0xfe; /* SDA to input */
for (i = 0;i < 8;i++)
{
/* each bit at a time, LSB first */
SetSCLHigh();
BitDelay();
bit = (PINB & 0x01);
result = (bit << (i)) | result;
WriteSCL(0);
BitDelay();
}
/* send ACK */
WriteSDA(lastbyte); /* no ack on last byte ... lastbyte = 1 for the last byte */
BitDelay();
SetSCLHigh();
BitDelay();
WriteSCL(0);
BitDelay();
WriteSDA(1);
BitDelay();
return(result);
}
Init.C
/* init.c */
#include "2wi.h"
void Init(void)
{
/* P0 = SDA - bidirectional */
/* P1 = SCL - output */
/* P2 = SER_EN - output */
/* P3 = CS - output */
/* P4 = RESET/OE - output */
/* P7, P6, P5, P4, P3, P2, P1, P0 */
/* O
O
O
O
O
O
O
O */
/* 1
1
1
1
1
1
1
1 */
DDRB = 0xfc;
PORTB = 0xfc;
8
AVR301
1450D–AVR–01/04
AVR301
/* Port c used to light leds on prototype board */
DDRC = 0xff;
PORTD |= 0xff;
PORTC = 0x00; /* 0 turns leds off ... really should be the other way around */
/* use pushbutton switches on atstk200 kit to start events */
DDRD = 0x00;
TCCR1A = 0x00; /* timer/counter 1 PWM disable */
TCCR1B = 0x00; /* timer/counter 1 clock disable */
TCNT1H = 0x00;
TCNT1L = 0x00; /* clear counter */
TCNT0 = 0x00;
TCCR0 = 0x00;
/* stop the clock */
TIMSK |= 0x82; /* enable timer counter 0 & 1 interrupt on overflow */
}
ProgramResetPoliarity.c
/* ProgramResetPolarity.c Locations 0x20000H through 0x20003H are used to store the reset/output enable
polarity for 512K/1M.
0xff = active low reset and active low output enable.
0x00 = active high reset and active high output enable.
So the memory location values determine the reset polarity.
After programming the data polling method is used to determine the end of the internal programming cycle.
Timer/Counter1 is used to ensure the polling code exits its while loop. */
#include "2wi.h"
extern volatile unsigned char t1_timed_out;
extern unsigned char SendByte(unsigned char byte, unsigned char order);
extern void SendStartBit(void);
extern void SendStopBit(void);
void ProgramResetPolarity(unsigned char state)
{
unsigned char i;
unsigned char test_ack = 0xff;
PORTB &= 0xf7; /* bring CS low */
PORTB &= 0xef; /* bring RESET/OE low */
PORTB &= 0xfb; /* bring SER_EN low */
SendStartBit();
SendByte(AT17 + WRITE,MSB_FIRST);
/* send device address byte */
SendByte(0x02,MSB_FIRST);
/* 1st address byte */
SendByte(0x00,MSB_FIRST);
/* 2nd address byte */
SendByte(0x00,MSB_FIRST);
/* 3rd address byte ... most significant byte */
9
1450D–AVR–01/04
for (i = 0; i < 4; i++)
SendByte(state,LSB_FIRST);
SendStopBit();
t1_timed_out = FALSE; /* set in timer counter 0 overflow interrupt routine */
/* 20 milli-second timeout */
/* 7.3728MHz / 1024 = 7200 Hz */
/* 7200 Hz = 138.8 us */
/* 20 ms / 138.8 us = 144.09 */
/* 65536 - 144 = 65392 = ff70 */
/* interrupt on ffff to 0000 transition */
TCNT1H = 0xff;
TCNT1L = 0x70; /* load counter */
TCCR1B = 0x05; /* timer/counter 1 clock / 1024 */
/* continue sending start bit and device address until we get an ack back */
/* data poll to program complete ... time out for error */
while (test_ack && !t1_timed_out)
{
SendStartBit();
test_ack = SendByte(AT17 + WRITE,MSB_FIRST); /* send device address byte */
}
SendStopBit();
PORTB |= 0x04; /* bring SER_EN high */
PORTB |= 0x10; /* bring RESET/OE high */
PORTB |= 0x08; /* bring CS high */
}
ReadPage.c
/* ReadPage.c Read PAGE_SIZE (128) bytes at address into bufptr Starts reading at address 0 within the page
Please refer to the application note titled: "Programming Specification for Atmel's AT17 and AT17A series FPGA
Configuration EEPROMS" found at www.atmel.com for detailed device address decoding and page a ddress
formatting */
#include "2wi.h"
extern void BitDelay(void);
extern unsigned char SendByte(unsigned char byte, unsigned char order);
extern unsigned char GetByte(unsigned char lastbyte);
extern void SendStartBit(void);
extern void SendStopBit(void);
void ReadPage(unsigned int address, unsigned char *bufptr)
{
unsigned char i;
unsigned char addr1;
unsigned char addr2;
10
AVR301
1450D–AVR–01/04
AVR301
unsigned char addr3;
PORTB &= 0xf7; /* bring CS low */
PORTB &= 0xef; /* bring RESET/OE low */
PORTB &= 0xfb; /* bring SER_EN low */
BitDelay();
addr1 = (unsigned char)(address >> 9);
addr2 = (unsigned char)(address >> 1);
addr3 = (unsigned char)(address << 7);
SendStartBit();
SendByte(AT17 + WRITE,MSB_FIRST);
/* send device address byte */
SendByte(addr1,MSB_FIRST);
/* 1st address byte */
SendByte(addr2,MSB_FIRST);
/* 2nd address byte */
SendByte(addr3,MSB_FIRST);
/* 3rd address byte */
SendStartBit();
SendByte(AT17 + READ,MSB_FIRST);
/* send device address byte with read bit */
for (i = 0; i < (PAGE_SIZE-1); i++)
bufptr(PAGE_SIZE-1) = GetByte(0);
bufptr[PAGE_SIZE-1] = GetByte(1); /* 1 signals last byte of read sequence */
SendStopBit();
PORTB |= 0x04; /* bring SER_EN high */
PORTB |= 0x10; /* bring RESET/OE high */
PORTB |= 0x08; /* bring CS high */
}
SendByte.c
/* SendByte.c send a byte of address or data to the TWI Slave parameter order used to select between sending
LSB or MSB first returns a 1 if the Slave didn't ack and a 0 if the Slave did */
#include "2wi.h"
extern void WriteSCL(unsigned char state);
extern void WriteSDA(unsigned char state);
extern void BitDelay(void);
extern unsigned char SetSCLHigh(void);
unsigned char SendByte(unsigned char byte, unsigned char order)
{
unsigned char i;
unsigned char error;
for (i = 0; i < 8; i++)
11
1450D–AVR–01/04
{
if (order)
{
WriteSDA(byte & 0x80); /* if > 0 SDA will be a 1 */
byte = byte << 1; /* send each bit, MSB first for address */
}
else
{
WriteSDA(byte & 0x01); /* if > 0 SDA will be a 1 */
byte = byte >> 1; /* send each bit, LSB first for data */
}
BitDelay();
SetSCLHigh();
BitDelay();
WriteSCL(0);
BitDelay();
}
/* now for an ack */
/* Master generates clock pulse for ACK */
WriteSDA(1); /* release SDA ... listen for ACK */
BitDelay();
SetSCLHigh(); /* ACK should be stable ... data not allowed to change when SCL is high */
/* SDA at 0 ?*/
error = (PINB & 0x01); /* ack didn't happen if bit 0 = 1 */
WriteSCL(0);
BitDelay();
return(error);
}
SendStartBit.c
/* SendStartBit.c generates an TWI start bit start bit is a 1 to 0 transition on SDA while SCL is high
____________
/
SCL ___/
__________
\
SDA
\_____
*/
#include "2wi.h"
extern void WriteSCL(unsigned char state);
12
AVR301
1450D–AVR–01/04
AVR301
extern void WriteSDA(unsigned char state);
extern void BitDelay(void);
extern unsigned char SetSCLHigh(void);
void SendStartBit(void)
{
WriteSDA(1);
BitDelay();
SetSCLHigh();
BitDelay();
WriteSDA(0);
BitDelay();
WriteSCL(0);
BitDelay();
}
SendStopBit.c
/* SendStopBit.c generates an TWI stop bit assumes SCL is low
stop bit is a 0 to 1 transition on SDA while SCL is high
____________
/
SCL ___/
______
/
SDA _________/
*/
#include "2wi.h"
extern void WriteSCL(unsigned char state);
extern void WriteSDA(unsigned char state);
extern void BitDelay(void);
extern unsigned char SetSCLHigh(void);
void SendStopBit(void)
{
WriteSDA(0);
BitDelay();
SetSCLHigh();
BitDelay();
WriteSDA(1);
BitDelay();
}
SetSCLHigh.c
/* SetSCLHigh.c Det SCL high, and wait for it to go high. Returns the value of t0_timed_out. If 0xff then we
timed out before SCL went high and should be used to indicate an error to the caller
13
1450D–AVR–01/04
Crystal frequency is 7.3728 MHz */
#include "2wi.h"
extern volatile unsigned char t0_timed_out;
extern void WriteSCL(unsigned char state);
unsigned char SetSCLHigh(void)
{
WriteSCL(1); /* release SCL*/
/* set up timer counter 0 for timeout */
t0_timed_out = FALSE; /* will be set after approximately 34 us */
TCNT0 = 0; /* clear counter */
TCCR0 = 1; /* ck/1 ..
enable counting */
/* wait till SCL goes to a 1 */
while (!(PINB & 0x02) && !t0_timed_out)
;
TCCR0 = 0; /* stop the counter clock */
return(t0_timed_out);
}
Timer0.c
/* timer0 */
#include "2wi.h"
extern volatile unsigned char t0_timed_out;
interrupt [TIMER0_OVF0_vect] void TIMER0_OVF0_interrupt(void)
{
t0_timed_out = TRUE;
}
Timer1.c
/* timer 1 timer */
#include "2wi.h"
extern volatile unsigned char t1_timed_out;
interrupt [TIMER1_OVF1_vect] void TIMER1_OVF1_interrupt(void)
{
t1_timed_out = TRUE;
}
14
AVR301
1450D–AVR–01/04
AVR301
VerifyResetPolarity.c
/* VerifyResetPolarity.c 4 bytes are read from locations 0x20000H through 0x20003H for 512k/1M.
The bytes are verified to be of all the same value. If they are then the value is returned.
return value = 0xff = active low reset and active low output enable.
return value = 0x00 = active high reset and active high output enable.
If they aren't then 0xaa is returned to signal an error condition. */
#include "2wi.h"
extern void BitDelay(void);
extern unsigned char SendByte(unsigned char byte, unsigned char order);
extern unsigned char GetByte(unsigned char lastbyte);
extern void SendStartBit(void);
extern void SendStopBit(void);
unsigned char VerifyResetPolarity(void)
{
unsigned char loc_1;
unsigned char loc_2;
unsigned char loc_3;
unsigned char loc_4;
unsigned char value;
PORTB &= 0xf7; /* bring CS low */
PORTB &= 0xef; /* bring RESET/OE low */
PORTB &= 0xfb; /* bring SER_EN low */
BitDelay(); /* for good measure */
SendStartBit();
SendByte(AT17 + WRITE,MSB_FIRST);
/* send device address byte */
SendByte(0x02,MSB_FIRST);
/* 1st address byte ... most significant byte first */
SendByte(0x00,MSB_FIRST);
/* 2nd address byte ... most significant byte first */
SendByte(0x00,MSB_FIRST);
/* 3rd address byte ... most significant byte first */
SendStartBit();
SendByte(AT17 + READ,MSB_FIRST);
/* send device address byte with read */
loc_1 = GetByte(0);
loc_2 = GetByte(0);
loc_3 = GetByte(0);
loc_4 = GetByte(1);
SendStopBit();
PORTB |= 0x04; /* bring SER_EN high */
PORTB |= 0x10; /* bring RESET/OE high */
PORTB |= 0x08; /* bring CS high */
if ((loc_1 == loc_2) && (loc_2 == loc_3) && (loc_3 == loc_4))
value = loc_1; /* valid reset/oe polarity */
else
15
1450D–AVR–01/04
value = 0xaa; /* error */
return(value);
}
WritePage.c
/* WritePage.c Writes PAGE _SIZE (128)bytes at address from bufptr Starts writing at address 0 within the page
Please refer to the application note titled: "Programming Specification for Atmel's AT17 and AT17A series FPGA
Configuration EEPROMS" found at www.atmel.com for detailed device address decoding and page address formatting
After programming the data polling method is used to determine the end of the internal programming cycle.
Timer/Counter1 is used to ensure the polling code exits its while loop. */
#include "2wi.h"
extern volatile unsigned char t1_timed_out;
extern unsigned char SendByte(unsigned char byte, unsigned char order);
extern void SendStartBit(void);
extern void SendStopBit(void);
extern void BitDelay(void);
void WritePage(unsigned int address, unsigned char *bufptr)
{
unsigned char i;
unsigned char addr1;
unsigned char addr2;
unsigned char addr3;
unsigned char test_ack = 0xff;
PORTB &= 0xf7; /* bring CS low */
PORTB &= 0xef; /* bring RESET/OE low */
PORTB &= 0xfb; /* bring SER_EN low */
BitDelay();
addr1 = (unsigned char)(address >> 9);
addr2 = (unsigned char)(address >> 1);
addr3 = (unsigned char)(address << 7);
SendStartBit();
SendByte(AT17 + WRITE,MSB_FIRST);
/* send device address byte with write bit */
SendByte(addr1,MSB_FIRST);
/* 1st address byte */
SendByte(addr2,MSB_FIRST);
/* 2nd address byte */
SendByte(addr3,MSB_FIRST);
/* 3rd address byte */
for (i = 0; i < PAGE_SIZE; i++)
SendByte(bufptr[i],LSB_FIRST);
SendStopBit();
t1_timed_out = FALSE; /* set in timer counter 0 overflow interrupt routine */
16
AVR301
1450D–AVR–01/04
AVR301
/* 20 milli-second timeout */
/* 7.3728MHz / 1024 = 7200 Hz */
/* 7200 Hz = 138.8 us */
/* 20 ms / 138.8 us = 144.09 */
/* 65536 - 144 = 65392 = ff70 */
/* interrupt on ffff to 0000 transition */
TCNT1H = 0xff;
TCNT1L = 0x70; /* load counter */
TCCR1B = 0x05; /* timer/counter 1 clock / 1024 */
/* continue sending start bit and device address until we get an ack back */
/* data poll to program complete ... time out for error */
while (test_ack && !t1_timed_out)
{
SendStartBit();
test_ack = SendByte(AT17 + WRITE,MSB_FIRST);
/* send device address byte */
}
TCCR1B = 0x00; /* disable timer/counter 1 clock */
SendStopBit();
PORTB |= 0x04; /* bring SER_EN high */
PORTB |= 0x10; /* bring RESET/OE high */
PORTB |= 0x08; /* bring CS high */
}
WriteSCL.c
/* WriteSCL.c */
#include "2wi.h"
void WriteSCL(unsigned char state)
{
if (state)
DDRB &= 0xfd; /* input ... pullup will pull high or Slave will drive low */
else
DDRB |= 0x02; /* output ... port latch will drive low */
}
WriteSDA.c
/* WriteSDA.c */
#include "2wi.h"
void WriteSDA(unsigned char state)
{
if (state)
DDRB &= 0xfe; /* input ... pullup will pull high or Slave will drive low */
else
DDRB |= 0x01; /* output ... port latch will drive low */
17
1450D–AVR–01/04
}
2wi.h
/* 2wi.h */
#include "io8515.h"
#include "ina90.h"
#pragma language=extended
#define MSB_FIRST
0xff
#define LSB_FIRST
0x00
#define READ
0x01
#define WRITE
0x00
#define AT17
0xa6
#define TRUE
0xff
#define FALSE
0x00
#define MAX_PAGES
1024 /*The total number of pages for 1M is 1024; for 512, it is 512 */
#define PAGE_SIZE
128
/*Page size = 128 bytes for 512k and 1M */
8515int.xlc
-!
XLINK command file for AT90S8515. 512 bytes data address
space and 8 Kbytes program address space. -!
-!
Define CPU type (AVR) -!
-ca90
-! Define reset and interrupt vector segment, requires 28(dec) locations -!
-Z(CODE)INTVEC=0-1B
-! Define segments in flash memory -!
-Z(CODE)RCODE,CDATA0,CDATA1,CCSTR,SWITCH,FLASH,CODE=1C-1FFF
-! Define segments in RAM
-!
-! The registers are in addresses 0-1F and memory mapped I/O in addresses 20-5F, built-in SRAM in
addresses 60-25F. Data stack(CSTACK) size is 60 bytes(hex), return stack(RSTACK) size is 20 bytes(hex)-!
-Z(DATA)IDATA0,UDATA0,RSTACK+20,IDATA1,UDATA1,ECSTR,CSTACK+60=60-25F
-!
Select reduced "printf" support to reduce library size.
See the configuration section of the IAR C-compiler Users Guide concerning use of printf/sprintf. -!
-e_small_write=_formatted_write
-e_small_write_P=_formatted_write_P
-!
Disable floating-point support in "scanf" to reduce library size.
See the configuration section of the IAR C-compiler Users Guide concerning use of scanf/sscanf -!
18
AVR301
1450D–AVR–01/04
AVR301
-e_medium_read=_formatted_read
-e_medium_read_P=_formatted_read_P
-! Suppress one warning which is not relevant for this processor -!
-w29
-! Load the 'C' library -!
cl1s
19
1450D–AVR–01/04
Atmel Corporation
2325 Orchard Parkway
San Jose, CA 95131, USA
Tel: 1(408) 441-0311
Fax: 1(408) 487-2600
Regional Headquarters
Europe
Atmel Sarl
Route des Arsenaux 41
Case Postale 80
CH-1705 Fribourg
Switzerland
Tel: (41) 26-426-5555
Fax: (41) 26-426-5500
Asia
Room 1219
Chinachem Golden Plaza
77 Mody Road Tsimshatsui
East Kowloon
Hong Kong
Tel: (852) 2721-9778
Fax: (852) 2722-1369
Japan
9F, Tonetsu Shinkawa Bldg.
1-24-8 Shinkawa
Chuo-ku, Tokyo 104-0033
Japan
Tel: (81) 3-3523-3551
Fax: (81) 3-3523-7581
Atmel Operations
Memory
2325 Orchard Parkway
San Jose, CA 95131, USA
Tel: 1(408) 441-0311
Fax: 1(408) 436-4314
RF/Automotive
Theresienstrasse 2
Postfach 3535
74025 Heilbronn, Germany
Tel: (49) 71-31-67-0
Fax: (49) 71-31-67-2340
Microcontrollers
2325 Orchard Parkway
San Jose, CA 95131, USA
Tel: 1(408) 441-0311
Fax: 1(408) 436-4314
La Chantrerie
BP 70602
44306 Nantes Cedex 3, France
Tel: (33) 2-40-18-18-18
Fax: (33) 2-40-18-19-60
ASIC/ASSP/Smart Cards
1150 East Cheyenne Mtn. Blvd.
Colorado Springs, CO 80906, USA
Tel: 1(719) 576-3300
Fax: 1(719) 540-1759
Biometrics/Imaging/Hi-Rel MPU/
High Speed Converters/RF Datacom
Avenue de Rochepleine
BP 123
38521 Saint-Egreve Cedex, France
Tel: (33) 4-76-58-30-00
Fax: (33) 4-76-58-34-80
Zone Industrielle
13106 Rousset Cedex, France
Tel: (33) 4-42-53-60-00
Fax: (33) 4-42-53-60-01
1150 East Cheyenne Mtn. Blvd.
Colorado Springs, CO 80906, USA
Tel: 1(719) 576-3300
Fax: 1(719) 540-1759
Scottish Enterprise Technology Park
Maxwell Building
East Kilbride G75 0QR, Scotland
Tel: (44) 1355-803-000
Fax: (44) 1355-242-743
Literature Requests
www.atmel.com/literature
Disclaimer: Atmel Corporation makes no warranty for the use of its products, other than those expressly contained in the Company’s standard
warranty which is detailed in Atmel’s Terms and Conditions located on the Company’s web site. The Company assumes no responsibility for any
errors which may appear in this document, reserves the right to change devices or specifications detailed herein at any time without notice, and
does not make any commitment to update the information contained herein. No licenses to patents or other intellectual property of Atmel are
granted by the Company in connection with the sale of Atmel products, expressly or by implication. Atmel’s products are not authorized for use
as critical components in life support devices or systems.
© Atmel Corporation 2003. All rights reserved. Atmel ® and combinations thereof, AVR ®, and AVR Studio ® are the registered trademarks of
Atmel Corporation or its subsidiaries. Microsoft®, Windows ®, Windows NT ®, and Windows XP ® are the registered trademarks of Microsoft Corporation. Other terms and product names may be the trademarks of others
Printed on recycled paper.
1450D–AVR–01/04