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

📄 idectrl.c

📁 自编的某项目中的基于NIOS II的硬盘控制程序
💻 C
字号:
// by dysch2000@163.com

#include "system.h"
#include "altera_avalon_pio_regs.h"
#include "altera_avalon_uart_regs.h"
#include "alt_types.h"
#include "stdio.h"

alt_u16 STATUS;
alt_u16 buffer0;


int main (void) __attribute__ ((weak, alias ("alt_main")));

  /* 
   * Use alt_main as entry point for this free-standing application
   */

#define DataReg   0x00            //硬盘数据寄存器      DataReg    
#define ErrFeaReg 0x01            //错误/特征寄存器     ErrFeaReg
#define SecNumReg 0x02            //扇区数寄存器        SecNumReg
#define SecCouReg 0x03            //扇区号寄存器        SecCouReg
#define CylinLReg 0x04            //柱面号寄存器L      CylinLReg
#define CylinHReg 0x05            //柱面号寄存器H      CylinHReg
#define DevHeaReg 0x06            //驱动器/磁头寄存器   DevHeaReg
#define StaComReg 0x07            //状态/命令寄存器     StaComReg

///////////////////位设置///////////////////////////
#define BSY STATUS&0x80
#define DRDY STATUS&0x40
#define DWF STATUS&0x20
#define DSC STATUS&0x10
#define DRQ STATUS&0x08
#define CORR STATUS&0x04
#define IDX STATUS&0x02
#define ERR STATUS&0x01


void delay(alt_u8 time)
{
    alt_u8 i,j;
    for(i=0;i<time;i++)
    for(j=0;j<255;j++);
}

/************************************************************
* D7   D6   D5   D4   D3   D2    D1   D0                    *
  BSY  DRDY DWF  DSC  DRQ  CORR  IDX  ERR                   *
BSY:驱动器忙;      1忙  0空闲                                       *
DRDY:驱动器准备好; 1准备好 0未准备好                                 *
DWF:驱动器写失败;  1写失败 0写成功                                   *
DSC:寻道结束;     1寻道结束                                         *
DRQ:请求服务,驱动器希望通过数据寄存器与CPU交换一字节数据;1请求服务    *
CORR:当可以纠正的读错误发生时,该位置1,数据传输将继续进行             *
IDX:收到综引信号1                                             *
ERR:命令执行出错1                                             *
*************************************************************/

/*******************************************************
*函数名称:void ReadReg(alt_u8 Address)                  *
*函数用途:读硬盘非数据寄存器内容,并将结果返回         *
********************************************************/
void ReadReg(alt_u8 Address)
{   
    IOWR_ALTERA_AVALON_PIO_DIRECTION(DATA_PIO_BASE, 0x0000);    //设置数据端口为输入方式
    IOWR_ALTERA_AVALON_PIO_DATA(CS_PIO_BASE, 0x02);
    IOWR_ALTERA_AVALON_PIO_DATA(DA_PIO_BASE, Address);   //向DA2 DA1 DA0 写入地址
    IOWR_ALTERA_AVALON_PIO_DATA(DIOWR_PIO_BASE, 0x01);   //读信号0有效
    STATUS=IORD_ALTERA_AVALON_PIO_DATA(DATA_PIO_BASE)&0x0ff;   //读取状态
    IOWR_ALTERA_AVALON_PIO_DATA(DIOWR_PIO_BASE, 0x03);   //读信号1无效
}

/*******************************************************
*函数名称:void WriteReg(alt_u8 Address,alt_u8 Date)          *
*函数用途:写硬盘非数据寄存器内容                       *
********************************************************/
void WriteReg(alt_u8 Address,alt_u8 Date)
{
    IOWR_ALTERA_AVALON_PIO_DIRECTION(DATA_PIO_BASE, 0xffff); //设置数据端口为输出方式
    IOWR_ALTERA_AVALON_PIO_DATA(CS_PIO_BASE, 0x02);
    IOWR_ALTERA_AVALON_PIO_DATA(DA_PIO_BASE, Address);   //向DA2 DA1 DA0 写入地址
    IOWR_ALTERA_AVALON_PIO_DATA(DIOWR_PIO_BASE, 0x02);   //写信号0有效
    IOWR_ALTERA_AVALON_PIO_DATA(DATA_PIO_BASE, Date);    //写入寄存器的对应的数据
    IOWR_ALTERA_AVALON_PIO_DATA(DIOWR_PIO_BASE, 0x03);   //写信号1无效
}

