stm32f103 generelles Problem

Gast #4894129
Lesenswert?
• ▲
▼
1
....
2

3
  init_vs1053();
4
  vs_zl_buffer=0;
5
  vs_hellotest();
6
  wait;//1000ms
7

8
/**/
9

10
  SPI1->CR1 &=~(0b111<<3);//fast spi
11
  SPI1->CR1 |=  (3<<3);//fast spi
12
  
13
...

vs1053 wird initialisiert und spielt anschließend den vs1053-hello-code 
hörbar ab. Anschließend werden mp3-Dateien abgespielt.

Dann soll der spi-prescaler reduziert werden. Jetzt sind nicht nur die 
mp3s weg, auch der hellocode - obwohl zeitlich früher - wird nicht mehr 
abgespielt.

Wie kann das sein?

bei SPi2 geht es korrekt/presc==2, bei spi1 obiges Phänomen. Warum?
#4894446
Lesenswert?
• ▲
▼
1
  SPI1->CR1 &=~(0b111<<3);//fast spi
2
  SPI1->CR1 |=  (3<<3);//fast spi

Das sind zwei Schreibzugriffe. Vermutlich knallt der erste, fass die 
doch mal zu einem Zugriff zusammen.

Achtung: Taktumschaltung während einer SPI Transaktion kann auch aus 
anderen Gründen knallen, z.B. weil interne Teiler/Zähler überlaufen. So 
könnten auch unschöne Glitches entstehen.
Gast #4894558
Lesenswert?
• ▲
▼
Jim M. schrieb:
> Das sind zwei Schreibzugriffe.

Erstmal Danke für den Hinweis.

???
- vorhandener Wert in Bit-Folge soll geändert werden:
1. Bit-Folge auf Null setzen
2. Bit-Folge auf gewünschten Wert setzen

Wie schaffst du das in einem Schreibzugriff?

Das oben beeschriebene Problem ist geklärt. Lag daran dass die #defines 
zur Umstellung spi1/2 fehlerhaft waren.
 Spi2 läuft mit presc=clk/2 Spi1 nur mit clk/16. Da anderer Bus wäre 
logisch mindestens mit clk/4.

Ich werde das ganze jetzt mit dem la untersuchen.
(Firma: TU Darmstadt) #4894673
Lesenswert?
• ▲
▼
Jim M. schrieb:
> Trivialste Grundlagen der Programmierung:
>
> SPI1->CR1 = (SPI1->CR1 & ~(7<<3)) | (3<<3);
>
> Ein einzelner Read-Modify-Write Zyklus.

Das das als einzelner Zyklus implementiert wird, ist durch nichts 
garantiert. Ebenso werden die meisten Compiler die Formulierung in zwei 
Zeilen auch nichts anderes implementieren.
Gast #4894788
Lesenswert?
• ▲
▼
Uwe B. schrieb:
> Das das als einzelner Zyklus implementiert wird, ist durch nichts
> garantiert.

Doch, das ist dadurch garantiert, dass die gelesene/geschriebene 
Speicheradresse als volatile deklariert ist. Der Compiler muss hier 
genau einen Lese- und genau einen Schreib-Zugriff erzeugen.
Gast #4894817
Lesenswert?
• ▲
▼
grundschüler schrieb:
> sicher?
> da meckert nichts und es funktioniert auch...

Meine Lieblingsargumentation... Gleich dahinter kommen noch folgende:

- "gestern ging es aber noch!"
- "ich habe daran NICHTS gemacht/verändert"
- "so hat es aber bisher IMMER funktioniert"
- "wer braucht Abblockkondensatoren? Geht doch auch ohne!"
- "EAGLE ist MINDESTENS so gut wie Altium. Wenn nicht sogar besser!"
- usw., gibt noch eine ganze Menge

Übrigens:

Was du meinst ist folgendes: "Mein Compiler schluckt das weil GCC auch 
Binärzahlen versteht. Da ich aber ein guter Programmierer bin, schreibe 
ich meinen Code so, dass compilerspezifische Besonderheiten darin nicht 
unnötig vorkommen" :-)

--> in C verwendet man HEX. Ist ja eigentlich auch nichts anderes als 
Binär wenn man jeweils 4 Stellen zusammenfasst.

wenn man UNBEDINGT binär haben möchte (ich programmiere seit über 20 
Jahren C, habe es noch nie wirklich gebraucht):
1
#define B(x) ( \
2
  0##x >>  0 & 0001 | \
3
  0##x >>  2 & 0002 | \
4
  0##x >>  4 & 0004 | \
5
  0##x >>  6 & 0010 | \
6
  0##x >>  8 & 0020 | \
7
  0##x >> 10 & 0040 | \
8
  0##x >> 12 & 0100 | \
9
  0##x >> 14 & 0200 )

Uwe schrieb:
> Doch, das ist dadurch garantiert, dass die gelesene/geschriebene
> Speicheradresse als volatile deklariert ist. Der Compiler muss hier
> genau einen Lese- und genau einen Schreib-Zugriff erzeugen.

Sehe ich genauso.
#4895594
Lesenswert?
• ▲
▼
Uwe B. schrieb:
> Das das als einzelner Zyklus implementiert wird, ist durch nichts
> garantiert. Ebenso werden die meisten Compiler die Formulierung in zwei
> Zeilen auch nichts anderes implementieren.

Das sind Register und die sind volatile. Damit macht der Compiler 
jeden Lese- und Schreibzugriff ganz genau so wie Du ihn hinschreibst. 
Dies wird spätestens durch den GCC garantiert.

Deshalb wird der GCC bei der Zwei-Zeilen-Version immer zwei 
Schreibzugriffe machen, was bei Hardware Registern unerwünschte 
Nebenwirkungen haben kann.

Schau Dir selbst mal das Disassembly an.

Antwort schreiben

Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt. Bitte hier nur auf die ursprüngliche Frage antworten, für neue Fragen einen neuen Beitrag erstellen.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.