AVR64DD28 Clock Source ändern

#7428386
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

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

#7428408
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

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

#7428544
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
#7428547
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.

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

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

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

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

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

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

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

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

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

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

#7428825
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!

#7428833
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

#7428838
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!

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

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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren