Forum: Mikrocontroller und Digitale Elektronik Erste Schritte: Bekomme STm32 nicht zum Laufen


von Domenik (Gast)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,

ich habe mir ein CMSIS-Projekt für ein STM32 Discovery-Board aufgebaut 
und wollte nun mal ein bisschen spielen... Leider kam ich nicht dazu, 
nicht einmal einen Port bekam ich gesetzt.

Ich habe mich entlang des Reference Manuals vorgearbeitet und mir die 
entsprechenden Aliasse aus der Datei stm32f0xx.h herausgesucht. Von 
einem Syntaxfehler (ist ja überschaubar) gehe ich jetzt nicht aus...

Kann mir vllt. jemand helfen? Ich vermute, dass es am Takt liegt, da ich 
im BSRR Register das Setzen Bit aktivieren, aber sich im ODR Register 
nichts tut...

void Periph_Init()
{
  RCC->AHBENR |= RCC_AHBENR_GPIOCEN;
// Takt an GPIOC aktivieren

  GPIOC->MODER |= GPIO_MODER_MODER8_0 | GPIO_MODER_MODER9_0;
// PortC.8/.9 als Ausgang setzen
  GPIOC->OTYPER &= ~(GPIO_OTYPER_OT_8 | GPIO_OTYPER_OT_9);
// PortC.8/.9 als Push/Pull setzen
  GPIOC->OSPEEDR &= ~(GPIO_OSPEEDER_OSPEEDR8 | GPIO_OSPEEDER_OSPEEDR9);
// PortC.8/.9 LowSpeed setzen
  GPIOC->PUPDR &= ~(GPIO_PUPDR_PUPDR8 | GPIO_PUPDR_PUPDR9);
// PortC.8/.9 PullUp/Down deaktivieren

  GPIOC->BSRR = GPIO_BSRR_BS_8 | GPIO_BSRR_BS_9;
// PortC.8/.9 highLevel treiben
}

von Uwe B. (Firma: TU Darmstadt) (uwebonnes)


Lesenswert?

Hast Du einen Debugger? Dann lasst die die Werte der GPIO Register 
ausgeben, jenachdem wie kompiliert wuerde mit
 p /x *GPIO1
oder
 p /x *(GPIO_TypeDef*) 0xXXXXXXXX

0xXXXXXXXX musst Du Dir heraussuchen...

von Programmierer (Gast)


Lesenswert?

Versuche mal statt
1
GPIOC->MODER |= GPIO_MODER_MODER8_0 | GPIO_MODER_MODER9_0;
das
1
GPIOC->MODER  = (GPIOC->MODER & ~(GPIO_MODER_MODER8 | GPIO_MODER_MODER9)) | GPIO_MODER_MODER8_0 | GPIO_MODER_MODER9_0;
um das 2. Bit sicher zu löschen.

Statt
1
#define true 1
2
#define false 0
ist zu empfehlen
1
#include <stdbool.h>
zu verwenden.

Sowie
1
void Periph_Init();
durch
1
void Periph_Init(void);
zu ersetzen, da Periph_Init ja keine Parameter nimmt, und nicht beliebig 
viele beliebigen Typs.

von W.S. (Gast)


Angehängte Dateien:

Lesenswert?

Domenik schrieb:
> ich habe mir ein CMSIS-Projekt...
> nicht einmal einen Port bekam ich gesetzt.

Ja, so geht das, wenn man an sowas wie ein Friseur rangeht - und die 
bisherigen eingetrudelten hilflosen Antworten machen die Sache nur noch 
viel schlimmer.

Also mein Rat:
1. lade dir den Keil herunter und benutze ihn in der auf 32 K 
beschränkten Bastelversion. Da hat man wenigstens eine verläßliche 
Basis, wo auch der Assembler mit einer erträglichen Syntax daherkommt. 
Dich mit dem GCC herumschlagen kannst du später immer noch nach 
Belieben.

2. schreib dir deinen Startupcode selber. Als Vorlage kannst du dir die 
angehängte Quelle hernehmen und an die Gegebenheiten deines Controllers 
anpassen. Dazu ist ein Blick in das RefMan nötig, denn nur dort findest 
du das Speicherlayout und die tatsächlichen interruptvektoren.

