Forum: Mikrocontroller und Digitale Elektronik ATMEL ARM SAMD ohne Framework programmieren


von chris_ (Gast)


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?

von chris_ (Gast)


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

von chris_ (Gast)


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/

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


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;

von chris_ (Gast)


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.

von chris_ (Gast)


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

von chris_ (Gast)


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
}

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


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.

von chris_ (Gast)


Lesenswert?

Gerade habe ich fest gestellt, dass die Arduino-SAMD library auch keine 
ASF benutzt, sondern die Register direkt anspricht.
Das könnte als Template für eigene Konfigurationen hilfreich sein.

Hier zum Beispiel der ARDUINO-SAMD-ADC:

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

von chris_ (Gast)


Angehängte Dateien:

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?

von chris_ (Gast)


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.

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


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]

: Bearbeitet durch Moderator
von chris_ (Gast)


Angehängte Dateien:

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.

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


Lesenswert?

chris_ schrieb:
> Wobei mir beim besten Willen nicht klar ist, warum PIO_SERCOM_ALT 3 ist.

Das ist der Wert für die Peripheriefunktion D:
1
#define   PORT_PMUX_PMUXE_D_Val           0x3u   /**< \brief (PORT_PMUX) Peripheral function D selected */

: Bearbeitet durch Moderator
von chris_ (Gast)


Lesenswert?

>Das ist der Wert für die Peripheriefunktion D:

Danke. Ich hatte die Zuordnung im Datenblatt gesucht, aber leider nicht 
gefunden.

Hier noch was anderes Interessantes. Eine Application-Note von Atmel für 
das serielle Interface:

http://www.atmel.com/Images/Atmel-42539-SAMD-SERCOM-USART-Configuration_ApplicationNote_AT11626.pdf

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


Angehängte Dateien:

Lesenswert?

chris_ schrieb:
>>Das ist der Wert für die Peripheriefunktion D:
>
> Danke. Ich hatte die Zuordnung im Datenblatt gesucht, aber leider nicht
> gefunden.

Siehe Screenshot.

von Marco H. (damarco)


Lesenswert?

Der Aufwand lohnt sich sich wirklich.  Da die Funktionen der SAM Libs im 
Hintergrund auch nichts anders machen. Aus dem Thread Titel dachte ich 
er an etwas anderes.

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

von chris_ (Gast)


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.

von Marco H. (damarco)


Lesenswert?

Es lohnt sich nicht. Zumal man eine weitere Fehlerquelle aufbaut.

Ein weiteres Problem ist das die Funktionen nicht portable sind, sie 
funktionieren nur für ein Device.

von Bernd K. (prof7bit)


Angehängte Dateien:

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.

: Bearbeitet durch User
von Marco H. (damarco)


Lesenswert?

Man braucht bloß den richtigen Debugger. Die ICE läuft außerhalb von 
Atmel Studio glaube ich nicht.

von Markus (Gast)


Lesenswert?

Zumindest wenn man ein xplain pro kit verwendet kann man endlich den 
edbg chip zu einem original jlink machen

http://embedded-computing.com/news/bringing-xplained-evaluation-kits/

von Wad W. (wad_wer)


Angehängte Dateien:

Lesenswert?

hi,

da ich grade auch mit dem SAMD spiele und auch größten teils ohne ASF 
(ich nehme mir das nötigste raus) arbeite, im Anhang ein SAMD10 template 
(LED blink und fade auf dem SAMD10 Xplained) mit makefile :)

von chris_ (Gast)


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.

von Wad W. (wad_wer)


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.

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


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.

von chris_ (Gast)


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.

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


Lesenswert?

chris_ schrieb:
> Insofern: Ansichtssache.

Naja.  Nein.  Interrupts sind ein wesentlicher Bestandteil aller
Prozessoren.  Es gibt keinen vernünftigen Grund, sie nicht zu
benutzen.

von chris_ (Gast)


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.

von chris_ (Gast)


Lesenswert?

Pin lesen
=========

Gerade eben habe ich festgestellt, dass das Pin-Lesen im obigen 
Code-Beispiel nicht funktioniert:

Beitrag "Re: ATMEL ARM SAMD ohne Framework programmieren"

Der Grund: man muss das INEN-Bit in dem zu dem Pin zugehörigen 
PINCFG-Register setzen, sonst wird das Bit nicht "gesampled".

Sehr Ihr einen Grund, warum man INEN nicht immer eingeschaltet lassen 
soll?

von Wad W. (wad_wer)


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)

von Marco H. (damarco)


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.

von chris_ (Gast)


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.

von chris_ (Gast)


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?

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


Lesenswert?

chris_ schrieb:
> Es sollte wohl keinen so großen Unterschied zwischen einem SAMD20J18 und
> einem SAMD20E17 geben, oder?

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

von chris_ (Gast)


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

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


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.

von Lothar (Gast)


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"

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


Lesenswert?

Lothar schrieb:
> Hat der SAMD20 tatsächlich keinen ROM Bootloader mehr?

Ja, hat er nicht.  SAM-BA gibt's dafür jetzt bei Bedarf sogar als
Quellcode, während man früher ein tolles Geheimnis draus gemacht hat.

Das Teil hat einfach mal keinen ROM.

: Bearbeitet durch Moderator
von Marco H. (damarco)


Lesenswert?

Leider offenbar auch kein Clock Fault, sonst hätte man den Oszillator 
kurz stillgelegt was dann einen Clock Fault auslöst. Worauf dieser auf 
den RC Oszillator umgeschaltet und dann in Hardfault geht.

von Lothar (Gast)


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.

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


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.

von chris_ (Gast)


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.

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


Lesenswert?

Naja, wie schon geschrieben, mit der aktuellen ICE-Firmware bekommst
du den Controller jederzeit wieder losgeeist.  Allerdings brauchst du
dafür das Studio 7.

von chris_ (Gast)


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.

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


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.

von Lothar (Gast)


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.

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


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.

von Lothar (Gast)


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.

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


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.

von chris_ (Gast)


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.

von Lothar (Gast)


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.

von Lothar (Gast)


Lesenswert?

chris_ schrieb:
> Ja, man kann die Geschwindigkeit heruntersetzen. Das habe ich ja oben
> schon beschrieben und gemacht: 32kHz.
> Aber es ging trotzdem nicht.

Das sind dann so 30 us das könnte immer noch zu kurz sein um direkt nach 
dem Reset reinzukommen.

von Marco H. (damarco)


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 ;)

von chris_ (Gast)


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.

von chris_ (Gast)


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"

von chris_ (Gast)


Lesenswert?

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

Du könntest ein AtmelSTART Projekt in ATMEL-Studio importieren, falls Du 
nicht "nativ" programmieren willst:

Beitrag "Arduino Zero mit ArduinoStart Konfigurieren"

von W.S. (Gast)


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.

von Marco H. (damarco)


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.

von Bernd K. (prof7bit)


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

: Bearbeitet durch User
von Marco H. (damarco)


Lesenswert?


von Marco H. (damarco)


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.

von chris_ (Gast)


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.

von Marco H. (damarco)


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.

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


Lesenswert?

Marco H. schrieb:
> Ich bin auch der Meinung das am ASF was fault ist.

Das kann gut sein, aber dann bist du hier im falschen Thread.

Der TE hat diesen Thread ja ausdrücklich ins Leben gerufen für die
Programmierung dieser Teile ohne Frameworks wie ASF.

von Marco H. (damarco)


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.

: Bearbeitet durch User
von Marco H. (damarco)


Lesenswert?

Also auch ohne Bootloader ist der WDT aktiv und verriegelt inkl. dem 
GCLK der ihn treibt.  Ich bin fast der Meinung hier wurde ein 
Montagsmodell verbaut.

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


Lesenswert?

Marco H. schrieb:
> Ich bin fast der Meinung hier wurde ein Montagsmodell verbaut.

Vergiss diese Idee ganz schnell.  Sie zeigt nur, dass du keine Ahnung
hast, wie solche ICs hergestellt werden. ;-)

von Marco H. (damarco)


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.

: Bearbeitet durch User
von Marco H. (damarco)


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.

von Jasson J. (jasson)


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.

von Marco H. (damarco)


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.

von Wad W. (wad_wer)


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

von Marco H. (damarco)


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.

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


Lesenswert?

Marco H. schrieb:
> Das müsste man eigentlich irrend wo annageln.

Vielleicht hier eine Wiki-Seite für die SAMD (und Konsorten) anfangen?

Da könnte auch dieser oder jener Beispielcode mit rein.

von Marco H. (damarco)


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.

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


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?

von chris_ (Gast)


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.

von chris_ (Gast)


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
}

von chris_ (Gast)


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

von Marco H. (damarco)


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.

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


Lesenswert?

Marco H. schrieb:
> #define PINMUX_PA16C_SERCOM1_PAD0

Wofür zum Geier™ sollte dieser Makro überhaupt gut sein?

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.