Forum: Mikrocontroller und Digitale Elektronik USB ist tot wenn ISR Code enthält


von Karl K. (karl_k69)


Lesenswert?

Hi,

ich habe hier ein schräges Problem mit meinem V-USB-Code. Der 
funktioniert prinzipiell super, es sei denn ISR(TIMER0_COMPA_vect) 
enthält Code.

So funktioniert alles ordnungsgemäß und das USB-Gerät wird erkannt:

    ISR(TIMER0_COMPA_vect)
    {
    }

    TCCR0A = (1<<WGM01); // CTC Modus
    TCCR0B |= (1<<CS01); // Prescaler 8
    OCR0A = 15; // 100 kHz

    TIMSK |= (1<<OCIE0A);

Sobald in der ISR aber Code drin ist, wird das Gerät nicht mehr erkannt:

    static volatile unsigned int pulseOnCtr=0,pulseOffCtr=0;

    ISR(TIMER0_COMPA_vect)
    {
       if (pulseOnCtr>0)
       {
          pulseOnCtr--;
          if (pulseOnCtr==0)
          {
          }
       }
       else if (pulseOffCtr>0)
       {
          pulseOffCtr--;
       }
    }

Ich weiß, dass die ISR so noch nichts sinnvolles macht, aber es reicht 
um die USB-Verbindung nicht zu stande kommen zu lassen.

Hat jemand eine Idee, was die Ursache sein könnte? Was an dem Code in 
der ISR ist falsch?

Danke!

von Kondi (Gast)


Lesenswert?

Deine leere isr wird wahrscheinlich wegoptimiert, auf jeden Fall werden 
keine Register gerettet. Vielleicht mag v-USB keine ISRs?

von test (Gast)


Lesenswert?

es muss nichts falsch sein. du darfst vusb aber einfach nicht länger als 
x takte unterbrechen. steht irgendwo in der beschreibung.

von tja (Gast)


Lesenswert?

ich habe mir deinen Code nicht weiter angeschaut, aber wenn deine 
Kommentare stimmen, dann würde die ISR mit 100 kHz aufgerufen werden.

Das kann selbst bei deinen kleinen Code schon zuviel sein, so das 
wichtige Sachen für USB zurückgesteckt werden müssen, und diese nicht 
mehr im richtigen Zeitfenster behandelt werden konnte.

Reduzier die Frequenz mal auf 100 Hz.

Btw. Mit welcher CPU Frequenz fährst du? Du kannst dir ja mal 
spasseshalber das Dissambly anschauen, die Takte von den 
Assemblerbefehlen zählen (inkl. den ganzen Push und Pop), und dann mal 
schauen, wieviel Zeit eigentlich für den restlichen Code bleibt.

Ist nur eine Vermutung, könnte dir aber weiterhelfen.

von sTUdent (Gast)


Lesenswert?

Du darfst V-USB nicht zu lange unterbrechen, nimm lieber einen µC mit 
Hardware USB anstatt dieser frickel-Lösung.

von MWS (Gast)


Lesenswert?

Karl K. schrieb:
> // 100 kHz

Keine Chance VUSB mit 'net 100kHz ISR zu unterbrechen, die jeweils ca. 
50 Takte verbraucht. Da sind gleich 5 MCycles der 12 weg, VUSB verträgt 
sowas nicht.

von Karl K. (karl_k69)


Lesenswert?

tja schrieb:
> Btw. Mit welcher CPU Frequenz fährst du?

Die CPU läuft mit 16,5 MHz. Wenn ich die Frequenz auf 10 kHz senke, 
klappt es wieder.

Allerdings erscheint mir das schon sehr wenig, in der ISR werden initial 
(also pulseOnCtr und pulseOffCtr beide auf 0) nur ein paar Takte 
verbraten. Das bringt den V-USB tatsächlich schon aus dem Tritt?

von test (Gast)


Lesenswert?

siehst du doch^^

von Karl K. (karl_k69)


Lesenswert?

MWS schrieb:
> Keine Chance VUSB mit 'net 100kHz ISR zu unterbrechen, die jeweils ca.
> 50 Takte verbraucht.

Autsch, dass da schon mal 50 Zyklen rein für die Verwaltung draufgehen 
wusste ich nicht...irgend eine Chance die Frequenz wenigstens auf 20 kHz 
hochzubekommen ohne das V-USB die Grätsche macht?

von Hp M. (nachtmix)


Lesenswert?

Karl K. schrieb:
> es sei denn ISR(TIMER0_COMPA_vect)
> enthält Code.

