Hallo,
ich habe mir im Zuge meines MP3-Player-Projektes die Ansteuerung einer Festplatte als ehrgeizige Zwischenetappe gesetzt. Leider gibts dabei (noch) Probleme. Aber nun von Anfang an: Ich habe im Internet vollständige Routinen inkl. Doku für die Ansteuerung einer Festplatte gefunden. Der Code stammt von den beiden Brasilianern Angelo Bannack und Giordano Bruno Wolaniuk. Meine Testschaltung ist der der beiden sehr ähnlich. Ich habe sowohl den kompletten Code inkl. Doku sowie meine Schaltung angehängt. Hier mal die ersten paar Zeilen der main():
Also die beiden printf-Ausgaben werden übertragen, aber in der ataInit() bleibt das Script hängen. Hier die Funktion:Code:int main(void) { TFILE *farq; struct direntry *de; char path[12]; mcuInit(); // start ATMega128 fdevopen(uart_putc, NULL); // configure printf to send data to serial port printf("FAT16/32 file system driver v1.00\r\n"); printf("Written by Angelo Bannack and Giordano Bruno Wolaniuk\r\n\r\n"); ataInit(); // Start ATA fatInit(); // Start FAT print_hd_info();
Der Code kommt über die folgende Zeile einfach nicht hinaus. Außerdem die Funktion IDE_Wait_State():Code:void ataInit(void) { unsigned char i; unsigned char* buffer = (unsigned char*) SECTOR_BUFFER_ADDR; DDR_DATAL= 0x00; // Use DATAL as the input from the hardrive DDR_DATAH= 0x00; // Use DATAH as the input from the hardrive PORT_DATAL= 0xFF; // Enable pullup on DATAL PORT_DATAH= 0xFF; // Enable pullup on DATAH DDR_ADDR = 0xDF; // Use ADDR PORT as the output for the hardrive // But use PORT_ADDR.5 as host interrupt (INPUT) PORT_ADDR= 0xc0; // Initialize PORT_ADDR to c0. ataWriteByte(ATA_REG_ACTSTATUS, 0x06); // Assert Software reboot. delay(100); ataWriteByte(ATA_REG_ACTSTATUS, 0x00); delay(100); //TESTTEIL: (hinzugefügt von mir) printf("ataReadByte(ATA_REG_ACTSTATUS): "); printf(ataReadByte(ATA_REG_ACTSTATUS)); // Wait until drive clear BUSY Bit in Alternate Status Register while(IDE_Wait_State(ATA_SR_BSY) == 1); // issue identify command ataWriteByte(ATA_REG_HDDEVSEL, 0); ataWriteByte(ATA_REG_ACTSTATUS, 0x02); while(IDE_Wait_State(ATA_SR_DRDY) == 0); ataWriteByte(ATA_REG_CMDSTATUS1, 0xEC); // wait for drive to request data transfer while(IDE_Wait_State(ATA_SR_DRQ) == 0); delay(200); // wait 200 us // read in the data ataReadDataBuffer(buffer, 512); // set local drive info parameters ataDriveInfo.cylinders = *( ((unsigned int*) buffer) + ATA_IDENT_CYLINDERS ); ataDriveInfo.heads = *( ((unsigned int*) buffer) + ATA_IDENT_HEADS ); ataDriveInfo.sectors = *( ((unsigned int*) buffer) + ATA_IDENT_SECTORS ); ataDriveInfo.LBAsupport = *( ((unsigned int*) buffer) + ATA_IDENT_FIELDVALID ); ataDriveInfo.sizeinsectors = *( (unsigned long*) (buffer + ATA_IDENT_LBASECTORS*2) ); // copy model string for(i=0; i<40; i+=2) { // correct for byte order ataDriveInfo.model[i ] = buffer[(ATA_IDENT_MODEL*2) + i + 1]; ataDriveInfo.model[i+1] = buffer[(ATA_IDENT_MODEL*2) + i ]; } // terminate string ataDriveInfo.model[40] = 0; // process and print info if(!ataDriveInfo.LBAsupport) { // CHS, no LBA support // calculate drive size ataDriveInfo.sizeinsectors = (unsigned long) ataDriveInfo.cylinders*ataDriveInfo.heads*ataDriveInfo.sectors; } }
Meine Testzeile darüber funktioniert auch nicht. Ich kann einfach kein Byte aus dem Alternate Status Register lesen. Hier die entsprechende Funktion:Code:while(IDE_Wait_State(ATA_SR_BSY) == 1); unsigned char IDE_Wait_State(unsigned char test_bit) { if ((ataReadByte(ATA_REG_ACTSTATUS) & test_bit) == test_bit) return 1; return 0; }
Die cbi() und sbi() habe ich wegkommentiert und ersetzt. Kann mir vielleicht jemand sagen, warum ich nicht auf die Register zugreifen kann? Ich weiß, es handelt sich um sehr viel Code, aber ich komme einfach nicht weiter. Ich verwende übrigens eine Seagate ST31720A, dessen Datenblatt ich auch angehängt habe.Code:unsigned char ataReadByte(unsigned char reg) { register unsigned char ret; PORT_DATAL = 0xFF; // habilita pull-ups DDR_DATAL = 0x00; // Use the DATAH as an input PORT_ADDR = PORT_ADDR & 0xe0; // Clear the lower 5 bits of the address line PORT_ADDR = PORT_ADDR | (reg & 0x1f); // Assert the address Line //cbi(PORT_IDE_RD, PIN_IDE_RD); // Assert DIOR PORT_IDE_RD &= ~(1 << PIN_IDE_RD); __asm volatile ("NOP"); __asm volatile ("NOP"); __asm volatile ("NOP"); ret = PIN_DATAL; //sbi(PORT_IDE_RD, PIN_IDE_RD); // Negate DIOR PORT_IDE_RD |= (1 << PIN_IDE_RD); return (ret); }
Ich hoffe auf eure Hilfe!







Zitieren
Lesezeichen