Forum: Mikrocontroller und Digitale Elektronik Einstieg in ARM


von Felix L. (flex)


Lesenswert?

Hallo,

ich habe mich jetzt eine Zeitlang mit Atmel AVR beschäftigt. Da das 
Preis/Leistungsverhältnis bei ARM Mikrocontrollern besser ist, möchte 
ich gerne umsteigen. Zum Einstieg habe ich mir eine KL25Z Freedom Board 
von Freescale besorgt.
http://www.freescale.com/webapp/sps/site/prod_summary.jsp?code=FRDM-KL25Z&tid=vanFRDM-KL25Z
Es ist möglich das Board über http://www.mbed.org zu programmiern, oder 
über die JTAG Schnittstelle. Da ich einen Segger J-Link besitze, möchte 
ich auch die JTAG Schnittstelle verwenden. Als IDE verwende ich zur Zeit 
IAR Embedded Workbench.

Bei der IDE war ein Beispielprogramm dabei:

blinky.c:
1
#include "common.h"
2
3
#define SLOW_BLINK      (10000000)
4
#define FAST_BLINK      (1000000)
5
#define BLINK_DELAY     FAST_BLINK
6
7
#define RED        (18)
8
#define RED_SHIFT    (1 << 18)
9
#define GREEN      (19)
10
#define GREEN_SHIFT    (1 << 19)
11
#define BLUE      (1)
12
#define BLUE_SHIFT    (1 << 1)
13
14
#define RED_OFF      (GPIOB_PSOR = RED_SHIFT)
15
#define RED_ON      (GPIOB_PCOR = RED_SHIFT)
16
#define RED_TOGGLE    (GPIOB_PTOR = RED_SHIFT)
17
18
#define GREEN_OFF    (GPIOB_PSOR = GREEN_SHIFT)
19
#define GREEN_ON    (GPIOB_PCOR = GREEN_SHIFT)
20
#define GREEN_TOGGLE  (GPIOB_PTOR = GREEN_SHIFT)
21
22
#define BLUE_OFF    (GPIOD_PSOR = BLUE_SHIFT)
23
#define BLUE_ON      (GPIOD_PCOR = BLUE_SHIFT)
24
#define BLUE_TOGGLE    (GPIOD_PTOR = BLUE_SHIFT)
25
26
void delay_time(int);
27
28
/********************************************************************/
29
int main (void)
30
{
31
    printf("\nRunning the blinky project.\n");
32
33
34
  /*
35
   * Initialize the Red LED (PTB18)
36
   */
37
  {
38
    /* Turn on clock to PortB module */
39
    SIM_SCGC5 |= SIM_SCGC5_PORTB_MASK;
40
41
    /* Set the PTB18 pin multiplexer to GPIO mode */
42
    PORTB_PCR18 = PORT_PCR_MUX(1);
43
44
    /* Set the initial output state to high */
45
    GPIOB_PSOR |= RED_SHIFT;
46
47
    /* Set the pins direction to output */
48
    GPIOB_PDDR |= RED_SHIFT;
49
  }
50
51
  /*
52
   * Initialize the Green LED (PTB19)
53
   */
54
  {
55
    /* Turn on clock to PortB module */
56
    SIM_SCGC5 |= SIM_SCGC5_PORTB_MASK;
57
58
    /* Set the PTB19 pin multiplexer to GPIO mode */
59
    PORTB_PCR19 = PORT_PCR_MUX(1);
60
61
    /* Set the initial output state to high */
62
    GPIOB_PSOR |= GREEN_SHIFT;
63
64
    /* Set the pins direction to output */
65
    GPIOB_PDDR |= GREEN_SHIFT;
66
  }
67
68
  /*
69
   * Initialize the Blue LED (PTD1)
70
   */
71
  {
72
    /* Turn on clock to PortB module */
73
    SIM_SCGC5 |= SIM_SCGC5_PORTD_MASK;
74
75
    /* Set the PTD1 pin multiplexer to GPIO mode */
76
    PORTD_PCR1 = PORT_PCR_MUX(1);
77
78
    /* Set the initial output state to high */
79
    GPIOD_PSOR = BLUE_SHIFT;
80
81
    /* Set the pins direction to output */
82
    GPIOD_PDDR |= BLUE_SHIFT;
83
  }
84
85
  while(1)
86
    {
87
    RED_ON;
88
    delay_time(BLINK_DELAY);  /* Red */
89
    RED_OFF;
90
    GREEN_ON;
91
    delay_time(BLINK_DELAY);  /* Green */
92
    GREEN_OFF;
93
    BLUE_ON;
94
    delay_time(BLINK_DELAY);  /* Blue */
95
    RED_ON;
96
    delay_time(BLINK_DELAY);  /* Blue + Red */
97
    GREEN_ON;
98
    BLUE_OFF;
99
    delay_time(BLINK_DELAY);  /* Red + Green */
100
    RED_OFF;
101
    BLUE_ON;
102
    delay_time(BLINK_DELAY);  /* Green + Blue */
103
    RED_ON;
104
    delay_time(BLINK_DELAY);  /* Green + Blue + Red */
105
    GREEN_OFF;
106
    BLUE_OFF;
107
  }
108
}
109
/********************************************************************/
110
111
void delay_time(int number){
112
  int cnt;
113
  for(cnt=0;cnt<number;cnt++);
114
}
115
/********************************************************************/
116
117
/********************************************************************/

Soweit verstehe ich den Code, aber was ich nicht verstehe ist, für was 
ist die common.h?
1
/*
2
 * File:        common.h
3
 * Purpose:     File to be included by all project files
4
 *
5
 * Notes:
6
 */
7
8
#ifndef _COMMON_H_
9
#define _COMMON_H_
10
11
/********************************************************************/
12
13
/*
14
 * Debug prints ON (#define) or OFF (#undef)
15
 */
16
17
#define DEBUG
18
#define DEBUG_PRINT
19
20
/* 
21
 * Include the generic CPU header file 
22
 */
23
#include "arm_cm0.h"
24
25
/* 
26
 * Include the platform specific header file 
27
 */
28
#if (defined(FIREBIRD))
29
  #include "firebird.h"
30
#elif (defined(TOWER))
31
  #include "tower.h"
32
#elif (defined(FREEDOM))
33
  #include "freedom.h"
34
#elif (defined(BACES))
35
  #include "baces.h"
36
#else
37
  #error "No valid platform defined"
38
#endif
39
40
/* 
41
 * Include the cpu specific header file 
42
*/
43
#if (defined (CPU_MKL05Z32LF4))
44
  #include "MKL05Z4.h"
45
#elif (defined(CPU_MKL25Z128LK4))
46
  #include "MKL25Z4.h"
47
#else
48
  #error "No valid CPU defined"
49
#endif
50
51
52
/* 
53
 * Include any toolchain specfic header files 
54
 */
55
#if (defined(__MWERKS__))
56
  #include "mwerks.h"
57
#elif (defined(__DCC__))
58
  #include "build/wrs/diab.h"
59
#elif (defined(__ghs__))
60
  #include "build/ghs/ghs.h"
61
#elif (defined(__GNUC__))
62
  #include "build/gnu/gnu.h"
63
#elif (defined(IAR))
64
  #include "iar.h"
65
#elif (defined(KEIL))
66
  
67
#else
68
#warning "No toolchain specific header included"
69
#endif
70
71
/* 
72
 * Include common utilities
73
 */
74
#include "assert.h"
75
#include "io.h"
76
#include "startup.h"
77
#include "stdlib.h"
78
#include "intrinsics.h"
79
80
/* 
81
 * Global Variable
82
 */
83
84
85
/********************************************************************/
86
87
#endif /* _COMMON_H_ */

Woher bekomme ich die Include, wenn ich ein neues Projekt anlege?

Gruß
Felix

von Pete K. (pete77)


Lesenswert?

Die common.h bringt die IDE mit und sollte im include-path stehen.

von Felix L. (flex)


Lesenswert?

Wenn ich jetzt bei IAR ein neues Projekt anlege, wie sage ich der IDE 
dann, was für einen µC ich verwende? Beim Atmel Studio oder auch beim 
Code Composer Studio kann ich am Anfang immer auswählen, was ich für 
einen µC verwende. Dann werden alle Include Dateien automatisch 
eingefügt. Nur bei IAR habe ich das noch nicht rausgefunden.

Gruß
Felix

von Barnabas (Gast)


Lesenswert?

Danke fürs Posten eines ersten Beispiels auf "Hallo Welt" Niveau! 
Verschafft dem Einsteiger gleich den rechten Einblick in die 
Leichtigkeit des ARM Daseins... Tja, das Preis/Leistungsverhältnis ist 
eben doch nicht alles, aber wer seine wertvolle Zeit dermaßen 
verschleudern will, bitte nur zu :-)

von old man (Gast)


Lesenswert?

Barnabas schrieb:
> Tja, das Preis/Leistungsverhältnis ist
> eben doch nicht alles, aber wer seine wertvolle Zeit dermaßen
> verschleudern will, bitte nur zu :-)

Besser mit der Zeit was dazu lernen als vorgekauten Kram zu benutzen von 
den man nichts versteht. Das macht vielleicht das "Hello World" einfach, 
aber sobald es ans Eingemachte geht wird gemeckert oder hier die 
blödesten Fragen gestellt die man nie gestellt hätte wenn man etwas 
tiefer eingedrungen wäre.

von Juergen G. (jup)


Lesenswert?

Barnabas schrieb:
> aber wer seine wertvolle Zeit dermaßen
> verschleudern will, bitte nur zu :-)

@Barnabas
Wiederverwendbaren Quellcode zu schreiben der auch auf mehreren 
Compilern laeuft scheint wohl ein unbekanntes Terrain fuer Dich zu sein.

Wenn Du die ganzen defines und Compiler Tweaks aus dem o.g. Code 
streichst wird er sehr viel verstaendlicher.

Wenn ich ein minimal Led-Blink-Programm fuer einen Arm und fuer nur 
einen Compiler schreibe, brauche ich 3 Zeilen Code mehr als auf einem 
AVR.

von tom57 (Gast)


Lesenswert?

Hallo guten Morgen,
wenn Du im IAR ein neues Projekt anlegst, hast Du die Möglichkeit über 
Optionen bzw. Einstellungen dieses Projektes auch den Core bzw. Deinen 
Prozessor auszuwählen. Der Projektrumpf wird dann automatisch generiert.

von M. N. (Gast)


Lesenswert?

Felix L. schrieb:
> Wenn ich jetzt bei IAR ein neues Projekt anlege, wie sage ich der IDE
> dann, was für einen µC ich verwende?

Mit linker Maustaste in der Liste "Workspace/Files" den Projektnamen 
anklicken.
Dann unter "Projekt->Options->General Options" die Einstellungen 
vornehmen.

von Felix L. (flex)


Angehängte Dateien:

Lesenswert?

Danke für die Antworten.

Wie ich den Prozessor einstelle habe ich gefunden. Noch eine Frage:
Woher bekomme ich die ganze Includes, die auf dem Screenshot zu sehen 
sind? Sind die bei der IDE dabei, oder wurde die extra für das "Hello 
World" geschrieben?

von M. N. (Gast)


Lesenswert?

Du solltest mit Deiner Maus mehr spielen!
Mit der rechten Taste auf die xxx.h tippen und "Open Containing 
Folder..." auswählen.

von Felix L. (flex)


Lesenswert?

M. N. schrieb:
> Du solltest mit Deiner Maus mehr spielen!
> Mit der rechten Taste auf die xxx.h tippen und "Open Containing
> Folder..." auswählen.

Dann komme ich immer in den Ordner des Beispiels. Im Zielverzeichnis der 
IDE gibt es nur die MKL25Z4.h.

von W.S. (Gast)


Lesenswert?

Felix L. schrieb:
> Wie ich den Prozessor einstelle habe ich gefunden. Noch eine Frage:
> Woher bekomme ich die ganze Includes, die auf dem Screenshot zu sehen
> sind? Sind die bei der IDE dabei, oder wurde die extra für das "Hello
> World" geschrieben?

Wenn du schon damit nicht klarkommst, dann soltest du erstmal ganz unten 
an der Basis anfangen. Vom Überfliegen hat noch keiner was gelernt und 
vom Herumwurschteln in irgendeiner bestimmten IDE mit deren 
Befindlickeiten wird man das Verstehen der ARM-Architektur nicht lernen, 
sondern allenfalls, was irgendwer in irgendwelchen Blinky und HelloWorld 
Programmen für eben diese IDE einem vorgekaut hat.

Mein Rat: Lies erstmal das Manual zum Prozessor. Dann mach dich mit den 
Standalone-Programmen zu deinem Segger vertraut, insbesondere mit dem 
Programm zum Flashen deines µC.

Probiere das dann erstmal aus, ob du Code schreiben, verifizieren und 
auch wieder zurücklesen kannst.

Dann mach dich dran, dir einen eigenen Startupcode zu schreiben. Dabei 
ist "verstehendes Lesen" von Startupcodes anderer Leute durchaus 
hilfreich, aber laß dir das nicht zum Korsett werden. Sieh zu, daß du 
dir diesen Startupcode mit dem Assembler fehlerfrei übersetzt bekommst.

Als nächstes solltest du dir KEIN irgendwo gebotenes Blinky- oder 
HelloWorld-Beispiel nehmen, sondern dir selbst eien Art Minimal-Monitor 
schreiben. Also etwas, mit dem man über ne serielle Schnittstelle 
sprechen kann. Da gibt's hier im Board auch Beispiele dafür, such mal 
nach der "Lernbetty". Davon kannst du dir ne Menge relativ 
hardwareunabhängiger Teile nehmen (Quellen lesen und verstehen 
vorausgesetzt).

So ein Minimal-Monitor ist ne wichtige Sache, denn er ist quasi wie der 
Fuß in der Tür für den geübten Vertreter. Läuft erstmal sowas auf einem 
µC, dann ist die Tür offen für alles Weitere.

