ATMEL ARM SAMD ohne Framework programmieren

Gast #4502912
Lesenswert?

Nach ausführlichen Versuchen hat sich gezeigt, dass die Frameworks von 
Atmel wie ASF oder AtmelSTART schwer zu bedienen sind oder gewisse 
Funktonen nicht bereitstellen.

Als beste Methode hat sich für mich die BareBone Programmierung 
herausgestellt. Dank Jörg Wunsch ist es endlich gelungen, einen 
Microsekunden Systemtimer aufzusetzen:

Beitrag "Re: SAMD20 timer counter 1 läuft nicht"

Das setup nutzt nur die Registerdefinitionsdateien des Prozessors:

"pm.h" defines für das Powermanagment
"tc.h" defines für den Timer

in "ASF\sam0\utils\cmsis\samd20\include\component\"

Ich würde diesen Thread gerne nutzen, um das BareBone Programming ein 
wenig auszubauen.

Als nächste möchte ich versuchen, die pins der IO-Ports des SAMD zu 
konfigurieren und anzusprechen.

Weiß jemand wie das geht?
Gast #4502942
Lesenswert?

Hier gibt es den Versuch von Rudolph, die Ports direkt anzusprechen:

Beitrag "Re: Erste Schritte mit ARM SAMD20"
1
#include "sam.h"
2

3
int main(void)
4
{
5
  SystemInit();
6
  
7
  PORT->Group[0].DIRSET.reg = PORT_PA14;
8
  PORT->Group[0].OUTTGL.reg = PORT_PA14;
9
  while (1){}; 
10
}

Hinter "sam.h" sind die definition von PORT und PORT_PA14 versteckt:

1. in der MCU spezifischen Datei "samd20e17.h" findet sich die 
Speicheraddres "PORT"
2. in "port.h" befindet sich das Richtungsregister
Gast #4503462
Lesenswert?

Hier mal die Port Funktionen zu Übung in sehr einfache Funktionen 
verpackt. Der Faulheit halber habe ich nur den LED-Pin definiert.
1
#define INPUT 0x0
2
#define OUTPUT 0x1
3
#define INPUT_PULLUP 0x2
4
#define INPUT_PULLDOWN  (0x3)
5

6
const uint32_t pin2portConnectionTable[]=
7
{
8
  0, // pin 0
9
  0, // pin 1
10
  0, // pin 2
11
  0, // pin 3
12
  
13
  0, // pin 4
14
  0, // pin 5
15
  0, // pin 6
16
  0, // pin 7
17
  
18
  0, // pin 8
19
  0, // pin 9
20
  0, // pin 10
21
  0, // pin 11
22
    
23
  0, // pin 12
24
  PORT_PA14 , // pin 13, ARDUINO LED
25
};
26

27
void pinMode( uint32_t ulPin, uint32_t ulMode )
28
{
29
  switch ( ulMode )
30
  {
31
    case INPUT:
32
      PORT->Group[0].DIRCLR.reg = pin2portConnectionTable[ulPin];
33
    break ;
34

35
    case INPUT_PULLUP:
36

37
    break ;
38

39
    case INPUT_PULLDOWN:
40

41
    break ;
42

43
    case OUTPUT:
44

45
    break ;
46

47
    default:
48
    // do nothing
49
    break ;
50
  }
51
}
52

53
void digitalWrite( uint32_t ulPin, uint32_t ulVal )
54
{
55
  // Enable pull-up resistor
56
  //PORT->Group[g_APinDescription[ulPin].ulPort].PINCFG[g_APinDescription[ulPin].ulPin].reg=(uint8_t)(PORT_PINCFG_PULLEN) ;
57
  switch ( ulVal )
58
  {
59
    case LOW:
60
      PORT->Group[0].OUTCLR.reg = pin2portConnectionTable[ulPin];
61
    break ;
62

63
    default:
64
      PORT->Group[0].OUTSET.reg = pin2portConnectionTable[ulPin];
65
    break ;
66
  }
67
  return ;
68
}
69

70
int digitalRead( uint32_t ulPin )
71
{
72
  if (PORT->Group[0].IN.reg&pin2portConnectionTable[ulPin] !=0 )
73
  {
74
    return HIGH ;
75
  }
76
  return LOW ;
77
}
78
// modified for just showing the principle of configuring and using the ports with native funktions
79
// https://github.com/arduino/ArduinoCore-samd/blob/master/cores/arduino/wiring_digital.c

Ja, wer kennt und liebt sie noch nicht, die Wiring Funkttionen? ;-)
Hier gibt es die sehr lesenswerte Geschichte zu Wiring:
http://arduinohistory.github.io/
Moderator Persönliche Seite #4503470
Lesenswert?

Ich bin in letzter Zeit leider nicht mehr groß dazu gekommen, an
meinem SAMD20-Setup weiter zu spielen.

Hier noch ein paar Schnipsel.

XOSC 16 MHz aktivieren:
1
#define WAIT_GCLK_SYNC()    while(GCLK->STATUS.bit.SYNCBUSY)
2

3
  /* turn off division of OSC8M by 8 */
4
  SYSCTRL->OSC8M.bit.PRESC = 0;
5
  /* enable XOSC (16 MHz) */
6
  SYSCTRL->XOSC.reg = SYSCTRL_XOSC_ENABLE | SYSCTRL_XOSC_XTALEN |
7
    SYSCTRL_XOSC_AMPGC | SYSCTRL_XOSC_STARTUP(11);
8
  while (SYSCTRL->PCLKSR.bit.XOSCRDY != 0) { /* wait */ }
9
  GCLK->GENDIV.reg = GCLK_GENDIV_ID(0) | GCLK_GENDIV_DIV(0);
10
  WAIT_GCLK_SYNC();
11
  GCLK->GENCTRL.reg = GCLK_GENCTRL_ID(0) | GCLK_GENCTRL_SRC_XOSC |
12
    GCLK_GENCTRL_GENEN | GCLK_GENCTRL_OE;
13
  WAIT_GCLK_SYNC();

32-kHz-Oszillator aktivieren:
1
#define WAIT_XOSC32K_READY()   while((SYSCTRL->PCLKSR.bit.XOSC32KRDY) == 0 )
2

3
  SYSCTRL->XOSC32K.bit.STARTUP = 6; /* ≈ 1 s */
4
  SYSCTRL->XOSC32K.bit.XTALEN = 1;  /* this is a crystal */
5
  /* Auto amplitude control – see errata, does not work */
6
  SYSCTRL->XOSC32K.bit.AAMPEN = false;
7
  /* 32KHz output Enable/Disable */
8
  SYSCTRL->XOSC32K.bit.EN32K = true;
9
  SYSCTRL->XOSC32K.bit.ONDEMAND = false;
10
  SYSCTRL->XOSC32K.bit.RUNSTDBY = true;
11

12
  SYSCTRL->XOSC32K.bit.ENABLE = true;
13

14
  /* Check the XOSC32K Clock source is ready to use */
15
  WAIT_XOSC32K_READY();

Weitere Taktereien:
1
  /* Generic clock generator 1: use XOSC32K without prescaler */
2
  GCLK->GENDIV.reg = GCLK_GENDIV_ID(1) | GCLK_GENDIV_DIV(0);
3
  WAIT_GCLK_SYNC();
4
  GCLK->GENCTRL.reg = GCLK_GENCTRL_ID(1) | GCLK_GENCTRL_SRC_XOSC32K |
