Hallo,
meines Wissens werden ja Arrays, sofern nicht mit PROGMEM
gekennzeichnet, im RAM des AVRs abgelegt, doch irgendwie passiert das
bei mir nicht.
1
// Sollte im RAM sein
2
constuint16_tc_FreqTable[]=
3
{
4
220,233,247,262,277,294,311,330,349,370,392,415,
5
440,466,494,523,554,587,622,659,698,740,784,831,
6
880
7
};
8
9
// ...
10
11
SetFrequency(c_FreqTable[7]);// Korrekte Ausgabe
12
SetFrequency(c_FreqTable[i]);// Müll
Wenn das Array tatsächlich im RAM liegt, dann müsste es gehen, wenn es
aber, whyever, im Flash ist, dann gehts ja wohl nicht.
Mein µC ist ein AtMega8, falls das hilft.
Danke
Wie versuchst du auf das Array im Flash zuzugreifen? Direkt mit dem
Variablennamen? -> Das geht nicht, du musst memcpy_P, pgm_read_byte,
pgm_read_word etc. benutzen.
Der Grund, dass es mit festen Zahlen funktioniert, ist der Optimierer
der direkt die richtigen Zahlen einsetzt, so dass im fertigen Programm
gar keine Zugriffe auf das Array stattfinden.
gregor schrieb:
> glaube ich nicht ;)
Natürlich nicht. Der restliche nicht gezeigte Code ist ja immer
fehlerfrei.
> Also i sollte keinen Müll enthalten, denn mit der "eleganten" Lösung> geht es.
Deine Lösung lässt keinen Rückschluss darauf zu, ob i irgendwann mal
Müll enthält. Sie verhindert nur, dass in dem Fall SetFrequency mit
einem ungültigen Wert aufgerufen wird. Setze doch noch ein else hinten
dran und schalte dort z.B. eine LED ein.
Wenn es auch nicht unmöglich ist, das Du da auf ein Problem gestossen
bist, so ist es doch eher unwahrscheinlich. Wahrscheinlicher ist, das in
Deinem ersten Code i tatsächlich keinen sinnvollen Wert enthielt.
>doch irgendwie passiert das bei mir nicht.
Das sollte sich durch einen Blick in das map-file bzw. Listing klären
lassen.
Du kannst die beiden Dateien hier auch als Anhang posten.
Sag uns doch bitte noch welchen Compiler und welche Entwicklungsumgebung
Du verwendest.
gregor schrieb:
> Soweit hatte ich das auch verstanden, aber warum ist das Array denn im> Flash, ich hab doch nirgendwo ein PROGMEM stehen?
Das Array ist auch nicht im Flash.
Du hast einen Fehler in den Programteilen die du nicht hergezeigt hast
(sofern man das bischen überhaupt als 'Programteil' bezeichnen kann)
Ich habe den Quellcode und die map file im Anhang.
Als Entwicklungsumgebung benutze ich Code::Blocks, zusammen mit dem
AVR-GCC und avrdude zum upload.
avr-gcc --version
(WinAVR 20090313) 4.3.2
Habe mal ans Ende der if's einmal LEDs umschalten gehängt, LED ist
dauerhaft eingeschaltet.
Hm... ins Makefile habe ich keinen EInblick, Code::Blocks verwendet sein
eigenes buildsystem. Es sind die -Os, --mmcu=atmega8, -g und -msize
Flags gesetzt.
[quote]Natürlich nicht. Der restliche nicht gezeigte Code ist ja immer
fehlerfrei.[/quote]
Sorry, so war das nicht gemeint, aber ich bin mir eben sicher, dass ich
es noch schaffe i von 0-24 laufen zu lassen. Der Code, den du natürlich
nicht gesehen hast, schien für mich einfach richtig.
Frage: Wie zitiert man in diesem Forum?
Danke,
Gregor
Ich bräuchte schon genau die komplette Kommandozeile von der
hex-File-Generierung. Also bitte entweder den Build-Output kopieren,
oder (besser) das Makefile posten.
Ich persönlich fände ein weniger exotisches Komprimierungsformat wie zip
oder gzip usw. gut. Diese 7z-Dateien kann ich nicht öffnen; es gibt
nichtmal einen offiziellen Port für Debian. Und ich habe auch keine Lust
jetzt erstmal ne Stunde zu versuchen das Ding zu kompilieren.
Hmm.
Der Arrayzugriff sieht gut aus.
Wie hast du festgestellt, dass die ausgelesenen Werte nicht stimmen?
Deine Erlaubnis vorausgesetzt habe ich den Code mal hier hereingestellt
> Wie hast du festgestellt, dass die ausgelesenen Werte nicht stimmen?
Per DDS werden die Frequenzen über einen passiven DAC an einen
Lautsprecher ausgegeben.
Wenn ich den Hack verwende, dann steigt der Ton tatsächlich in 1/4
Sekundenschritten an.
Wenn ich den direkten Zugriff
1
SetFrequency(c_FreqTable[i]);// Das klappt nicht
verwende, dann wird die ganze Zeit ein durchgehender Ton ausgegeben.
Wer die c_FreqTable anschaut, der sieht, dass es a0 - a'' in
Halbtonschritten ist ;)
Schlechtes Timing :P
> Und synth.elf.hex ist auch das, womit du dann den Controller> programmierst? Oder vielleicht synth.elf?
Ja, mit synth.elf.hex wird der Controller programmiert.
Was sagt die Mapfile? Mit dennen habe ich mich nie auseiander gesetzt
und weiss daher nicht, wie man bei ihnen sieht, wo ein Array gespeichert
ist.
gregor schrieb:
> Wenn ich den Hack verwende, dann steigt der Ton tatsächlich in 1/4> Sekundenschritten an.> verwende, dann wird die ganze Zeit ein durchgehender Ton ausgegeben.
Hmm. Interessant.
Aber der Ton an sich ist richtig?
>Was sagt die Mapfile? Mit dennen habe ich mich nie auseiander gesetzt>und weiss daher nicht, wie man bei ihnen sieht, wo ein Array gespeichert>ist.
Die beiden wesentlichen Punkt sind:
1. Die Memory Map.
Memory Configuration
Name Origin Length Attributes
text 0x00000000 0x00002000 xr
data 0x00800060 0x0000ffa0 rw !x
eeprom 0x00810000 0x00010000 rw !x
fuse 0x00820000 0x00000400 rw !x
lock 0x00830000 0x00000400 rw !x
signature 0x00840000 0x00000400 rw !x
default 0x00000000 0xffffffff
text ist das Flash, data das RAM und EEPROM .... (habe ich vergessen
:-))
Hier (etwas später im File) dann die Adresse des Arrays.
.data 0x00800060 0x37 obj\Debug\main.o
0x00800065 c_FreqTable
[Klugscheissmodus]
"Die" Datei oder "das" File. Also das Map-File.
[/Klugscheissmodus]
>Hmm. Interessant.>Aber der Ton an sich ist richtig?
Nein, leider nicht. Er ist viel zu hoch für 220Hz. Ich hab das ganze mal
mit Audacity am PC aufgenommen und die Frequenz näherungsweise bestimmt:
etwa 1501Hz
>Laut dem Map-File liegt das Array im Datensegment.
Also im EEPROM? Wie bekomme ich das Array da raus?
Naja, wenn am Ende nichts hilft, dann werde ich wohl die Daten mit
EEPROM oder Flash zugriffen auslesen...
gregor schrieb:
>>>Laut dem Map-File liegt das Array im Datensegment.> Also im EEPROM? Wie bekomme ich das Array da raus?
Nein.
data ist das SRAM
eeprom hat seine eigene Section
gregor schrieb:
>>Hmm. Interessant.>>Aber der Ton an sich ist richtig?>> Nein, leider nicht. Er ist viel zu hoch für 220Hz. Ich hab das ganze mal> mit Audacity am PC aufgenommen und die Frequenz näherungsweise bestimmt:> etwa 1501Hz
Mach mal die Absicherung gegen einen Interrupt in der SetFrequency.
>>Laut dem Map-File liegt das Array im Datensegment.>Also im EEPROM? Wie bekomme ich das Array da raus?
Hä? Wieso EEPROM. Da war ich wohl zu lakonisch.
Data ist im Ram und liegt bei:
data 0x00800060 0x0000ffa0 rw !x
Das ist also NICHT Dein Problem.
Aber: Diese ganzen Casts sind mir etwas suspekt.
>du solltest das setzen von phaseStep atomar machen
Ich habe es gerade kurz versucht, aber jetzt habe deutlich hörbare
Klopfer.
>Zeit das elf-File zu posten (von der i-Variante).
Ich habe jetzt das elf-File hochgeladen, nicht elf.hex, hoffe das war
richtig.
Karl heinz Buchegger schrieb:
> gregor schrieb:>>>Hmm. Interessant.>>>Aber der Ton an sich ist richtig?>>>> Nein, leider nicht. Er ist viel zu hoch für 220Hz. Ich hab das ganze mal>> mit Audacity am PC aufgenommen und die Frequenz näherungsweise bestimmt:>> etwa 1501Hz>> Mach mal die Absicherung gegen einen Interrupt in der SetFrequency.
Duch die direkten Zugrife hast du ein geringfügig anders Timing und
möglicherweise einfach nur Glück, dass dir kein Interrupt während der
4-Byte Zuweisungsaktion dazwischenknallt.
gregor schrieb:
>>du solltest das setzen von phaseStep atomar machen> Ich habe es gerade kurz versucht, aber jetzt habe deutlich hörbare> Klopfer.
Das wird die 64-Bit Arithmetik sein. Dauert einfach zu lange
-> Die Interrupts nur so kurz wie möglich, aber so lange wie notwendig
sperren
>>du solltest das setzen von phaseStep atomar machen>Ich habe es gerade kurz versucht, aber jetzt habe deutlich hörbare Klopfer.
[bloedesgequatsche]
Ja, es wird immer erst schlimmer ehe es besser wird.
[/bloedesgequatsche]
Naja schrieb:
>>>du solltest das setzen von phaseStep atomar machen>>Ich habe es gerade kurz versucht, aber jetzt habe deutlich hörbare Klopfer.>> [bloedesgequatsche]> Ja, es wird immer erst schlimmer ehe es besser wird.> [/bloedesgequatsche]
Vor allen Dingen gibt es keine wirkliche Erklärung für einen 'falschen'
Arrayzugriff. Ausser einem Compilerfehler. Aber daran glaube ich erst
wenn es keine andere Möglichkeit mehr gibt, bzw wenn er im Assemblercode
nachweisbar ist.
>Vor allen Dingen gibt es keine wirkliche Erklärung für einen 'falschen'>Arrayzugriff.
Ich würde wirklich gerne mal das Assemblerlisting sehen. Eben den
Aufruf:
1
SetFrequency(c_FreqTable[i]);
Bin gerade dabei einen ganzen Schwung commits zu machen, sonst würde ich
mir das elf mal disassembliert anschauen.
Naja schrieb:
>Aber: Diese ganzen Casts sind mir etwas suspekt.
Bei setFrequency? Die Berechnung hatte ich aus Topic 89387,
Karl heinz Buchegger schrieb:
>Das wird die 64-Bit Arithmetik sein. Dauert einfach zu lange>-> Die Interrupts nur so kurz wie möglich, aber so lange wie notwendig>sperren
Hab deinen Vorschlag eingebaut: Jop, die Klopfer sind weg, aber der Ton
hat immernoch eine falsche Frequenz, die sich nicht ändert.
Naja schrieb:
>Hä? Wieso EEPROM. Da war ich wohl zu lakonisch.>Data ist im Ram und liegt bei:
Wir haben diePosts zeitlgleich losgeschickt gehabt, hatte es deswegen
noch nicht gelesen und nur gemutmaßt ;)
Okay, aber wenn es im RAM ist, dann sollte ja der zugriff gehen?
Bin eine Assemblerniete, kann demnach nicht selbst nachschauen.
Hab mal mit
gregor schrieb:
> Okay, aber wenn es im RAM ist, dann sollte ja der zugriff gehen?
Grundsätzlich ja.
Ich denke immer noch, das nicht der Zugriff das Problem ist, sondern
irgendetwas anders.
> Bin eine Assemblerniete, kann demnach nicht selbst nachschauen.
Hier ist der Zugriff
1
mov r30,r17
2
ldi r31,lo8(0)
3
lsl r30
4
rol r31
5
subi r30,lo8(-(c_FreqTable))
6
sbci r31,hi8(-(c_FreqTable))
7
ld r24,Z
8
ldd r25,Z+1
sieht gut aus und ist richtig. (r17 enthält i, der Tabellenwert kommt
nacht r24/r25)
>den Assemlber Code erstellt.
Ah. Suppe.
Das sieht komisch aus:
/* #APP */
; 45 "main.c" 1
sei
; 0 "" 2
/* #NOAPP */
ldi r17,lo8(0)
ldi r28,lo8(1000)
ldi r29,hi8(1000)
.L23:
mov r30,r17
ldi r31,lo8(0)
lsl r30
rol r31
subi r30,lo8(-(c_FreqTable))
sbci r31,hi8(-(c_FreqTable))
ld r24,Z
ldd r25,Z+1
rcall SetFrequency
Der Index ist konstant 0.
Schalte mal -Os aus.
Das ist die Optimierung auf Grösse. Ich weiss nicht wo das Dein Deiner
IDE geht.
[ErinnerungenEinesProgrammiers]
Da hatte ich vor einer Woche schon mal ein Problem das ich aber
ignorieren wollte bis ich die Rechnung schreibe.
[ErinnerungenEinesProgrammiers]
Naja schrieb:
> @ Karl-Heinz>> Das sieht gut aus für Dich? Hmm. Habe ich mich vertan?>> Er lädt doch R30, R31 im Endeffekt mit 0.
Ja, aber nur beim ersten mal, wenn i gleich 0 ist.
Kurz danach wird r17 erhöht
Und nach dem Delay wird L23 angesprungen. Dann ist r17 nicht mehr 0
>Schalte mal -Os aus.
_delay_ms Meldung ignoriert ;)
Geht nicht, kein Unterschied.
Ich habe gerade etwas interessantes getestet:
Ich habe SetFrequency(c_FreqTable[i]); zu SetFrequency(c_FreqTable[0]);
gemacht, doch er gibt immernoch den falschen Ton aus, der Zustand hat
sich also verschlechtert!
Die einzige Änderung, die ich seit dem letzten erfolgreichen Test
gemacht habe, war in SetFrequency die Interrupts auszuschalten.
Ich habe also cli(); und sei(); auskommentiert, da spielt er tatsächlich
den 220Hz Ton ab!
Zugriff über den Index i will er aber immernoch nicht...
gregor schrieb:
> Die einzige Änderung, die ich seit dem letzten erfolgreichen Test> gemacht habe, war in SetFrequency die Interrupts auszuschalten.> Ich habe also cli(); und sei(); auskommentiert,
Das ist kontraproduktiv.
Du brauchst die Sicherung beim Schreiben auf g_PhaseStep. Während des
Schreibvorganges müssen die Interrupts deaktiviert sein, sonst ist nicht
garaniert, dass die ISR auf ein intaktes und in sich stimmiges
g_PhaseStep zugreift.
Karl heinz Buchegger schrieb:
> Das sind doch nie und nimmer 250 Millisekunden
Doch, sind es. Ich hatte nämlich vor ein paar Minuten exakt den selben
Gedanken. ;-)
>Das ist kontraproduktiv.
Das ist mir (inzwischen) klar, es war ja nur ein Test. Der ein seltsames
Ergebnis hatte. Inzwischen hab ich es wieder einkommentiert, nur das
jetzt nicht mal mehr der Hack mit den vielen ifs vom Anfang geht.
Bei der Assemblerdiskussion kann ich leider nicht mitmachen...
gregor schrieb:
> Das ist mir (inzwischen) klar, es war ja nur ein Test. Der ein seltsames> Ergebnis hatte. Inzwischen hab ich es wieder einkommentiert, nur das> jetzt nicht mal mehr der Hack mit den vielen ifs vom Anfang geht.
Könntest du davon bitte nochmal den Code posten?
Stefan Ernst schrieb:
>Könntest du davon bitte nochmal den Code posten?
War mir nicht sicher welchen du wolltest:
Im ZIP sind zwei Ordner: ton_richtig (cli und sei auskommentiert) und
ton_falsch (cli und sei im Code drinne).
Beide Ordner enthalten jeweils den Assembler-Code, C-Code und das
elf-File des jeweiligen Übersetzervorgangs.
Der Vollständigkeit halber:
Der Vektor liegt praktisch sowohl im .text- als auch im .data-Segment.
Schließlich wird er wohl kaum ins RAM teleportiert :-)
So sehr ich auch suche. Ich finde nichts!
Du bist sicher, dass die Berechnung stimmt?
(Nicht dass deine jetzige Frequenz mit dem cli-sei die richtige ist,
und die sich so gut anhörenden ohne cli-sei eigentlich falsch sind und
sich nur durch den cli-sei Fehler richtig anhören)
Hintergrund: Die Berechnung sieht für mich nämlich auf den ersten Blick
seltsam aus. Eine Multiplikation mit 0xffffffff kommt selten genug vor.
Genauso wie das hier
uint8_t Index = (g_Phase >> 24);
uint8_t Value = Index>159?64:0;
Warum 159? (Ok ist nur ein Treshhold Wert aber immerhin)
@ Sven:
Hat das auf das Problem eine Auswirkung?
gregor schrieb:
>Feler mainersaits :)
Wo wir gerade dabei sind, ich hab einen fehler beim Messen der Frequenz
gemacht (ich sag aber nicht was, ist mir zu peinlich). Die Frequenz
liegt im Berech von 667Hz bis 723Hz, die Rechteckswellenfrequenz
schwankt also leicht (Mess-, Programm-, Aufnahmefehler?).
Ich denke aber nicht, dass es etwas erklärt, jedenfalls sagen mir die
Werte nichts besonderes.
Die Berechnung habe ich aus diesem Thread
Beitrag "DDS-Direct Digital Synthesis"
Karl schrieb:
>Nicht dass deine jetzige Frequenz mit dem cli-sei die richtige ist,
Wie oben gesagt, die Frequenz mit cli-sei ist 667Hz oder mehr.
Ich hab jetzt nochmal ohne cli-sei gemessen: 221Hz, das kann ich als
Messfehler verbuchen :P
Hinzu kommt, dass bei cli-sei + if-Hack die Frequenz IMMER gleich
bleibt, sie ändert sich nur, wenn ich das cli-sei weg mache...
Hmm.... hast du einen Vorschlag was ich machen soll? Wenn ich ehrlich
bin finde ich das Projekt viel zu spannend als es in die Tonne zu
treten.
Rewrite wäre mehr als verschmerzlich, weill es ja nur extrem wenig Code
ist, nur ist die Frage, ob der Fehler weg ist?
>Genauso wie das hier> uint8_t Index = (g_Phase >> 24);
Ich verwende aus der Phase nur die oberen 8 bits für den DAC, die
Widerstandsleiter hat halt keine höhrere Auflösung ;)
> Warum 159? (Ok ist nur ein Treshhold Wert aber immerhin)
Das ist vom Spielen mit Tastverhältnissen übrig. Ursprünglich hatte ich
da 127, dann 32 und dann 159. Habs aber nicht mehr geändert :) Noch
früher habe ich da eine Sägezahnwelle ausgegeben. Da vermute ich keinen
Fehler.
Simon K. schrieb:
>Und du verwendest auch einen ATmega8 ja?
Japp, habe nix anderes (außer einem ATmega644, der ist aber noch nicht
ausprobiert worden).
>Warum eigentlich avr-g++ fürs linken? Nehm da doch auch mal den avr-gcc.
Hm.. bei Code::Blocks war avr-g++ als Linker eingetragen, habe es in
avr-gcc geändert und nochmal ein vorher nicht funktionierendes Programm
compiliert. Leider geht es immernoch nicht.
Trotzdem danke für den Hinweis
@Jonathan
Das PORTB = ~PORTB hatte ich nur eingefügt um zu schauen, ob beim langen
if-Block ein ungültiger Wert auftritt.
Aber nun eine freudige Ankündigung: DO NOT WANT!!!!!!!
Ich habe das Problem gelöst. Tatsächlich lag das Problem in
SetFrequency, ich hab mir die "Formeln" die ich übers DDS gefunden hatte
noch mal angeschaut .. und keinen unterschied gefunden.
Ich hab aber den 32bit Phasenakkumulator durch einen 16bit Akku ersetzt,
dementsprechend muss ich mit 0xffff mutliplizieren. Und was soll man
sagen: so geht es!
Ich habe aber keine Erklärung, warum es mit den größeren Zahlen nicht
funktioniert hat, vor allem warum es, zum Teil, mit den konstanten
Indexangaben funktioniert hat...
Also, für alle die es interessiert, hier der komplette, funktionierende
Code:
Sorry wenn ich ein bisschen spamme, aber das muss sein:
Ich möchte mich ganz arg bei allen bedanken, die versucht haben mir zu
helfen und ihre Zeit dafür geopfert haben und ganz besonders großen Dank
an Karl, dass er mich auf die richtige Spur geführt hat!!