ARM Arrayzugriff Hardfault

Gast #4965691
Hallo Community,

ich programmiere gerade eine simple Kommunikation über den ARM M0+ 
SAMC20 von Atmel in dem Atmel Studio 7.

Folgendes Problem:
1
  uint16_t* writeptr =   (uint16_t*)write_data;
2
  uint16_t* readptr = (uint16_t*)DB_get_DBAdress() + startpos;
3
  uint16_t count = 0;
4
  
5
  while (count != n_Register)
6
  {
7
      writeptr[count]  =swap16(readptr[count]);
8
      count++;
9
  }

write_data ist ein Pointer, der der Funktion übergeben ist. Write_data 
Zeigt auf ein Byte in einem Sendepuffer. Diese Daten müssen in das 
Telegramm eingefügt werden, vorher muss die Eandiness geändert werden. 
(swap16)

Außerdem kann write_data auf ein Byte zeigen, welches nicht im 16 bit 
alignment liegt.

Ich suche nun nach einer Möglichkeit dem Compiler dies mitzuteilen. Das 
Programm geht regelmäßig in HardFault.

ARM Information Center sagt:
1
__packed uint32_t* pMyPointer = (__packed uint32_t*)(&tmp)
was jedoch vom Atmel Studio beim Compilieren laut Meldung ignoriert 
wird.

Kann mir jemand die Lösung nennen?

Danke & Gruß

Markus
Gast #4965697
Markus schrieb:
> write_data ist ein Pointer, der der Funktion übergeben ist. Write_data
> Zeigt auf ein Byte in einem Sendepuffer

wenn es ein Zeiger auf 8bit ist, darfst du nicht einfach ein Zeiger auf 
16bit daraus machen.

Auch macht es wenig sinn, bei 8 bit die Eandiness zu ändern.
Gast #4965723
Hallo Peter,

Danke für deine Antwort.

Peter II schrieb:
> wenn es ein Zeiger auf 8bit ist, darfst du nicht einfach ein Zeiger auf
> 16bit daraus machen.
>
> Auch macht es wenig sinn, bei 8 bit die Eandiness zu ändern.




Vielleicht habe ich mich missverständlich ausgedrückt.

Im DB liegen 16 bit Zahlen, bei denen die Eandiness geändert werden 
muss. (Readpointer). Bei diesem Zugriff ist 16bit alignment 
sichergestellt.

Der übergebene Pointer (Write_Data) ist Byte Adressiert, je nach größe 
des Telegrammkopfs liegt dieser im 16bit Raster oder nicht.


Dieses Problem ist einfach zu lösen, indem ich die 16bit Zahl aus dem DB 
lese, schreibe, shifte und schreibe auf 8 bit.
Jedoch muss es eine Möglichkeit geben dem compiler dies zu überlassen. 
Denn: Wenn ich in dieser Funktion direkt auf den Sendepuffer (Bytearray) 
adressiere ohne Variablen, so läuft die Funktion nicht in den Hard Fault 
obwohl das Alignment nicht stimmt.

Diese Möglichkeit suche ich, da mir das Alignment Problem öfters bei den 
ARM´s begegnet. Wahrscheinlich löst das eine bestimmte Syntax zum 
Pointer die ich nicht kenne.


Gruß

Markus
Gast #4966288
Markus schrieb:
> Der übergebene Pointer (Write_Data) ist Byte Adressiert, je nach größe
> des Telegrammkopfs liegt dieser im 16bit Raster oder nicht.

Und warum? Mach daraus ein 16Bit array und gut isses. Zum Füllen aus 
einem 8Bit Register kannst du casten oder legst ein 8Bit pointer an die 
Startadresse.
#4966463
Markus schrieb:
> je nach größe
> des Telegrammkopfs liegt dieser im 16bit Raster oder nicht.

Und da liegt Dein Problem. Entweder änderst Du das Protokoll so dass 
alles immer ordentlich aligned ist oder Du greifst auf die Bytes einzeln 
zu. Aber wenn Du eh bei jedem Integer das Alignment noch umdrehen musst 
ist das auch kein Geschwindugkeitsnachteil, musst eh alle Bytes einzeln 
anfassen.
#4966605
Lothar schrieb:
> Oder verwende einen Cortex M3 z.B. LPC13 ist auch nicht teurer als
> der
> SAM M0+ dann haben sich die Alignment Probleme erledigt.

Oh ja, klar das geht auch. Tausch einfach Dein Auto gegen einen LKW ein, 
das ist einfacher als einmal im Jahr die Rückenlehne umzuklappen, dann 
haben sich alle Weihnachtsbaum-Transportprobleme für immer erledigt. Ich 
liebe dieses Formum mit seinen kreativen Ideen ;-)
Gast #4966736
Was ist denn das für ein Vergleich. Es gibt kein solches Argument für 
den M0+

Was der an Gates gegenüber dem M3 einspart wird durch mehr Flash für 
mehr Code Speicherbedarf wegen nicht-bedingter Befehlsausführung wieder 
zunichte gemacht.
Gast #4966744
Markus schrieb:
> writeptr[count]  =swap16(readptr[count]);

dann macht es ohne die 16bit Funktion
1
uint8_t tmp = readptr[count];
2
writeptr[count] = writeptr[Count+1];
3
writeptr[Count+1] = tmp

aber dann seht es zwar im dem Puffer richtig drin, das hilft aber meist 
nicht weiter, du muss die Daten ja auch verwenden können.

Ich würde einfach eine neue struct anlegen, und die Daten einzeln in die 
Passenden members übernehmen.
Moderator Persönliche Seite #4966861
Lothar schrieb:
> Es gibt kein solches Argument für den M0+

Es gibt kein solches Argument für den M3: unaligned access, egal ob
er nun trapt oder nicht, ist immer Käse, denn es bringt am Ende
Performancenachteile.

Da er in diesem Falle aber sowieso die Bytes verwurschteln muss, gibt
es gar keinen Grund, sie als uint16_t anzusprechen.
1
  uint8_t* writeptr =   (uint8_t*)write_data;
2
  uint8_t* readptr = (uint8_t*)DB_get_DBAdress() + 2 * startpos;
3
  uint_fast16_t count = 0;
4
  
5
  while (count != n_Register)
6
  {
7
      uint8_t tmp = *readptr++;
8
      *writeptr++ = *readptr++;
9
      *writeptr++ = tmp;
10
      count++;
11
  }

Fertig ist die Laube …

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 9 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

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.