Hallo liebes mikrocontroller.net-Forum,
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?
Liebe Grüße und lieben Dank im Voraus
MW
Also für einen AVR128Dx28 und in Assembler sieht es so aus: 1 | puti CPU_CCP,CPU_CCP_IOREG_gc
| 2 | 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.
In C gibt es die Funktion '_PROTECTED_WRITE', siehe
Beitrag "Re: AVR ATtiny Stromaufnahme"
S. L. schrieb:
> 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.
S. L. schrieb:
> 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.
Liebe Grüße und nochmals danke!
MW
> Woher weiß ich denn, dass diese Funktion existiert?
Kann ich auch nicht sagen, ich bekomme C-Spezifisches immer nur am Rande
mit.
Hallo,
Bsp. 1 | CPU_CCP = CCP_IOREG_gc; // write access for four CPU instructions
| 2 | CLKCTRL_MCLKCTRLA = CLKCTRL_CLKSEL_OSC20M_gc; // select Source before prescaler set
|
Keine Ahnung, ob Ihnen das irgendetwas bringt, aber 1 | #include <avr/io.h>
| 2 | int main(void)
| 3 | {
| 4 | #include <avr/io.h>
| 5 | int main(void)
| 6 | {
| 7 | CPU_CCP = CCP_IOREG_gc;
| 8 | CLKCTRL.OSCHFCTRLA = (8<<CLKCTRL_FREQSEL_gp); // 9:24, 8:20, 7:16, 6:12, 5:8, 4:-, 3:4
| 9 | VPORTA_DIR = 0x80;
| 10 | while (1) VPORTA_IN = 0x80;
| 11 | }
| 12 | // _PROTECTED_WRITE(CLKCTRL.OSCHFCTRLA, (8<<CLKCTRL_FREQSEL_gp));
|
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.
Hallo,
in meinen Notizen finde ich folgendes 1 | CPU_CCP = CCP_IOREG_gc; // IO Register Protection
| 2 | oder
| 3 | CPU_CCP = CCP_SPM_gc; // SPM Instruction Protection
|
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. 1 | #ifndef _PROTECTED_WRITE_SPM
| 2 | #define _PROTECTED_WRITE_SPM(reg, value) \
| 3 | __asm__ __volatile__("out %[ccp], %[ccp_spm_mask]" "\n\t" \
| 4 | "sts %[ioreg], %[val]" \
| 5 | : \
| 6 | : [ccp] "I" (_SFR_IO_ADDR(CCP)), \
| 7 | [ccp_spm_mask] "d" ((uint8_t)CCP_SPM_gc), \
| 8 | [ioreg] "n" (_SFR_MEM_ADDR(reg)), \
| 9 | [val] "r" ((uint8_t)value))
| 10 | #endif
|
Ah, hallo Veit Devil!
Können Sie mir vielleicht sagen, warum Registernamen in C mal mit '.'
und mal mit '_' geschrieben werden?
Und eben fällt mir auf - auf welchem Controller läuft Ihr
Beispielprogramm?
> Das Makro _PROTECTED_WRITE gibt es bei den AVR Dx nicht.
Also wie geschrieben, bei mir geht das, warum auch immer.
> FREQSEL
1.9.119 (2021-07-20)
Renamed bitfield in CLKCTRL.OSCHFCTRLA from FREQSEL to FRQSEL.
https://packs.download.microchip.com/
Hallo,
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.
1 | AVR64DD28:
| 2 |
| 3 | /* Ungrouped common registers */
| 4 | #define CCP _SFR_MEM8(0x0034) /* Configuration Change Protection */
| 5 | #define SP _SFR_MEM16(0x003D) /* Stack Pointer */
| 6 | #define SPL _SFR_MEM8(0x003D) /* Stack Pointer Low */
| 7 | #define SPH _SFR_MEM8(0x003E) /* Stack Pointer High */
| 8 | #define SREG _SFR_MEM8(0x003F) /* Status Register */
| 9 |
| 10 | Die sind im Headerfile sogar doppelt definiert :-)
| 11 |
| 12 | /* CPU - CPU */
| 13 | #define CPU_CCP _SFR_MEM8(0x0034)
| 14 | #define CPU_SP _SFR_MEM16(0x003D)
| 15 | #define CPU_SPL _SFR_MEM8(0x003D)
| 16 | #define CPU_SPH _SFR_MEM8(0x003E)
| 17 | #define CPU_SREG _SFR_MEM8(0x003F)
|
Wegen dem Protected Makro. Ich musste mir das einmal woher holen. :-)
Beitrag "xmega.h - _PROTECTED_WRITE_SPM"
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.
Danke, Veit Devil, für die Erklärung.
Ü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.
Georg M. schrieb:
>> FREQSEL
>
> 1.9.119 (2021-07-20)
> Renamed bitfield in CLKCTRL.OSCHFCTRLA from FREQSEL to FRQSEL.
>
> https://packs.download.microchip.com/
Hallo,
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.
Hallo,
wenn Max nur den Prescaler abschalten möchte reicht 1 | CPU_CCP = CCP_IOREG_gc;
| 2 | CLKCTRL_MCLKCTRLB = 0; // no prescaler, disable prescaler
|
Danach hängt es nur von der Taktquelle ab die im OSCHFCTRLA Register
konfiguriert wird. Seite 105. Defines im Headerfile Zeile 660.
Meine Zeile von 18:31 Uhr ist für den AVR DD falsch gewesen.
Georg M. schrieb:
> Veit D. schrieb:
>> 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.
> 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): 1 | #include <avr/io.h>
| 2 | int main(void)
| 3 | {
| 4 | CPU_CCP = CCP_IOREG_gc;
| 5 | CLKCTRL.OSCHFCTRLA = 0b00011100; // 16 MHz output
| 6 |
| 7 | VPORTA_DIR = 0x80;
| 8 | while (1) VPORTA_IN = 0x80;
| 9 | }
|
Auf PA7 2.67 MHz, mal 6 ergibt die gewünschten 16 MHz.
Hallo,
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.
S. L. schrieb:
>> 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. :-)
> Der AVRDD läuft also mit Default 4MHz.
Klar - beachten Sie den Reset-Wert von 0x0C, der schreibt eine 3 nach
FRQSEL; und am Ende der Zeile steht es nochmal: 'default'.
Einen schönen Abend allerseits, mir langt's für heute.
Hallo,
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/
S. L. schrieb:
> Können Sie mir vielleicht sagen, warum Registernamen in C mal mit '.'
> und mal mit '_' geschrieben werden?
Veit D. schrieb:
> 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.
1 | /* Virtual Ports */
| 2 | typedef struct VPORT_struct
| 3 | {
| 4 | register8_t DIR; /* Data Direction */
| 5 | register8_t OUT; /* Output Value */
| 6 | register8_t IN; /* Input Value */
| 7 | register8_t INTFLAGS; /* Interrupt Flags */
| 8 | } VPORT_t;
| 9 |
| 10 | #define VPORTA (*(VPORT_t *) 0x0000) /* Virtual Ports */
| 11 |
| 12 | /* VPORT (VPORTA) - Virtual Ports */
| 13 | #define VPORTA_DIR _SFR_MEM8(0x0000)
| 14 | #define VPORTA_OUT _SFR_MEM8(0x0001)
| 15 | #define VPORTA_IN _SFR_MEM8(0x0002)
| 16 | #define VPORTA_INTFLAGS _SFR_MEM8(0x0003)
|
Man sieht hier schön die entsprechend aufsteigende Adressvergabe.
Max W. schrieb:
> 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.
C-hater schrieb:
> 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???
S. L. schrieb:
> Danke, Veit Devil, für die Erklärung.
>
> Ü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.
Veit D. schrieb:
> CP
S. L. schrieb:
>> 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.
C-hater schrieb:
> Max W. schrieb:
>
>> 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!
> CPU.CCP
"In the Datasheet "CPU.CCP" has to be set to "IOREG", respectevely to
"0xD8" before enabling the Watchdog. For me just "CPU_CCP" worked. So
instead of the dot, I had to use the underscore. Is that a mistake in
the Datasheet?"
https://forum.arduino.cc/t/arduino-uno-wifi-rev-2-atmega4809-watchdog-always-restarts-whole-system/563521
"It seems like they forgot to add it into .h file."
https://electronics.stackexchange.com/questions/666241/why-is-nothing-happening-on-my-clkout-pin-despite-the-rtc-working-fine
Georg M. schrieb:
> "It seems like they forgot to add it into .h file."
Es gibt im Header kein CPU_t, keine Struktur. Daher kann auch der
member-access-operator nicht angewendet werden.
Es gibt einfach einen/zwei Schreibfehler in einem Kommentar des Headers:
1 | /* CPU - CPU */
| 2 | /* CPU.CCP bit masks and bit positions */
| 3 |
| 4 | /* CPU.SREG bit masks and bit positions */
|
Kommentare sind halt Scheiße!
Randy B. schrieb:
> 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...
> Clock Source ändern
Apropos Clock Source ändern: nach dem Source-Wechsel - abwarten bevor es
weiter gehen kann.
1 | _PROTECTED_WRITE(CLKCTRL.MCLKCTRLA, CLKCTRL_CLKSEL_OSC32K_gc); // select
| 2 | while(CLKCTRL.MCLKSTATUS & CLKCTRL_SOSC_bm){} // wait
|
SOSC: Main Clock Oscillator Changing
The clock source for CLK_MAIN is undergoing a switch and will change as
soon as the new source is stable.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
|