3. übersetze dann deinen Startupcode mal von Hand - ähh.. per Aufruf des 
Assemblers von der Kommandozeile bzw. Batchdatei.

4. schreib dir dein STM32Fblabla.h selber und füge dort NUR!! das zeugs 
ein, was du tatsächlich brauchst - das sind erstmal wirklich NUR die 
Adressen der in der hardware vorhandenen Register und sonst nix. Also 
beispielsweise etwa so in dieser Art:

/* Ports PA..PG ..wo: RefManual ab Seite 139 */
struct T_GPIO
{ volatile unsigned long CRL;   /* Config Bits 0..7  */
  volatile unsigned long CRH;   /* Config Bits 8..15 */
  volatile unsigned long IDR;   /* Port-Inputs (r/o) */
  volatile unsigned long ODR;   /* Port-Outputs (r/w) */
  volatile unsigned long BSRR;  /* Bit-SetReset:
                                   Bits 0..15->set ODR Bits 0..15,
           Bits 16..31->reset ODR Bits 0..15 */
  volatile unsigned long BRR;   /* Bit-Reset: Bits 0..15->reset ODR Bits 
0..15 */
  volatile unsigned long LCKR;  /* Port lock: freeze CRL, CRH  */
};

#define GPIOA   ((struct T_GPIO*) 0x40010800)
#define GPIOB   ((struct T_GPIO*) 0x40010C00)
#define GPIOC   ((struct T_GPIO*) 0x40011000)
#define GPIOD   ((struct T_GPIO*) 0x40011400)
#define GPIOE   ((struct T_GPIO*) 0x40011800)
#define GPIOF   ((struct T_GPIO*) 0x40011C00)
#define GPIOG   ((struct T_GPIO*) 0x40012000)

Oder je nach deinem Geschmack auch ohne struct's etwa so in dieser Art:
/* Externer Bus */
#define FSMC_BCR1  (*(volatile unsigned long*) 0xA0000000)
#define FSMC_BTR1  (*(volatile unsigned long*) 0xA0000004)


5. dann mache dich an eine vorläufig ganz einfache main.c und setze dort 
erstmal einen Port so auf, wie es dein Board erfordert. Mir ist es in 
solchen Fällen hilfreich, mit sowas zu arbeiten:
/* Hilfsbezeichnungen zum Port-Konfigurieren */
/* Beispiel: #define wert_fuer_pa0  (mode?+conf?)  */
#define input   0     /* Pin ist Input */
#define out10   1     /* Pin ist Output, max. 10 MHz schnell */
#define out2    2     /* Pin ist Output, max.  2 MHz schnell */
#define out50   3     /* Pin ist Output, max. 50 MHz schnell */

#define conf0   0     /* in:analog, out:gpio */
#define conf1   4     /* in:hi-z, out:open drain */
#define conf2   8     /* in:pullup/dn, out:alternate function */
#define conf3  12     /* in:verboten, out:alternate fkt mit open drain 
*/

/* aufgedröselte Port-Konfiguationen: */
/* CNF=0 */
#define in_analog        0
#define out10_gpo        1
#define out2_gpo         2
#define out50_gpo        3
/* CNF=1 */
#define in_gpi           4
#define out10_od         5
#define out2_od          6
#define out50_od         7
/* CNF=2 */
#define in_pupd          8
#define out10_altfu      9
#define out2_altfu      10
#define out50_altfu     11
/* CNF=3 */
#define verboten        12
#define out10_altfu_od  13
#define out2_altfu_od   14
#define out50_altfu_od  15