5
    GCLK_GENCTRL_GENEN | GCLK_GENCTRL_OE;
6
  WAIT_GCLK_SYNC();
7

8
  /* Enable RTC clock as GCLK[1] */
9
  GCLK->CLKCTRL.reg = GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN(1) | GCLK_CLKCTRL_ID_2;
10
  /* PB23 as GCLK_IO[1] */
11
  //PORT->Group[1].DIRSET.bit.DIRSET = (1 << 23);
12
  PORT->Group[1].PMUX[23 / 2].bit.PMUXO = PORT_PMUX_PMUXE_H_Val;
13
  PORT->Group[1].PINCFG[23].bit.PMUXEN = 1;
Gast #4503546
Lesenswert?

>Ich bin in letzter Zeit leider nicht mehr groß dazu gekommen, an
>meinem SAMD20-Setup weiter zu spielen.

Wie schade. Aber danke für die Code-Schnipsel.
Interessant wäre eine rudimentäre UART-Setup für "putchar und gechar" 
ohne Interrupt und Buffer.
Gast #4503693
Lesenswert?

Im Moment untersuche ich gerade die maximale Toggle-Geschwindigkeit.

Ich verwende folgenden Code, bei dem das Port-Toggle-Bit direkt 
geschrieben wird:
1
#include "sam.h"
2

3
int main(void)
4
{
5
    SystemInit();
6

7
  PORT->Group[0].DIRSET.reg = PORT_PA15;
8

9
    while (1) 
10
    {
11
      PORT->Group[0].OUTTGL.reg = PORT_PA15;
12
    }
13
}

Der Assemblercode der while-Loop sieht so aus:
1
000001D4   str  r3, [r2, #28]  % 2 cycles 
2
000001D6   b  #-6    % 3 cycles

Insgesammt sollten für das togglen 5 Zyklen verbraucht werden. Das 
entspricht bei 1Mhz Default-Clk 5us.
Mit dem Oszi messe ich aber

6.04us

Da geht wohl irgendwo ein Takt verloren und wenn mein Oszi stimmt, liegt 
der interne Oszillator wohl fast 1% daneben.



I
Gast #4503730
Lesenswert?

Ich habe das Setup von Rudolf
Beitrag "Re: Erste Schritte mit ARM SAMD20"
etwas refakturiert. Damit sollte der Sysclk bei 48 MHz liegen.
Als Pulslänge messe ich mit dem Oszi 126.8ns was eine ToogleFrequenz von 
ca. 4Mhz ergibt.
Was mir am Oszi auffällt: Die Periodendauer schwankt stark, so dass das 
Signal in X-Richtung stark verschmiert.
Ich vermute, dass die PLL mit dieser Einstellung ziemlich instabil 
läuft.
1
#include "sam.h"
2
void clock_init(void)
3
{
4
  // Enable the XOSC32K and set the start up time
5
  REG_SYSCTRL_XOSC32K = SYSCTRL_XOSC32K_STARTUP(6)    |
6
                          SYSCTRL_XOSC32K_EN32K         |
7
                          SYSCTRL_XOSC32K_XTALEN        |
8
                          SYSCTRL_XOSC32K_ENABLE;
9
  // Wait for the XOSC32K is stable and ready            
10
  while((REG_SYSCTRL_PCLKSR & SYSCTRL_PCLKSR_XOSC32KRDY) == 0); 
11
  
12
  // Enable the Generic Clock GEN 1 and Configure the XOSC32K as Clock Source for it
13
    REG_GCLK_GENCTRL    = GCLK_GENCTRL_ID_GCLK1         |
14
                          GCLK_GENCTRL_SRC_XOSC32K      |
15
                          GCLK_GENCTRL_GENEN            |
16
                          GCLK_GENCTRL_IDC;
17
  // Wait for the synchronization between clock domain is complete            
18
  while((REG_GCLK_STATUS & GCLK_STATUS_SYNCBUSY) != 0); 
19
  
20
    // Enable the DFLL and set the operation mode as closed loop
21
    REG_SYSCTRL_DFLLCTRL = SYSCTRL_DFLLCTRL_ENABLE      |
22
                         SYSCTRL_DFLLCTRL_MODE;
23
  // Wait for the synchronization between clock domain is complete
24
  while((REG_SYSCTRL_PCLKSR & SYSCTRL_PCLKSR_DFLLRDY) == 0);
25
  
26
  // Load the Multiply factor, Coarse Step and fine Step for DFLL
27
  REG_SYSCTRL_DFLLMUL = SYSCTRL_DFLLMUL_CSTEP(0x1F/4) |
28
                          SYSCTRL_DFLLMUL_FSTEP(0xFF/4) |
29
                          SYSCTRL_DFLLMUL_MUL(1465);
30
  
31
  // Enable the Generic Clock GEN 1 as DFLL48 as Reference
32
  REG_GCLK_CLKCTRL    = GCLK_CLKCTRL_CLKEN            |
33
                          GCLK_CLKCTRL_GEN_GCLK1        |
34
                          GCLK_CLKCTRL_ID(0);
35
  
36
  while((REG_SYSCTRL_PCLKSR & SYSCTRL_PCLKSR_DFLLLCKF) == 0); // wait for fine lock
37
  
38
  // Set the NVM Read Wait States to 1, Since the operating frequency 48 MHz
39
  NVMCTRL->CTRLB.bit.RWS = 1;
40
  //  Enable the Generic Clock 0 and Configure the DFLL as Clock Source for it
41
  REG_GCLK_GENCTRL   = GCLK_GENCTRL_ID_GCLK0         |
42
                       GCLK_GENCTRL_SRC_DFLL48M      |
43
                       GCLK_GENCTRL_GENEN            |
44
                         GCLK_GENCTRL_IDC;
45
             
46
  // Wait for the synchronization between clock domain is complete
47
  while((REG_GCLK_STATUS & GCLK_STATUS_SYNCBUSY) != 0); 
48
}
49

50
int main(void)
51
{
52
    SystemInit();
53
  clock_init();
54
  
55
  PORT->Group[0].DIRSET.reg = PORT_PA15;
56

57
    while (1) 
58
    {
59
      PORT->Group[0].OUTTGL.reg = PORT_PA15;
60
    }
61
}
Moderator Persönliche Seite #4503862
Lesenswert?

chris_ schrieb:

> Damit sollte der Sysclk bei 48 MHz liegen.
> Als Pulslänge messe ich mit dem Oszi 126.8ns was eine ToogleFrequenz von
> ca. 4Mhz ergibt.

Durch die wait states wird das langsamer.  Eigentlich lohnt sich
so ein schneller CPU-Takt nur, wenn man zumindest Teile des
Programms aus dem RAM abarbeitet.

> Was mir am Oszi auffällt: Die Periodendauer schwankt stark, so dass das
> Signal in X-Richtung stark verschmiert. Ich vermute, dass die PLL mit
> dieser Einstellung ziemlich instabil läuft.

Das ist ja keine PLL, sondern eine FLL, und die jittert in der Tat
ein bissel herum.

Der SAMD21 als Nachfolger hat auch 'ne PLL.
Gast #4506545
Lesenswert?

Die Uart stellt sich als ziemlich harte Nuss dar. Ich habe den Code für 
das senden mittels TX  für einen SAMD21 zusammengebaut.
Leider geht es nicht richtig:

1. Das TX-Register wird beschrieben
2. es geht eine Weile bis das TX-Register wieder leer ist
3. Es kommt keine Signal am TX-Ausgang ( PB22 ) heraus.

Woran könnte das liegen?
Angehängte Dateien:
Gast #4506760
Lesenswert?

Mittlerweile habe ich den Fehler eingekreist. Er liegt hier:
1
void Uart_begin(unsigned long baudrate)
2
{
3
  // set port directions
4
  PORT->Group[1].DIRSET.reg = PORT_PB22; // TX as output
5
  PORT->Group[1].DIRCLR.reg = PORT_PB23; // RX as input

Hier werden die beiden die Pins Tx und Rx als Output und Input 
definiert.
Das ist aber falsch. Man muss statt dessen den I/O Multiplexer so 
konfigurieren, dass die UART-Peripherie an die Pins angeschlossen wird.
Das ist allerdings einigermaßen kompliziert, weil es im Multiplexer auch 
wieder haufenweise Einstellungen gibt und ich noch nicht heraus gefunden 
habe, wie die Zuordnung ist.
Moderator Persönliche Seite #4506804
Lesenswert?

chris_ schrieb:
> Man muss statt dessen den I/O Multiplexer so konfigurieren, dass die
> UART-Peripherie an die Pins angeschlossen wird.

Yep.

SERCOM5 pad 2 und 3 sind PB22/23, die du nehmen willst, und zwar auf
Funktion D.
1
  PORT->Group[1].PMUX[22 / 2].bit.PMUXE = PORT_PMUX_PMUXE_D_Val;
2
  PORT->Group[1].PINCFG[22].bit.PMUXEN = 1;
3
  PORT->Group[1].PMUX[23 / 2].bit.PMUXO = PORT_PMUX_PMUXO_D_Val;
4
  PORT->Group[1].PINCFG[23].bit.PMUXEN = 1;

Das müsste es sein.  Ist ein bisschen verwirrend, weil man zwischen
den "even" und "odd"-Subregistern unterscheiden muss (oder über das
Gesamtregister gehen statt die Bits).

Du musst in der SERCOM auch noch die Pinzuordnung passend setzen,
damit auch wirklich Pad 2 und 3 benutzt werden.  Das passiert im
CTRLA.

[Edit: bei PORT_PMUX_PMUXO_D_Val hatte ich mich vertan]
Gast #4506849
Lesenswert?

Hallo Jörg,

danke für die Hilfestellung. Ich habe es inzwischen auch so geschafft, 
siehe Anhang.
Da meine Version etwas aus den Arduino-Sourcen zusammengeschustertes 
ist, sieht es nicht besonders übersichtlich aus. Da ist der Code von Dir 
viel besser.
1
Das muesste es sein.  Ist ein bisschen verwirrend, weil man zwischen
2
den "even" und "odd"-Subregistern unterscheiden muss (oder ueber das
3
Gesamtregister gehen statt die Bits).
Ja, das Datenblatt finde ich in der Hinsicht nicht wirklich veständlich.
Aus den Arduino-Sourcen geht diese Zeile hervor

#define PIO_SERCOM_ALT 3
..
PORT->Group[PORTGROUP_PORTB].PMUX[PORTB_TX_PIN>>1].reg = temp | 
PORT_PMUX_PMUXE( PIO_SERCOM_ALT );

Wobei mir beim besten Willen nicht klar ist, warum PIO_SERCOM_ALT 3 ist.
Angehängte Dateien:
Gast #4508475
Lesenswert?

>Der Aufwand lohnt sich sich wirklich.

Deinen Text habe ich nicht ganz verstanden: Meinst Du jetzt es lohnt 
sich oder eher nicht?

>Die SAM Libs ohne Atmel Studio z.Bsp mit Eclipse zu verwenden :)

Das wäre der nächste Schritt. Da ich eher unter Linux arbeite, will ich 
irgendwann auf Eclipse umstellen.
Für die BareMetal-Programmierung hat AtmelStudio aber erst einmal einen 
großen Vorteil: Man kann sich im Debugger wirklich jedes Peripheral-Bit 
anschauen.
#4508592
Lesenswert?

chris_ schrieb:
> Für die BareMetal-Programmierung hat AtmelStudio aber erst einmal einen
> großen Vorteil: Man kann sich im Debugger wirklich jedes Peripheral-Bit
> anschauen.

Das geht in Eclipse auch, siehe Screenshot.

Oben ist zwar ein STM32 zu sehen, die Definitionen für Atmel SAM sind 
aber auch vorhanden, siehe zweiter Screenshot.
Angehängte Dateien:
Gast #4509808
Lesenswert?

Danke, dass Du auch Code veröffentlicht hast. Dein Code ist schön 
aufgeräumt und übersichtlich.

Wie ich sehe, hast Du die Real-Time-Clock (RTC) für die Funktion 
"micros" verwendet.
Das hatte ich verworfen, weil ich vermutet habe, dass das "reload" nur 
mit Interrupts geht und ich Interrupts vermeiden wollte. Wenn ich Deinen 
Code richtig verstehe, geht es wohl auch ohne.
Ich habe statt dessen wie weiter oben gezeigt, TC2-TC3 verwendet.
Das hat den Vorteil, dass man später die RTC vielleicht für eine Uhr mit 
32kHz Quarz im Standby verwenden kann.

Wenn ich es richtig sehe, gehst Du auf 48MHz.
Irgendwo im Datenblatt meine ich gelesen zu haben, dass man die 
FLL-Clock für den Systemtakt lieber von einem langsamen Grundtakt 
ableiten soll, weil die Regelung dann stabiler ist.
#4509992
Lesenswert?

Hi,

gerne :) code Schnipsel aus dem Forum hier haben mir schon oft geholfen.

