📄 idectrl.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 + -