Forum: Mikrocontroller und Digitale Elektronik stm32f103c8 lässt sic nich flashen


von grundschüler (Gast)


Lesenswert?

Habe dieses board -

http://www.ebay.de/itm/1-2-5-10Stks-STM32F103C8T6-ARM-STM32-Minimum-System-Development-Board-Module-/272425764978?var=&hash=item3f6dd74872:m:mrAOyKktZjIFkrwmEnoO1Mg 
-

vergeblich versucht mittels St-Link V2 zu flashen.
Fehlermeldung coide:
C:\CooCox\CoIDE>"C:/CooCox/CoIDE/bin\coflash.exe" program STM32F103C8 
"C:/CooCox/CoIDE/workspace/y/y/Debug/bin/y.elf" --adapter-name=ST-Link 
--port=SWD --adapter-clk=1000000 --erase=affected --reset=SYSRESETREQ 
--driver="C:/CooCox/CoIDE/flash/STM32F10x_MD_64.elf"
Erase:   Done
Program:   Failed
Error: Flash driver function execute error



vom Hersteller aufgespieltes Blink-programm läuft noch, so dass erase 
offenbar auch nicht geht.

Alle möglichen jumper-Stellungen des bootladers durchprobiert. Chip ist 
richtig ausgewählt.

103VE lässt sich flashen, also link und coide in Ordnung.

Hat jemand eine Idee, was der Fehler sein könnte?

von SMD-Bastler (Gast)


Lesenswert?

Probier mal den ST Visual programmer :

http://www.st.com/en/development-tools/stvp-stm32.html

Wenn der nicht geht, liegt es an der Hardware.

von Pete K. (pete77)


Lesenswert?

Zu lange Kabel?

von Zu lange Kabel? (Gast)


Lesenswert?

Oder:

Vor dem  Starten des Programmiervorgangs den Reset Knopf gedrückt halten 
und
erst nach dem Start loslassen.

Könnte sein, dass die existierende Firmware die für SWD benötigten Pins
umprogrammiert hat.

von W.S. (Gast)


Lesenswert?

grundschüler schrieb:
> Alle möglichen jumper-Stellungen des bootladers durchprobiert. Chip ist
> richtig ausgewählt.

Also, was willst du benutzen? Den Bootlader oder SWD? Das sind zwei 
verschiedene Dinge.

Frage:
Schaffst du es, aus deinem "STM32F10x_MD_64.elf" ein dazu passendes 
Hexfile oder Binärfile zu erzeugen? Also FromElf oder ObjCopy benutzen?

Wenn ja, dann lade dir den Stm32Prog hier aus dem Forum herunter und 
versuche dein Glück damit. Dort kannst du alles in Einzelschritten tun, 
also Löschen, Leertest, Programmieren usw.

W.S.

von noreply@noreply.com (Gast)


Lesenswert?

Ich habe mit einen Discovery-Board die Platinen schon programmiert.

Platine an Discovery-Board über SWD anschließen. Vorher bestimmte Jumper 
auf dem Discovery-Board ziehen.
Discovery-Board mit USB an Linux-PC.
Open-OCD auf Linux-PC draufinstallieren.

von grundschüler (Gast)


Lesenswert?

Danke erstmal für die Unterstützung.

Kabel sind ca. 40cm. Kann daran eigentlich nicht liegen, weil 103VE und 
103ZE damit geflasht werden können.

>Also, was willst du benutzen? Den Bootlader oder SWD? Das sind zwei
verschiedene Dinge.
Wenns irgend geht, SWD, einfach weil ich noch nie - außer bei asuro? - 
einen bootlader benutzt habe. Es fehlt mit auch das passende Kabel für 
den usb-Usart. Wenn ich das passende Kabel finde, werde ich deinen 
Bootlader mal ausprobieren.

>Probier mal den ST Visual programmer :
werde ich probieren.

>Vor dem  Starten des Programmiervorgangs den Reset Knopf gedrückt halten
hat nicht geholfen

aus der Fehlermeldung:
adapter-clk=1000000
Kann man den Takt irgendwie herabsetzen?

Der 103C8 ist doch ein Massenprodukt. Hat jemand Erfahrung mit flashen 
mittels link-v2?

von STMler (Gast)


Lesenswert?

Bei diesen China-Boards ist meistens der Schreibschutz der Controller 
gesetzt (Warum auch immer...).
Einfach mit dem ST-Tool den Schreibschutz entfernen und das Ganze läuft.