Die Verwendung von sowas geht dann etwa so:
/* Port B: */
#define wf_PB0   (in_pupd)            /* ?    an Testpunkt */
#define wf_PB1   (in_pupd)            /* ?    an Testpunkt */
#define wf_PB2   (out50)              /* out  Enable für USB-rstout ?? 
*/
#define wf_PB3   (out50_altfu)        /* JTAG TDO */
#define wf_PB4   (out50_altfu)        /* JTAG RST */
#define wf_PB5   (out50_altfu)        /* interrupt CLK vom PS/2 Mini-Din 
*/
#define wf_PB6   (out2_altfu_od)      /* I2C1 SCL (RTC8564)*/
#define wf_PB7   (out2_altfu_od)      /* I2C1 SDA (RTC8564)*/
#define wf_PB8   (in_gpi)             /* in   DATA vom PS/2 Mini-Din */
#define wf_PB9   (in_pupd)            /* ?    an Testpunkt */
#define wf_PB10  (out2_altfu)         /* TXD3 */
#define wf_PB11  (out2_altfu)         /* RXD3 an Messerleiste TTL-Pegel 
*/
#define wf_PB12  (input+conf2)        /* SPI2=I2S  Audio: L/R WCLK */
#define wf_PB13  (input+conf2)        /* SPI2=I2S  SCK */
#define wf_PB14  (input+conf2)        /* SPI2=I2S  MISO */
#define wf_PB15  (input+conf2)        /* SPI2=I2S  MOSI */

#define wf_GPIOB_CRL  (wf_PB0 | (wf_PB1<<4) | (wf_PB2<<8)  | 
(wf_PB3<<12)  | (wf_PB4<<16)  | (wf_PB5<<20)  | (wf_PB6<<24)  | 
(((unsigned)wf_PB7)<<28))
#define wf_GPIOB_CRH  (wf_PB8 | (wf_PB9<<4) | (wf_PB10<<8) | 
(wf_PB11<<12) | (wf_PB12<<16) | (wf_PB13<<20) | (wf_PB14<<24) | 
(((unsigned)wf_PB15)<<28))

und dann hiermit hinein in die Peripherie:
 GPIOB->CRL = wf_GPIOB_CRL;
 GPIOB->CRH = wf_GPIOB_CRH;

So. damit hast du erstmal nen Port verwendbar gemacht (Obiges ist ein 
BEISPIEL und muß auf deine Gegebenheiten übertragen werden!!!!!) und nun 
kanns du wenigstens erstmal ein simples Blinky damit machen.

W.S.

von Meister (Gast)


Lesenswert?

Whoah. Also die Tipps von W.S. machen dich zwar nachher zum echten 
Profi, der Weg zu den ersten Erfolgsergebnissen ist aber IMHO lang. 
Meiner Meinung nach ist das ein späterer Schritt, wenn du ihn den 
irgendwann überhaupt gehen musst.

Mein Tipp: Verwendet die Stm Peripheral Lib oder die Stm32 Cube Library. 
Es gibt auch sehr viele Beispiele von ST für jeden Controller wie du 
dich rantasten kannst. Vorteil: Man neigt dazu nicht alles zu bedenken, 
die Libraries geben einem da einiges auf den Weg, die Beispiele auch.

Noch besser für den Einstieg: Fertige Projekte nutzen und eine gute 
Entwicklungsumgebung mit Debugger Unterstützung. Hier z.B. gibts 
Beispiele http://mikrocontroller.bplaced.net/wordpress/?page_id=744. Die 
Projekte sind mit CooCox nutzbar.

von Patrick B. (p51d)


Lesenswert?

Mal so eine Frage:
Wieso macht sich heute einer noch die Mühe, einen ARM ohne BSP zu 
programmieren? STM hat eine sehr sehr gute Standard Peripheral Library. 
Mit dieser habe ich schon mehrere Industrieprojekte umgesetzt. Klar 
musste man an gewissen Stellen optimieren...

Hier ist der Code für einen STM32F4xx (da der TO nicht weiter auf den 
Typ eingeht.). Sollte aber innerhalb von 30sec auf JEDEN Cortex von STM 
portierbar sein.
1
#include <stm32f4xx_rcc.h>
2
#include <stm32f4xx_gpio.h>
3
4
GPIO_InitTypeDef  GPIO_InitStructure;
5
6
/* GPIOG Periph clock enable */
7
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
8
9
/* Configure PC9 and PC8 in output pushpull mode */
10
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;
11
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
12
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
13
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
14
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
15
GPIO_Init(GPIOC, &GPIO_InitStructure);
16
17
18
GPIO_SetBits(GPIOC, GPIO_Pin_8);
19
GPIO_ResetBits(GPIOC, GPIO_Pin_8);
20
21
// ODER, was je nach Einstellungen effizienter umgesetzt wird
22
/* Set PC9 */
23
GPIOC->BSRRL = GPIO_Pin_9;
24
/* Reset PC9 */
25
GPIOC->BSRRH = GPIO_Pin_9;