Der RTC läuft soweit ich weiß ganz normal über.

Zu den 48MHz ich nehmen ja den DPLL nicht den FLL.. aber auch hier muss 
man recht seltsam die 8MHz erstmal runterteilen, nur um dann wieder hoch 
zu gehen. aber es läuft so ganz gut.
Moderator Persönliche Seite #4510009
Lesenswert?

chris_ schrieb:
> dass man die FLL-Clock für den Systemtakt lieber von einem langsamen
> Grundtakt ableiten soll, weil die Regelung dann stabiler ist.

Nein, man „soll“ nicht nur, sondern man muss.  Der Eingang der FLL
ist darauf ausgelegt, mit dem 32-kHz-Oszillator (egal ob RC oder
Quarz) getrieben zu werden und nichts anderem.

Die PLL arbeitet anders, aber die hat der SAMD20 nicht.

> und ich Interrupts vermeiden wollte

Schlechter Ansatz.
Gast #4510100
Lesenswert?

>Schlechter Ansatz.

Sagst Du. Ich baue schon sehr lange, relativ große, synchrone möglichst 
Interrupt freie System.
Insofern: Ansichtssache. Aber ich will darüber jetzt lieber keinen 
Philosophiestreit beginnen. Nur so viel: man muss nicht immer das 
machen, was andere machen.
Gast #4510158
Lesenswert?

Ja, schon, für viele Sachen Probleme muss man Interrupts verwenden.
Interessanterweise hat der Parallax Propeller keinen Interrupts.
Gut, der Prozessor arbeitet ganz anders als die sonstigen Single-Core 
Prozessoren, aber immerhin.
Irgend jemand hat mir mal erzählt, dass man nach neueren 
Programmiermethoden möglichst ohne Interrupts programmiert. Ich fand die 
Idee gut und versuche mich so lange es geht daran zu halten.
#4510394
Lesenswert?

