Datum:
Angehängte Dateien:Hallo, Ich hab ein Problem mit einem Atmel SAM3S4B. Datenblatt: http://www.atmel.com/Images/doc6500.pdf Die Timer sind ab Seite 743 zu finden. Folgendes Vorhaben: - Timer 0 erzeugt ein Signal mit ~1ms Periode und 4 * 5us an-Zeit. - in diesen 4 * 5us wird die Clock für Timer 2 freigegeben. - Timer 2 macht dann 4 Perioden zu je 5us und triggert jedes Mal den ADC. - (Timer 0 und 2 haben den selben Prescaler und sind synchronisiert). Ich will also alle 1ms 4 ADC-Shots. Danach einen Interrupt. Das klappt auch mehr oder weniger gut. Immer die erste Periode von Timer 0 erzeugt einen Puls zu wenig an Timer 2. Und ich verstehe nicht, warum. Anbei Aufzeichnungen von meinem Logcanalyzer. led_rt: active low im Interrupt - also nach 4 ADC-Shots. TIOA2: Trigger-Signal an den ADC. 1.png: der gesamte Ablauf. Bei den Pulsen im gelben Kreis beginnt der ganze Ablauf. Die Pulse davor sind vom vorherigen Ablauf und uninteressant. Hier wird Timer 0 angestoßen und löst das erste mal beim orangen Kreis aus. Beim organgen Kreis würde ich dann auch den ersten Interrupt erwarten. Wie in 2.png und 3.png zu sehen ist, passiert das aber nicht, weil der TIOA2 den ADC nur 3 mal triggert und nicht 4 mal. Erst ab dem zweiten Auslösen des Timers 0 läuft alles wie gewollt - zu sehen in 4.png. Die eigentliche Frage: warum hat der Timer 2 beim ersten Auslösen von Timer 0 nur drei Perioden anstatt vier. Der Code zum Timer-Setup:
#define ADCSHOTS 4 PMC_ENABLE_PC(TC0IRQ); PMC_ENABLE_PC(TC2IRQ); /* * timer2 as the adc trigger source * burst mode for ADC_SHOTS samples at 200kHz */ TCB0_BASE->TC[2].TC_CMR = TCMCK2 | BurstXc2 | WAVE | CPCTRG | \ (ClearOutput << B_ACPA) | (SetOutput << B_ACPC); TCB0_BASE->TC[2].TC_RC = sys_clock / 2 / 200000; TCB0_BASE->TC[2].TC_RA = TCB0_BASE->TC[2].TC_RC / 2; /* * timer0 as the tc2 gate * 1000Hz sampling rate */ TCB0_BASE->TC[0].TC_CMR = TCMCK2 | BurstNone | WAVE | CPCTRG | \ (SetOutput << B_ACPA) | (ClearOutput << B_ACPC); TCB0_BASE->TC[0].TC_RC = sys_clock / 2 / 1000; TCB0_BASE->TC[0].TC_RA = TCB0_BASE->TC[0].TC_RC - (TCB0_BASE->TC[2].TC_RC * ADC_SHOTS); /* gate clk of tc2 by tc0 */ TCB0_BASE->TC_BMR = TIOA0XC2; |
Gestartet werden die Timer damit:
di(); TCB0_BASE->TC[0].TC_CCR = CLKEN; TCB0_BASE->TC[2].TC_CCR = CLKEN; TCB0_BASE->TC_BCR = TCSYNC; ei(); |
Grüße, Michael
Datum:
Angehängte Dateien:Ich hab jetzt noch eine Leitung zum TIOA0 gefädelt. Es scheint, als wären die beiden Timer nicht synchron. Sie werden aber über das Block_Control_Register gleichzeitig mit der gleichen Clock getriggert. Ein Trigger macht einen Zähler-Reset und Clock-Enable. Und noch ein Nachtrag zum Ausgangspost: die Timer laufen völlig unbeeinflusst, bis der Interrupt n Mal ausgeführt wurde. Dann erst werden die Timer wieder angehalten und zurückgesetzt. Es werden keine Register von Timern geschrieben und nicht mal gelesen, während die Messung läuft.
Datum:
Hm ich würd an Deiner Stelle mal die AT91support hotline anschreiben, ich hab bei meinen Problemchen immer recht schnell eine Antwort bekommen. Kannst gern das Ergebnis hier Posten, ich verwende zwar SAM3A aber hatte bisher noch nicht mit derart Timern gearbeitet.
Datum:
Falls jemand diesen Thread über eine Suche findet: Heute die Bestätigung bekommen: das wird ein neues Errata... Der Synchronisierungs-Block vorm Clock-Eingang hat einen Fehler, der in den ersten paar µs Pulse verschluckt.
Datum:
Hi Michael, ist ein Workaround bekannt? Kannst Du bitte die Antwort posten? Vielen Dank! Michael
Datum:
Sie haben "empfohlen", DMA nicht zu verwenden und einen Timer-Interrupt aufzusetzen, anstatt den Timer triggern zu lassen. Das allerdings für meinen Anwendungsfall. Im nächsten Datenblatt-Release kann auch etwas anderes stehen. Nachdem das ganze auch schon ein Workaround für das ADC-Sequencing-Errata ist, werde ich auf einen anderen Prozessor umsteigen. Meine Stromverbrauchsanforderungen lassen das ganze Interrupt-Gehampele nicht zu.