von grundschüler (Gast)


Lesenswert?

STMler schrieb:
> Schreibschutz
> ST-Tool

Hört sich gut an. Wo finde ich dieses tool?

von SMD-Bastler (Gast)


Lesenswert?

ST-Tool = ST Visual programmer

von Cyborg (Gast)


Lesenswert?

Welche Datei hast du denn versucht zu flashen?
Versuch doch mal eine andere Datei aus dem Netz zu flashen,
aber die muss natürlich compiliert sein. Der Quelltext geht
da natürlich nicht, nie.

von STMler (Gast)


Lesenswert?

grundschüler schrieb:
> STMler schrieb:
>> Schreibschutz
>> ST-Tool
>
> Hört sich gut an. Wo finde ich dieses tool?


http://www.st.com/content/st_com/en/products/embedded-software/development-tool-software/stsw-link004.html

von grundschüler (Gast)


Lesenswert?

STMler schrieb:
> grundschüler schrieb:
> http://www.st.com/content/st_com/en/products/embed...

schon gedownloadet. jetzt fehlt eprcore60.dll und wahrscheinlich noch 
mehr. Scheint zu st-link zu gehören.

Schluss für heute...

von hp-freund (Gast)


Lesenswert?


von bla (Gast)


Lesenswert?

Massekabel vom ST-link-Programmer nicht vergessen! Ansonsten einfach mal 
via USART einen FullChip-Erease(mit FTDI) durchführen.
http://www.st.com/en/development-tools/flasher-stm32.html

von Zu lange Kabel? (Gast)


Lesenswert?

Ich wiederhole  mich:

Zu lange Kabel? schrieb:
> Oder:
>
> Vor dem  Starten des Programmiervorgangs den Reset Knopf gedrückt halten
> und
> erst nach dem Start loslassen.
>
> Könnte sein, dass die existierende Firmware die für SWD benötigten Pins
> umprogrammiert hat.

von grundschüler (Gast)


Lesenswert?

hp-freund schrieb:
> Fehlt wohl der Treiber:

stlink v2 nochmal installiert. Funktioniert mit 103ve. eprcore60.dll 
nicht gefunden.

stvp ist wohl nur eine oberfläche, die den Zugriff auf verschiedene 
Programmer ermöglicht - wie coflash.exe.

Mit coflash.exe direkt ist es mir nun gelungen, einen "erase" 
auszuführen: es blinkt nichts mehr. Lässt sich aber auch nicht neu 
beschreiben.

Das ganze macht so keinen Spaß.

Ich schmeiß die Dinger weg und bestell mir noch einen 103ve

von Andreas R. (daybyter)


Lesenswert?

Mal unter Linux probieren?

von grundschüler (Gast)


Lesenswert?

Zu lange Kabel? schrieb:
> Vor dem  Starten des Programmiervorgangs den Reset Knopf gedrückt halten
>> und
>> erst nach dem Start loslassen.

alles in allen denkbaren Varianten erfolglos probiert


>> Könnte sein, dass die existierende Firmware die für SWD benötigten Pins
>> umprogrammiert hat.

Unwahrscheinlich da Massenprodukt und der blinkende pin c13 sicher nicht 
ein swd-pin ist.

von grundschüler (Gast)


Lesenswert?

Andreas R. schrieb:
> Mal unter Linux probieren?

Es geht irgendwas vermutlich richtig in den usb-link rein, denn es geht 
ja mit dem 103ve.

Dann ist irgendwo zwischen link und 103c8 ein problem.

Jetzt noch das Betriebssystem wechseln ist mir zu heftig. Wenn 
103c8-Stm-chips nicht einfach funktionieren nehm ich halt was anderes.

von flupp (Gast)


Lesenswert?

Ich hab dke dinger auch. Hast du den schreibschutz entfernt? Musste ich 
zwar nicht aber soll vorkommen das es noetig ist. Bei mir funktionieten 
die dinger uebrigens tadellos

von flupp (Gast)


Lesenswert?

Bevor du die wegwirfst schenk sie lieber mir ^^

von john doe (Gast)


Lesenswert?

Wir hatten für ein Projekt hundert dieser <€1,50 Boards bei 
verschiedenen chinesischen Anbietern gekauft.
Zuerst sind wir auch fast verzweifelt, als wir die unter Linux nicht 
flashen konnten.