Aber wenn man jedesmal das Rad neu erfinden will... Man kennt dann zwar 
den Controller perfekt (jedes Bit), aber das zahlt heute niemand mehr. 
(Meine Meinung, so jetzt könnt Ihr widersprechen).

von klausr (Gast)


Lesenswert?

Habe sowas vor längerer Zeit mal ausprobiert, bin mir nicht mehr ganz 
sicher, aber ich glaube, es hat funktioniert. Probiers mal so:
1
#include "stm32f0xx.h"
2
#define BSRR_VAL        0x0300
3
4
void delay (int a);
5
6
int main(void)
7
{
8
  /*!< At this stage the microcontroller clock setting is already configured,
9
       this is done through SystemInit() function which is called from startup
10
       file (startup_stm32f0xx.s) before to branch to application main.
11
       To reconfigure the default setting of SystemInit() function, refer to
12
       system_stm32f0xx.c file
13
     */
14
15
  /* GPIOC Periph clock enable */
16
    RCC->AHBENR |= RCC_AHBENR_GPIOCEN;
17
18
    GPIOC->MODER |= (GPIO_MODER_MODER8_0 | GPIO_MODER_MODER9_0) ;
19
    /* Configure PC8 and PC9 in output  mode  */
20
21
    GPIOC->OTYPER &= ~(GPIO_OTYPER_OT_8 | GPIO_OTYPER_OT_9) ;
22
    // Ensure push pull mode selected--default
23
24
    GPIOC->OSPEEDR |= (GPIO_OSPEEDER_OSPEEDR8|GPIO_OSPEEDER_OSPEEDR9);
25
    //Ensure maximum speed setting (even though it is unnecessary)
26
27
    GPIOC->PUPDR &= ~(GPIO_PUPDR_PUPDR8|GPIO_PUPDR_PUPDR9);
28
    //Ensure all pull up pull down resistors are disabled
29
30
    while (1) {
31
        /* Set PC8 and PC9 */
32
        GPIOC->BSRR = BSRR_VAL;
33
        delay(500000);
34
        /* Reset PC8 and PC9 */
35
        GPIOC->BRR = BSRR_VAL;
36
        delay(500000);
37
    }
38
    return 0;
39
}
40
41
void delay (int a)
42
{
43
    volatile int i,j;
44
45
    for (i=0 ; i < a ; i++) {
46
        j++;
47
    }
48
    return;
49
}
Quelle: http://www.hertaville.com/stm32f0-gpio-tutorial-part-1.html

von W.S. (Gast)


Lesenswert?

Patrick B. schrieb:
> Wieso macht sich heute einer noch die Mühe, einen ARM ohne BSP zu
> programmieren? STM hat eine sehr sehr gute Standard Peripheral Library.

Wiebitte?
Diese hirnrissige ST-Lib ist der allerletzte Schund. Anstatt für 
irgendetwas einen ordentlichen Treiber zu liefern, bewirkt sie nur 
eines: eine gewaltige Schaumschlägerei ohne Sinn und Verstand.
Das sieht man hier sehr deutlich:

Patrick B. schrieb:
> /* Configure PC9 and PC8 in output pushpull mode */
> GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;
> GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
> GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
> GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
> GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
> GPIO_Init(GPIOC, &GPIO_InitStructure);