Der Code in einem ISR ist so kurz wie möglich zu halten, und dann ist 
zum unterbrochenen Programm zurückzukehren, oder der Hardware-Interrupt 
wieder zu enablen.
Sonst besteht die Gefahr, dass andere Interrupt Requests nicht 
rechtzeitig bedient werden.
Die Ausrechnung irgenwelcher Dinge kann meist später erfolgen, wenn 
jemand die Daten des Interrupts anfordert.
Oft teilt man deshalb die ISR in einen schnellen Raw-ISR, der z.B. nur 
ein Timer-Register liest, und einen Mediated ISR, der z.B. dann das 
Datum daraus errechnet, auf.

: Bearbeitet durch User
von MWS (Gast)


Lesenswert?

Karl K. schrieb:
> Autsch, dass da schon mal 50 Zyklen rein für die Verwaltung draufgehen
> wusste ich nicht...irgend eine Chance die Frequenz wenigstens auf 20 kHz
> hochzubekommen ohne das V-USB die Grätsche macht?

War nur geschätzt, aber 2 volatiles, da werden jeweils LD(S), modify, 
ST(S) draus, die verwendeten Register und das Statusregister muss 
gesichert werden. Multipliziert mit 100kHz werden da schnell jede Menge 
Cycles verbraucht und VUSB ist empfindlich. Schau Dir das Disassemblat 
an, oder simulier's. Wüsste nicht, wie 100kHz klappen soll, denn um 
maximalen Speed zu erreichen, müssten Prozessorregister für die uints 
reserviert sein und da spielt der Compiler nicht mit.

von Jim M. (turboj)


Lesenswert?

Karl K. schrieb:
> Autsch, dass da schon mal 50 Zyklen rein für die Verwaltung draufgehen
> wusste ich nicht...irgend eine Chance die Frequenz wenigstens auf 20 kHz
> hochzubekommen ohne das V-USB die Grätsche macht?

VUSB mag keine Interupt Last, weil Atmel AVR MCUs keine Interrupt 
Prioritäten oder unterbrechbare Interrupts kennen. Andere Interrups 
verzögern die VUSB Interrupts, die relativ genau getimed sind.

Abhilfe:
Man nehme eine Atmel MCU mit integriertem USB, da hat man das Problem 
VUSB nicht mehr. Die Hardware USB Implementationen bei der Interrupt 
Latenz nicht empfindlich.

von Peter II (Gast)


Lesenswert?

am code kann man aber noch ein stück optimieren.

pulseOnCtr

wird 3 mal verwendet, ist vermutlich volatile - das kosten viel zeit.

lass man das volatil weg und caste in der main auf volatile. Dann wird 
die ISR schneller.

von Karl K. (karl_k69)


Lesenswert?

Hp M. schrieb:
> oder der Hardware-Interrupt
> wieder zu enablen.

Ein sei() am Anfang der ISR und bei den Variablen das "volatile" 
weglassen hat geholfen - Danke!!! :-)

von MWS (Gast)


Lesenswert?

Karl K. schrieb:
> Ein sei() am Anfang der ISR und bei den Variablen das "volatile"
> weglassen hat geholfen - Danke!!! :-)

Das verspricht noch interessante Ergebnisse ;D

von test (Gast)


Lesenswert?

yay, wahrscheinlich hast du jetzt einen zufallszahlengenerator. :D

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Du kannst deine Timer ISR auch als ISR_NOBLOCK deklarieren, damit 
erlaubst du V-USB, welches immer die höchste Priorität haben sollte, die 
ISR zu unterbrechen:
1
 ISR(TIMER0_COMPA_vect, ISR_NOBLOCK)

Vorsicht vor Race Conditions. Die Timer ISR sollte mgölichst an nichts 
rumfummeln, was der V-USB IRQ benutzt.

: Bearbeitet durch User
von Volker S. (vloki)


Lesenswert?

Karl K. schrieb:
> Hi,
>
> ich habe hier ein schräges Problem mit meinem V-USB-Code.

Ach, jetzt sind die "Schmalspurelektroniker im Hipsterforum" doch wieder 
gut genug ;-)

@Glühwürmchen: kannst du von mir aus löschen ...

: Bearbeitet durch User
von Karl K. (karl_k69)


Lesenswert?

test schrieb:
> yay, wahrscheinlich hast du jetzt einen zufallszahlengenerator. :D

Nö, die erzeugte Frequenz ist ausreichend stabil.

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.