Nach zwei Tagen Experimentieren haben wir dann mal auf einem Windows-PC 
die Teile mit dem ST-Tool angesehen und wie oben schon berichtet, war 
auf ALLEN der Schreibschutz gesetzt. Was sich die Chinesen dabei gedacht 
haben???

Nach dem Entfernen lief unter Linux alles wunderbar.

von grundschüler (Gast)


Lesenswert?

john doe schrieb:
> die Teile mit dem ST-Tool angesehen und wie oben schon berichtet, war
> auf ALLEN der Schreibschutz gesetzt. Was sich die Chinesen dabei gedacht


Schreibschutz hört sich plausibel an. Dagegen spricht nur, dass das 
"erase" inzwischen geklappt hat. Das st-tool läuft -wie oben 
beschrieben- nicht. Müsste micht in die st-tool-dokumentation 
einarbeiten. Die Zeit verwende ich lieber auf mein Projekt.

von flupp (Gast)


Lesenswert?

grundschüler schrieb:
> john doe schrieb:
>> die Teile mit dem ST-Tool angesehen und wie oben schon berichtet, war
>> auf ALLEN der Schreibschutz gesetzt. Was sich die Chinesen dabei gedacht
>
> Schreibschutz hört sich plausibel an. Dagegen spricht nur, dass das
> "erase" inzwischen geklappt hat. Das st-tool läuft -wie oben
> beschrieben- nicht. Müsste micht in die st-tool-dokumentation
> einarbeiten. Die Zeit verwende ich lieber auf mein Projekt.

"Erase" ist etwas ganz anderes als "write".

von flupp (Gast)


Lesenswert?


von W.S. (Gast)


Lesenswert?

john doe schrieb:
> Nach zwei Tagen Experimentieren haben wir dann mal auf einem Windows-PC
> die Teile mit dem ST-Tool angesehen und wie oben schon berichtet, war
> auf ALLEN der Schreibschutz gesetzt. Was sich die Chinesen dabei gedacht
> haben???

Ich habe da so eine Idee: möglicherweise ist dort überall die Firmware 
des ST-Link's drauf. Die gibt's im Netz auch separat und sie wird wohl 
ganz gern als Test genommen: FW drauf und gucken wie es blinkt und wie 
sich das Teil am USB anmeldet.

Das hilft ein Bulkerase.

W.S.

von grundschüler (Gast)


Lesenswert?

flupp schrieb:
> ahso
>
> guckst du hier:
>
> Youtube-Video "Short Tutorial: How To Start Programming STM32 Arduino
> MCUs"



Meine Nerven. Das war der entscheidende Hinweis. Alten usb-to-serial 
gesucht und irgendwo auch gefunden. Alles genau so gemacht wie im Video, 
Schreibschutz entfernt. mit link-v2 eigenes blinkprogramm aufgespielt. 
Es blinkt!


Respekt für alle Beiträge aus dem Forum. Ohne diese Hilfe hätte ich 
keine Chance gehabt.

von Klugscheißer (Gast)


Lesenswert?

Denke auch an den wahrscheinlich falsch bestückten Widerstand falls Du 
USB benutzen möchtest!

von Markus M. (Firma: EleLa - www.elela.de) (mmvisual)


Lesenswert?

Mache ein Update von der ST-Link/V2 Firmware und versuche es noch 
einmal.

http://www.st.com/content/st_com/en/products/embedded-software/development-tool-software/stsw-link004.html

von grundschüler (Gast)


Lesenswert?

Entschädigt wird man durch im Vergleich zum AVR gewaltige Rechenleistung 
der 3€-boards und durch den -im Vergleich zu winAVR- sehr hilfreichen 
Coide-debugger. Hier mal ein Vorschlag zur Vermeidung der 
stm-Structuren:
1
#define GLUE(a, b)  a##b
2
#define GPIO(x)         GLUE(GPIO, x)
3
#define PORTA 0
4
#define PORTB 1
5
#define PORTC 2
6
#define PORTD 3
7
#define PORT(x)         GLUE(PORT, x)
8
9
#define pinDIRout(port,pin) {*(uint32_t*)(GPIOA_BASE + PORT(port) *0x400 + (pin/8)*4)&=~(0b1111<<(4*(pin%8)));*(uint32_t*)(GPIOA_BASE + PORT(port) *0x400 + (pin/8)*4)|=(0b0011<<(4*(pin%8)));}
10
11
#define pinDIRin(port,pin) {*(uint32_t*)(GPIOA_BASE + PORT(port) *0x400 + (pin/8)*4)&=~(0b1111<<(4*(pin%8)));*(uint32_t*)(GPIOA_BASE + PORT(port) *0x400 + (pin/8)*4)|=(0b1000<<(4*(pin%8)));}
12
13
#define pinSET(x,y)        GPIO(x)->ODR|=(1<<y)
14
#define pinCLR(x,y)        GPIO(x)->ODR&=~(1<<y)
15
#define pinTOG(x,y)        GPIO(x)->ODR^=(1<<y)

