Forum: Mikrocontroller und Digitale Elektronik Atmel SAM Frage


von Felix L. (flex)


Lesenswert?

Hallo,

ich habe mir gerade folgendes Beispiel zum Atmel SAM D10 angeschaut:
1
#include "sam.h"
2
3
int main(void)
4
{
5
  SystemInit();
6
7
  PORT->Group[0].DIRSET.reg = PORT_PA09;
8
9
  while(1)
10
  {
11
    if (PORT->Group[0].IN.reg & PORT_PA25;
12
    {
13
      PORT->Group[0].OUTSET.reg = PORT_PA09;
14
    }
15
    else
16
    {
17
      PORT->Group[0].OUTCLR.reg = PORT_PA09;
18
    }
19
  }
20
}

Was ich hier nicht verstehe, ist das setzen der Ausgangsregister(PA09) 
sowie das auslesen des Tasters (PA25). Was bedeutet dieses "Group[0]"? 
Gibt es noch eine andere Schreibweise?

Gruß
Felix

: Bearbeitet durch User
von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Felix L. schrieb:
> Was bedeutet dieses "Group[0]"?

Der PIO-Modul der neuen SAMs hat nur noch eine Instanz, und die
einzelnen Ports (A, B, C) sind dann in dieser Gruppe vertreten.

> Gibt es noch eine andere Schreibweise?

Zuweilen habe ich schon sowas im Code gesehen:
1
#define PORTA PORT->Group[0]
2
#define PORTB PORT->Group[1]
3

4
   if (PORTA.IN.reg & PORT_PA25)

von Felix L. (flex)


Lesenswert?

Danke Jörg für die Antwort.

Also bleibt es mir überlassen, ob ich Group[1],[2],[...] verwende?

Gruß

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Felix L. schrieb:
> Also bleibt es mir überlassen, ob ich Group[1],[2],[...] verwende?

Mit den Standard-Headerdateien hast du keine andere Wahl, als sie zu
verwenden. ;-)

Die gezeigten Definitionen für PORTA etc. müsstest du dir selbst
irgendwo hinlegen.

p.s.: Natürlich fängt die Zählung bei 0 an, also PORT A ist
PORT->Group[0] (du hast bei 1 angefangen).

: Bearbeitet durch Moderator
von Rudolph (Gast)


Lesenswert?

Ich habe vorhin mal damit auf meinem SAMD20 Board gespielt, einfach nur 
mal um direkten Register-Zugriff zu testen.

Und spielt soweit, also nicht das Beispiel, sondern blinken lassen der 
LED auf dem SAMD20 xplained.

Nun mal eine Frage, woher kommt so ein Konstrukt wie 
"PORT->Group[0].DIRSET.reg" - ist das CMSIS?
Oder ist das was eigenes von Atmel?

Ist das auch irgendwo dokumentiert?
Zumindest im Datenblatt vom SAMD20 taucht sowas wie "port->group" oder 
"port->" überhaupt nicht auf.
Wenn man nach dem Datenblatt geht und das so machen würde wie bei den 
AVRs dann müsste das Register einfach nur DIRSET heissen.

Also "DIRSET = 0x00000000" oder so sollte nach Datenblatt funktionieren 
- was es aber natürlich nicht tut.
Und es gibt davon ja auch noch mehrere.

Wie soll man auf sowas kommen wenn das nichtmal im Datenblatt steht?

von Felix L. (flex)


Lesenswert?

Rudolph schrieb:
> Wie soll man auf sowas kommen wenn das nichtmal im Datenblatt steht?

Genau dieses Problem habe ich auch.

Atmel hat vor einigen Tagen Tutorials in YouTube hochgeladen:
https://www.youtube.com/user/AtmelCorporation

Gruß

: Bearbeitet durch User
von Rudolph (Gast)


Lesenswert?

Felix L. schrieb:
> Atmel hat vor einigen Tagen Tutorials in YouTube hochgeladen:

Das hilft, YouTube ist bei mir auf der Arbeit gesperrt. :-)

von Felix L. (flex)


Lesenswert?

Rudolph schrieb:
> Felix L. schrieb:
>> Atmel hat vor einigen Tagen Tutorials in YouTube hochgeladen:
>
> Das hilft, YouTube ist bei mir auf der Arbeit gesperrt. :-)