Überlege doch mal, was da bei einem 120 Pinner so an Code zusammenkommt, 
bloß dazu, daß die lumpigen GPIO's aufgesetzt werden sollen.
Ich geb dir hier mal ne Gegendarstellung:
/*  Pin-Funktionen aufsetzen */
 GPIOA->CRL = wf_GPIOA_CRL;
 GPIOA->CRH = wf_GPIOA_CRH;
 GPIOB->CRL = wf_GPIOB_CRL;
 GPIOB->CRH = wf_GPIOB_CRH;
 GPIOC->CRL = wf_GPIOC_CRL;
 GPIOC->CRH = wf_GPIOC_CRH;
 GPIOD->CRL = wf_GPIOD_CRL;
 GPIOD->CRH = wf_GPIOD_CRH;
 GPIOE->CRL = wf_GPIOE_CRL;
 GPIOE->CRH = wf_GPIOE_CRH;
 GPIOF->CRL = wf_GPIOF_CRL;
 GPIOF->CRH = wf_GPIOF_CRH;
 GPIOG->CRL = wf_GPIOG_CRL;
 GPIOG->CRH = wf_GPIOG_CRH;

/* Pin-Remap */
 AFIO->MAPR = wf_AFIO_MAPR;

Damit werden ALLE Pins eines STM32F103 aufgesetzt - und das sind 
verdammt viele. Überlege mal, was du mit deinem oben zitierten Gehampel 
mit GPIO_Initstructure.xyz veranstalten müßtest...

Ganz ähnlich sieht das bei peripheren Cores aus. Versuche mal, mit der 
ST-Lib einen tatsächlich zuverlässig arbeitenden USB-VCP aufzusetzen. Da 
landet tonnenweise sinnloser Code in deinem Projekt und den eigentlichen 
VCP mußt du trotzdem noch selber designen.



Patrick B. schrieb:
> Aber wenn man jedesmal das Rad neu erfinden will... Man kennt dann zwar
> den Controller perfekt (jedes Bit), aber das zahlt heute niemand mehr.
> (Meine Meinung, so jetzt könnt Ihr widersprechen).

ja, deine Meinung. Es wäre natürlich viel einfacher, wenn so ein elender 
Hersteller seine Controller mit besseren Quellcodes unterstützen würde 
- aber bei ST ist dies definitiv NICHT der Fall.

Abgesehen erwartet ein Chef tatsächlich, daß jemand wie du den von dir 
verwendeten Controller kennt undnicht wie ein Kind mit Bauklötzchen 
herumspielt, dafür einen teureren Chip braucht und anschließend trotzdem 
stundenlang vor dem Debugger sitzt - eben wegen fehlenen Verstehens ganz 
am Anfang der Entwicklung.

Merke: wer von den Zutaten zu wenig versteht, sitzt später die dreifache 
Zeit am Debugger.

W.S.

von Programmierer (Gast)


Lesenswert?

W.S. schrieb:
> Überlege doch mal, was da bei einem 120 Pinner so an Code zusammenkommt,
> bloß dazu, daß die lumpigen GPIO's aufgesetzt werden sollen.
Ist doch egal, die STM32 haben bis zu Megabytes an Flash. Und da die Pin 
Initialisierung typischerweise eh nur 1x beim starten läuft, macht die 
1ms auch nix.

W.S. schrieb:
> Diese hirnrissige ST-Lib ist der allerletzte Schund.
Ja. Aber den kompletten Header für alle Peripherie-Definitionen (bis zu 
10000 Zeilen) selbst zu schreiben ist nicht hirnrissig? Vor allem wenn 
du die dann genauso schlecht machst wie die von ARM/ST (also mit #define 
statt Konstante usw.)? Come on.

W.S. schrieb:
> dafür einen teureren Chip braucht und anschließend trotzdem
> stundenlang vor dem Debugger sitzt
Du sitzt lieber wochenlang am schreiben von Headern, die man auch vom 
Hersteller herunter laden könnte?

W.S. schrieb:
> 2. schreib dir deinen Startupcode selber.
Hier gilt das selbe wie für den Header - sinnlose Arbeit

... Der Fehler liegt hier höchstwahrscheinlich nicht an einem kaputten 
Header oder Startup-Code von ST. Wenn schon falsch gemessen, falsch 
gestartet, falsche Compiler-Optionen...