von Nico W. (nico_w)


Lesenswert?

grundschüler schrieb:
> #define pinSET(x,y)        GPIO(x)->ODR|=(1<<y)
> #define pinCLR(x,y)        GPIO(x)->ODR&=~(1<<y)

Guck mal nach dem BSR und BRR. Das ist noch nen Tick schneller ohne 
R/M/W.

von Markus M. (Firma: EleLa - www.elela.de) (mmvisual)


Lesenswert?

Man sollte immer BSR / BRR zur Manipulation verwenden, nur in 
Ausnahmefällen ODR. Damit wird das ganze Interruptsicher.

von W.S. (Gast)


Lesenswert?

grundschüler schrieb:
> Hier mal ein Vorschlag zur Vermeidung der
> stm-Structuren:

Ja, eben. Solche Denkweisen kommen angesichts dessen, was man hier seit 
Jahren lesen muß, immer wieder von AVR-Leuten.

mein ganz dringender Rat dazu: Löse dich von solcher Denke. Die Ports in 
den Controllern der ARM-Riege sind was Anderes als das, was man früher 
bei AVR gehabt hat.

Es gibt bei den Cortexen deutlich effizientere Port-Benutzungsmethoden, 
angefangen von Write-only-Registern zum Setzen und Rücksetzen von Pins 
bis hin zu Bitfeldern, wo jedes Pin quasi als ein bool oder longbool 
angesprochen werden kann.

Irgendwelche Pseudo-Vereinheitlichungen a la "#define PORTC 2" und so 
sind überhaupt nicht hilfreich, sondern schaffen bloß einen uneffektiven 
Code.

Stattdessen solltest du wirklich das RefManual lesen und dich mit dem 
Gebrauch der GPIO-Peripheriecores und deren Registern, also der echten 
Hardware vertraut machen.

W.S.

von grundschüler (Gast)


Lesenswert?

W.S. schrieb:
> deutlich effizientere Port-Benutzungsmethoden

Schau dir mal im Debugger an, was bei der Abarbeitung einer Structur 
passiert.