Das ist dann natürlich schlecht. Ich finde Atmel macht gute Dev Boards 
und viel Werbung aber Informationen zur Programmierung (von SAM) findet 
man so gut wie gar nicht. Oder kennt jemand ein Tutorial?

Gruß

Nachtrag:
Habe hier ein PDF Dokument gefunden indem die Funktionen des D20 sowie 
Codebeispiele gezeigt werden:
http://www.atmel.com/images/atmel-42139-asf-manual-sam-d20_application-note_at03665.pdf

: Bearbeitet durch User
von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Rudolph schrieb:

> Nun mal eine Frage, woher kommt so ein Konstrukt wie
> "PORT->Group[0].DIRSET.reg" - ist das CMSIS?

Nö, die Peripherals (bis auf ein paar zentrale Dinge wie NVIC, SysTick
und so) werden von ARM nicht koordiniert.  Da kocht jeder Hersteller
sein eigenes Süppchen.  Auf den älteren Atmel-ARMs sahen die ja auch
noch anders aus (aber meiner Meinung nach viel angestaubter).

> Wenn man nach dem Datenblatt geht und das so machen würde wie bei den
> AVRs dann müsste das Register einfach nur DIRSET heissen.

Nein, selbst bei Xmega gab es da schon immer den Namen des Moduls
und die Instanznummer davor.  Die Register im Datenblatt beschreiben
dann nur noch den Offset innerhalb der Instanz.  Beispiel:
1
  /* PF3 is output for VLCD charge pump (PWM on OC0D) */
2
  PORTF.DIRSET = _BV(3);
3
  TCF0.CTRLA = TC_CLKSEL_DIV1_gc; /* TCF0 @ 16 MHz */
4
  TCF0.CTRLB = TC0_CCDEN_bm | TC_WGMODE_SS_gc;
5
  TCF0.PER = 256;               /* 62.5 kHz PWM frequency */
6
  TCF0.CCD = 4;                 /* -> VLCD abt. -1.3 V */

Allerdings heißt PORTF eben dort noch PORTF und nicht PORT->Group[5].

> Wie soll man auf sowas kommen wenn das nichtmal im Datenblatt steht?

Steht schon, aber bei den Ports zugegebenermaßen ziemlich
verklausuliert:
1
The I/O pins are organized in groups with up to 32 pins. Group 0 consists 
2
of the PA pins, group 1 the PB pins, etc. Each group has its own set of 
3
registers. For example, the register address offset for the Data Direction 
4
(DIR) register for group 0 (PA00 to PA31) is 0x00, while the register 
5
address offset for the DIR register for group 1 (PB00 to PB31) is 0x80.

Verwunderlich ist eigentlich nur das System PORT->Group, während bei
allen anderen Peripherals (auch im SAMDxx) die Instanzen jeweils eine
eigene Basisadresse bilden, also TC0->xxx oder SERCOM5->xxx.

Es gibt auch unterhalb von PORT nichts außer den Gruppen selbst, aber
es gibt eben nur eine einzige Instanz von PORT.

Wie ich schon schrieb, wenn es dir logischer erscheint, dann verziere
deine Projekte global mit sowas:
1
#define PORTA PORT->Group[0]
2
#define PORTB PORT->Group[1]
3
#define PORTB PORT->Group[2]

und benutze PORT.DIRSET etc.  Dann hast du so ziemlich das gleiche,
wie es bspw. auch bei den Xmegas war.

Neu ist für jedes Register die Union, die einerseits einen direkten
Zugriff auf alle Bits gestattet (über .reg), andererseits einzelne
Bits registersicher per Namen ansprechen lässt (.bit.xxx).  Für
die Parallelports ist das egal, aber für die Registerbits in den
diversen Steuerregistern ist es ein Segen, weil man jetzt einen
Compilerfehler bekommt, wenn man versucht, ein namentlich benanntes
Bit in einem falschen Register zu behandeln.  Das hatten wir beim
ATmega128RFA1 auch versucht einzuführen, aber hatte sich damals nicht
ernsthaft durchgesetzt (und beim ATmega256RFR2 wurde das Feature
in der Atmel-eigenen Toolchain demoliert, obwohl es in der avr-libc
noch drin ist).

von Felix L. (flex)


Lesenswert?

Danke für die Antwort. Ich werde mal schauen wie es mit anderen 
Peripheriemodulen aussieht.

Gruß

von Rudolph (Gast)


Lesenswert?

Jörg Wunsch schrieb:
>> Wenn man nach dem Datenblatt geht und das so machen würde wie bei den
>> AVRs dann müsste das Register einfach nur DIRSET heissen.
>
> Nein, selbst bei Xmega gab es da schon immer den Namen des Moduls
> und die Instanznummer davor.

Die XMega habe ich mir nie ernsthaft angesehen weil es da bis heute 
keinen mit CAN gibt.

Ist das im Datenblatt der XMega wenigstens beschrieben wie man den 
Register-Zugriff machen soll?

> Allerdings heißt PORTF eben dort noch PORTF und nicht PORT->Group[5].
>
>> Wie soll man auf sowas kommen wenn das nichtmal im Datenblatt steht?
>
> Steht schon, aber bei den Ports zugegebenermaßen ziemlich
> verklausuliert:

Das nützt ja garnichts, was fehlt ist jeder Hinweis auf die zu 
benutzende Syntax.

Ein paar einsame Zeilen Code-Beispiele ich C würden das Datenblatt nicht 
schlechter machen.

Auf der Embedded World habe ich am Atmel Stand jemanden dazu 
angesprochen wie man denn mit dem SAMD20 Register-Zugriffe machen soll.
Der war ziemlich überrascht und hat mir das kurz gezeigt, Dokumentation 
konnte er aber auch keine aus dem Hut ziehen.

Und Beispiel-Programme für das SAMD20 Xplained hatte ich nur mit dem AFS 
gesehen - die Arduino-Abstraktion finde ich aber grausam.

von Bernd K. (prof7bit)


Lesenswert?

Rudolph schrieb:
> Das nützt ja garnichts, was fehlt ist jeder Hinweis auf die zu
> benutzende Syntax.

Die Syntax ist C.

Die obigen Strukturen und Konstanten sind in den Headerfiles deklariert 
(wirf da mal einen Blick rein, dann wird vieles klarer), die eigentliche 
Funktion der Register, also welche Bits du wo setzen musst um was zu 
bewirken findest Du alles im Datenblatt bzw. Reference manual.

Sobald Du das System einmal durchschaut hast hilft auch schon das 
Autocomplete Deiner IDE die genauen Namen der Register zu finden und die 
Namen der benötigten Bitmasken auch wenn Du als Ausgangspunkt nur die 
Bezeichnungen aus dem Datenblatt hast.

: Bearbeitet durch User
von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Rudolph schrieb:

> Ist das im Datenblatt der XMega wenigstens beschrieben wie man den
> Register-Zugriff machen soll?

Nö, allerdings gab's da wohl noch eine Appnote "Getting started
writing C code".

> Ein paar einsame Zeilen Code-Beispiele ich C würden das Datenblatt nicht
> schlechter machen.

Ja.

> Und Beispiel-Programme für das SAMD20 Xplained hatte ich nur mit dem AFS
> gesehen - die Arduino-Abstraktion finde ich aber grausam.

Wenn's denn wenigstens eine Abstraktion wäre, die genauso gut wie
Arduino ist.  Kannste aber vergessen, dass du vielleicht einen SAM3S
(für das es gerade mal ein Beispiel gab) schnell durch einen SAM4E
ersetzen kannst – so weit geht die Abstraktion nicht.

Was übrig bleibt bei ASF ist ein nutzlos aufgeblähtes API, bei dem
man zum Setzen eines Bits in einem Register einen kompletten
Funktionsaufruf verplempert, aber dennoch keine weitere Erläuterung,
welche Bits man denn für einen bestimmten Zweck nun setzen muss.
Diese Art von „Abstraktion“ ist bestimmt nicht das, was der Welt noch
gefehlt hätte … ganz davon abgesehen, dass der Salat sowieso bloß unter
Windows zu haben ist.

von Rudolph (Gast)


Lesenswert?

Bernd K. schrieb:
> Die obigen Strukturen und Konstanten sind in den Headerfiles deklariert
> (wirf da mal einen Blick rein, dann wird vieles klarer), die eigentliche
> Funktion der Register, also welche Bits du wo setzen musst um was zu
> bewirken findest Du alles im Datenblatt bzw. Reference manual.

Ja nee, eben nicht.

Was fehlt ist jeglicher Hinweis, dass man sich das
zu "PORT->Group[0].DIRSET.reg" zusammen puzzeln soll wenn man das nur 
als DIRSET im Datenblatt beschriebene Register von PORTA beschreiben 
möchte.

Es ist völlig egal wie einfach und offensichtlich das ist wenn man das 
erstmal verstanden hat, wenn es keine Grundlage gibt auf der man das 
verstehen kann.

von Bernd K. (prof7bit)


Lesenswert?

Rudolph schrieb:
> Es ist völlig egal wie einfach und offensichtlich das ist wenn man das
> erstmal verstanden hat, wenn es keine Grundlage gibt auf der man das
> verstehen kann.

Dann schau doch mal in die header files, oder stochere einfach mal mit 
dem Autocomplete drin rum, da siehst du doch dann wie es aufgebaut ist, 
das Datenblatt legst Du daneben und vergleichst, solange bis Du den 
Zusammenhang und die Logik hinter den Strukturen siehst.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Bernd K. schrieb:
> Dann schau doch mal in die header files, oder stochere einfach mal mit
> dem Autocomplete drin rum, da siehst du doch dann wie es aufgebaut ist

Kann man machen, aber wie ich oben schon schrieb, die Philosophie
mit den "Gruppen" unterhalb von PORT ist nun nicht wirklich allzu
offensichtlich, und sie entspricht auch nicht so recht dem, wie der
Rest dieser Controller aufgebaut ist.  Man hätte da eher sowas wie
PORT0->DIRSET erwartet.

Selbst bei der derzeitigen Implementierung hätte es wohl deutlich
weniger Verwunderung bewirkt, wenn Atmel die #defines für PORTA,
PORTB etc. gleich mitgeliefert hätte, denn im Rest des Datenblatts
werden die Portpins eben auch als PB25 bezeichnet, und nicht etwa als
PORT[1].25 oder sowas.

Aber wenn man das einmal weiß, und sich das Wissen durchs Netz
hinreichend breitstreut, ist es am Ende auch kein großes Thema mehr.
Im Moment sind diese Teile einfach noch ziemlich neu „in freier
Wildbahn“.

von Kaj (Gast)


Lesenswert?

Jörg Wunsch schrieb:
> ganz davon abgesehen, dass der Salat sowieso bloß unter Windows zu.
> haben ist.
Noe, die Atmel-Toolchain gibt es direkt fuer Linux x86_64 bei Atmel als 
Download, incl. dem ganzen cmsis-zeug, compiler pipapo als archiv. 
Runterladen, entpacken, fertig.

Oder meinst du was anderes?

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Kaj schrieb:
> Jörg Wunsch schrieb:
>> ganz davon abgesehen, dass der Salat sowieso bloß unter Windows zu.
>> haben ist.
> Noe, die Atmel-Toolchain gibt es direkt fuer Linux x86_64 bei Atmel als
> Download, incl. dem ganzen cmsis-zeug, compiler pipapo als archiv.

Wo eigentlich?  Ich habe da immer nur eine für den AVR gefunden,
keine für ARM.

> Oder meinst du was anderes?

Ich meinte das ASF.  Aber ok, das scheint es auch so zum Download zu
geben, ohne das Studio-Gedöns.

von Kaj (Gast)


Angehängte Dateien:

Lesenswert?

Jörg Wunsch schrieb:
> Kaj schrieb:
>> Jörg Wunsch schrieb:
>>> ganz davon abgesehen, dass der Salat sowieso bloß unter Windows zu.
>>> haben ist.
>> Noe, die Atmel-Toolchain gibt es direkt fuer Linux x86_64 bei Atmel als
>> Download, incl. dem ganzen cmsis-zeug, compiler pipapo als archiv.
>
> Wo eigentlich?  Ich habe da immer nur eine für den AVR gefunden,
> keine für ARM.

http://distribute.atmel.no/tools/opensource/Atmel-ARM-GNU-Toolchain/4.8.4

Diese Info findet man versteckt in einem PDF von Atmel, habs mal 
angehangen :)  Seite 4, Abschnitt 2.2

Funktioniert bei mir unter Arch Linux einwandfrei :)

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Danke, dann habe ich zumindest mal eine „offizielle“ Toolchain zum
Vergleich, auch wenn es natürlich ansonsten die generische völlig für
meinen Zweck tut.  (Wirklich ernsthafte Patches haben sie ja auch
nicht drin, anders als bei der AVR-Toolchain.)

: Bearbeitet durch Moderator
von Kaj (Gast)


Lesenswert?

Jörg Wunsch schrieb:
> Danke

Kein Problem :)

von Felix L. (flex)


Lesenswert?

Hallo,

ich würde gerne einen Artikel anlegen in dem es um das konfigurieren des 
Atmel Studios geht sowie die Programmierung von SAM D20/D21. Es soll 
besonders für die Umsteiger von AVR auf ARM sein, die sich vom Atmel 
Studio nicht trennen können (manchen mögen es andere nicht). Es soll wie 
ein Tutorial aufgebaut sein, also von Grund auf. Ich würde mich über 
Unterstützung freuen da ich sehr wenig Erfahrung mit den SAM habe.

Gruß

von ChrisSo1986 (Gast)


Lesenswert?

Hallo,

beschäftige mich ebenfalls mit dem SAM D10D14AM und habe Probleme bei 
der Programmierung.

Ich möchte als Übung nur die interne LED zum blinken bekommen und suche 
nun den richtigen BEfehl für die Delay-Time. Bei dem ATMEga hat ja 
delay_ms ausgereicht, jedoch wird er bei diesem COntroller nicht 
anerkannt. Kann mir jemand weiterhelfen.

Ich nutze die #include "sam.h" Datei.

MfG
 CHristian

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Naja, die _delay_us/_delay_ms-Routinen sind doch weiter nichts als
(in Inline-Assembler) gehackte Zählschleifen.

Du kannst genauso gut auf einem ARM eine Zählschleife bauen, zumal
diese Cortex-M0+ keinen Cache haben, die Ausführungszeit also recht
gut vorhersagbar ist.

Wenn ich das hier:
1
void delay(int count) {
2
  register volatile int c = count;
3
  while (--c > 0) { /* delay */ }
4
}

compiliere (arm-none-eabi-gcc -mcpu=cortex-m0plus -mthumb -Os -S 
delay.c), bekomme ich
1
        .thumb_func
2
        .type   delay, %function
3
delay:
4
        sub     sp, sp, #8
5
        str     r0, [sp, #4]
6
.L3:
7
        ldr     r3, [sp, #4]
8
        sub     r3, r3, #1
9
        str     r3, [sp, #4]
10
        cmp     r3, #0
11
        bgt     .L3
12
        add     sp, sp, #8
13
        @ sp needed
14
        bx      lr

Du müsstest mithin mal zählen, wie lange die drei Befehle von LDR
bis BGT dauern, dann hast du die Zeit für einen Durchlauf.

Dass man natürlich in der Praxis einen Timer benutzen wird, dürfte
selbstverständlich sein …

von Martin J. (bluematrix) Benutzerseite


Lesenswert?

Hallo an alle,

ich habe jetzt die Atmegas, Xmegas (ohne ASF, anfangs gab es ja noch 
einzelne Treiber ohne gleich das ganze ASF verwenden zu müssen) und 
einge alte Infineon Controller hinter mir. In den nächsten Wochen will 
ich mich in die SAM4 einarbeiten.

Nutzt ihr die SAM4 nur mit dem ASF oder soll man das lieber ohne machen?
Mein erster Eindruck...
- Durch die ganze Flexibilität des ASF für die verschiednen Controller, 
scheint es teilweise sehr ineffizient zu sein.
- Sehr unübersichtlich
- Will ich die Hardwaremodule wirklich gut ausnutzen, muss ich sicher 
wieder vieles selber initialisieren, da einige Funktionen nicht alle 
Konfigurationen zulassen. Diese Erfahrung habe ich bei den Xmegas 
gemacht, weshalb ich dann doch nicht das ASF zur programmierung 
verwendet habe.
+ fertige treiber für USB und Co

Was empfehlt ihr?

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Martin J. schrieb:
> Was empfehlt ihr?

Einen eigenen Thread zu starten, statt einen zu kapern, bei dem es um
SAMD20/21 geht.

von Martin J. (bluematrix) Benutzerseite


Lesenswert?

Welcher SAM ist mir eigentlich egal.
Hier ging es bisher hauptsächlich um das ASF und die Programmierung der 
SAMs, daher mein Posting.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Martin J. schrieb:
> Welcher SAM ist mir eigentlich egal.

Trotzdem kaperst du einen fremden Thread.  Das ist unhöflich.  Auch
wenn sich der TE nicht mehr gemeldet hat bislang, könnte es ja sein,
dass er nach ein wenig Bedenkzeit sein Thema doch noch gern
weiterführen möchte.

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.