PS: Wenn man schon grundsätzlich keinen fremden Code akzeptiert, sollte 
man es wenigstens selber besser können!

von W.S. (Gast)


Lesenswert?

Programmierer schrieb:
> Hier gilt das selbe wie für den Header - sinnlose Arbeit

Für dich scheint alles, was irgendwie nach eigener Arbeit aussieht, eine 
sinnlose Arbeit zu sein. Für solche Leute gibt es ne Reihe von weniger 
schönen Bezeichnungen.

OK, wenn du BWLler bist, dann wäre es aus deiner Sicht das Beste, die 
gesamte Arbeit an ein dafür geeignetes Ingenieurbüro zu vergeben. Da 
brauchst du dich garnicht mehr um Sachdetails zu kümmern, sondern nur um 
andere dir wichtigere Dinge.

Also:
1. Wenn ein Hersteller eine ordentliche prozessortyp.h liefert, dann 
kann man die auch nehmen. Das ist bei ST definitiv NICHT der Fall. Von 
deiner Behauptung "(bis zu 10000 Zeilen)" ist man aber vernünftigerweise 
meilenweit entfernt. Hab hier grad einen .h von NXP vorliegen, 1136 
Zeilen und 74 K Gesamtgröße. Geht doch - da liegst du mit deinen 10000 
Zeilen krass daneben.

2. Für die Verwendung in konkreten Projekten macht man sich auch einen 
sinnvollen Startupcode, denn das, was gemeinhin bei den diversen 
Toolchaines mitgeliefert wird, ist "for evaluation only" und nicht 
wirklich praxistauglich. Siehe Exceptionhandler, die nur aus einem B . 
bestehen. Wenn du mir sowas in einem konkreten Projekt liefern würdest, 
gäbe es ne saftige Abreibung für dich von mir. Ich stell mir grad vor, 
das ABS in meinem Wagen würde bei einem Gewitter in der Nähe eben mal 
auf nen B . aufschlagen bis zum nächsten Start des Wagens...

3. Sowas wie ein wirklich guter Startupcode und eine benutzbare 
prozessor.h sind quasi Anschaffungen für's Prozessorleben. Eine auf 
10000 Zeilen aufgeblasene und mit tausenderlei Bezeichnern angefüllte .h 
ist hingegen schlecht bis unbenutzbar, weil man in all dem überflüssigen 
Zeug praktisch ersäuft. Ist kontraproduktiv und extrem fehlerträchtig - 
man sucht sich halbtot und benutzt dann doch versehentlich hie und da 
mal was völlig Verkehrtes.

4. Und nochwas: wir reden hier von C und da gibt es #define und das 
war's. Punkt.

Aber nochmal zu deinem Beitrag: Anstatt herumzunörgeln und bloß die 
eigene Bequemlichkeit zur Schau zu stellen, wäre ein positiver 
Sachbeitrag zum Lösen des Problems des TO wesentlich sinnreicher 
gewesen.

W.S.

von Patrick B. (p51d)


Lesenswert?

W.S. schrieb:
> Wiebitte?
> Diese hirnrissige ST-Lib ist der allerletzte Schund. Anstatt für
> irgendetwas einen ordentlichen Treiber zu liefern, bewirkt sie nur
> eines: eine gewaltige Schaumschlägerei ohne Sinn und Verstand.
> Das sieht man hier sehr deutlich:

Ok, dafür sind aber die Erratas, die Datenblätter und die App-Notes von 
NXP absoluter Müll.
W.S. schrieb:
> Damit werden ALLE Pins eines STM32F103 aufgesetzt - und das sind
> verdammt viele. Überlege mal, was du mit deinem oben zitierten Gehampel
> mit GPIO_Initstructure.xyz veranstalten müßtest