z.B. dieser Befehl
 {*(uint32_t*)(GPIOA_BASE + PORT(port) *0x400 + 
(pin/8)*4)&=~(0b1111<<(4*(pin%8)));
für das Setzen eine Registers + sehr viel mehr völlig überflüssige 
Befehle. Ich habe ger übersichtlichen Code bei dem ich weiß, was die mcu 
macht.

Du kannst davon ausgehen, dass ich mich mit dem Aufbau der Register 
beschäftigt habe, weil ich sie ohne structs direkt ansprechen kann. Ohne 
Lesen des Manuals wird man dies nicht können. Gerade das ist es, was 
mich an Stm-Structuren stört, dass sie sich nicht auf das Manual 
zurückführen lassen.

>  Die Ports in den Controllern der ARM-Riege sind was Anderes als das, was
>  man früher bei AVR gehabt hat.

Register sind Register. So groß sind die Unterschiede gar nicht.

Mit ODR / BSR,BSRR habt ihr sicher recht. Das wird noch geändert.

von Nico W. (nico_w)


Lesenswert?

Die CMSIS-Struktur ist sehr stark am Datenblatt.

Ich habe mir das einmal für den STM32F411 zusammenkopiert: 
https://github.com/Traumflug/Teacup_Firmware/blob/arm-stm32f411-port/cmsis-stm32f4xx.h

Lesen und schreiben z.B. so:
1
/// Read a pin.
2
  #define _READ(IO)     (IO ## _PORT->IDR & MASK(IO ## _PIN))
3
  /// Write to a pin.
4
  #define _WRITE(IO, v) \
5
    do { \
6
      if (v) \
7
        IO ## _PORT->BSRR = MASK(IO ## _PIN); \
8
      else \
9
        IO ## _PORT->BSRR = MASK((IO ## _PIN + 16)); \
10
    } while (0)

Den Rest kannst du dir hier ansehen.
https://github.com/Traumflug/Teacup_Firmware/blob/arm-stm32f411-port/pinio.h#L117

Pin-Definitionen: 
https://github.com/Traumflug/Teacup_Firmware/blob/arm-stm32f411-port/arduino_stm32f411.h

Da ist dann nix überflüssig und auch andere können mit dem Code was 
anfangen.

grundschüler schrieb:
> ~(0b1111<<(4*(pin%8)))

Was das bedeutet, weißt du sicher in einer Woche selbst nicht mehr.

: Bearbeitet durch User
von grundschüler (Gast)


Lesenswert?

Nico W. schrieb:
> Was das bedeutet, weißt du sicher in einer Woche selbst nicht mehr.

Das hab ich einmal gemacht und interessiert mich gar nicht mehr. Ich 
wüsste aber immer, dass hier die für pin zuständigen Werte im dafür 
zuständigen Register gelöscht werden.
1
   do { \
2
      if (v) \
3
        IO ## _PORT->BSRR = MASK(IO ## _PIN); \
4
      else \
5
        IO ## _PORT->BSRR = MASK((IO ## _PIN + 16)); \
6
    } while (0)

Die while-0-Schleife verstehe ich nicht. Die if-abfrage ist überflüssig.

W.S. schrieb:
> deutlich effizientere Port-Benutzungsmethoden

Ich zitiere mal aus einer früher geführten Diskussion:
"Ob man nun UART0->TRH = MyByte; oder nach anderer Deklaration UART0THR 
=
MyByte; schreibt, ist damit egal und das Verwenden von Struct's führt zu
keinerlei Vorteil. Da ist mir das separate Deklarieren mit exakt den
gleichen Namen wie im RefMan bedeutend lieber."
Beitrag "Re: LPC Registerzugriff Fehler in LPC176x.h"

genau meine Meinung. Mine #defines beruhen auf dem früheren nxp-Konzept 
in z.B. der lpc1768x.h Datei. Da sind auch solche #defines enthalten. 
Kann also nicht so ganz falsch sein.






Die Stm-routine zum Setzen von wenigen Registern auf Eingan/Ausgang ist 
einfach nur grausam:
1
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct)
2
{
3
  uint32_t currentmode = 0x00, currentpin = 0x00, pinpos = 0x00, pos = 0x00;
4
  uint32_t tmpreg = 0x00, pinmask = 0x00;
5
  /* Check the parameters */
6
  assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
7
  assert_param(IS_GPIO_MODE(GPIO_InitStruct->GPIO_Mode));
8
  assert_param(IS_GPIO_PIN(GPIO_InitStruct->GPIO_Pin));  
9
  
10
/*---------------------------- GPIO Mode Configuration -----------------------*/
11
  currentmode = ((uint32_t)GPIO_InitStruct->GPIO_Mode) & ((uint32_t)0x0F);
12
  if ((((uint32_t)GPIO_InitStruct->GPIO_Mode) & ((uint32_t)0x10)) != 0x00)
13
  { 
14
    /* Check the parameters */
15
    assert_param(IS_GPIO_SPEED(GPIO_InitStruct->GPIO_Speed));
16
    /* Output mode */
17
    currentmode |= (uint32_t)GPIO_InitStruct->GPIO_Speed;
18
  }
19
/*---------------------------- GPIO CRL Configuration ------------------------*/
20
  /* Configure the eight low port pins */
21
  if (((uint32_t)GPIO_InitStruct->GPIO_Pin & ((uint32_t)0x00FF)) != 0x00)
22
  {
23
    tmpreg = GPIOx->CRL;
24
    for (pinpos = 0x00; pinpos < 0x08; pinpos++)
25
    {
26
      pos = ((uint32_t)0x01) << pinpos;
27
      /* Get the port pins position */
28
      currentpin = (GPIO_InitStruct->GPIO_Pin) & pos;
29
      if (currentpin == pos)
30
      {
31
        pos = pinpos << 2;
32
        /* Clear the corresponding low control register bits */
33
        pinmask = ((uint32_t)0x0F) << pos;
34
        tmpreg &= ~pinmask;
35
        /* Write the mode configuration in the corresponding bits */
36
        tmpreg |= (currentmode << pos);
37
        /* Reset the corresponding ODR bit */
38
        if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPD)
39
        {
40
          GPIOx->BRR = (((uint32_t)0x01) << pinpos);
41
        }
42
        else
43
        {
44
          /* Set the corresponding ODR bit */
45
          if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPU)
46
          {
47
            GPIOx->BSRR = (((uint32_t)0x01) << pinpos);
48
          }
49
        }
50
      }
51
    }
