⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ata.c

📁 atmelmega128ATA驱动内含FAT32源码
💻 C
📖 第 1 页 / 共 5 页
字号:
unsigned int ata_read_word(void)
{
   unsigned int ata_word_read,ata_byte_read;
   avr_databus_in;
   PORT_ATA_IO_CNTL = ATA_IO_DATA;
   PORT_ATA_IO_CNTL &= ~ATA_DIOR;
   delay_us(1);
   ata_byte_read = PORT_ATA_DATA_H_IN; 
   ata_word_read = ata_byte_read << 8;
   ata_byte_read = PORT_ATA_DATA_L_IN; 
   ata_word_read |= ata_byte_read;
   PORT_ATA_IO_CNTL |= ATA_DIOR;
   PORT_ATA_IO_CNTL = ATA_IO_HIZ;
   return ata_word_read;
}   
//******************************************************************
//*	WRITE WORD TO ATA DEVICE
//*   This routine does not use SRAM as a buffer.
//*   
//******************************************************************										 									 									 
unsigned int ata_write_word(unsigned int wordout)
{
   unsigned int returncode;		 
   avr_databus_out;
   PORT_ATA_DATA_H_OUT = wordout >> 8;
   PORT_ATA_DATA_L_OUT = wordout;
   PORT_ATA_IO_CNTL = ATA_IO_DATA;
   ata_write_pulse;
   PORT_ATA_IO_CNTL = ATA_IO_HIZ;
   avr_databus_in;
   return returncode;
 }  
 //******************************************************************
//*	WRITE A BYTE TO THE ATA I/O
//*   This routine writes a byte on the lower 8 bits of the data bus.
//*   
//******************************************************************										 									 									 
void ata_write_byte(unsigned char atabyte)
 {
   avr_databus_out; 
  PORT_ATA_DATA_L_OUT = atabyte;
  ata_write_pulse;
  PORT_ATA_IO_CNTL = ATA_IO_HIZ;
  avr_databus_in;
 } 					 
//******************************************************************
//*	SEND ATA COMMAND
//*   Sends an ATA command out of lower 8 bits of data bus.
//*   
//******************************************************************										 									 									
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;
} 										 
//******************************************************************
//*	READ STATUS BYTE 
//*   Read ATA status byte.
//*   
//******************************************************************										 									 									
unsigned char ata_get_status_byte(void)
{
   unsigned char ata_byte_read;
   avr_databus_in;
   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;
   avr_databus_in; 
   return ata_byte_read;  
}	
//******************************************************************
//*	READ REGISTER 
//*   
//*   
//******************************************************************										 									 									
unsigned char ata_get_register(unsigned char cbreg)
{
   unsigned char ata_byte_read;
   avr_databus_in;
   PORT_ATA_IO_CNTL = cbreg;
   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;
   avr_databus_in; 
   return ata_byte_read;  
}															 									 
//******************************************************************
//*	PERFORM HARDWARE RESET
//*   This routine toggles ATA RESET line low for 10ms.
//*   
//******************************************************************										 									 									 
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;
 }   