Mhm, mahl überlegen...
1
#define RCC_AHB1Periph_GPIO_ALL    0x1FF      // Neu definieren
2
3
GPIO_InitTypeDef  GPIO_InitStructure;
4
5
6
/* GPIOG Periph clock enable */
7
RCC_AHB1PeriphClockCmd(  RCC_AHB1Periph_GPIO_ALL, ENABLE);
8
9
/* Configure PC9 and PC8 in output pushpull mode */
10
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All;
11
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
12
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
13
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
14
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
15
GPIO_Init(GPIOA, &GPIO_InitStructure);
16
GPIO_Init(GPIOB, &GPIO_InitStructure);
17
GPIO_Init(GPIOC, &GPIO_InitStructure);
18
GPIO_Init(GPIOD, &GPIO_InitStructure);
19
GPIO_Init(GPIOE, &GPIO_InitStructure);
20
GPIO_Init(GPIOF, &GPIO_InitStructure);
21
GPIO_Init(GPIOG, &GPIO_InitStructure);
22
GPIO_Init(GPIOI, &GPIO_InitStructure);
=> 22 Zeilen gegen 18 (wobei das Clockmanagement bei dir noch fehlt), 
übersichtlich (verständlicher und lesbarer/intepretierbarer Code), und 
als nettes Feature gibts noch die Assertion für jeden Fall (also die 
Redundanz steigt...).

W.S. schrieb:
> Versuche mal, mit der
> ST-Lib einen tatsächlich zuverlässig arbeitenden USB-VCP aufzusetzen. Da
> landet tonnenweise sinnloser Code in deinem Projekt und den eigentlichen
> VCP mußt du trotzdem noch selber designen.

Komisch, bei mir lief das ohne Probleme. Musste auch nichts erweitern, 
da die Lib komplett mit DMA- und Interrupt-Funktionalitäten ausgerüstet 
ist.

W.S. schrieb:
> 2. Für die Verwendung in konkreten Projekten macht man sich auch einen
> sinnvollen Startupcode

Das gilt dann aber auch für das Interrupt handling und das ganze 
Programm. Nur der Startup-Code macht dein Controller nicht 
"unsterblich".

W.S. schrieb:
> Aber nochmal zu deinem Beitrag: Anstatt herumzunörgeln und bloß die
> eigene Bequemlichkeit zur Schau zu stellen, wäre ein positiver
> Sachbeitrag zum Lösen des Problems des TO wesentlich sinnreicher
> gewesen.

Wurde in etwa 3-facher Ausführung mit unterschiedlichen Ansätzen zur 
Verfügung gestellt. Und wir kommen vom Thema ab, so für mich ist hier 
Schluss.

von Programmierer (Gast)


Lesenswert?

W.S. schrieb:
> Programmierer schrieb:
>> Hier gilt das selbe wie für den Header - sinnlose Arbeit
>
> Für dich scheint alles, was irgendwie nach eigener Arbeit aussieht, eine
> sinnlose Arbeit zu sein. Für solche Leute gibt es ne Reihe von weniger
> schönen Bezeichnungen.
Ich verwende meine Arbeitskraft lieber auf sinnvolle Dinge. Zum x.ten 
Mal exakt das gleiche (!!) zu schaffen was schon existiert ist sonnlos.
> Also:
> 1. Wenn ein Hersteller eine ordentliche prozessortyp.h liefert, dann
> kann man die auch nehmen. Das ist bei ST definitiv NICHT der Fall.
Interessant. Wo genau ist jetzt der Unterschied zwischen der 
prozessortyp.h von ST und deinem Vorschlag? Bis darauf dass ST 
wenigstens sinnvollerweise die Adressen berechnet, sodass man sie 
leichter anpassen kann?
> Von
> deiner Behauptung "(bis zu 10000 Zeilen)" ist man aber vernünftigerweise
> meilenweit entfernt.
Stimmt, die stm32f4xx.h ist nur 9194 Zeilen lang.
> Hab hier grad einen .h von NXP vorliegen, 1136
> Zeilen und 74 K Gesamtgröße. Geht doch - da liegst du mit deinen 10000
> Zeilen krass daneben.
Ja, es gibt auch kleine Controller. Und was machst du wenn du einen 
STM32F4 hast?
> 2. Für die Verwendung in konkreten Projekten macht man sich auch einen
> sinnvollen Startupcode, denn das, was gemeinhin bei den diversen
> Toolchaines mitgeliefert wird, ist "for evaluation only" und nicht
> wirklich praxistauglich.

