Atmel applications journal.Spring 2004
.pdfA T M E L A P P L I C A T I O N S J O U R N A L
diate area between acceptance and rejection, where additional information or action is requested by the person seeking identification. For example, the person may be requested to re-scan the same finger, or scan another finger if a second template is available. The process of template/sample matching is carried out entirely by software, and is independent of the technology used for fingerprint capture. However, a high-quality image is essential to keep the FAR and FFR to a minimum.
Atmel’s Strategic Positioning in the Security Market
Strategic Security Focus
Atmel has a strategic commitment to the market for electronic security systems. A range of complementary integrated circuits is being developed to serve this market, often in collaboration with market leaders in end-user security products. The result is ICs that are closely adapted to the requirements of their particular market segment. These are supported by software drivers and thirdparty applications modules that provide security system developers with a solution that combines performance (from hardware) and flexibility (from software).
Markets for Security Products
The market for secure identity products is extremely diverse. At present it is partitioned into the following broad segments:
--Electronic key access to motor vehicles and other high-value objects
--Financial transactions, including Smart Cards and their readers, ATMs (cash terminals) and Internet transactions
--Access control, including entry to buildings, stadiums, public open spaces and secure installations such as military installations, or secure areas in any of these
--Transportation, including road, tunnel and bridge tolls and screened access to subway, bus and air travel
--Administrative applications, including health, social security, passports, drivers’ licenses and ID cards.
All of these are high-growth markets where electronic products are a long way from saturation. For example, Smart Cards are well established in parts of Europe but are just starting to be introduced in the USA, and are likely to leapfrog older technologies such as magnetic stripe cards in Asia. The potential market runs to billions of units.
These markets demand mixture of products with electrical contacts (such as Smart Cards and their readers), contactless products (such as radio road toll transponders) and sensors (such as fingerprint readers).
Summary of Atmel’s Security Products
Atmel is developing complementary ICs that address all segments of the security products market, as described above. These ICs fall into five broad categories:
--Sensors, including FingerChip, CCD and CMOS image sensors
--Radio Frequency (RF) ICs, including RFID tags and RF front-end elements for other secure applications. Many of these are based on SiliconGermanium (SiGe) technology.
--Secure Memories, including secure EEPROMS with sectors that are locked/unlocked by a challenge/response system
--Secure Microcontrollers, including the secure AVR® Flash-based 8-bit RISC
microcontroller for Smart Cards and other secured applications
---Secure ASSPs, including a PC security module that implements the Trusted Computing Platform Alliance (TCPA) specification for Trusted Platform Modules (TPM).
These elements can be used together in an end-user application. A typical combination is a sensor or RF front-end for data capture, a secure microcontroller for processing and one or more secure memories for storage. These ASSPs and standard products can also be used as system-on-chip building blocks for high- ly-integrated customer-specific ICs (ASICs) in high-volume applications.
FingerChip Deliverables, Business Model and Roadmap
Atmel’s business model for FingerChip is to develop and market the AT77C101B FingerChip IC together with software drivers for common operating systems and image reconstruction software. These are supported on common hardware platforms including ARM®, StrongARM™, Intel® XScale® and Texas Instruments® DSPs. Operating Systems include Windows™ CE and Linux™.
Application-specific software such as that for minutiae extraction and sample/template comparison is being developed by qualified thirdparty suppliers with whom Atmel works in partnership on a non-exclusive basis. This strategy enables customers to benefit from the performance, reliability and low cost of Atmel ICs while retaining the choice of the most appropriate software provider for the specific requirements of the end-user product. Atmel’s deliverables and modules provided by third-parties are shown in Figure 9. The roadmap for the FingerChip product builds on the basic thermal image capture tech-
nology with a succession of higher-performance interfaces including USB and SPI. This leverages the core product into a successively broader field of applications.
Application Examples
Application Scenario: Smart Card and Reader with Fingerprint Authentication
For reasons of confidentiality, the example given below is hypothetical. It shows how Atmel’s FingerChip IC can be combined with other Atmel products in a representative security application.
In order to provide a higher level of security than that given by a conventional PIN code, a Smart Card can be loaded with an encrypted template of the fingerprint of its owner. When using the Smart Card, the owner provides (in addition to the PIN code) a fingerprint sample to the Smart Card reader as a further means of authentication. Atmel can supply all of the ICs used in such a system, in both the Smart Card and the reader, as ASSPs or standard products. They are illustrated in the system block diagram in Figure 10.
The fingerprint-enhanced Smart Card contains an AT90SC secure 8-bit microcontroller with embedded Flash memory. This memory contains (in addition to the software and reference data) an encrypted version of the fingerprint template that is loaded during the enrolment of the Smart Card owner. The Smart Card reader is built around an AT91 32-bit ARM-based microcontroller with an AT49BV Flash memory for program and reference data storage. Communication between the AT90SC and AT91 is via an industry-standard ISO 7816 secure interface. Fingerprint image capture and digitization is carried out by the AT77C101B FingerChip.
At the start of the authentication operation, the AT90SC in the Smart Card is activated by the AT91 in the reader and a conventional PIN code entry/validation is carried out. This is done via the ISO 7816 interface. This provides an initial level of confidence in the validity of the Smart Card and the person claiming to be its owner.
www.atmel.com
page 39
A T M E L A P P L I C A T I O N S J O U R N A L
Figure 10: Smart Card Reader with Fingerprint Authentication
The fingerprint of the person claiming to be the Smart Card owner is then captured by the FingerChip, digitized and sent to the AT91microcontroller. The AT91 re-constructs the image from the sequence of frames and extracts the sample from it. It then encrypts the sample and uploads it to the AT90SC in the Smart Card. The AT90SC compares the encrypted sample that it has received from the fingerprint reader with the encrypted template stored in its secure memory. If the matching score is sufficiently high, it sends a confirmation message to the AT91 in the reader. The person is authenticated as the owner of the Smart Card, and the associated transaction is authorized. This procedure is known as match-on-card. It ensures that the encrypted fingerprint template never leaves the Smart Card, and that the sample is sent to the Smart Card only in encrypted form.
The numerous benefits of this system include the low component count, which keeps size, power consumption and cost to a minimum. The AT91 and AT49BV ICs can be encapsulated in a single package for further size and cost reduction. The use of ASSPs and standard products eliminates the NRE (Non-Recurring Engineering) costs of custom IC development. Flash memory in both the Smart Card and the reader allows for system upgrades based entirely on software. The acceptance/rejection cutoff point can be adjusted by software according to the security requirements of the application, and it is a matter of an additional software module to require one or more additional fingerprint scans in doubtful cases. No fingerprint templates or samples are permanently stored on the reader – the encrypted template never leaves the Smart Card, and the sample is erased after each authentication operation. This eliminates the need for access to a database of enrolled templates and greatly reduces the possibilities for fraudulent use of this data.
Bioki Fingerprint Reader and Biothentic Fingerprint-enhanced Smart Card Reader
The Bioki Fingerprint Reader (Figure 11) from ID3 provides secure access to PCs. It functions as a PC peripheral, connected via a USB bus. Using a FingerChip IC and biometrics software from ID3, it captures the image of a fingerprint, and can enroll and authenticate authorized user(s) of the PC system. Also from ID3, the Biothentic Smart Card reader with fingerprint sensor (Figure 12) implements the match-on-card application scenario described in the previous section. It includes a FingerChip and two ISO 7816-compliant Smart Card interfaces. It is aimed at a wide range of secured electronic transactions, including electronic commerce and ID card authentication.
iPAQ H5000 Pocket PC
The iPAQ® H5000 Pocket PC from HP® (Figure 13) is a multimedia PDA that integrates Atmel’s FingerChip for biometric login authentication. It relieves the user of the task of memorizing and updating login passwords, and makes it almost impossible for a lost or stolen device to be used by someone else.
Figure 11: ID3 Bioki Fingerprint Reader
Figure 12: ID3 Biothentic Smart Card Reader with Fingerprint Sensor
Figure 13: HP iPAQ H5000 Pocket PC with FingerChip for Biometric Login
Amongst the additional features of the H5000 is wireless LAN access using the AT76C503A IEEE 802.11b/USB Wireless LAN Media Access Controller (MAC), also from Atmel.
Conclusion
Atmel has selected fingerprint recognition as the most established means of biometric identification, and thermal imaging as the means of image capture that offers the highest possible reliability at minimal cost. This is the basis of its FingerChip product. A complete security system can be constructed using Atmel ASSPs and standard products together with industry-standard software that combines performance and flexibility with low development and production costs. Atmel’s Flash memory technology allows for system upgrades with no substitutions of its ICs.
Biometrics is an emerging activity that is likely to become an integral part of our daily lives, creating an enormous on-going market for products based on state-of-the-art technology such as the Atmel FingerChip.
www.atmel.com
page 40
A T M E L A P P L I C A T I O N S J O U R N A L
We’re interested in your experiences in working with the AVR.
Please send your tips, shortcuts, and insights to: bob@convergencepromotions.com, and we’ll try and print your submissions in future issues.
Designer’s Corner:
Rapid Application
Development:
Race Against the Clock
by Robert Severson, USBmicro
Tueday Evening, 8:30 p.m. Client call
I understood his system well, most of it was either done for him, or earlier design work that I maintained. I do for him involved creating designs that became
work was one-of-a-kind test equipment. It was the latter ed in. He wanted a piece of hardware that would have use. “It can be held together with duct tape, for all I care,” a quick design for you.”
He told me that he needed something that would gather about six different light levels. The device would once a minute and log the data to the laptop hard drive. plans. From what he told me I was making mental notes ject’s specification. A simple set of photoresistors would of light that he would want to measure.
Six different channels - better make that eight, just to urement. The range and precision would not need to be measurements he was talking about 64 levels would suffice log to digital conversion would certainly work nicely.
His laptop only has a USB port, no serial or parallel ports.
thinking. In fact I said this to him on the phone. He asked that I incorporate the data logging into a PC application that I had designed for him earlier. “No problem!” I repeated. “My demo is Thursday morning, I need hardware Wednesday by 4:00, he said.” “No problem!” I’m not sure who said that, but it sounded a lot like me.
Tueday Evening, 8:40 p.m. First plan
Perhaps it really wouldn’t be too bad. I know that I have some
phototransistors in my junk bin for testing. Eight ADC 0831 A/D parts reading the voltage levels from the phototransistors would convert the levels to digital values.
I have a board called the U401 that plugs into the USB port of a PC and can interface to SPI communication devices. My client already uses several of these boards.
So in the morning I will need to quickly assemble eight A/D chips, a set of screw terminals, and the USB to SPI board. This will mainly be made from rummaging through my parts bins. No problem.
As they say, ignorance is bliss. Had I made an effort to check my stock of converters before going to bed, I probably would have tossed and turned all night. But, I slept like a baby, oblivious to how my plans would be irrelevant come dawn.
Wednesday, 7:45 a.m. Frustration
My search turned up only a single A/D part. Some other project had consumed the other parts. I looked at several
cuit boards imagining that I could steal enough A/D devices to make up for the missing seven parts. Nothing was found. My plans would need to change.
I couldn’t order additional A/D parts: even an overnight delivery would be too late for this fast-turn development effort.
My plan changed to using a multiplex chip to read the eight analog values with the single A/D converter. I can use the digital lines on the U401 to control the mux.
Wednesday, 9:00 a.m. Eureka!
While rummaging through bins to find a suitable multiplex chip, I had a stroke of luck. I bumped into an application note
on SPI design for the Atmel AVR. I had used the AVR quite a bit to talk to the SPI A/D devices as a master. This app note was an intro to using the SPI on an AVR as a slave.
I was immediately filled with thoughts. Why not use a single AVR in place of the eight A/D converters? (Or what became a single A/D and a mux.) The AVR would be a slave SPI device, just like the A/D devices. There is an AVR that has eleven A/D pins. I used the ATTiny26 not so long ago.
The eight channel protoresistor schematic.
www.atmel.com
page 41
A T M E L A P P L I C A T I O N S J O U R N A L
I found an ATTiny26 immediately. In fact I found eight. Go figure. Now this will be the way that I will complete this design. But, the clock is ticking.
Wednesday, 9:10 a.m. Out of the starting gate
Dropping a micro into the works is more complicated than just using the A/D parts. There is always more stuff to add the design. A brownout detector, a reset device, and a many little embedded designs.
But not with this AVR. The ATTiny26 has integral brownout pin will be connected to the USB to SPI board for in-system the microcontroller has an internal RC clock. This solution than the other approaches. There is, however, the matter of ed to create firmware that will gather the analog values. SPI let the U401 pull these values from the AVR.
Wednesday, 9:30 a.m. Hardware assembly
First things first. The hardware design was simple enough [See the schematic] The AVR receives power from the U401, which is powered from the USB port of the laptop. The (AVCC) and the analog reference pin (AREF) are connected
The eight lines on port A can be used for analog measurement lines, however, is the reference pin. Using a single line from reading rounds out the eight total A/D channels.
The ATTiny26 is programmable in-circuit (ISP). The first B are used for the SPI in-circuit programming as well as for ation. ISP works when the AVR is in reset; the reset line is connection.
As a slave device the MOSI, MISO, and SCK lines are used When the firmware is running, this would suffice to move the chip. I have, however, also included a “chip select” on port B bit six. This pin can be set to allow an external
The sparsely populated eight channel protoresistor board.
I assembled the components on a small board. Screw terminals were lined up in a row along one edge for the client’s connection to his photoresistors. There are pull-up resistors for each of these eight devices. The resistors pull up to VCC.
The board is sparsely populated. I added a transistor driving an LED from a spare port pin. A couple of test pins and “standard” AVR ISP header round out the parts. This is certainly a minimum design, as can be seen in the photo.
Wednesday, 10:45 a.m. Rapid tools
Now the pressure is on. It would have taken longer to once assembled I could start
. Unfortunately with a micro middle step: firmware development.
as the solution to this problem. I had hoped that the trade off would be even. In other words I would have a piece of hardware that would take less time to assemble because of fewer parts. But the time that I save would be consumed developing firmware for the AVR.
Luckily I didn’t start at ground zero. I had previously used many AVRs, the ATTiny26 specifically. That was why I had some in my bin.
And I wasn’t beginning the process of learning this architecture. I already had programmer tools, and, more specifically, a Rapid Application Development tool: the Imagecraft C compiler and development environment. The Imagecraft IDE has a tool that speeds development, the Application Builder. This mini application, selected from the “tool” menu of the IDE, helps build code for the peripherals of the AVR.
The Application Builder’s CPU page.
If you run Application Builder the initial page (CPU) allows you to select the target AVR device. The latest version of the compiler that I downloaded has support for the ATTiny26 by selecting “T26” under “Target CPU”.
I chose a crystal speed of 8MHz. When implementing timer functions, or using the UART peripherals, selecting the appropriate clock speed here will let the Application Builder automatically determine the best values for the often hard- to-calculate registers. Just getting the right values into UART registers can be a nightmare.
I used port B bit 6 for a chip select. I didn’t want to poll the pin to know when the U401 has selected the AVR. I wanted an interrupt to be triggered when the AVR is selected. Under “External Interrupts” I checked “INT0” and picked “Falling Edge” for the detection of the signal.
The selections “Watchdog”, “Pin change”, and “EEPROM” remained untouched.
In the second Application Builder page, Ports, selection of the port direction and initial values are made. I chose values appropriate for the hardware design.
The lower section of the Application Builder screen, the part that does not change when you change pages, has a “Preview” button. Selecting this button will bring up a sub screen containing the generated code.
www.atmel.com
page 42
A T M E L A P P L I C A T I O N S J O U R N A L
ABOUT THE AUTHOR
Robert Severson is an embedded hardware designer and firmware/software developer with experience in microcontrollers “from Atmel to Zilog”. As owner of USBmicro he has worked on products that range from security systems to pacemakers to aircraft cargo systems. Rob can be reached at robert@usbmicro.com
The generated code can be inserted project code. The code below was Somewhere in your code, likely very a call to the function that App
Init_devices in turn calls routines that initialize the peripherals that you intend to use.
Listing 1—See Code Patch page 48
So far, the RAD tool has made code to initialize the port lines and interrupt registers. When the time came, the App Builder was used to initialize the SPI and A/D converter, as well as set up a template routine for the SPI byte reception and the external interrupt.
The Application Builder helped more with the project, but when I got to this point my goal was to make a first initial test. Something simple just to make sure that I have my ducks in a row.
Wednesday, 11:15 a.m. Rapid
The board has an output device. The transistor/LED nation is there to provide a “heartbeat” – an
the processor is alive and kicking.
The LED was also the first part of the project to show any sanity check to make sure that I was getting code into was running the code, and that it was not stuck in reset.
To the initialization code that was automatically “main()” routine. The intent of the routine was to turn the it off, delay, and repeat forever.
Listing 2—See Code Patch page 48
I compiled the code and turned to the tools menu item The IDE comes with an “In System Programmer” to have programming hardware compatible with this tool, the AVR without leaving the IDE.
I actually use my U401 to program the AVR via a USB port programming software to the IDE menu, so that I can venience. The U401 application will run when the menu the U401 AVR programmer application I can program and well as communicate with it via SPI. I set the fuse settings 8 MHz operation, and loaded the AVR with code. I then
Eureka! Blinking light. Time for a quick lunch break.
“blinky” is a milestone. Usually if something is going to will help with the debug process.
If you are new to the AVR, lean on the Imagecraft
be invaluable in setting up the AVR peripherals. In this case, I leaned on the Application Builder to provide Rapid Application Development for this one-day project. It helped a good deal.
If blinking were all that my client needed, I’d be done. The device needed to scan the photoresistors, and report the values in a slave SPI message.
The eight channel A/D board with a variety of photoresistors.
I added photoresistors to the small circuit. At least I was right about having a lot of these in my parts bin. They don’t all match, but for testing they will suffice. Once again I turned to the App Builder to quickly help put the A/D operation in place. The App Builder “Analog” page is for A/D selections. The ATTiny26 A/D channels are ten bit. For the sake of simplicity (and speed) I only wanted to read eight bits. One very nice feature of the A/D subsystem lends itself well to doing this. The ten bits can be placed into an eight-bit register either justified to the right, or left. I certainly didn’t need the lower two bits of the ten. I was interested only in the most significant eight. This feature is realized by selecting “Left adjust”.
I also chose “ADC enable” and “Free-run select”. I wanted the analog conversions to “just happen”. A call to the A/D initialization routine, “adc_init”, was added to the “init_devices” routine.
|
The Application Builder’s Analog page. |
|
I added code to the main loop. I left the light blinking in place, but added code |
The U401 Software that supports AVR programming. |
to read the A/D register, and advance to the next A/D channel. |
www.atmel.com |
page 43 |
|
A T M E L A P P L I C A T I O N S J O U R N A L
REFERENCE INFO
The code for this article, as well as some project pictures/graphics, can be found at the author’s website: www.usbmicro.com.
SOURCES
ATTiny26 Atmel Corp.
(714) 282-8080
USBmicro www.usbmicro.com info@usbmicro.com
Imagecraft ICCAVR www.imagecraft.com (650) 493-9326
Listing 3—See Code Patch page 48
The A/D channels stored in the “ADValue” array would need to be accessed by the slave SPI routine. For the final time, I let the App Builder help.
Initially I added code to select channel zero, and display its value. The pointer just barely moved. I covered the sensor, shined light into the sensor. The results never changed. I even tried yelling at the sensor. Still no change.
Out of desperation (and panic) I selected channel one. The slider bumped to the top. I covered the sensor and the slider slid down. Nice. It turned out that the first sensor was damaged. After replacing it I added code to scan all of the sensors. I covered the sensors with a pattern of fingers to get some random results.
The Application Builder’s USI (Universal Serial Interface) page.
On the USI page I selected 3-wire (SPI) mode with no clock source. When there is a full byte in the receive register an interrupt can be generated. A template for the interrupt is created by selecting “Counter ovf interrupt”. Once again the USI init code is added to the “init_devices” routine.
The SPI master device, the U401, will be sending two bytes to the AVR. The first byte addresses the A/D channel number. The second byte sent is a dummy byte to clock the A/D value out of the AVR. I wanted to keep the two SPI devices in sync. The external interrupt routine is triggered when the U401 selects the AVR. The routine only needs to clear the pointer to the reply array.
The USI ovf interrupt will place the message into the USI data register byte is then clocked back to the
Listing 4—See Code Patch page 48
Wednesday, 2:30 p.m. Application test
Only an hour before I need to hit the road, I started the PC application changes. I created a sub-screen to my client’s application just for this testing. The application displays eight A/D values on sliders. There is a button to transmit the AVR, and gather the A/D values. The final application a file every 60 seconds.
The VB application opens a handle to the U401. Commands application to initialize the U401. The SPI subsystem of enabled, and a digital line is set to output for the AVR chip
Once initialized, a command from the application sets the low. The external interrupt in the AVR senses this edge pointer (index) of the array. The application then writes a returns the chip select high.
The application performs this action eight times, once for AVR sends back the reading associated with the channel.
The Application Builder’s USI (Universal Serial Interface) page.
About 18 hours earlier I had made up my mind to solve the problem with eight bind when I realized that I didn’t
AVR to replace the eight A/D converters. It was certainly simple using a RAD tool to quickly generate the initialization code, time that I would otherwise waste pouring over the datasheets.
My client was oblivious to the rapid pace of development, but liked the demo. “Nice,” he said. “I can’t wait to demo it next week.”
“Next week?” I asked.
“Yes. Next week Thursday, like I said.”
www.atmel.com
page 44
A T M E L A P P L I C A T I O N S J O U R N A L
Code Patch is a reservoir of the code used in this issue's articles, conveniently displayed in one section. To electronically download this code for use in your
development projects, go to the Atmel Applications Journal archives at www.atmel.com
Construct an ATA Hard Drive Controller
CODE (From Page 12)
Listing 1—A core set of registers is the gateway to the hard drive platters. Everything needed to access a particular data point on the hard drive is represented here.
//ATA I/O port functions and address definitions
//Control block registers |
|
// |
RESET |
// |
|DIOW |
// |
||DIOR |
// |
|||DA0 |
// |
||||DA1 |
// |
|||||DA2 |
// |
||||||CS0 |
// |
|||||||CS1 |
// |
|||||||| |
#define ATA_IO_HIZ |
0b11111111 |
#define ATA_IO_ASTAT |
0b11101110 |
#define ATA_IO_DEVICECNTL |
0b11101110 |
//Command block register addresses |
|
#define ATA_IO_DATA |
0b11100001 |
#define ATA_IO_ERROR |
0b11110001 |
#define ATA_IO_FEATURES |
0b11110001 |
#define ATA_IO_SECTORCNT |
0b11101001 |
#define ATA_IO_SECTORNUM |
0b11111001 |
#define ATA_IO_CYL_L |
0b11100101 |
#define ATA_IO_CYL_H |
0b11110101 |
#define ATA_IO_DEVICE_HEAD |
0b11101101 |
#define ATA_IO_STATUS |
0b11111101 |
#define ATA_IO_CMD |
0b11111101 |
Listing 2—Because the routines are identical, with exception to the status bit that’s checked, I took some liberties and squashed all three ready, busy, and error routines into a single function to save some space. The unsigned int ata_bsy(void) function includes the if(ata_byte_read & ATA_STAT_BSY) line and the other two functions follow the same logic.
#define |
recalibrate |
ata_send_cmd(CMD_RECALIBRATE) |
#define |
CMD_RECALIBRATE |
0x10 |
#define PORT_ATA_IO_CNTL |
PORTF |
|
#define ATA_DIOR |
0x20 |
|
#define |
PORT_ATA_DATA_L_IN |
PINA |
#define ATA_STAT_BSY |
0x80 |
//ATA busy |
|
#define ATA_STAT_RDY |
0x40 |
//ATA ready |
|
#define ATA_STAT_ERR |
0x01 |
//ATA error |
|
#define busy |
ata_bsy() |
|
|
#define drq |
ata_drq() |
|
|
#define error |
ata_err() |
|
|
#define ready |
ata_rdy() |
|
|
#define hard_reset |
ata_hard_reset() |
||
#define select_device_0 |
ata_select_device(0x00) |
||
#define select_device_1 |
ata_select_device(0x01) |
||
#define |
recalibrate |
ata_send_cmd(CMD_RECALIBRATE) |
|
#define |
identify_device |
|
|
ata_send_cmd(CMD_IDENTIFY_DEVICE)
**************************************************************
Initialize drive. This routine assumes drive 0 is the only drive that is attached.
**************************************************************
void init_ata(void)
{
while(!ready & busy); hard_reset; delay_ms(10); while(!ready & busy); select_device_0; while(!ready & busy); recalibrate; while(busy); if(error)
printf("ERROR!"); printf("\r\nDrive is READY!\r\n");
//Functions are squashed for space savings unsigned int ata_bsy(void)
unsigned int ata_rdy(void) unsigned int ata_err(void)
{
unsigned char ata_byte_read; avr_databus_in;
delay_us(1);
PORT_ATA_IO_CNTL = ATA_IO_STATUS; PORT_ATA_IO_CNTL &= ~ATA_DIOR; delay_us(1);
ata_byte_read = PORT_ATA_DATA_L_IN; PORT_ATA_IO_CNTL |= ATA_DIOR; PORT_ATA_IO_CNTL = ATA_IO_HIZ;
continued next page
www.atmel.com
page 45
A T M E L A P P L I C A T I O N S J O U R N A L
Construct – CODE - Listing 2 - continued
|
if(ata_byte_read & ATA_STAT_BSY) |
|
|
if(ata_byte_read & ATA_STAT_RDY) |
|
|
if(ata_byte_read & ATA_STAT_ERR) |
|
|
return |
1; |
|
else |
|
|
return 0; |
|
} |
//End |
of squashed functions |
void ata_hard_reset(void)
{
avr_databus_in; PORT_ATA_IO_CNTL = ATA_IO_HIZ; PORT_ATA_IO_CNTL &= ~ATA_RESET; delay_ms(10);
PORT_ATA_IO_CNTL |= ATA_RESET;
}
void ata_select_device(unsigned char device)
{
PORT_ATA_IO_CNTL = ATA_IO_DEVICE_HEAD; switch (device)
{
case 0x00: ata_write_byte(ATA_DH_DEV0); break;
case 0x01: ata_write_byte(ATA_DH_DEV1); break;
default: ata_write_byte(ATA_DH_DEV0); break;
}
}
void ata_send_cmd(unsigned char atacmd)
{
PORT_ATA_IO_CNTL = ATA_IO_CMD; avr_databus_out; PORT_ATA_DATA_L_OUT = atacmd; ata_write_pulse; PORT_ATA_IO_CNTL = ATA_IO_HIZ; avr_databus_in;
}
Listing 3—There aren’t any tricks in this code. It’s all simple read and write I/O between the hard disk and the SRAM. The routine reads an LBA-addressed sector into an SRAM page.
**************************************************************
Read a sector. device = 0x00 or 0x01
**************************************************************
unsigned char ata_read_sector(unsigned char device, unsigned long lbasector \ ,unsigned int page)
{
unsigned int i,ram_address; lbasector &= 0x0FFFFFFF; ata_set_io_addr(ATA_IO_DEVICE_HEAD); switch (device)
{
case 0x00:
ata_write_byte(lbasector >> 24 | 0xE0); break;
case 0x01:
ata_write_byte(lbasector >> 24 | 0xF0); break;
default:
ata_write_byte(lbasector >> 24 | 0xE0); break;
}
while(busy); ata_set_io_addr(ATA_IO_CYL_H); ata_write_byte(lbasector >> 16); while(busy); ata_set_io_addr(ATA_IO_CYL_L); ata_write_byte(lbasector >> 8); while(busy); ata_set_io_addr(ATA_IO_SECTORNUM); ata_write_byte(lbasector); while(busy); ata_set_io_addr(ATA_IO_SECTORCNT); ata_write_byte(0x01); while(busy); ata_send_cmd(CMD_READ_SECTORS); while(busy);
while(!drq);
ram_address = page * 0x100; for(i=0;i<256;++i)
{
avr_databus_out;
PORT_ATA_DATA_H_OUT = ram_address >> 8; PORT_ATA_DATA_L_OUT = ram_address; latch_ram_addr;
avr_databus_in; ram_on; while(busy);
PORT_ATA_IO_CNTL = ATA_IO_DATA;
PORT_ATA_IO_CNTL &= ~ATA_DIOR; delay_us(1);
ram_write_pulse; delay_us(1);
PORT_ATA_IO_CNTL |= ATA_DIOR;
PORT_ATA_IO_CNTL = ATA_IO_HIZ; while(busy);
ram_off; ++ram_address;
}
return (error);
}
A Compact Scheduler for AVR
Microcontrollers
CODE(From Page 17)
THE CODE
************
// Author: Steve Duckworth, with contributions from Andy Gayne.
//Customer: GD Technik internal
//Target: Tiny26 (or any other SRAM enabled AVR).
//Project: Very small task scheduler for Atmel
Tiny 26.
//Date: 12/02/2003 - 08/09/2003.
//Notes: Array based with limit on maximum
number of tasks allowed.
//Demonstration based on STK500 and ATtiny26.
//Connect LEDs to PORTB and switches to PORTA.
continued next page
www.atmel.com
page 46
A T M E L A P P L I C A T I O N S J O U R N A L
Compact Scheduler - continued
#include <stdlib.h>
#include <iotiny26.h> |
|
|
|
#define led0 |
PORTB_Bit0 |
// led0 on STK500 |
|
#define led1 |
PORTB_Bit1 |
// led1 on STK500 |
|
#define led2 |
PORTB_Bit2 |
// led2 on STK500 |
|
#define led3 |
PORTB_Bit3 |
// led3 on STK500 |
|
#define sw0 |
PINA_Bit0 |
// sw0 on |
STK500 |
#define sw1 |
PINA_Bit1 |
// sw1 on |
STK500 |
#define sw2 |
PINA_Bit2 |
// sw2 on |
STK500 |
#define sw3 |
PINA_Bit3 |
// sw3 on |
STK500 |
#define ON |
0 |
// for LED control |
|
#define OFF |
1 |
// for LED control |
|
#define maxtasks |
3 |
// max tasks allowed on |
|
|
|
queue. |
|
unsigned char tasks = 0; |
// keep count of number of |
||
|
|
active tasks. |
|
void(*x[maxtasks+1])(void); |
// task array, with space |
||
|
|
for null |
|
|
|
// terminator. |
|
typedef void(*fp)(void); |
// function pointer |
||
|
|
typedef |
|
// prototypes |
|
|
|
unsigned char |
FindTask |
(void(*fp)(void)); |
|
void |
CreateTask |
(void(*task)(void)); |
|
void |
DeleteTask |
(void(*fp)(void)); |
|
void |
task0 |
(void); |
|
void |
task1 |
(void); |
|
void |
task2 |
(void); |
|
void |
task3 |
(void); |
|
void |
task4 |
(void); |
|
void |
task5 |
(void); |
|
//scan array to see if task exists, if not then add task
and
//shift NULL pointer to end.
void CreateTask(void(*task)(void)){ unsigned char n;
if(!FindTask(task)){ |
// check task is not present |
|||
for(n=0;n<maxtasks || x[n]!=NULL ;n++ ) // find position |
||||
|
|
|
of |
null |
|
|
|
// |
terminator |
if (x[n] == |
NULL){ |
|
|
|
x[n] = task; |
// add task to queue |
|||
x[++n] = |
NULL; |
// add new null terminator |
||
return; |
|
|
|
|
}// |
end if |
|
|
|
}// end if |
|
|
|
|
} |
|
|
|
|
// deletes task if found. |
|
|||
void DeleteTask(void(*task)(void)) |
|
|||
{ |
|
|
|
|
unsigned |
char |
n; |
|
|
for(n=0;n<maxtasks;n++)
if(x[n] == task){ // task found. do{
x[n] = x[n+1]; |
// shuffle tasks down in |
|
array |
n++; |
// inc index |
}while(x[n] != NULL); |
// keep shuffle going |
|
until NULL |
return; |
|
}// end if |
|
}
//checks to see if a task already exists on the queue...
returns 0
//if task not found, else returns array index of task if found.
unsigned char FindTask(void(*fp)(void)){ unsigned char n;
for(n=0;n<maxtasks || x[n] != NULL;n++) if(x[n] == fp) return 1;
return 0;
}
// adds and deletes task1 if sw0 or sw1 pressed respectively
void task0(void){ |
|
if (!sw0){ |
//if sw0 pressed |
CreateTask(task1); |
|
led0=ON; |
|
led1=OFF; |
|
} |
|
else if (!sw1){ |
//if sw1 pressed |
DeleteTask(task1); |
|
led0=OFF; |
|
led1=ON; |
|
} |
|
} |
|
// if active, turns led3 on if sw3 is pressed void task1(void){
if (!sw3) led3=ON; else led3=OFF;
}
void task2(void){} void task3(void){} void task4(void){} void task5(void){}
void main(void)
{
unsigned char n = 0;
DDRB |
= |
0xff; |
// PORT B |
is |
outputs |
DDRA |
= |
0x00; |
// PORT A |
is |
inputs |
PORTB = 0xff; |
// all LEDs off |
x[0] = NULL; // always NULL the first array element //before we use it.
CreateTask(task0); |
// add task zero to queue |
|
//(must have one task) |
while(1){ |
// loop forever |
while(x[n]!=NULL) x[n++](); // execute tasks. |
|
n = 0; |
// reset index. |
} |
|
}
www.atmel.com
page 47
A T M E L A P P L I C A T I O N S J O U R N A L
Rapid Application Development
Race Against the Clock
Listing 1: The Application Builder automatically generates initialization code for the peripheral features that you have enabled. Here is the first pass at using this feature.
//ICC-AVR application builder
//Target : T26
//Crystal: 8.0000Mhz
#include <iom26v.h> #include <macros.h>
void port_init(void)
{
PORTB = 0xDD; DDRB = 0x22; PORTA = 0xFF; DDRA = 0x00;
}
#pragma interrupt_handler int0_isr:2 void int0_isr(void)
{
//external interupt on INT0
}
//call this routine to initialize //all peripherals
void init_devices(void)
{
//stop errant interrupts until set up CLI(); //disable all interrupts port_init();
MCUCR = 0x02;
TIMSK = 0x00; //timer interrupt sources GIMSK = 0x40; //interrupt sources PLLCSR = 0x00; //PLL
SEI(); //re-enable interrupts
//all peripherals are now initialized
}
Listing 2: This is the main routine written to check out the operation of the hardware. The init_devices function is called, then a loop turns the LED on and off with delays.
void main(void)
{
unsigned int loop;
init_devices();
while (1)
{
PORTB |= 0x20;
for (loop = 0; loop < 60000; loop++)
{
}
PORTB &= 0xDF;
for (loop = 0; loop < 60000; loop++)
{
}
}
}
Listing 3: The main loop now keeps the light blinking functionality, but adds scanning eight A/D channels. The scanned values are stored in an array.
unsigned char CommandIndex; unsigned char Command[5]; unsigned char Reply[5]; unsigned char ADValue[10];
void main(void)
{
unsigned int loop; unsigned char ADMuxIndex;
init_devices();
// Initial SPI return value USIDR = 0x00;
USISR |= 0x40;
// Initial MUX ADMUX |= 0x20;
CommandIndex = 0;
Reply[0] = 0;
Reply[1] = 0;
Reply[2] = 0;
Reply[3] = 0;
Reply[4] = 0;
Reply[5] = 0;
ADMuxIndex = 0;
while (1)
{
PORTB |= 0x20;
for (loop = 0; loop < 60000; loop++)
{
}
ADValue[ADMuxIndex] = ADCH;
if (ADMuxIndex == 7) ADMuxIndex = 0;
else ADMuxIndex++;
PORTB &= 0xDF;
for (loop = 0; loop < 60000; loop++)
{
}
ADMUX = 0x20 + ADMuxIndex;
}
}
Listing 4: The external interrupt routine clears the index to the returned values array. The ovf interrupt transmits the A/D information indexed by the first byte of the message.
}#pragma interrupt_handler int0_isr:2 void int0_isr(void)
{
//The command has just started.
//Set pointer to start. CommandIndex = 0;
}//int0_isr
#pragma interrupt_handler usi_ovf_isr:9 void usi_ovf_isr(void)
{
Command[CommandIndex] = USIDR;
if (CommandIndex == 0)
{
Reply[1] = ADValue[Command[0]];
}
USIDR = Reply[CommandIndex+1]; USISR |= 0x40;
CommandIndex++;
} //USI overflow
Publisher: Glenn ImObersteg
glenn@convergencepromotions.com
Managing Editor: Bob Henderson
bob@convergencepromotions.com
Technical Editor: Markus Levy
markus@convergencepromotions.com
Designer: Dave Ramos
dbyd@garlic.com
This Issue of the Atmel Applications Journal is published by Convergence Promotions. No portion of this publication may be reproduced in part or in whole without express permission, in writing, from the publisher. Copyright © Atmel corporation 2003. Atmel®, AVR® and combinations thereof, and megaAVR®, tinyAVR® are the registered trademarks, and AVRStudio™ and SecurAVR™ are the trademarks of Atmel Corporation or its subsidiaries. AVRFreaks®, IAR Systems, Innovative Design and Solutions, Inc®, Visual State®, eTokens®, Motorola®, and ARM® are the trademarks of their respective companies. All product copyrights and trademarks are property of their respective owners. All other product names, specifications, prices and other information are subject to change without notice. The publisher takes no responsibility for false or misleading information or omissions. Any comments may be addressed to the publisher, Convergence Promotions at 2220 Sunset Point, Discovery Bay, CA 94514. Printed in the USA.
www.atmel.com
page 48