52
    GPIOx->CRL = tmpreg;
53
  }
54
/*---------------------------- GPIO CRH Configuration ------------------------*/
55
  /* Configure the eight high port pins */
56
  if (GPIO_InitStruct->GPIO_Pin > 0x00FF)
57
  {
58
    tmpreg = GPIOx->CRH;
59
    for (pinpos = 0x00; pinpos < 0x08; pinpos++)
60
    {
61
      pos = (((uint32_t)0x01) << (pinpos + 0x08));
62
      /* Get the port pins position */
63
      currentpin = ((GPIO_InitStruct->GPIO_Pin) & pos);
64
      if (currentpin == pos)
65
      {
66
        pos = pinpos << 2;
67
        /* Clear the corresponding high control register bits */
68
        pinmask = ((uint32_t)0x0F) << pos;
69
        tmpreg &= ~pinmask;
70
        /* Write the mode configuration in the corresponding bits */
71
        tmpreg |= (currentmode << pos);
72
        /* Reset the corresponding ODR bit */
73
        if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPD)
74
        {
75
          GPIOx->BRR = (((uint32_t)0x01) << (pinpos + 0x08));
76
        }
77
        /* Set the corresponding ODR bit */
78
        if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPU)
79
        {
80
          GPIOx->BSRR = (((uint32_t)0x01) << (pinpos + 0x08));
81
        }
82
      }
83
    }
84
    GPIOx->CRH = tmpreg;
85
  }
86
}
87
88
/**
89
  * @brief  Fills each GPIO_InitStruct member with its default value.
90
  * @param  GPIO_InitStruct : pointer to a GPIO_InitTypeDef structure which will
91
  *         be initialized.
92
  * @retval None
93
  */
94
void GPIO_StructInit(GPIO_InitTypeDef* GPIO_InitStruct)
95
{
96
  /* Reset GPIO init structure parameters values */
97
  GPIO_InitStruct->GPIO_Pin  = GPIO_Pin_All;
98
  GPIO_InitStruct->GPIO_Speed = GPIO_Speed_2MHz;
99
  GPIO_InitStruct->GPIO_Mode = GPIO_Mode_IN_FLOATING;
100
}
101
102
/**
103
  * @brief  Reads the specified input port pin.
104
  * @param  GPIOx: where x can be (A..G) to select the GPIO peripheral.
105
  * @param  GPIO_Pin:  specifies the port bit to read.
106
  *   This parameter can be GPIO_Pin_x where x can be (0..15).
107
  * @retval The input port pin value.
108
  */
109
uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
110
{
111
  uint8_t bitstatus = 0x00;
112
  
113
  /* Check the parameters */
114
  assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
115
  assert_param(IS_GET_GPIO_PIN(GPIO_Pin)); 
116
  
117
  if ((GPIOx->IDR & GPIO_Pin) != (uint32_t)Bit_RESET)
118
  {
119
    bitstatus = (uint8_t)Bit_SET;
120
  }
121
  else
122
  {
123
    bitstatus = (uint8_t)Bit_RESET;
124
  }
125
  return bitstatus;
126
}

von Nico W. (nico_w)


Lesenswert?

grundschüler schrieb:
> Die while-0-Schleife verstehe ich nicht. Die if-abfrage ist überflüssig.

Ohne die while-0-Schleife funktioniert das Beispiel hier nicht.
1
if (something)
2
  WRITE(PA_1, 1);
3
else
4
  do_something_else();

Die if-Abfrage ist nicht überflüssig. Damit kann ich den Pin an und aus 
schalten.

: Bearbeitet durch User
von Markus M. (Firma: EleLa - www.elela.de) (mmvisual)


Lesenswert?

grundschüler schrieb:
> Mine #defines beruhen auf dem früheren nxp-Konzept
> in z.B. der lpc1768x.h Datei. Da sind auch solche #defines enthalten.

NXP hat KEIN Konzept! NXP hatte noch nie ein eigenes Konzept. Alles was 
damals geschrieben wurde, das wurde von irgend welchen Leuten in einer 
Comunity frei erfunden - nur hat diesen tollen Code nun NXP an sich 
genommen und frickelt damit weiter - entsprechend große Differenzen gibt 
es im Code z.B. zwischen LPC176x und LPC43xx. Abgesehen davon dass auch 
noch die ein oder andere Register Deklaration komplett fehlt.