/*******************************************************
*函数名称:void ReadData()                              *
*函数用途:读硬盘数据寄存器内容                         *
********************************************************/
void ReadData()
{
    IOWR_ALTERA_AVALON_PIO_DIRECTION(DATA_PIO_BASE, 0x0000); //设置数据端口为输入方式
    IOWR_ALTERA_AVALON_PIO_DATA(CS_PIO_BASE, 0x02);
    IOWR_ALTERA_AVALON_PIO_DATA(DA_PIO_BASE, DataReg);   //向DA2 DA1 DA0 写入数据寄存器地址
    IOWR_ALTERA_AVALON_PIO_DATA(DIOWR_PIO_BASE, 0x01);   //读信号0有效
    buffer0=IORD_ALTERA_AVALON_PIO_DATA(DATA_PIO_BASE);  //读入16位数据存入buffer0
    IOWR_ALTERA_AVALON_PIO_DATA(DIOWR_PIO_BASE, 0x03);   //读信号1无效
}

/*******************************************************
*函数名称:void WriteData(alt_u16 Data)      *
*函数用途:写硬盘数据寄存器内容                         *
********************************************************/
void WriteData(alt_u16 Data)
{
    IOWR_ALTERA_AVALON_PIO_DIRECTION(DATA_PIO_BASE, 0xffff);  ////设置数据端口为输出方式
    IOWR_ALTERA_AVALON_PIO_DATA(CS_PIO_BASE, 0x02);
    IOWR_ALTERA_AVALON_PIO_DATA(DA_PIO_BASE, DataReg);   //向DA2 DA1 DA0 写入数据寄存器地址
    IOWR_ALTERA_AVALON_PIO_DATA(DIOWR_PIO_BASE, 0x02);   //写信号0有效
    IOWR_ALTERA_AVALON_PIO_DATA(DATA_PIO_BASE,Data);     //写入数据
    IOWR_ALTERA_AVALON_PIO_DATA(DIOWR_PIO_BASE, 0x03);   //写信号1无效
}

/*********************************************************
*函数名称:WriteCHS(alt_u16 cylinder,alt_u8 head,alt_u8 sector)*
*函数用途:写CHS信息(地址信息)                            *
**********************************************************/
void WriteCHS(alt_u8 head,alt_u16 cylinder,alt_u8 sector)
{
    alt_u8 timeout=0;
    do
      {
        ReadReg(StaComReg);
        if(++timeout>254)return;     //超时服务判断
      }while(BSY);                   //读状态寄存器,看是否忙
    WriteReg(DevHeaReg,0xe0&head);      //1110 0000&head  1 CHS/LBA 1 D HS3 HS2 HS1 HS0
    WriteReg(CylinHReg,cylinder>>8);    //high 2-bit cylinder
    WriteReg(CylinLReg,cylinder&0x00ff);//low 8-bit cylinder
    WriteReg(SecCouReg,sector); //start sector
    WriteReg(SecNumReg,0x01);   //sector counter
}

/*********************************************************
*函数名称:WriteCommand(command)                          *
*函数用途:写命令                                         *
**********************************************************/
void WriteCommand(command)
{   
    alt_u8 timeout=0;
    do
      {
        ReadReg(StaComReg);
        if(++timeout>254)return;
      }while(BSY);
    WriteReg(StaComReg,command);
}
/**********************************************************
*函数名称:GetData()                                       *
*用途:将硬盘的返回数据读入BUFFER数组                      *
***********************************************************/
/*void GetData()
{
    alt_u16 i=256;
  alt_u8 timeout=0;
    do
      {
        ReadReg(StaComReg);
      if(++timeout>254)return;
      }while(BSY|(!DRQ));
    if(ERR)
    {
        printf("ERROR!");
    }
    while(i)
    {
        ReadData();
        printf("%d",buffer0);
        i--;
    }
}*/