welches Beispiel meinst du genau?

Normalerweise stehen alle Pins erstmal auf in. Siehe z.B. Atmels 
"getting started" Beispiel.
1
int main(void)
2
{
3
   PORT->Group[0].DIRSET.reg = PORT_PA09;
4
   while (1)
5
   {
6
      if (PORT->Group[0].IN.reg & PORT_PA25)
7
      {
8
         PORT->Group[0].OUTSET.reg = PORT_PA09;
9
      }
10
      else
11
      {
12
         PORT->Group[0].OUTCLR.reg = PORT_PA09;
13
      }
14
   }
15
}

(http://www.atmel.com/images/atmel-42421-mcu-getting-started-with-atsamd10d14a-at12616_application-note.pdf)
#4510446
Lesenswert?

chris_ schrieb:
> Interessanterweise hat der Parallax Propeller keinen Interrupts.

Dafür hat jede Task eine genau garantierte Zeit.

Du solltest dich mal mit der Hardware eines ARMs beschäftigen.  Man kann 
die Interrupts in der Priorität steuern.  Somit auch das Zeitliche 
Verhalten bei der Auslösung. Außerdem sorgt man dafür das die Routinen 
möglichst kurz sind.

Aber auch die Hardware z.Bsp der DMA Controller hat einiges zu bieten um 
zeitkritische Dinge zu erledigen.
Gast #4510470
Lesenswert?

>welches Beispiel meinst du genau?

Wenn Du auf den Link klickst, kommst Du genau zum Beispiel. Man kann im 
MC-Netz die Links auf einen bestimmten Post setzen. Leider wird das 
nicht angezeigt und es sieh so aus, als wenn der Link auf den Thread 
Anfang zeigt.

Im Arduino-Code für den SAMD21

https://github.com/arduino/ArduinoCore-samd/blob/master/cores/arduino/wiring_digital.c

sieht man die benötigte Zeile:
1
 PORT->Group[g_APinDescription[ulPin].ulPort].PINCFG[g_APinDescription[ulPin].ulPin].reg=(uint8_t)(PORT_PINCFG_INEN) ;

"PORT_PINCFG_INEN" muss gesetzt werden, sonst ist der Pin nicht mit dem 
"IN" Register verbunden.
Gast #4515512
Lesenswert?

Im Moment versuche ich gerade, die Main-Clock für ein selbst gebautes 
Board mit einem SAMD20E17 hoch zu stellen.

Das Board startet mit 1MHZ, es soll aber mit 48MHz laufen.

Oben habe ich das Beispiel für das XPlained-Board mit dem SAMD20J18:

Beitrag "Re: ATMEL ARM SAMD ohne Framework programmieren"

Es funktioniert gut auf dem XPLained Board.

Wenn ich das Beispiel aber auf das andere Board übertrage, bleibt es in 
der DFLL Synchronisation hängen.
1
  // Enable the Generic Clock GEN 1 as DFLL48 as Reference
2
  REG_GCLK_CLKCTRL    = GCLK_CLKCTRL_CLKEN            |
3
  GCLK_CLKCTRL_GEN_GCLK1        |
4
  GCLK_CLKCTRL_ID(0);
5
  
6
==>  while((REG_SYSCTRL_PCLKSR & SYSCTRL_PCLKSR_DFLLLCKF) == 0); // wait for fine lock

Wie kann das passieren? Es sollte wohl keinen so großen Unterschied 
zwischen einem SAMD20J18 und einem SAMD20E17 geben, oder?
Gast #4515663
Lesenswert?

>Vergewissere dich, dass der Eingangstakt der DFLL
>auch tatsächlich stabil anliegt.

Tja, guter Tipp. Zum Test habe ich mit Atmel-Start eine Konfiguration 
für den externe 32kHz Oszillator gemacht.
Ergebnis: Nachdem ich es programmiert hatte, komme ich mit dem ATMEL-ICE 
und SWDIO nicht mehr auf den Prozessor. Ich habe SWD-Clock auf 32Khz 
runter gestellt, damit bei langsamem Systemtakt die Verbindung noch 
klappt.

Ist der Prozessor jetzt verloren? So ähnlich wie beim AVR wenn man ihn 
"ver-fused".
Moderator Persönliche Seite #4515674
Lesenswert?

chris_ schrieb:
> Ist der Prozessor jetzt verloren?

Hatte ich auch schon mal, Rettung klappte nur mit dem SAM-ICE (Segger).
Da habe ich einen Bugreport bei Atmel aufgemacht, und sie haben mir
dann irgendwann geantwortet, dass es mit einem aktuellen Studio 7 (und
der ICE-Firmware, die es mitbringt) repariert sei, was ich für mein
Beispiel bestätigen konnte.
Gast #4516016
Lesenswert?

chris_ schrieb:
> Ist der Prozessor jetzt verloren? So ähnlich wie beim AVR wenn man ihn
> "ver-fused"

Hat der SAMD20 tatsächlich keinen ROM Bootloader mehr? Habe im 
Datenblatt gesehen:

"Unlike existing SAM products using a ROM monitor, on the Atmel SAM D20 
SAM-BA is stored in flash memory"
Gast #4516131
Lesenswert?

Jörg W. schrieb:
> Das Teil hat einfach mal keinen ROM

Dann muss ich aber sagen, das ist nicht gut. Praktisch alle anderen ARM 
haben und sind somit un-ver-fuse-bar. Selbst die 8051 hatten eine Flash 
Security Page im oberen Flash, wo man einen Bootloader 
nicht-versehentlich-löschbar unterbringen konnte. SAM-BA beginnt bei 0 
und kann somit jederzeit versehentlich überschrieben werden.
Moderator Persönliche Seite #4516154
Lesenswert?

Lothar schrieb:
> Praktisch alle anderen ARM haben und sind somit un-ver-fuse-bar.

Du wieder mit deiner Fusophobie.

Der ist auch nicht „verfuset“, es ist nur, dass ältere Firmwareversionen
des Atmel-ICE da einen Bug haben und das Ding nicht sauber in den
Reset gezogen haben, bei dem man zumindest erstmal wieder den Flash
löschen kann.

Ich denke, man wird sich dran gewöhnen dürfen, dass die Sonderlösung
„Device mit Masken-ROM“ ein Auslaufmodell ist, denn sie generiert
nur Kosten für vergleichsweise wenig Gewinn.  Wenn man also die Kosten
runterbringen will, verzichtet man auf solche Kinkerlitzchen.
Gast #4516190
Lesenswert?

Mittlerweile kann ich ihn wieder programmieren.
Wenn ich das Oszi an den 32kHz Quarz gehalten habe, konnte ich keine 
Schwingung sehen. Deshalb habe ich ein Kabel an XIN ( PA0, Eingang für 
den 32kHz Quarz ) angelötet um extern den Takt einzuspeisen ( Der Trick 
hatte schon mal beim AVR geklappt ). Auf dem Board sind für 32kHz XTAL 
keine Cs.
Scheinbar hat aber das Kabel gereicht, um den Oszillator anzuschwingen. 
Dann habe ich den Clock scnell wieder auf den internen 8MHz Osczi 
umprogrammiert.
Gast #4516209
Lesenswert?

>Der ist auch nicht „verfuset“, es ist nur, dass ältere Firmwareversionen
>des Atmel-ICE da einen Bug haben und das Ding nicht sauber in den
>Reset gezogen haben, bei dem man zumindest erstmal wieder den Flash
>löschen kann.

Das hier gibt die Tool information aus:

Atmel-ICE
Debug host        127.0.0.1
Debug port        51159
Serial number     J41800039355
Connection        com.atmel.avrdbg.connection.cmsis-dap
Features          1
Firmware Version  1.1c
Hardware Version  0

Beim ersten einstecken vor ca. 4 Wochen wurde der ATMEL-ICE von 
AVR-Studio 7 auf die Firmware-Version 1.1.c aktualisiert.
Moderator Persönliche Seite #4516212
Lesenswert?

chris_ schrieb:
> Beim ersten einstecken vor ca. 4 Wochen wurde der ATMEL-ICE von
> AVR-Studio 7 auf die Firmware-Version 1.1.c aktualisiert.

1.1c (hex) = 1.28 (dezimal)

Ja, das ist in der Tat die aktuelle Version.  Damit hätte es dir
zumindest gelingen sollen, den Controller zu löschen.  Wenn das nicht
geht, solltest du Atmel einen Bugreport bescheren.
Gast #4516260
Lesenswert?

Jörg W. schrieb:
> Damit hätte es dir zumindest gelingen sollen, den Controller zu löschen

Versuch es mal mit der niedrigsten Taktfrequenz mit "force the debugWIRE 
speed" oder / und "use external reset"

Jörg W. schrieb:
> „Device mit Masken-ROM“ ein Auslaufmodell

Zumindest NXP sieht das anders, alle neuen LPC kommen mit riesigem ROM 
nicht nur mit Bootloader sondern APIs für UART, SPI, I2C, USB, sogar 
einer mit CANopen Stack. Scheint also billiger zu sein als mehr Flash 
dafür zu spendieren. Könnte natürlich damit zusammenhängen, dass 
schneller Flash (ohne Waitstates) teuer ist. Andererseit ist ja leider 
noch nicht raus, ob LPC oder Kinetis erhalten bleiben.
Moderator Persönliche Seite #4516286
Lesenswert?

Lothar schrieb:

> Versuch es mal mit der niedrigsten Taktfrequenz mit "force the debugWIRE
> speed" oder / und "use external reset"

DebugWIRE? Das ist kein AVR.

> Jörg W. schrieb:
>> „Device mit Masken-ROM“ ein Auslaufmodell
>
> Zumindest NXP sieht das anders, alle neuen LPC kommen mit riesigem ROM
> nicht nur mit Bootloader sondern APIs für UART, SPI, I2C, USB, sogar
> einer mit CANopen Stack. Scheint also billiger zu sein als mehr Flash
> dafür zu spendieren. Könnte natürlich damit zusammenhängen, dass
> schneller Flash (ohne Waitstates) teuer ist.

Dafür darfst du für jeden Bugfix auf eine neue Siliziumversion warten.

Klar, Flash ist nicht so schnell, das wäre so ziemlich der einzige
wirkliche Pluspunkt.  Dafür bin ich dann mit meiner Software an diesen
Hersteller gebunden und kann sie nicht einfach mal schnell woanders
hin portieren.
Gast #4516314
Lesenswert?

Jörg W. schrieb:
> DebugWIRE? Das ist kein AVR

Habe kein Atmel-ICE vor mir, aber die Option, die DEBUG CLK auf ein 
Minimum zu setzen gibt es wohl auch für SWD:

"Debug sessions on SAM target devices over the SWD interface can be 
clocked at up to ten times the CPU clock (but limited to 2MHz max)"

Wenn die DEBUG CLK sehr langsam ist, kommt der Debugger eventuell direkt 
nach dem Reset rein, vor der PLL. Dann könnte man sich eventuell das 
beschriebene Anschliessen eines externen langsamen Quarz sparen.

> Dafür darfst du für jeden Bugfix auf eine neue Siliziumversion warten

Gibt natürlich ein Patch EEPROM :-)

