Forum: Mikrocontroller und Digitale Elektronik HDD + Interrupt Problem


von Andreas Auer (Gast)


Lesenswert?

Hi.

Gleich zur Sache. Ich versuche gerade WAV-Files von einer Festplatte
über einen DAC abzuspielen. Zum Testen des DAC hab ich mir ne
Sinustabelle geschrieben, die einfach nur einen Sinus mit 1kHz
ausgibt.
Das funktioniert auch ganz gut. Genauso funktioniert die Ansteuerung
der Festplatte alleine ganz gut!
Um das Timing hinzubekommen, hab ich einen OUTPUT COMPARE Interrupt,
durch den der OC1B Pin toggelt (takt für den DAC) und jedesmal ein
Interrupt aufgerufen wird. Während des Interrupts werden dann die Daten
an den DAC via SPI gesendet!

Problem:
Wenn ich jetzt den Interrupt aktiviert habe (also den DAC anspreche),
dann funktioniert das Auslesen der Festplatte teilweise nicht mehr. Ich
hab aber keine Ahnung warum. Normalweise sollte er das Auslesen zum
Beispiel eines Sektors einfach unterbrechen, dann die ISR ausführen und
dann ganz normal im Programm weitergehen, oder??

Vielleicht hat sowas schonmal jemand gemacht und kann mir dabei
helfen!

mfg
Andreas

--
Andreas Auer              aauer1 (at) sbox.tugraz.at
Student of Telematics     http://home.pages.at/aauer1
Graz, University of Technology

von Benedikt (Gast)


Lesenswert?

Der Festplatte ist das egal, ob ne Pause drin ist. Ohen Quellcode kann
man da kaum was sagen, aber schau mal ob irgendwelche Register in der
IR verändert werden und so was anderes überschreiben.

von Andreas Auer (Gast)


Lesenswert?

Ok, mal ein bisschen Source:

unsigned char hddReadDataRegister(unsigned char address,
                                  unsigned char *buffer)
{
  unsigned int i = 0;

  hddReadInit();

  HDD_ADDR_PORT = address << HDD_ADDR_OFFSET;

  for(i=0;i<512;i+=2)
  {
    while((hddGetStatus() & (STATUS_BSY | STATUS_DRDY)) !=
STATUS_DRDY);

    HDD_ADDR_PORT = address << HDD_ADDR_OFFSET;
    HDD_READ_PORT &= ~_BV(HDD_READ_PIN);
    asm volatile("nop\n\t"::);
    asm volatile("nop\n\t"::);

    buffer[i]   = HDD_DATA_LOW_INPIN;
    buffer[i+1] = HDD_DATA_HIGH_INPIN;
    HDD_READ_PORT |= _BV(HDD_READ_PIN);
  }

  return (hddGetStatus() & STATUS_ERR);
}


So sieht der Code aus, der das 512 Bytes vom Datenregister der HDD
rausliest.
Jetzt noch kurz die ISR. Die ist in Assembler geschrieben. Der Grund
dafür war einfach, dass mein C-Code einfach zu groß wurde. Der
Interrupt wird übrigens etwa alle 10us aufgerufen!

#include <avr/io.h>

.global SIG_OUTPUT_COMPARE1B

.extern sinustable
.extern counter

SIG_OUTPUT_COMPARE1B:
  push r17      ; 2
  push ZH       ; 2
  push ZL       ; 2
  push r16      ; 2

  in r17, 0x0e              ; 1
  lds r16, counter          ; 2
  ldi r17, 0                ; 1
  ldi ZL, lo8(sinustable)   ; 1
  ldi ZH, hi8(sinustable)   ; 1

  add ZL, r16     ; 1
  adc ZH, r17     ; 1
  ldd r17, Z+1    ; 2
  out 0x0f, r17   ; 1
  ld r17, Z

  sbis 0x16, PB0
  rjmp CONTINUE

  inc r16
  inc r16
  cpi r16, 0x60
  brne NEXT
  ldi r16, 0
NEXT:
  sts counter, r16

CONTINUE:
  pop r16
  pop ZL
  pop ZH

LOOP_0:
  sbis 0x0e, SPIF
  rjmp LOOP_0
  out 0x0f, r17   ; 1

  pop r17         ; 2
  reti            ; 4


Vielleicht hat auch schonmal jemand sowas gemacht und weiß vielleicht
noch nen Rat!?
Besten Dank schonmal!

mfg
Andreas

von Andreas Auer (Gast)


Lesenswert?

Also, ich denke mein Code sind eigentlich ganz in Ordnung aus, oder?
Jetzt hätte ich noch eine Bitte! Und zwar... es gibt ja einige unter
euch, die schon ne Ansteuerung für ne Festplatte gemacht haben. Könnte
mir jemand vielleicht seinen Code (auch ASM) geben, damit ich diesen
dann ausprobieren könnte. Ich hab bei meinen schon alle möglichen
Variationen ausprobiert. Aber irgendwie hat nichts so richtig
gefruchtet!

Danke,
Andreas

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.