/**********************************************************
*函数名称:void IniHard(void)                              *
*用途:初始化硬盘                                          *
***********************************************************/
void IniHard(void)
{
    alt_u8 timeout=0;
    
    IOWR_ALTERA_AVALON_PIO_DATA(CS_PIO_BASE, 0x01);
    IOWR_ALTERA_AVALON_PIO_DATA(DA_PIO_BASE, 0x06);//选择设备控制REG  - - - - 1 SRST /IEN 0
    IOWR_ALTERA_AVALON_PIO_DIRECTION(DATA_PIO_BASE, 0xffff);
    IOWR_ALTERA_AVALON_PIO_DATA(DIOWR_PIO_BASE, 0x02);   //写信号0有效
    IOWR_ALTERA_AVALON_PIO_DATA(DATA_PIO_BASE, 0x0c);    //写入软复位信号
    IOWR_ALTERA_AVALON_PIO_DATA(DIOWR_PIO_BASE, 0x03);   //写信号1无效
    delay(255);    //做一个延时
    IOWR_ALTERA_AVALON_PIO_DATA(DIOWR_PIO_BASE, 0x02);   //写信号0有效
    IOWR_ALTERA_AVALON_PIO_DATA(DATA_PIO_BASE, 0x08);    //去掉软复位信号
    IOWR_ALTERA_AVALON_PIO_DATA(DIOWR_PIO_BASE, 0x03);   //写信号1无效    
    IOWR_ALTERA_AVALON_PIO_DATA(CS_PIO_BASE, 0x03);
    delay(255);
    do
    {
        WriteReg(DevHeaReg,0xa0); //1010 0000&head  1 LBA/CHS  1   DRV    HS3 HS2 HS1 HS0 
        ReadReg(StaComReg);       //                   1 / 0     0主/1从   磁头选择或LBA低4位
        if(++timeout>254)return;
    }while((!DRDY)|BSY);
    WriteReg(DevHeaReg,0xb0);     //0010 0000  最大磁头数 0xa0+磁头数
    WriteReg(SecNumReg,0xff);       //扇区数 0xff
    WriteReg(StaComReg,0x91);     //初始化磁盘指令0x91
    do
      {
        ReadReg(StaComReg);
        if(++timeout>254)return;
      }while(BSY);
    WriteReg(StaComReg,0x10);     //
    do
      {
        ReadReg(StaComReg);
        if(++timeout>254)return;
      }while(BSY); 
}  
/**********************************************************
*函数名称:void DriveID(void)                              *
*用途:读硬盘ID                                            *
***********************************************************/ 
void DriveID(void) 
{
    alt_u16 i=256;
    alt_u8 timeout=0;
    do
      {
        ReadReg(StaComReg);
        if(++timeout>254)return;
      }while(BSY);
    WriteReg(StaComReg,0xec);    //设备识别指令0xec
    do
      {
        ReadReg(StaComReg);
        if(++timeout>254)return;
      }while(BSY|(!DRQ));
    while(i)
    {
        ReadData();
        IOWR_ALTERA_AVALON_UART_TXDATA(UART_BASE,buffer0);
        i--;
    }
}

void SpinDown()  // 让硬盘休眠(停转)
{
  alt_u8 timeout=0;
    do
      {
        ReadReg(StaComReg);
        if(++timeout>254)return;
      }while(BSY); 
    WriteReg(StaComReg,0xE0); 
} 

/*******************************************************
*函数名称:主函数                                       *
*函数用途:                                             *
********************************************************/
void HardDiskControl(void)
{
    
    
    IniHard();
    DriveID();
    WriteCHS(0,0,0);    //0磁头,0柱面,0扇区
    WriteCommand(0x20); //读扇区命令
    //GetData();
    SpinDown();    
    /*for(i=0;i<512;i++)
    {
        printf("%d",i);
        delay(255);
    }*/
    
}


void SpinUP()    // 激活硬盘(转动) 
{
  alt_u8 timeout=0;
    do
      {
        ReadReg(StaComReg);
      if(++timeout>254)return;
      }while(BSY);
    WriteReg(StaComReg,0xE1); 
} 




int alt_main (void)
{

    char* msg="http://cnis.xidian.edu.cn\n";
   while(*msg!='\0')
    { 

      
      IOWR_ALTERA_AVALON_UART_TXDATA(UART_BASE,*msg++);//直接调用,只能单个字,占资源应该少
    }
    
    IOWR_ALTERA_AVALON_PIO_DATA(CS_PIO_BASE, 0x03);
    IOWR_ALTERA_AVALON_PIO_DATA(DIOWR_PIO_BASE, 0x03);
    HardDiskControl();
    SpinUP();
    
  return 0;
}

⌨️ 快捷键说明

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