> Dafür bin ich dann mit meiner Software an diesen Hersteller gebunden und
> kann sie nicht einfach mal schnell woanders hin portieren

"Schnell" eine Software zwischen ARM von verschiedenen Herstellern 
portieren? Will ich sehen (trotz CMSIS). Zudem hat LPC für die ROM 
Treiber Lizenzen gekauft (USB VID, CANopen), die sind also dabei. Für 
Software Stacks wären die sehr teuer.
Moderator Persönliche Seite #4516327
Lesenswert?

Lothar schrieb:

>> Dafür bin ich dann mit meiner Software an diesen Hersteller gebunden und
>> kann sie nicht einfach mal schnell woanders hin portieren
>
> "Schnell" eine Software zwischen ARM von verschiedenen Herstellern
> portieren? Will ich sehen (trotz CMSIS).

Auf jeden Fall noch langsamer, wenn du für die Portierung dann auch
noch die ROM-Routinen ersetzen musst.

> Zudem hat LPC für die ROM
> Treiber Lizenzen gekauft (USB VID, CANopen), die sind also dabei. Für
> Software Stacks wären die sehr teuer.

Mit CAN hab' ich keine Ahnung, aber die USB VID zu benutzen, gestatten
auch andere Hersteller ihren Kunden, auch ganz ohne ROM.  Bei Atmel
darfst du beispielsweise die VID:PID-Paare aus ihren Beispielcodes für
die jeweilige Funktionalität benutzen.  Bei Microchip kann man sich,
glaub' ich, mit seinem Produkt registrieren.
Gast #4516333
Lesenswert?

>Habe kein Atmel-ICE vor mir, aber die Option, die DEBUG CLK auf ein
>Minimum zu setzen gibt es wohl auch für SWD:

Ja, man kann die Geschwindigkeit heruntersetzen. Das habe ich ja oben 
schon beschrieben und gemacht: 32kHz.
Aber es ging trotzdem nicht.
Gast #4516348
Lesenswert?

Jörg W. schrieb:
> Auf jeden Fall noch langsamer, wenn du für die Portierung dann auch
> noch die ROM-Routinen ersetzen musst

Das führt jetzt doch etwas vom Thema weg, aber z.B. die LPC ROM-Routinen 
für USB sehen so aus:

(*rom)->pUSBD->init_clk_pins();
(*rom)->pUSBD->init(&DeviceInfo);
(*rom)->pUSBD->connect(TRUE);

void USBIRQ_IRQHandler()
{
  (*rom)->pUSBD->isr();
}

Alles andere ist im Software Stack (den es für LPC ja auch gibt: LPCopen 
oder USBlib) gleich, also Device Descriptor bestücken, Report Funktionen 
schreiben und als Callback registrieren.

Und wenn jetzt ein anderer ARM diese ROM-Routinen nicht hat, dann muss 
man genau dafür die Library-Funktionen von diesem Hersteller rein 
kopieren. Das ist jetzt nicht der Mehraufwand. Den würde ich woanders 
sehen.
#4517758
Lesenswert?

