ich versuche mich gerade durch den AVR64 zu fuchsen und es klappt mehr oder minder ganz okay. Ich versuche die Clockfrequenz zu ändern (von den urspr. 4 MHz auf 16 MHz) und muss dafür das ccp Register disablen. Jedoch finde ich leider nirgends, wie das funktioniert. In älteren Codes wird einfach CCP beschrieben. Das funktioniert leider nicht. Und CPU.CCP gibt es leider auch nicht, obwohl es in der "ioavr64dd28.h" erwähnt wird:
/* CPU.CCP bit masks and bit positions */
Wo liegt mein Fehler? Und wieso gibt es verschiedene Versionen, von AVR-Code?
Also für einen AVR128Dx28 und in Assembler sieht es so aus: puti
CPU_CCP,CPU_CCP_IOREG_gc
puti CLKCTRL_OSCHFCTRLA,($6<<CLKCTRL_FREQSEL_gp) ; B:32, A:28, 9:24,
8:20, 7:16, 6:12, 5:8, 4:-, 3:4
In C müssen wohl die '_' in den Registernamen durch '.' ersetzt werden.
Wie gesagt, CPU.CPP existiert bei mir zumindest nicht.
In C gibt es die Funktion '_PROTECTED_WRITE', siehe
Beitrag "Re: AVR ATtiny Stromaufnahme"
DANKE! Ich habe nur 'PROTECTED_WRITE' ausprobiert, aber nirgends gefunden. Woher weiß ich denn, dass diese Funktion existiert? Ich habe nichts im Datenblatt des AVR64DD28 gefunden.
wird bei mir für einen AVR128DB28 übersetzt und läuft, an PA7 messe ich 3.33 MHz. Die Verwendung von '_PROTECTED_WRITE' ist natürlich bequemer und auch narrensicher.
Das Makro _PROTECTED_WRITE gibt es bei den AVR Dx nicht. Das wurde im Headerfile vergessen. Müßte man selbst nachrüsten.
Aus einem xmega Header rausgezogen.
das '_' oder '.' hängt mit den Defines im Headefile zusammen.
So richtig sauber erklären kann ich es auch nicht aber ich versuche es. Es hängt mit dem Aufbau des Headerfiles zusammen ob es ein struct gibt oder nicht.
Bsp. AVR128DB48
1
#define DAC0_DATAH _SFR_MEM8(0x06A3)
Hier ist DAC0_DATAH direkt als Registeradresse definiert.
Mit DAC0.DATAH läuft ein Makro ab der die Adresse aus Basis und Offset zusammensetzt.
Wie ich das anders erklären kann weiß ich im Moment leider nicht. Sonst müßte das Headerfile "zerlegen".
In dem Fall CPU_CPP hier liegt der Fall allerdings anders. Es gibt es kein Register namens CPU mit Basisadresse im Headerfile. Das heißt mit Namen wirklich CPU_CCP. Deswegen ist CPU.CPP nicht möglich.
Aktuell habe ich aus dem Thread hier oder für den Thread hier nichts getestet. Habe das aus meinem Projekten schnell rausgezogen.
Im AVR64DD28 Manual auf Seite 97 steht das für CPU_CPP der "Key" IOREG zuständig ist. Also die Gruppenbitmaske CCP_IOREG_gc wie du schon richtig geschrieben hast.
Übrigens: leichte Irritation hat, zumindest bei mir, der Betreff mit dem "Clock Source" verursacht - wenn ich es richtig verstanden habe, so möchte Max W. diese eben nicht ändern, so lediglich die Frequenz.
solche Änderungen gab es öfters und hat sich langsam beruhigt. Manches war aus meiner Sicht Unsinnig und manches gut. Aktuell ist 2.2.253. Man könnte noch viel mehr Aufräumen und konsequenter mit den Namen sein. Beim Timer TCA bspw.. Ob die Unterscheidung SPLIT und SINGLE immer notwendig ist weiß ich nicht. Oder ob es schlau ist wie es ist. Die Prescaler Defines sind ja immer gleich. Aber das ist ein anderes Thema.
Im AVR64DD28 Manual auf Seite 97 steht das für CPU_CPP
Ich kann das "CPU_CPP" nirgendwo finden.
Vielleicht muss ich zu Fielmann?
Hallo,
nicht im Manual, im Headerfile. Nur was im Headerfile steht kann man nutzen. :-) Im Manual Seite 97 steht welche CPU Register Protected sind wofür man es erst "freischalten" muss.
Bei neuen uC muss man flexibel bleiben, weil manches im Manual noch nicht stimmt und deswegen auch "Preliminary" ist. Beim DD werden wohl auch noch paar Änderungen im Headerfile und irgendwann im Manual kommen. Das Update vom Manual vom DB hat ca. 2 Jahre gedauert.
ist der TO noch da? Wenn du reinkommen möchtest empfehle ich dir die TBxxxx AppNotes, auch als Getting Startet bezeichnet. Da die Controller alle ähnlich aufgebaut sind kann man auch AppNotes der Verwandten nehmen und muss dann Kleinigkeiten ändern. Das Namenskaos wie hier im Thread ist nur am Anfang "Kaos", weil ggf. ungewohnt anders. Wenn man drin steckt wirkt es aufgeräumter. Da steckt wirklich eine Logik dahinter mit den Basisadressen und Offsets.
wenn Max nur den Prescaler abschalten möchte reicht ...
Dann hat er ja wieder die 4 MHz, von denen er aber wegwill.
Hier nochmals mein Programm (für einen AVR128DB28), diesmal ganz korrekt
(ich bin heute abend etwas schwerfällig):
Und ich springe "zu viel" zwischen den Manuals hin und her. ;-) Der AVRDD läuft also mit Default 4MHz. Wußte ich noch nicht. Hatte nur Prescaler im Kopf. Deine Konfig passt. :-)
noch ein Tipp für die leidigen Microchip Manuals. Ein richtig guter PDF Konvertierer bzw. "Freischalter". Einstellungen können so bleiben. Nur wenn man mehrere pdf übergibt sollte man den Modus auf Einzeln ändern.
https://online2pdf.com/
das '_' oder '.' hängt mit den Defines im Headefile zusammen.
So richtig sauber erklären kann ich es auch nicht aber ich versuche es.
Echt?
Einmal sind es volatile uint8_t (wie VPORTA_DIR) und einmal sind es Aggregate (struct) (wie VPORTA). In C ist es definiert, das die Elemente eines Aggregats aufsteigend im Speicher platziert werden. Daher reicht es aus, wenn man die Startadresse auf bspw. VPORT_t castet, dann sind alle Elemente automatisch an der richtigen Adresse. Das nennt sich structure-mapping.
Hier mal das Beispiel mit VPORT aus der entsprechenden Header-Datei.
DANKE! Ich habe nur 'PROTECTED_WRITE' ausprobiert, aber nirgends
gefunden. Woher weiß ich denn, dass diese Funktion existiert? Ich habe
nichts im Datenblatt des AVR64DD28 gefunden.
Das steht auch nicht im Datenblatt. Es handelt sich um eine Support-Funktion, die im Rahmen der gcc-Toolchain mitgeliefert wird.
#include <avr/xmega.h"
macht sie verfügbar.
Übrigens gibt es dort auch noch eine zweite Funktion für den Zugriff auf "SPM"-geschützte IO-Register (_PROTECTED_WRITE_SPM).
Das ist leider nötig, weil es Atmel/MC nicht für nötig befunden haben, in den Device-Headern mitzuteilen, ob und wie der Zugriff auf ein IO-Register geschützt ist. So bleibt es dem Programmierer überlassen, dies anhand des DB selber herauszufinden und dann ggf. die passende Funktion zu verwenden.
Das ist leider nötig, weil es Atmel/MC nicht für nötig befunden haben,
in den Device-Headern mitzuteilen, ob und wie der Zugriff auf ein
IO-Register geschützt ist. So bleibt es dem Programmierer überlassen,
dies anhand des DB selber herauszufinden und dann ggf. die passende
Funktion zu verwenden.
Och. lieber C-hater: Du bist doch sonst immer derjenige, der auf das Studium der DBer hinweist. Dort steht es doch klar drin. Und die Supportfunktion braucht es gar nicht. Man, was ist mit Dir los???
Übrigens: leichte Irritation hat, zumindest bei mir, der Betreff mit dem
"Clock Source" verursacht - wenn ich es richtig verstanden habe, so
möchte Max W. diese eben nicht ändern, so lediglich die Frequenz.
Richtig, ich dachte, ich müsse zuerst auf eine neue Clock umstellen, um die alte zu konfigurieren, war offenbar nicht notwendig.
wenn Max nur den Prescaler abschalten möchte reicht ...
Dann hat er ja wieder die 4 MHz, von denen er aber wegwill.
Hier nochmals mein Programm (für einen AVR128DB28), diesmal ganz korrekt
(ich bin heute abend etwas schwerfällig):#include <avr/io.h>
int main(void)
{
CPU_CCP = CCP_IOREG_gc;
CLKCTRL.OSCHFCTRLA = 0b00011100; // 16 MHz output
VPORTA_DIR = 0x80;
while (1) VPORTA_IN = 0x80;
}
Auf PA7 2.67 MHz, mal 6 ergibt die gewünschten 16 MHz.
Ganz lieben dank! Hat sofort funktioniert. Und dass man das CCP Register mit CPU_CCP beschreiben kann ist sehr gut zu wissen. Ich habe leider gedacht, dass ich "CPU.CCP" wie es in der Header oder im Datenblatt beschreiben müsste.
DANKE! Ich habe nur 'PROTECTED_WRITE' ausprobiert, aber nirgends
gefunden. Woher weiß ich denn, dass diese Funktion existiert? Ich habe
nichts im Datenblatt des AVR64DD28 gefunden.
Das steht auch nicht im Datenblatt. Es handelt sich um eine
Support-Funktion, die im Rahmen der gcc-Toolchain mitgeliefert wird.
#include <avr/xmega.h"
macht sie verfügbar.
Übrigens gibt es dort auch noch eine zweite Funktion für den Zugriff auf
"SPM"-geschützte IO-Register (_PROTECTED_WRITE_SPM).
Das ist leider nötig, weil es Atmel/MC nicht für nötig befunden haben,
in den Device-Headern mitzuteilen, ob und wie der Zugriff auf ein
IO-Register geschützt ist. So bleibt es dem Programmierer überlassen,
dies anhand des DB selber herauszufinden und dann ggf. die passende
Funktion zu verwenden.
Also mein größeres Problem war, dass "CPU.CCP" im Datenblatt und im Header erwähnt werden, aber nicht existieren. Klar gibt es das CPU_CCP Register als #define, aber ich hatte ehrlich gesagt nicht auf dem Schirm, diese dafür zu benutzen. Wieder was gelernt.
Ganz lieben Dank für die ganzen Infos hier in dem Post. Hab' viel über den AVR gelernt!
Och. lieber C-hater: Du bist doch sonst immer derjenige, der auf das
Studium der DBer hinweist.
Natürlich. Muss ich mich dafür schämen oder was?
Und die
Supportfunktion braucht es gar nicht.
Natürlich braucht man die nicht. Macht die Sache nur ein wenig komfortabler. Richtig komfortabel würde es aber eben nur dadurch werden, dass man sich überhaupt nicht darum kümmern müßte. Wenn also der Compiler automagisch alle diese write-protections adäquat behandeln würde.
Das wäre machbar, wenn halt in den Device-Headern des Herstellers die entsprechenden Informationen hinterlegt wären. Sind sie aber halt leider nicht. Die stehen nur im DB.
Im Übrigen würde ich es auch als Asm-Programmierer zu schätzen wissen, wenn ich das den Headern entnehmen könnte. Würde ich meine UIN- und UOUT-Macros ein wenig aufpeppen können und denselben Komfort erreichen...