Forum: Mikrocontroller und Digitale Elektronik AVR64DD28 Clock Source ändern


von Max W. (crackerlino)


Lesenswert?

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

: Bearbeitet durch User
von S. L. (sldt)


Lesenswert?

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.

von S. L. (sldt)


Lesenswert?

In C gibt es die Funktion '_PROTECTED_WRITE', siehe
Beitrag "Re: AVR ATtiny Stromaufnahme"

von Max W. (crackerlino)


Lesenswert?

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

von S. L. (sldt)


Lesenswert?

> Woher weiß ich denn, dass diese Funktion existiert?

Kann ich auch nicht sagen, ich bekomme C-Spezifisches immer nur am Rande 
mit.

von Veit D. (devil-elec)


Lesenswert?

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

: Bearbeitet durch User
von S. L. (sldt)


Lesenswert?

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.

von Veit D. (devil-elec)


Lesenswert?

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

von S. L. (sldt)


Lesenswert?

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.

von Georg M. (g_m)


Lesenswert?

> FREQSEL

1.9.119 (2021-07-20)
Renamed bitfield in CLKCTRL.OSCHFCTRLA from FREQSEL to FRQSEL.

https://packs.download.microchip.com/

von Veit D. (devil-elec)


Lesenswert?

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.

von S. L. (sldt)


Lesenswert?

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.

von Veit D. (devil-elec)


Lesenswert?

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.

von Georg M. (g_m)


Lesenswert?

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?

https://ww1.microchip.com/downloads/aemDocuments/documents/MCU08/ProductDocuments/DataSheets/AVR64DD32-28-Prelim-DataSheet-DS40002315B.pdf

von Veit D. (devil-elec)


Lesenswert?

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.

von Veit D. (devil-elec)


Lesenswert?

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.

: Bearbeitet durch User
von S. L. (sldt)


Lesenswert?

> 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.

von Veit D. (devil-elec)


Lesenswert?

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.

von Veit D. (devil-elec)


Lesenswert?

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.  :-)

von S. L. (sldt)


Angehängte Dateien:

Lesenswert?

> 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.

von Veit D. (devil-elec)


Lesenswert?

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/

von Randy B. (rbrecker)


Lesenswert?

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.

von C-hater (c-hater)


Lesenswert?

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.

von Randy B. (rbrecker)


Lesenswert?

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???

von Max W. (crackerlino)


Lesenswert?

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!

von Georg M. (g_m)


Lesenswert?

> 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

von Randy B. (rbrecker)


Lesenswert?

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!

: Bearbeitet durch User
von C-hater (c-hater)


Lesenswert?

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...

von Georg M. (g_m)


Lesenswert?

> 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.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.