Und zum Schluß noch ein paar Ratschläge:
- laß sowas wie printf lieber bleiben. Schreib dir ein paar simplere 
Funktionen, um irgendwas zu irgendeiner Schnittstelle herauszukriegen. 
Das reduziert die Fehlermöglichkeiten.
- sieh zu, nicht alles und jedes Headerfile einzubinden, sondern 
wirklich nur das, was du WIRKLICH brauchst. Ich weiß, daß gerade bei 
einigen tollen Hardwareherstellern sowas wie deren noch viel tollere 
Standardbibliotheken haufenweise Headerfiles aller Art einbinden, bis 
man als Einsteiger sich zugeschüttet fühlt. Siehe deine Frage. Also: Laß 
erstmal all diesen Kram beiseite für den Anfang.

Das was du immer brauchst, sind die Verweise auf die typabhängigen 
Register in der Hardware. Ob das nun in einem Sammel-Headerfile ist oder 
jeweils intern in den diversen Treiber-Quellen für die einzelnen 
Peripherie-Teile, ist eigentlich egal. Es gibt aber noch ein elendes 
Ärgernis: Häufig muß man sehen, daß in fertigen Headerfiles die 
Registerbezeichnungen anders sind als im Hardware-Manual. Sowas ist 
Ober-Bockmist, denn wenn man mit jemand anderem über HW-Probleme reden 
will, ist Babylon angesagt: keiner versteht den anderen. Ich hab mir 
genau deswegen inzwischen angewöhnt, in solchen Fällen mir meine eigenen 
Headerfiles zu schreiben - und zwar mit exakt den gleichen 
Registerbezeichnungen wie in der Hardware-Doku.

W.S.

von Felix L. (flex)


Lesenswert?

Hallo,

vielen Dank für die sehr ausführliche Antwort.

W.S. schrieb:
> Mein Rat: Lies erstmal das Manual zum Prozessor.

Damit meinst du das hier?:
http://cache.freescale.com/files/32bit/doc/ref_manual/KL25P80M48SF0RM.pdf

W.S. schrieb:
> Dann mach dich dran, dir einen eigenen Startupcode zu schreiben. Dabei
> ist "verstehendes Lesen" von Startupcodes anderer Leute durchaus
> hilfreich, aber laß dir das nicht zum Korsett werden.

Was genau macht ein Startup Code? Bei z.B. Keil wird man beim erstellem 
eines Projektes immer gefragt, ob der Startupcode mit eingefügt werden 
soll.

W.S. schrieb:
> Ich hab mir
> genau deswegen inzwischen angewöhnt, in solchen Fällen mir meine eigenen
> Headerfiles zu schreiben - und zwar mit exakt den gleichen
> Registerbezeichnungen wie in der Hardware-Doku.

Wenn die Header File aber vom selben Hersteller kommt, wie der µC, dann 
sollte das doch sitmmen? z.B.die MKL25Z4.h

Gruß
Felix

von Mops Fidibus (Gast)


Lesenswert?

@Felix: Welche konkrete Anwendung schwebt Dir eigentlich vor die den 
ganzen Aufwand hier rechtfertigt?

von W.S. (Gast)


Lesenswert?

Felix L. schrieb:
> Was genau macht ein Startup Code?

Ei was macht er wohl?

Stell dir vor, es ist kurz nach dem Reset und der prozessor kriegt 
seinen ersten Takt. Was wird er da wohl machen? Klar, das, was seine 
Konstrukteure ihm an Funktionalität gegeben haben. Er fängt also auf 
irgend eine Weise an zu arbeiten und das, was er dabei sinnvollerweise 
tun sollte ist, deinen Startupcode abzuarbeiten.

Was du dort unterbringst, ist deinen Erwägungen überlassen.
Ich setze dort die diversen Stacks auf, behandle Exceptions (sofern 
vorgekommen), arrangiere den Takt und starte anschließend "main".

Es ist wohl doch besser, du vertiefst dich erstmal in die Lektüre zu 
deinem Prozessor. Ist ein Cortex M0+ ja? Dann lies auch zusätzlich die 
zugehörigen PDF's von ARM. Anschließend sollte es dir so einigermaßen 
klar sein, wie man mit diesem Chip umgeht.

Felix L. schrieb:
> Wenn die Header File aber vom selben Hersteller kommt, wie der µC, dann
> sollte das doch sitmmen? z.B.die MKL25Z4.h

Vertrauen ist gut, Kontrolle ist besser - und haarsträubende 
Bitfelder-Konstrukte, wie sie manche Hersteller offenbar lieben, sind 
schlechter. Mein Rat (immer wieder): Schreib einen einfachen Stil, 
verzichte auf "tolle" C-Features, Macros und halsbrecherische 
Preprozessor-Akrobatik. Benutze #define's sparsam und nicht ausufernd 
und vermeide sowas wie #ifdef. Und überlasse das Optimieren dem 
Compiler.

W.S.

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.