So langsam verstehe ich warum du dir die Mühe machst. Mir wurde ein 
Arduino Zero auf den Tisch geschoben. Auch noch die abgespeckte Version. 
Also mir ist es nach 20 Versuchen nicht gelungen mit der IDE etwas drauf 
zu schieben. Da jemand so schlau war den Taster vom Bootloader 
wegzulassen. Nach den Start geht er also sofort in den Bootloader und 
man hat 5sec um den richtigen Moment zu treffen. Also mit USB Balim 
Balim -> ich habe es aufgegeben.


Ok also SWD Kabel zusammen gefummelt und so was mit J-link -> (auf die 
Adresse achten oder linker Script anpassen) aufgeschoben.

Resultat das es beim system_init() hängen bleibt und zwar an der 
Funktion die erst mal den Clock von den PERIPHERAL ausschaltet die in 
der clock_conf.h nicht an sind.

Beim dritten bleibt er hängen und wartet auf den sync -> vergeblich. 
Dabei wurde an der Clock noch nichts konfiguriert. Läuft nach dem Start 
intern 8MHZ /8 = 1MHZ

Ohne system_init() kann ich auch Ports setzen etc. , aber nur mit 1MHZ. 
Einstellungen in der clock_conf.h bleiben wirkungslos da sie erst danach 
verarbeitet werden.

Jemand eine Idee was da schief läuft? Da in Atmel Studio  es kein Board 
Projekt dafür gibt habe ich es aus dem Devices zusammen gebaut.


Also doch eigenen Funktionen bauen ;)
Gast #4517975
Lesenswert?

Den externen 32kHz Quarz wollte ich verwenden, um auf die 48Mhz zu 
kommen.
Da mir dadurch der Prozessor hängen geblieben ist, habe ich das Problem 
erst mal ignoriert und bin vorerst mit 8MHz zufrieden:
1
void MCU_setup_sysclk_8MHz(void)
2
{
3
  // internal 8MHz oscillator no prescaling
4
  SYSCTRL->OSC8M.bit.PRESC=0;
5
  //while(!(SYSCTRL->PCLKSR.reg & SYSCTRL_PCLKSR_XOSCRDY));
6
}

Das müsste auch auf dem Arduino-Zero so klappen, wenn er mit 1MHz los 
läuft.
Gast #4517977
Lesenswert?

Ursprünglich hatte ich den ARDUINO-ZERO-Pro.

Dort hat es auch ein Weile gedauert, bis ich ihn über AVR-Studio 
programmieren konnte.

Der entscheidende Tipp kam von Jürgen M. :

"Ich musste bei den Fuses im Programmdialog NVMCTRL_BOOTPROT auf 0x07
stellen, um programmieren zu können.
Danach kann man aber nicht mehr über die Arduino-IDE flashen"

Beitrag "Re: Arduino Zero Pro - Kommunikation über EDBG-Chip"
Gast #4518870
Lesenswert?

Lothar schrieb:
> Andererseit ist ja leider
> noch nicht raus, ob LPC oder Kinetis erhalten bleiben.

Naja, ich vermute mal, daß es den Kinetis so ähnlich ergeht wie den 
BlueStreaks. Das Spielchen hatten wir ja schon mal - und der Bursche, 
den ich auf der Embedded ohne so rechten Erfolg auszuquetschen versucht 
habe, meint zu den Kinetis nur "solange die Kunden sie kaufen...".

Bei den Kinetis stören mich zwei Dinge: die Doku und das Fehlen des 
residenten Bootladers. Und bei den LPC stört mich eigentlich nur, daß 
die M4F-Fraktion eigentlich nur aus Boliden besteht, dabei gibt es 
garantiert einen recht ordentlichen Markt für 48..64 pinnige M4F mit ca. 
100 MHz und 32..128K Flash nebst 8..32 K Ram.

W.S.
#4518943
Lesenswert?

Hmm also mit dem Atmel Start geht es erst mal. Ich vermute das etwas 
beim ASF mit dem PM fehl schlägt. Der Bootloader bringt ja das Board 
zuerst in Gang und springt dann in den Anwender Code.  Der versucht dann 
den Clock konfigurieren und das schlägt fehl.  Warum, keine Ahnung 
bekomme ich noch raus ;)

http://www.atmel.com/Images/Atmel-42258-ASF-Manual-SAM-D21_AP-Note_AT07627.pdf 
damit kann ich was anfangen.

Nach langen suchen ... Das Problem bei Atmel das man nie das findet was 
man gebrauchen kann. Einfach grausam.
#4518958
Lesenswert?

W.S. schrieb:
> das Fehlen des
> residenten Bootladers.

Wozu soll sowas gut sein? Im industriellen Umfeld werden (falls 
benötigt) eh individuelle (eigene) Bootloader verwendet die irgendwelche 
speziellen Anforderungen erfüllen (zum Beispiel kompatibel zu sein zu 
den Bootloadern und den zugehörigen Tools die man schon seit x Jahren 
auf y anderen Plattformen verwendet).
#4519149
Lesenswert?

Tja der Schreibschutz für den Generator ist aktiv. WRTLOCK für den 
Generator ist 1 und damit wartet die schleife vergeblich das dass BIT 
CLKEN 0 wird.

Dieser ist auf die ID 3 -> WDT gelegt.
1
/* Disable the generic clock */
2
  GCLK->CLKCTRL.reg &= ~GCLK_CLKCTRL_CLKEN;
3
  while (GCLK->CLKCTRL.reg & GCLK_CLKCTRL_CLKEN) {
4
    /* Wait for clock to become disabled */
5
  }

Der Bootloader wird wohl das WRTLOCK setzen.
Gast #4519356
Lesenswert?

>Hmm also mit dem Atmel Start geht es erst mal.

Das ist der Vorteil der vorgefertigten Konfigurationen: sie gehen erst 
mal, wenn man nicht mehr will als vorgesehen.

>Der Bootloader wird wohl das WRTLOCK setzen.

Ich bin mir nicht sicher, ob ich Deine Beschreibung richtig verstanden 
habe:

Versuch 1: AtmelSTART verwenden, mit Bootloader laden ==> geht
Versuch 2: ASF verwenden, mit Bootloader laden ==> geht nicht

Wenn das so ist, würde das Problem in der ASF liegen.
#4520213
Lesenswert?

Also das Start Projekt wird auch ein Bootloader verwendet. Das 
Linkerscript enthält.
1
MEMORY
2
{
3
  rom      (rx)  : ORIGIN = 0x00000000, LENGTH = 0x00040000
4
  ram      (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000
5
}

Ich habe jetzt nicht geschaut was im ROM bzw. im RAM einsortiert wird. 
Ewt wird auch nur von dort in den RAM gesprungen.


Im Bootloader wird der Generator jednefals nicht geblockt. Wäre ja auch 
Blödsinn. Da sich dieser nur per PowerOn wieder zurücksetzen lässt.

Ich bin auch der Meinung das am ASF was fault ist. An der kann es kaum 
liegen da noch kein Clock konfiguriert wurde. Es bleibt ja bei 
Ausschalten schon hängen. Das Problem ist offenbar nicht so unbekannt.

Also man kann doch erwarten wenn man ein Pojekt aus einen Device erzeugt 
das dies läuft. Wie gesagt ich habe nichts hinzugefügt bzw. um 
konfiguriert und es hängt sich beim system_init schon auf. Das an einer 
Stelle die man eigentlich abfangen sollte. Das man einen Generator 
ausschalten möchte der geblockt ist sollte man schon bedenken und dies 
so lösen das es zu mindestens weiter geht.
#4520323
Lesenswert?

Also die Erkenntnis ist folgende.

Die Funktion _switch_peripheral_gclk schaut in die clock_conf ob irrend 
ein Generator ausgeschaltet ist.
1
 
2
for (gclk_id = 0; gclk_id < GCLK_NUM; gclk_id++) {
3
    system_gclk_chan_set_config(gclk_id, &gclk_conf);
4
  }

Dann läuft folgendes ab. Es laufen alle möglichen Channels durch und 
jede Peripherie die damit verbunden ist wird ausgeschaltet, genau 37 
Channels  sind das.

Beim WDT scheitert das ganze, nach einen Reset ist dieser standardmäßig 
auf einen GCLK geschaltet und ewt. gelockt.  Der Bootloader löst ein SW 
Reset aus worauf Clock und WDT sich neu Konfigurieren, siehe Referenz..

Das deaktivieren schlägt aus diesen Grund wohl fehl. Ewt. muss erst der 
WDT deaktiviert werden bevor man an dem GCLK fummelt.
#4520842
Lesenswert?

Dann erkläre mir Bitte wie das lock da rein kommt ?

Der Code ist Simple und ich habe nachgeschaut was aufgerufen wird. Mit 
dem GCLK und das der WDT an ist nach einen Reset steht in der Referenz 
aber gelockt ? Macht ja keinen Sinn.

Der WDT lässt sich nicht mehr konfigurieren.

Ich habe das jetzt so gelöst.
1
 while (GCLK->CLKCTRL.reg & GCLK_CLKCTRL_CLKEN) {
2
    /* Wait for clock to become disabled */
3
    /* abort when GCLK is lock */ 
4
    if(GCLK->CLKCTRL.bit.WRTLOCK)break;
5
    
6
  }

Wenn der GCLK geblockt ist wird die schleife abgebrochen. Das schlimmste 
was passiert das dieser weiter läuft.

Was noch sein kann das die Registeradresse nicht stimmt da irrend wo das 
Devices nicht definiert ist. Da muss ich nochmal genau prüfen ... 
Komisch ist aber das auch beim Start Projekt der WDT genau den selben 
Status aufweist.  Selbst das hier verlinkte Projekt mit dem DFLL hat der 
WDT und der Clock den selben Status.
#4521489
Lesenswert?

Nach dem die erste Hürde genommen wurde habe ich mit der Hardware etwas 
gespielt.

Tja du hattest recht das ASF lässt viele Sachen offen. Wichtige 
Mechanismen sind in den Funktionen nicht enthalten. Man muss auf 
Registerebene an vielen Stellen nachhelfen um zum gewünschten Ergebnis 
zu kommen.

Die Zeit die man braucht die ASf Funktionen nach ihrer Funktionsweise zu 
untersuchen nimmt sich nicht viel wenn man die Register direkt setzt 
bzw. dies in eigene Funktionen packt.

Immerhin weiß man dann was passiert und es bleibt nicht schon beim 
system_int() hängen ;)

Beim SAM3x ist das etwas besser und verständlicher gelöst.
#4521523
Lesenswert?

Ich habe jetzt weder mit dem SAM noch dessen Framework was gemacht. Wie 
geht ihr denn da ran bei BoneProgramming? Bei den stm´s habe ich das so 
gemacht, dass ich zunächst im Manual das Kapitel einer Peripherie 
quergelesen habe (um eine prinzipielle Idee zu bekommen), dann in der 
IDE mit "goto definition" das Framework "reverse-engineert" habe und 
dann noch mal detailierter ins Manual geschaut habe.
#4521946
Lesenswert?

Also erst mal die Referenz durcharbeiten, um die Hardware zu verstehen. 
Dann stellt sich auch heraus ist das Devices auch das richtige für mein 
Projekt ? Lassen sich die gewünschten Abläufe überhaupt verwirklichen ? 
Welche zusätzliche Hardware wird benötigt ? Wie lässt sich diese 
anbinden ?

Dann muss man hoffen das dass Framework irrend wo beschrieben ist. Die 
grobe Anleitung zum Benutzen sollte ja in den Header Files vorhanden 
sein.

Das obligatorische "Blinky" bekommt man recht schnell zum laufen ;) Beim 
clock,Timer,DMA,Schnittstellen wird es schon schwieriger.

Funktioniert es nicht wie gewollt muss man eben schauen ob die 
Mechanismen aus der Referenz in den Funktionen umgesetzt wurden.

Das ganze dauert natürlich seine Zeit. Mit einer Deadline im Hintergrund 
ist es ganz schlecht sich in einen neuen Device einzuarbeiten.
#4522063
Lesenswert?

Hi,

Ich bin grade dabei. "Umstieg" von STM32 zu SAM.. ein Umstieg ist es 
nicht wirklich da ich auch weiterhin mit den STM32's Arbeiten werde. 
Bisher muss ich sagen das sich beim SAM die Funktionsweisen einfacher 
aus dem Datenblatt als aus der ASF ableiten lassen. bei den STM32's 
waren die Librarys für mich viel hilfreicher.

Was ich Außerdem bei den STM32 libs besser finde ist das die viel 
unabhängiger voneinander ist. Man kann einfach einen Teil rausnehmen und 
benutzen. bei der ASF hängt immer irgendwie alles zusammen. Und bevor 
man es geschafft hat einen Teil alleine in betrieb zu nehmen, hat man es 
schneller von Hand geschrieben ;)

.. also das ist meine subjektive Wahrnehmung :)
#4522287
Lesenswert?

Marco H. schrieb:
> Dann erkläre mir Bitte wie das lock da rein kommt ?

Gerne :) denn ich habe die Lösung gefunden !

Das oben genannte trifft soweit zu der WDT ist aktiv und der Clock der 
ihn Treibt ist verriegelt.

Das Geheimnis steckt im evm Controller. Mit dem kann man ein EEROM 
emulieren. Da der Bereich wo der Bootloader ist schreibgeschützt ist 
lassen sich hier Parameter unterbringen die beim Boot geladen werden 
sollten.

Hier zu wird ein Bereich im RAM reserviert bzw. bei einigen ist dieser 
schon vorhanden.  Da ich das Teil erst mal Blank gemacht habe stand hier 
auch nichts drin. Womit das oben genannte auftrat beim PowerOn.

Folgender Code behebt das Problem
1
  struct nvm_fusebits  my_fuseBits;
2
  my_fuseBits.wdt_always_on=false;
3
  my_fuseBits.wdt_enable=false;
4
  my_fuseBits.bootloader_size=NVM_BOOTLOADER_SIZE_0;
5
  my_fuseBits.eeprom_size=NVM_EEPROM_EMULATOR_SIZE_0;
6
  nvm_set_fuses(&my_fuseBits);


Es setzt die entsprechenden FuseBits in einen reservierten Teil des 
RAMs.
Um die Konfiguration zu aktivieren muss man die Stromversorgung trennen 
!  So lange man den Bereich nicht überschreibt ändert sich am Verhalten 
nichts. Macht man das Devices allerdings Blank muss man die Fusebits 
wieder setzen.

Man kann diese auch Auslesen und ggf. setzen und dann einen PowerOn 
reset auslösen.  Genau das hat Atmel in ihren ASF nicht gemacht.

Mit Bootloader etc. ist die Konfiguration natürlich anzupassen. Also 
Vorsicht wenn man den Chip komplett löscht man muss aufpassen in welche 
Bereiche man schreibt. Durch den WDT geht dieser auch dann noch zyklisch 
in den Reset.

Das hat mich 1 Tag meines Lebens gekostet ;) Das müsste man eigentlich 
irrend wo annageln.
#4526081
Lesenswert?

Könnte man ;) Aber wenn man mal so schaut sehr gängig ist das Devices 
nicht. Obwohl ein SAMD21G18 auf dem Arduino Zero ist.

Ich könnte noch einen weiteren Pferdefuß zum besten geben -> Thema 
PinMux. Das hat mich nur 2 Kaffee Längen gekostet. Dies ist auch so 
herrlich missverständlich in der ASF Dokumention beschrieben.
Moderator Persönliche Seite #4526111
Lesenswert?

Marco H. schrieb:
> Könnte man ;)

Mach doch.

> Aber wenn man mal so schaut sehr gängig ist das Devices
> nicht.

Nun, Atmel hat das Renovieren seiner ARM-Linie wohl bisschen lange
vor sich her geschoben.  Die alten SAM3/4 wirken in vieler Hinsicht
doch etwas antik vom Design.  Sie haben sich dann vor paar Jahren
drauf besonnen, dass man der ARMada der Konkurrenz :) auch mal was
moderneres entgegensetzen müsste, sodass sich SAMD & Co. nun erst
allmählich ihren Weg bahnen.

> Ich könnte noch einen weiteren Pferdefuß zum besten geben -> Thema
> PinMux.

Erzähl mal, was denn?
Gast #4540891
Lesenswert?

>Nun, Atmel hat das Renovieren seiner ARM-Linie wohl bisschen lange
>vor sich her geschoben.  Die alten SAM3/4 wirken in vieler Hinsicht
>doch etwas antik vom Design.  Sie haben sich dann vor paar Jahren
>drauf besonnen, dass man der ARMada der Konkurrenz :) auch mal was
>moderneres entgegensetzen müsste, sodass sich SAMD & Co. nun erst
>allmählich ihren Weg bahnen.

Obwohl die Arduinos die SAM-Arms benutzen, scheint STM in punkto 
Bastler-Verbreitung vorne zu liegen. Da gibt es den tollen Teensy 3.2 
und viel extrem billige Arduino-Uno ähnliche Boards mit USB 
Schnittstelle wie die Maple Mini:
http://www.rogerclark.net/stm32f103-and-maple-maple-mini-with-arduino-1-5-x-ide/
Die scheinen so um 4.50$ zu kosten, was schon sehr günstig für 
Arm-Platinen ist.

Etwas ähnlich günstiges habe ich für die SAMD noch nicht gefunden.

Ich glaube, dass solche Bastlerware durchaus zur Verbreitung von 
Prozessoren in der Industrie beitragen kann. Es hat ja eine ganze Weile 
gedauert, bis die Entwicklungsboardhersteller begriffen haben, dass Sie 
ihre Boards irgendwie Arduino-kompatible erscheinen lassen. Mittlerweile 
gibt es von fast jedem Hersteller Boards mit dem etwas verunglückten 
Arduino-Header.
Gast #4540895
Lesenswert?

Der Vorteil der weiten Verbreitung einer MCU-Platform für die Entwickler 
ist die enorme Dokumentations- und Code-Basis im Internet. Da dürfte es 
im Moment mehr für die STMs als für die SAMDs geben.

Heute will ich mich mit der SPI-Schnittstelle des SAMD20 befassen.
Und ich scheine Glück zu haben, hier gibt es ein sehr übersichtliches 
Bare-Metal-Code-Beispiel:
http://atmel.force.com/support/articles/en_US/FAQ/How-to-configure-single-SERCOM-module-with-multiple-interfaces-at-runtime-without-ASF
1
/*
2
 * main.c
3
 *
4
 * Created: 15-09-2014 14:29:56
5
 *  Author: samson.jagadam
6
 */ 
7

8
#include "sam.h"
9

10

11
void init_SAMD20_spi(void)
12
{
13
  /*APBCMASK*/
14
  PM->APBCMASK.reg |= PM_APBCMASK_SERCOM0;
15

16
  /*gclk configuration for sercom0 module*/
17
  GCLK->CLKCTRL.reg |= ((uint16_t)(GCLK_CLKCTRL_GEN_GCLK0_Val|GCLK_CLKCTRL_ID_13_Val|GCLK_CLKCTRL_CLKEN));
18
  
19
  /*reset the SERCOM0 module*/
20
  SERCOM0->SPI.CTRLA.reg |= 1;
21
  
22
  /*wait until reset is done*/
23
  while((SERCOM0->SPI.STATUS.reg & (1<<15)) || (SERCOM0->SPI.CTRLA.reg & 1));
24
  
25
  /*SPI module configuration*/
26
  SERCOM0->SPI.CTRLA.reg |= SERCOM_SPI_CTRLA_MODE_SPI_MASTER;
27
  SERCOM0->SPI.CTRLA.reg |= 1<<16;
28
  
29
  SERCOM0->SPI.BAUD.reg |= ((uint16_t)(SERCOM_SPI_BAUD_BAUD(100)));
30
  
31
  
32
  
33
  /*port mux configuration*/
34
  PORT->Group[0].DIR.reg |= 1<<5;      //CS
35
  PORT->Group[0].PINCFG[4].bit.PMUXEN =1;  //DI
36
  PORT->Group[0].PINCFG[6].bit.PMUXEN =1;  //DO
37
  PORT->Group[0].PINCFG[7].bit.PMUXEN =1;  //SCK
38
  
39
  PORT->Group[0].PMUX[2].reg |= 0x03;
40
  PORT->Group[0].PMUX[3].reg |= 0x33;
41

42
  /*enable sercom0*/
43
  SERCOM0->SPI.CTRLA.reg |= SERCOM_SPI_CTRLA_ENABLE;
44
}
45

46
void write_spi_data(uint8_t data)
47
{
48
  
49
  while(!(SERCOM0->SPI.INTFLAG.reg & 1)); //wait SPI module ready to receive data
50
  PORT->Group[0].OUTCLR.reg = 1<<5;  //CS = low
51
  
52
  SERCOM0->SPI.DATA.reg = data;
53
  while(!(SERCOM0->SPI.INTFLAG.reg & 2)); //wait until TX complete;
54
  
55
  PORT->Group[0].OUTSET.reg = 1<<5;  //CS = high
56
}
Gast #4541414
Lesenswert?

Tja, auf das Internet ist nicht immer Verlass. Der obige Code lässt sich 
nicht compilieren weil die Clock-Configuration nicht stimmt.

Hier die korrigierte Initialisierung des Clocks:
1
GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID_SERCOM0_CORE |// connected  SERCOMx to
2
                    GCLK_CLKCTRL_GEN_GCLK0 |  // generic Clock Generator 0
3
                    GCLK_CLKCTRL_CLKEN ; // and enable it
#4541528
Lesenswert?

Vorsicht beim PINMUX, das ist einer der Pferdefüße.

PINMUX_PA16C_SERCOM1_PAD0

Das macro besteht aus
1
#define PINMUX_PA16C_SERCOM1_PAD0 ((PIN_PA16C_SERCOM1_PAD0 << 16) | MUX_PA16C_SERCOM1_PAD0)


Drei mal raten was die ASF Vorschlägt ? MUX und PIN  das funktioniert so 
natürlich nicht.

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