//******************************************************************
//*	CHECK ATA READY BIT 
//*   Checks READY status bit.
//*   Returns 1 if device is ready.
//****************************************************************** 
unsigned int ata_rdy(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;
   if(ata_byte_read & ATA_STAT_RDY)
   	return 1;
   else
    return 0;				
}
//******************************************************************
//*	CHECK ATA BUSY BIT 
//*   Checks READY status bit.
//*   Returns 1 if device is busy.
//****************************************************************** 
unsigned int ata_bsy(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;
   if(ata_byte_read & ATA_STAT_BSY)
   	return 1;
   else
    return 0;				
}
//******************************************************************
//*	CHECK ATA DRQ BIT 
//*   Checks READY status bit.
//*   Returns 1 if device is requesting service.
//******************************************************************    
unsigned int ata_drq(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;
   if(ata_byte_read & ATA_STAT_DRQ)
   	return 1;
   else
    return 0;				
}
//******************************************************************
//*	CHECK ATA ERROR BIT 
//*   Checks READY status bit.
//*   Returns 1 if device is reporting an error condition.
//****************************************************************** 
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;
   if(ata_byte_read & ATA_STAT_ERR)
   	return 1;
   else
    return 0;				
}
//******************************************************************
//*	READ A PAGE OF SRAM 
//*   A page = 256 words.
//*   This routine reads 512 bytes from SRAM to a buffer in the AVR.
//****************************************************************** 		
void ram_read_page(unsigned int page)
{
 unsigned int i,j,ram_page,ram_address;
 j=0x00;
 ram_page = page;
 ram_address = ram_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;
  nop;
  ram_page_buffer[j] = PORT_ATA_DATA_L_IN;  //changed H to L
  ram_page_buffer[j+1] = PORT_ATA_DATA_H_IN;//changed L to H
  ram_off;
  ++ram_address;
  j += 2;
  }	
}  
//******************************************************************
//*	FILL A PAGE OF RAM 
//*   A page = 256 words.
//*   This routine fills a ram page with a user-defined word.
//****************************************************************** 	
void ram_fill_page(unsigned int page,unsigned int dataword)
{
 unsigned int ram_address,i;
 ram_address = page * 0x100;
 avr_databus_out;
 for(i=0;i<256;++i)
 {
  PORT_ATA_DATA_H_OUT = ram_address >> 8;
  PORT_ATA_DATA_L_OUT = ram_address;
  latch_ram_addr;
  PORT_ATA_DATA_H_OUT = dataword >> 8;
  PORT_ATA_DATA_L_OUT = dataword;
  ram_on;
  ram_write_pulse;
  ram_off;
  ++ram_address;
  //++dataword;	// this line increments the original dataword
 }
} 
//******************************************************************
//*	 WRITE A SECTOR 
//*   device = 0x00 or 0x01 //// 
//*   This routine writes an LBA-addressed sector.
//******************************************************************  	
unsigned char ata_write_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);
 #if debug
 gotreg=ata_get_register(ATA_IO_DEVICE_HEAD);
 printf("devhead %#x\r\n",gotreg);
 gotreg=ata_get_register(ATA_IO_CYL_H);
 printf("cylH %#x\r\n",gotreg);
 gotreg=ata_get_register(ATA_IO_CYL_L);
 printf("cylL %#x\r\n",gotreg);
  gotreg=ata_get_register(ATA_IO_SECTORNUM);
 printf("sectnum %#x\r\n",gotreg);
 for(;;);
 #endif
 ata_send_cmd(CMD_WRITE_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;
  PORT_ATA_IO_CNTL = ATA_IO_DATA;
  ata_write_pulse;
  delay_us(1);  // nop works here too
  while(busy);
  ram_off;
  ++ram_address;
 } 
  return (error);
}	
//******************************************************************
//*	READ A SECTOR 
//*   device = 0x00 or 0x01  
//*   This routine reads an LBA-addressed sector into a SRAM page.
//******************************************************************  	
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);
	   //printf("\r\nhead %#x\r\n",ata_get_register(ATA_IO_DEVICE_HEAD));
	   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);
 //printf("cylh %#x\r\n",ata_get_register(ATA_IO_CYL_H));
 while(busy);
 ata_set_io_addr(ATA_IO_CYL_L);
 ata_write_byte(lbasector >> 8);
 //printf("cyll %#x\r\n",ata_get_register(ATA_IO_CYL_L));
 while(busy);
 ata_set_io_addr(ATA_IO_SECTORNUM);
 ata_write_byte(lbasector);
 //printf("sector %#x\r\n",ata_get_register(ATA_IO_SECTORNUM));
 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);
}			 		 
//******************************************************************
//*	Delay millisecond Function
//*   This function uses Timer 3 and the A compare registers
//*   to produce millisecond delays.
//*   Clock = 14.746MHz
//******************************************************************
void delay_ms(unsigned int delay)
{
 unsigned int i;
 OCR3AH = 0x39;
 OCR3AL = 0x9A;          
 TCCR3B = 0x00;          // Stop Timer3
 for(i=0;i<delay;++i)
 {
 TCCR3B = 0x00;          // Stop Timer3
 TCNT3H = 0x00;          // Clear Timer3
 TCNT3L = 0x00;          
 TCCR3B = 0x09;          // Start Timer3 with clk/1
 while(!(ETIFR & 0x10));
 ETIFR |= 0x10;
 }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -