Pogrammierung SAM D21 mit Atmega ICE und SWD

achim S.

Mitglied
16. Jan. 2010
704
13
18
Berlin Biesdorf
Sprachen
  1. ANSI C
Hallo Gemeinde
habe mir das Board mit dem ARN SAM 21 (hier von Dev-Tool) und den Atmega ICE Programmer zugelegt.
Soweit. so gut. Doch wie geht es weiter?
Verwende das AVR Studio 7 und habe Erfahrung mit dem Atmega 1284p und einigen anderen.
Doch woe mache das mit dem ARM?
Was schon geht:

- der Atmega ICE Programmer wird vom AVR Studio erkannt und ist eingestellt
- stecke den Programmer auf den SWD des SAM D21
- der SAM D21 wird vom AVR Studio erkannt und mit der Nummer angezeigt

Bis her hatte ich alle notwendigen Datein und Libs auf meinem Rechner und konnte sie, falls nötig kopieren oder wurden geladen.
Erstelle ich jetzt ein Programm, z.B. einfache Pinabfrage, so bekomme ich die Fehlermeldung das die Libs fehlen. Wo bekomme ich diese Libs und wie ins Programm einbinden?
Möchte beim "normalen" C bleiben und das kastrierte vom Arduino nehmen.
Gibt es ein Tut für so was?
Könnte mir jemand auf die Sprünge helfen?
achim
 
Hallo Achim,

bei Arduino in Verbindung mit ARM kann ich dir leider nicht so gut weiterhelfen.

Ich habe mal ein einfaches Beispielprojekt für AtmelStudio hochgeladen, dieses verwendet das ASF (Atmel Software Framework).

Vielleicht kann dir das ja etwas weiter helfen.


Kurze Erläuterung zum Programm:
Der Systickhandler wird initialisiert. In dessen ISR (1ms) wird die LED des NanoSAMD21 getoggelt (250ms)
Das Hauptprogramm macht soweit nichts, außer die Taste abfragen, wird diese gedrückt, wird die LED angeschaltet.

Das ASF ist sicherlich hierfür etwas überdimensioniert, aber zum Starten denke ich ganz gut ... und es gibt ja noch komplizierte Sachen als GPIO konfigurieren ;)

Beispielprojekt:
NanoSAMD21_Example.zip



CodeBox C
#define BUTTON_PIN       PIN_PA13
#define LED0_PIN       PIN_PB30
#define LED0_ACTIVE       false
#define LED0_INACTIVE   !LED0_ACTIVE

#define LED_ON           port_pin_set_output_level(LED0_PIN, LED0_ACTIVE);
#define LED_OFF           port_pin_set_output_level(LED0_PIN, LED0_INACTIVE);
#define LED_TOGGLE       port_pin_toggle_output_level(LED0_PIN);   

/** Handler for the device SysTick module, called when the SysTick counter
 *  reaches the set period.
 *
 *  \note As this is a raw device interrupt, the function name is significant
 *        and must not be altered to ensure it is hooked into the device's
 *        vector table.
 */


void SysTick_Handler(void)
{
   
   static uint16_t delaycount = 0;

   if (delaycount < 250)
   {
       delaycount++;
   } else {
       delaycount = 0;
       LED_TOGGLE       
   }
   
}

static void configure_systick_handler(void)
{
   SysTick->CTRL = 0;
   SysTick->LOAD = 8000; //48000; // 1ms Event (1ms/(1/48Mhz))   
   SysTick->VAL  = 0;
   SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk;
}

int main (void)
{
                  
   // Initialization Section           
   irq_initialize_vectors();
   cpu_irq_enable();   
   system_init();
       
   // LED
   struct port_config config_port_pin;
   port_get_config_defaults(&config_port_pin);
   config_port_pin.direction = PORT_PIN_DIR_OUTPUT;
   port_pin_set_config(LED0_PIN, &config_port_pin);
   
   // BUTTON
   port_get_config_defaults(&config_port_pin);   
   config_port_pin.direction = PORT_PIN_DIR_INPUT;
   config_port_pin.input_pull = PORT_PIN_PULL_UP;
   port_pin_set_config(BUTTON_PIN, &config_port_pin);
       
   configure_systick_handler();

LED_ON
   while (1)
   {
       
       // main loop of application code
       
       if (!port_pin_get_input_level(BUTTON_PIN)) {
           /* Button is pressed */
           LED_ON
       }
       
   }

}

 
Hallo Dirk
danke für deine Antwort. Habe mir das ZIP geholt und schon mal angeschaut. Dabei fällt mir sofort das "asf.h" auf. Habe auch was von GCC gelesen. In deinem Projekt ist asf enthalten. Wie kann ich das asf und die ganzen anderen datein dauerhaft einbinden?
Werde das Programm gleich mal laden und mein erstes Programm mit ARN ausführen.
Mit Arduino habe ich auch nichts zu tun. Ist mir einfach zu " .... ". Andere finden ihn gut, ich halt nicht. Mekde mich mit einem Ergebnis.
achim
 
Hallo Dirk
habe das Programm mit allen Datein geladen, angeschaut welche Pins du benutzt und gestartet. Es liess sich ohne Fehler kompilieren und funktioniert. LED 1 an PB30 blinkt. Wenn ich den Taster an PA13 betätige geht die LED auf Dauerlicht. Klappt sehr gut. Jetzt kann ich mich auch an die einzelnen Funktionen machen und feststellen was alles benötigt wird. Bleiben allerdings noch die Fragen vonoben.
achim
 
Bleiben allerdings noch die Fragen vonoben.
Du meinst
(1) deine eigenen Libs verwenden und wie diese "einbauen"?
(2) Tutorials für SAMD21 und C? (Ich kenne da leider keine, die alles abhandeln. Wenn du das ASF nutzt sind eigentlich immer Hilfen in der Dokumentation vorhanden, siehe im ASF Explorer)
 
Hallo Dirk
da ja dein erstes Programm bei mir geht, kann ich weitermachen.
Meine Fragen mal anders:

- Wie hast du das Projekt (Beispiel erstellt)?
- Wie kann ich ASF einbauen?
- Ist dein Programm auch in C geschrieben? (Da es einen relativ grossen Unterschied zum At128 gibt)

Bin für jeden Hinweis dankbar und werde gern (wenn es geht) alles hier veröffentlichen, z.B. als Tut zur Anleitung des SAM D21.
Arbeitet keiner sonst mit dem SAM D21?

achim
 
Hallo Achim,
- Wie hast du das Projekt (Beispiel erstellt)?
- Wie kann ich ASF einbauen?
- Ist dein Programm auch in C geschrieben?

hier eine Kurzbeschreibung, wie due ein Projekt mit ASF erstellst ...

AtmelStudio starten
Menüpunkt New/Project wählen

Dialog "New Project":
GCC C ASF Board Projekt wählen, unten Projektname und Location angeben, OK

Dialog "Device Selection":
Hier den Mikrocontroller auswählen.
SAMD21/ATSAMD21J17A

Menüpunkt ASF/ASF Wizard auswählen

Dialog "Board Selection Wizard":
User Board Template auswählen.
Next ... Finish ... Apply

Im ASF Wizard nun Driver, Services oder Components auswählen.
z.B. Port-GPIO Pin Control driver
Add>> ... Apply

Rechts im ASF Explorer sind nun die importierten Sachen aus dem ASF, mit Dokumentation.
 
Hallo Achim,


hier eine Kurzbeschreibung, wie due ein Projekt mit ASF erstellst ...

AtmelStudio starten
Menüpunkt New/Project wählen

Dialog "New Project":
GCC C ASF Board Projekt wählen, unten Projektname und Location angeben, OK

Dialog "Device Selection":
Hier den Mikrocontroller auswählen.
SAMD21/ATSAMD21J17A

Menüpunkt ASF/ASF Wizard auswählen

Dialog "Board Selection Wizard":
User Board Template auswählen.
Next ... Finish ... Apply

Im ASF Wizard nun Driver, Services oder Components auswählen.
z.B. Port-GPIO Pin Control driver
Add>> ... Apply

Rechts im ASF Explorer sind nun die importierten Sachen aus dem ASF, mit Dokumentation.
 
Dialog "Board Selection Wizard":
User Board Template auswählen.
Next ... Finish ... Apply

Beim ersten Versuch hat schon eine Menge funktioniert. Leider komme ich hier nicht weiter. Das "User Board Template " wird angezeigt und kann ausgewählt werden (beim anklicken wird es blau), aber das "Next - Finish - Apply" kommt nicht. Sind grau hinterlegt und kann es nicht anklicken.
Ein paar Kleinigkeiten sind auch anders, ist unerheblich.
achim
 
Hallo Dirk
habe weiter nach dem (Fehler) gesucht. Du schreibst


Dialog "Device Selection":
Hier den Mikrocontroller auswählen.
SAMD21/ATSAMD21J17A

Dort erscheint bei mir "Auswahl Board", kann zwar den SAM eingeben nimmt aber das Board mit dem Prozessor drauf und kann es nicht mehr ändern. Wahrscheinlich eine Einstellung falsch. Bin am suchen.
achim
 
Habe das Programm von Dirk auf meuner Hardware zum laufen bekommen. Innerhalb des Programmes sind bestimmte Befehle drin, die ich nicht so ganz nachvollzeihen kann. Zum Beispiel:

static void configure_systick_handler(void){ SysTick->CTRL = 0; SysTick->LOAD = 8000; //48000; // 1ms Event (1ms/(1/48Mhz)) SysTick->VAL = 0; SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk;}

Habe im Netz nach Antworten gesucht, aber leider nur mit mässigen Erfolg.
Gibt es denn entsprechende Bücher oder Anleitungen oder Tuts zu dem Thema? Vielleicht sogar in deutsch? Oder könnte mir jemand das kurz erläutern. Bin für jede Hilfe dabei dankbar.

achim
 
Hallo Achim,

der SAMD21 verfügt über einen SysTickTimer. In der Routine configure_systick_handler() wird dieser in meinem Beispiel so konfiguriert, dass er einen Interrupt alle 1ms auslöst. Wenn der zugehörige Interrupt-Handler SysTick_Handler() definiert ist, wird diese Routine einmal jede 1ms ausgeführt.
Du kannst dir hier zum Beispiel Signale an das Hauptprogramm senden oder Programmteile direkt in der Interrupt-Routine abarbeiten (möglichst nur kurze und zeitkritische Sachen, keine größeren Programmteile).

Der SysTickTimer ist übrigens kein Hardwaremodul vom SAMD21, sondern ein Bestandteil vom ARM Cortex M0+ Kern. Du wirst hierzu also somit keine Infos im Atmel/Microchip Datenblatt des SAMD21 finden, sondern bei ARM direkt.

Allerdings musst du hier garnicht so viel wissen oder einstellen, um dieses Feature nutzen zu können.

Die Periodendauer des Interrupts stellst du durch den Wert im RELOAD Register ein. Es ist die Anzahl der benötigten Clock Pulse - 1.

Die Funktion ist im Prinzip so ähnlich, wie wenn du bei einem AVR einen Timer mit Timerinterrupt (overflow oder compare) konfigurierst und hier alle 1ms eine entsprechende Timer-Interruptroutine ausführen lässt.

Für deutschsprachige Literatur zu dem Thema habe ich leider keine Quellen oder Tipps.

Dirk :ciao:
 
Hallo Dirk
danke für die Info. Wenn ich das richtig verstanden habe brauchen wir die Angabe aus dem Programm und den einmalgen Aufruf zu Anfang. Damit müsste alles gehen. Mit welcher Frequenz läuft dann der SAM. Er kann bis zu 48Mhz (nach Datenblatt) und wird mit dem Quarz auf der Platine synchronisiert.
Gibt es leichte Kost in englisch? Dachte so an die Sorte wie "C von A bis Z", mit dem ich viel arbeite oder einzelne Befehle angegeben sind.
achim
 
Hallo Achim,
Mit welcher Frequenz läuft dann der SAM.
nach Reset ...

Generic Clock 1MHz (OSC8M div 8)
CPU und BUS Clock 8MHz (OSC8M)

Er kann bis zu 48Mhz (nach Datenblatt) und wird mit dem Quarz auf der Platine synchronisiert.
Hierzu liefere ich noch ein Beispiel für die Konfiguration mittels ASF.

Gibt es leichte Kost in englisch? Dachte so an die Sorte wie "C von A bis Z", mit dem ich viel arbeite oder einzelne Befehle angegeben sind.

Wenn du direkt C programmieren möchtest, ohne spezielle Bibliotheken (für Anfänger schwer):
C Reference Kernighan+Richie (behandelt nicht das Zielsystem)
Datasheet vom Controller und ARM Cortex M0+ Hilfe (Internet)
Fach-Foren

Wenn du das Atmel Software Framework verwenden möchtest (empfehle ich für Anfänger):
hierzu zusätzlich Erläuterungen zu ASF (Onlinehilfe)


Dirk :ciao:
 
Für die nächste Frage biite nicht gleich hauen (sehr primitiv)
Möchte mit dem "klassiker" Word das erste selbst geschriebene Programm anfangen, es soll eine LED blinken. Dazu brauche ich delay_ms. Welche Bibliothek, muss ich laden und wie heisst der Befehl korrekt?
 
Dazu brauche ich delay_ms. Welche Bibliothek, muss ich laden und wie heisst der Befehl korrekt?

Da du ja sicherlich das ASF verwendest, kannst du hier auch die enthaltenen Delay Routine nutzen.
Gehe in den ASF Wizard und importiere den Service "Delay Routines". Du kannst noch wählen, ob die Delay Routine selber Maschinenzyklen (verbraten) zählen soll oder ob sie hierfür den SystickTimer verwenden soll (cycle oder systick).

Falls du den Systick Timer verwenden möchtest, musst du noch im main einmal delay_init() aufrufen, bei cycle ist dies nicht notwendig.

Aufruf erfolgt dann so ...

delay_ms(10); // 10ms

Weitere Infos findest du in der API Dokumentation (ASF Explorer).

Dirk :ciao:
 
Sorry, muss wieder was fragen. Leider hilft mir ASF nicht weiter. In Dirk seinem Programm steht das drin:


// LED
struct port_config config_port_pin;
port_get_config_defaults(&config_port_pin);
config_port_pin.direction = PORT_PIN_DIR_OUTPUT;
port_pin_set_config(LED0_PIN, &config_port_pin);

und das noch

// TASTE
port_get_config_defaults(&config_port_pin);
config_port_pin.direction = PORT_PIN_DIR_INPUT;
config_port_pin.input_pull = PORT_PIN_PULL_UP;
port_pin_set_config(BUTTON_PIN, &config_port_pin);

Habe versucht mit ASF und dem Internet rauszufinden was das genau macht. Im Grunde was ich gefunden habe wird ein Pin als Ausgang für LED gesetzt und der Andere für den Eingang des Tasters. Leider ist mir der genaue Ablauf unklar. Könnte jemand zu meier Erhellung beitragen?

achim
 
Hallo Achim,
Leider ist mir der genaue Ablauf unklar. Könnte jemand zu meier Erhellung beitragen?

am Beispiel der LED:

Hiermit erstellst du eine Variable config_port_pin, diese hat die struct port_config.
struct port_config config_port_pin;

Deine Variable config_port_pin wird nun mit Standardwerten initialisiert.
port_get_config_defaults(&config_port_pin);


Hier die Elemente der Struktur und die Standardwerte:


CodeBox C
/* Default configuration values */
config->direction  = PORT_PIN_DIR_INPUT;
config->input_pull = PORT_PIN_PULL_UP;
config->powersave  = false;


Du kannst nun diese Werte ändern. Bei der LED benötigst du einen Ausgang.
config_port_pin.direction = PORT_PIN_DIR_OUTPUT;

Und nun weist du einem Portpin diese Einstellung zu:
port_pin_set_config(PIN_PB30, &config_port_pin);
Nun ist PIN_PB30 ein Ausgang.

Diese Pinkonfiguration wird nun auf das Hardware Modul angewandt. Da es im oberen Beispiel ein Ausgang ist, wird Pullup/Pulldown ignoriert.

Äquivalent funktioniert dies mit Input für einen Taster.




Hier einmmal die möglichen Werte für direction und input_pull

config_port_pin.direction = ...


CodeBox C
enum port_pin_dir {
   /** The pin's input buffer should be enabled, so that the pin state can
    *  be read */
   PORT_PIN_DIR_INPUT               = SYSTEM_PINMUX_PIN_DIR_INPUT,
   /** The pin's output buffer should be enabled, so that the pin state can
    *  be set */
   PORT_PIN_DIR_OUTPUT              = SYSTEM_PINMUX_PIN_DIR_OUTPUT,
   /** The pin's output and input buffers should be enabled, so that the pin
    *  state can be set and read back */
   PORT_PIN_DIR_OUTPUT_WTH_READBACK = SYSTEM_PINMUX_PIN_DIR_OUTPUT_WITH_READBACK,
};


config_port_pin.input_pull = ...


CodeBox C
enum port_pin_pull {
   /** No logical pull should be applied to the pin */
   PORT_PIN_PULL_NONE = SYSTEM_PINMUX_PIN_PULL_NONE,
   /** Pin should be pulled up when idle */
   PORT_PIN_PULL_UP   = SYSTEM_PINMUX_PIN_PULL_UP,
   /** Pin should be pulled down when idle */
   PORT_PIN_PULL_DOWN = SYSTEM_PINMUX_PIN_PULL_DOWN,
};
 
Hallo Dirk
danke für die Info. Ist ganz schön kompliziert, da werde ich noch einiges lesen und tun müssen um das zu verstehen. Ist eine ganz andere Welt als so AVR.
Mal sehen ob ich das alles begreiffe
achim
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)