Hingegen die STM Header und die automatisch generierten Sourcen 
entsprechen schon sehr stark der ARM driver Specification.

Du tust gut daran sich an das zu halten, denn damit sind deine Sourcen 
automatisch für die Zukunft leichter portierbar auf andere µC von ST.

Außerdem ist damit auch der Einstieg in das Berufsleben als µC 
Programmierer leichter und du verstehst viel schneller den existierenden 
Code.

von grundschüler (Gast)


Lesenswert?

Nico W. schrieb:
> grundschüler schrieb:
>> ~(0b1111<<(4*(pin%8)))
>
> Was das bedeutet, weißt du sicher in einer Woche selbst nicht mehr.

besser:
1
#define AF_PP     1011
2
#define AF_OPD      1111
3
#define IO_IN_PuPd       1100
4
#define IO_OUT_PP    0011
5
#define clrGPIO_CRHL(port,pin) {*(uint32_t*)(GPIOA_BASE + PORT(port) *0x400 + (pin/8)*4)&=~(0b1111<<(4*(pin%8)));}
6
#define setGPIO_CRHL(port,pin,mask4bit) {clrGPIO_CRHL(port,pin);*(uint32_t*)(GPIOA_BASE + PORT(port) *0x400 + (pin/8)*4)|=(mask4bit<<(4*(pin%8)));}
7
8
setGPIO_CRHL(A,8,AF_PP);//TIM1_ch1
9
setGPIO_CRHL(A,9,AF_PP);//tim1_ch2

von Nico W. (nico_w)


Lesenswert?

grundschüler schrieb:
> besser:

Nein!

https://stackoverflow.com/questions/1067226/c-multi-line-macro-do-while0-vs-scope-block

Du kannst ja mal versuchen folgenden Code zu kompilieren:
1
volatile int x = 1;
2
if (x)
3
  setGPIO_CRHL(A,7,AF_PP);
4
else
5
  setGPIO_CRHL(A,8,AF_PP);

: Bearbeitet durch User
von grundschüler (Gast)


Lesenswert?

Nico W. schrieb:
> Nein

danke für den Hinweis. Verstanden. Ich habe einen Macro aus zwei 
statements und muss die sicher verbinden. dazu ist der Macro bei mir mit 
{} eingeklammert, bei dir mit do{}while(0), was mglw. das gleiche ist, 
mglw. auch nicht. werde ich ausprobieren und ggf. ändern.



Markus M. schrieb:
> NXP hat KEIN Konzept!

und STM?

Für meine Hobby-Anwendungen ist der Hersteller im Prinzip egal. Ich 
verwende inzwischen hauptsächlich AVRs und STMs, früher LPCs. Sind alle 
gut.

zur Zeit Mega328 und STM32F103C8, weil man da ohne Rücksicht auf das 
3€-board alles ausprobieren kann. Ich verwende noch winAVR und Coide. 
studio ist mir zu nervig. Cube weiß ich nicht. LPCXpresso war sicher 
besser als coide - coide ist aber auch nicht schlecht.

Ich muss mir für coide den Zugang zu Standard-Funktionen neu erarbeiten 
und versuche das durch Macros in reproduzierbare Schritte zu fassen. Da 
läuft in den Stm-Structuren einfach zu viel im Hintergrund ab. Obwohl 
ich inzwischen einige mcu-Erfahrung habe, ist es mir mit den STM-structs 
nicht gelungen, ein I2c-lcd zum laufen zu bringen. Ging erst nach 
Transfer der Fleury-lib von avr auf arm.

von grundschüler (Gast)


Lesenswert?

wo ichs schreibe, wenn man einklammert, muss hinter jedes Statement ein 
';'

von Nico W. (nico_w)


Lesenswert?

grundschüler schrieb:
> mglw. auch nicht

grundschüler schrieb:
> wo ichs schreibe, wenn man einklammert, muss hinter jedes Statement ein
> ';'

Nein, Nein!

Was ist
1
#define DO_SOMETHING {do_something;}
2
3
if (what)
4
  DO_SOMETHING;
5
else
6
  whoops();
hiermit?

Das wird zu:
1
if (what)
2
  {do_something;};
3
else
4
  whoops();
und der compiler streikt.
1
 error: 'else' without a previous 'if'

: Bearbeitet durch User
von grundschüler (Gast)


Lesenswert?

Nico W. schrieb:
> error: 'else' without a previous 'if'

Das lässt sich auch mit do-while-0 nicht vermeiden. Ist aber auch kein 
wirkliches Problem, weil man nach der Fehlermeldung weiß, dass ein semi 
zu viel bzw. 2Klammern zu wenig sind.

wegen eines bugs nochmal der getestete code:
1
#define GPIO_IN_AF_PP      0b1011
2
#define GPIO_IN_AF_OPD     0b1111
3
#define GPIO_IN_PuPd      0b1000
4
#define GPIO_OUT_PP     0b0011
5
#define clrGPIO_CRHL(port,pin) *(uint32_t*)(GPIOA_BASE + PORT(port) *0x400 + (pin/8)*4)&=~(0b1111<<(4*(pin%8)))
6
#define setGPIO_CRHL(port,pin,mask4bit) {clrGPIO_CRHL(port,pin);*(uint32_t*)(GPIOA_BASE + PORT(port) *0x400 + (pin/8)*4)|=(mask4bit<<(4*(pin%8)));}

von W.S. (Gast)


Lesenswert?

grundschüler schrieb:
> Mine #defines beruhen auf dem früheren nxp-Konzept
> in z.B. der lpc1768x.h Datei. Da sind auch solche #defines enthalten.
> Kann also nicht so ganz falsch sein.

Es geht nicht um "so ganz falsch", sondern um Strategien. Du hast weiter 
oben mit sowas wie #define pinset(port, pin) und so angefangen. Das ist 
die falsche Richtung.

Man braucht sowas nicht nur NICHT, sondern es ist auch letztlich etwas 
Schlechtes. Sowohl für die Effizienz des erzeugten Codes als auch für 
die Quellen an sich.

Denke du mal lieber daran, sinnvolle Low-Level-Treiber für die diversen 
Peripherien zu schreiben. Also solche, die die Hardware ordentlich 
puffern, kapseln, betreiben. In so einem Treiber kann man viel besser 
mit direkten Anweisungen arbeiten, wie z.B.
void Motor_Ein (void)
{ GPIOB_BSRR = 1<<7; }
oder so ähnlich. Das übergeordnete Programm braucht wirklich nicht zu 
wissen, an welchem Pin der Motor hängt und ob man das nun H oder L 
setzen muß. Zum Portieren braucht man dann auch bloß eben diesen 
Lowlevel-Treiber zu ändern - und an Routine, die den Motor tatsächlich 
betreibt, ihn vielleicht kompliziert regelt oder sonstwas, braucht es 
gar keine Änderung. Das ist letztlich viel übersichtlicher, als wenn du 
mit pinset(...) arbeiten würdest.

Es gibt viele Firmen, die solche von dir genannten hochkomplizierten 
Makros mit Vorliebe unter die Leute streuen. Find ich schlecht, da es 
auf Dauer damit nur unleserlich wird und man abgeschottet ist davon, was 
wirklich passiert, beim Lesen zu verstehen. Gut gemeint ist fast immer 
das Gegenteil von gut gemacht.

Also: System KISS: mach's lieber einfach, laß hakelige Makros bleiben, 
programmiere nicht wie ein Seiltänzer sondern auf eher biedere Weise.

W.S.

von Nico W. (nico_w)


Lesenswert?

grundschüler schrieb:
> Das lässt sich auch mit do-while-0 nicht vermeiden.

Natürlich lässt sich das mit do-while(0) vermeiden.
1
#define DO_SOMETHING do { do_something; }while(0)
2
3
if (what)
4
  DO_SOMETHING;
5
else
6
  yupp();

wird zu
1
if (what)
2
  do { do_something; } while(0);
3
else
4
  yupp();

Und die do-while(0) wird der Compiler dann eh rausschmeißen. Es geht 
hier um eine gescheite Syntax. Du wolltest doch was gescheites basteln 
und weg von der HAL oder StdPeriph. Aber so wird das nur deutlich mehr 
murks.

von grundschüler (Gast)


Lesenswert?

Nico W. schrieb:
> Natürlich lässt sich das mit do-while(0) vermeiden.


kein Problem, kommt halt do-while-0 um Makros aus mehreren Zeilen drum 
rum.

Jedenfalls Danke für den hINWEIS.

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.