> Siehe Exceptionhandler, die nur aus einem B .
> bestehen. Wenn du mir sowas in einem konkreten Projekt liefern würdest,
> gäbe es ne saftige Abreibung für dich von mir.>
Ich stelle mir gerade vor wie du vermutlich alter verbitterter Sack, der 
nach 30 Jahren Anstellung immer noch auf dem untersten 
Code-Monkey-Posten hockt, deinem vermutlich dann vorgesetzten Software 
Architect eine "Abreibung" geben willst :3

Was hat das "b ." im Startupcode verloren? Nichts. Die Exception-Handler 
kommen in den eigenen C/C++ Code. Das interessiert den Startupcode 
überhaupt nicht.
> Ich stell mir grad vor,
> das ABS in meinem Wagen würde bei einem Gewitter in der Nähe eben mal
> auf nen B . aufschlagen bis zum nächsten Start des Wagens...
Genau, das Gewitter löst ja freundlicherweise einen Lightning_Handler 
aus, den man einfach nur behandeln muss um sämtliche EMV-Probleme aus 
der Welt zu schaffen. Únd das muss natürlich im Startupcode sein, weil 
Interrupthandler im C/C++ Code ja, hm, uncool sind. Wenn "Alle Interrupt 
Handler im Startupcode behandeln" dein Konzept zur Sicherheit ist, dann 
gute Nacht.

> 3. Sowas wie ein wirklich guter Startupcode und eine benutzbare
> prozessor.h sind quasi Anschaffungen für's Prozessorleben. Eine auf
> 10000 Zeilen aufgeblasene und mit tausenderlei Bezeichnern angefüllte .h
> ist hingegen schlecht bis unbenutzbar, weil man in all dem überflüssigen
> Zeug praktisch ersäuft. Ist kontraproduktiv und extrem fehlerträchtig -
> man sucht sich halbtot und benutzt dann doch versehentlich hie und da
> mal was völlig Verkehrtes.
Genau, alle Werte aus dem Manual abschreiben und in die prozessor.h 
schreiben ist total nicht fehleranfällig. Die prozessortyp.h sind 
typischerweise aus der SVD generiert o.ä. ...
Ich verrate dir mal einen Geheimtip: Anständige IDE's haben 
Codenavigation und Strg+F. Da sind ein paar Tausend Zeilen Library-Code 
überhaupt kein Problem. Bei vielen Frameworks zB am PC hat es noch viel 
mehr Bezeichner, und da hat auch (außer dir?) Probleme mit 
durchzublicken.
> 4. Und nochwas: wir reden hier von C und da gibt es #define und das
> war's. Punkt.
Es gibt "static const". Und selbst wenn man meint dumme Textersetzungen 
aus der Zeit er Makro-Assembler verwenden zu müssen, kann man sie 
wenigstens korrekt anwenden, sprich überall Klammern hinpacken.
> Aber nochmal zu deinem Beitrag: Anstatt herumzunörgeln und bloß die
> eigene Bequemlichkeit zur Schau zu stellen, wäre ein positiver
> Sachbeitrag zum Lösen des Problems des TO wesentlich sinnreicher
> gewesen.
Mein Beitrag war auch wesentlich hilfreicher und bezogen auf das 
eigentliche Problem, anstatt deiner üblicher Stänkerei das Rad zum 100. 
Mal neu zu erfinden.

von StandardLib user (Gast)


Lesenswert?

W.S. schrieb:
> Ganz ähnlich sieht das bei peripheren Cores aus. Versuche mal, mit der
> ST-Lib einen tatsächlich zuverlässig arbeitenden USB-VCP aufzusetzen. Da
> landet tonnenweise sinnloser Code in deinem Projekt und den eigentlichen
> VCP mußt du trotzdem noch selber designen.
>

und du hast deinen USB-VCP Code komplett selbst geschrieben ?

solange du davon nicht einen Teil hier postest
(damit man ihn mit dem "Sinnlosen-Code" von ST vergleichen kann)
sage ich da nur : LOL

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.