Forum: Mikrocontroller und Digitale Elektronik C Programmierung Wie abfrage ob eine Adresse gerade ist


von HaaanSoul (Gast)


Lesenswert?

Hey,

folgendes Problem, ich darf bei der STM HAL nur Buffer an die SPI 
übergeben welche mit einer geraden Adresse anfangen. Ansonsten landet 
man im HardFault.
Ist eine ziemlich dämliche Sache aber nun gut, nicht zu ändern.

daher muss ich überprüfen ob die an meine Funktion übergeben Adresse des 
Sende-Buffers um eine geradzahlige handelt.

mit dem Code
1
void myFunktion(char * sendBuf)
2
{
3
    if ((sendBuf % 2) != 0)
4
    {
5
        //Abbruch, Fehlerbehandlung
6
    }
7
}
bekomme ich folgende Fehlermeldung
"invalid operands to binary % (have 'char *' and 'int')"

meine Q&D Lösung sieht jetzt erst mal so aus:
1
void myFunktion(char * sendBuf)
2
{
3
    if ((((uint32_t)sendBuf) % 2) != 0)
4
    {
5
        //Abbruch, Fehlerbehandlung
6
    }
7
}

allerdings gefällt mir der Cast auf 32bit nicht. was ist wenn ich den 
code auf eine andere Platform portiere auf dem die Adressen nicht 
32bittig sind?

ok bei einem Vergleich auf gerade/ungerade würden auch ein 8bit 
(eigentlich sogar nur das letzte Bit) Wert reichen, aber es ist eher die 
Frage nach dem "wie mach ich das richtig"

von Tom (Gast)


Lesenswert?

Und was ist, wenn du guckst, ob das letzte Bit von sendBuf gesetzt ist? 
Dann ist doch die Adresse ungerade...

von Theor (Gast)


Lesenswert?

@ HaaanSoul

Es scheint mir ratsamer an der Ursache anzusetzen, als die Folgen zu 
vermeiden.

Woher bekommst Du denn eigentlich möglicherweise ungerade (unaligned) 
Adressen?

von (prx) A. K. (prx)


Lesenswert?

HaaanSoul schrieb:
> allerdings gefällt mir der Cast auf 32bit nicht. was ist wenn ich den
> code auf eine andere Platform portiere auf dem die Adressen nicht
> 32bittig sind?

Dafür gibt uintptr_t

von dirk (Gast)


Lesenswert?

Moin
Stimmt doch, das eine bit, das erste von rechts, mit (n)and verknüpfen.
Dirk St

von Walter T. (nicolas)


Lesenswert?

HaaanSoul schrieb:
> was ist wenn ich den
> code auf eine andere Platform portiere auf dem die Adressen nicht
> 32bittig sind?

Dann wird die Einschränkung vermutlich auch eine andere sein.

von HaaanSoul (Gast)


Lesenswert?

Theor schrieb:
> Es scheint mir ratsamer an der Ursache anzusetzen, als die Folgen zu
> vermeiden.
>
> Woher bekommst Du denn eigentlich möglicherweise ungerade (unaligned)
> Adressen?

Hallo,

Die Adresse bekomme ich übergeben, woher die genau stammt kann ich zum 
jetzigen Zeitpunkt nicht sagen, da es ein Softwaremodul wird welches 
universell eingesetzt werden kann.

kurzes Beispiel wie das passieren kann
jemand implementiert mein Modul und benutzt es so
1
static char[20] myBuf;
2
fillBuf(myBuf); // hier einfach mal als Beispiel wie der Buffer gefüllt wird
3
myFunktion(myBuf)

soweit ok, nun kommt derjeneige auf den Gedanken das es sich bei dem 
ersten Byte um ein Steuerzeichen handelt welches nicht mit übergeben 
werden soll, also benutzt er den folgenden Code
1
static char[20] myBuf;
2
fillBuf(myBuf);
3
myFunktion(&myBuf[1])

und schon knallt es bei der Übergabe an die HAL Spi Funktion.
Da fange ich das lieber ab und gebe eine Rückmeldung, was nicht passt.
Die alternative wäre den ganzen Buffer in eine zweite Variable zu 
kopieren, was aber auf kleinen µC eine riesen Platzverschwendung währe.

von A. F. (artur-f) Benutzerseite


Lesenswert?

HaaanSoul schrieb:
> und schon knallt es bei der Übergabe an die HAL Spi Funktion.
Welche Art von Daten werden da überhaupt übergeben und warum sind die 
statisch?

> Da fange ich das lieber ab und gebe eine Rückmeldung, was nicht passt.
> Die alternative wäre den ganzen Buffer in eine zweite Variable zu
> kopieren, was aber auf kleinen µC eine riesen Platzverschwendung währe.
Das wäre nicht wirklich tragisch, jeder STM32 hat genug RAM, aber es 
wäre nur ein Workaround und keine Lösung des Problems.

>folgendes Problem, ich darf bei der STM HAL nur Buffer an die SPI
>übergeben welche mit einer geraden Adresse anfangen. Ansonsten landet
>man im HardFault.
Ich habe mit HAL SPI noch nie gearbeitet, das hier halte ich aber für 
Quatsch.

Die HAl Funktion erwartet einen Pointer auf einen Buffer? Vom welchen 
Typ Buffer?

Poste bitte die komplette Funktion.
Wahrscheinlich müsst du statt sendBuf (char *)sendBuf übergeben....

von A. S. (Gast)


Lesenswert?

+ und - machen bei Pointern was ganz anderes als bei einem Int.

Eine Funktion % auf einen Pointer kenne ich nicht.

Von daher ist Dein Cast genau richtig.

Ob du das auf 32, 8 oder 16 Bit castest oder uintptr_t, ist erstmal 
egal, solange es unsigned ist.

Von daher: Alles richtig, Weitermachen!

von Theor (Gast)


Lesenswert?

HaaanSoul schrieb:
> Theor schrieb:
>> Es scheint mir ratsamer an der Ursache anzusetzen, als die Folgen zu
>> vermeiden.
>>
>> Woher bekommst Du denn eigentlich möglicherweise ungerade (unaligned)
>> Adressen?
>
> Hallo,
>
> Die Adresse bekomme ich übergeben, woher die genau stammt kann ich zum
> jetzigen Zeitpunkt nicht sagen, da es ein Softwaremodul wird welches
> universell eingesetzt werden kann.
>
> kurzes Beispiel wie das passieren kann
> jemand implementiert mein Modul und benutzt es so
>
1
> static char[20] myBuf;
2
> fillBuf(myBuf); // hier einfach mal als Beispiel wie der Buffer gefüllt 
3
> wird
4
> myFunktion(myBuf)
5
>
>
> soweit ok, nun kommt derjeneige auf den Gedanken das es sich bei dem
> ersten Byte um ein Steuerzeichen handelt welches nicht mit übergeben
> werden soll, also benutzt er den folgenden Code
>
1
> static char[20] myBuf;
2
> fillBuf(myBuf);
3
> myFunktion(&myBuf[1])
4
>
>
> und schon knallt es bei der Übergabe an die HAL Spi Funktion.
> Da fange ich das lieber ab und gebe eine Rückmeldung, was nicht passt.
> Die alternative wäre den ganzen Buffer in eine zweite Variable zu
> kopieren, was aber auf kleinen µC eine riesen Platzverschwendung währe.

Hm. Sowas Ähnliches dachte ich mir schon.

Man könnte es auch einfach bei dem Hardfault belassen. Der Anwender 
Deiner Bibliothek müsste da ja sowieso beim Testen drauf stossen. Mir 
täte es um die Laufzeit leid. Naja. Ansichtssache.

Neben uintptr_t gibt (oder gab?) es dann noch ptrdiff_t.

von Peter D. (peda)


Lesenswert?

Da ja das SPI Bytes ausgeben kann, sollte das HAL-SPI aber auch jede 
Byteadresse verarbeiten können.
Die beste Lösung wäre daher, den Bug im HAL-SPI zu reparieren.

von A. B. (Gast)


Lesenswert?

In HAL_SPI wurde wohl ein wenig "überoptimiert", ohne auf ein eventuell 
nicht korrektes Alignment zu achten ...
Die einfachste Lösung ist, die Zweige mit den 4-Byte bzw. 2-Byte-Paketen 
zu entfernen:

https://community.st.com/s/question/0D53W00000MfuaASAR/stm32h7xx-serious-bug-in-spi-driver-hal-version-130-170-and-180

Das Problem schlummert dort vermutlich an mehreren Stellen, und nicht 
nur bei der H7-HAL ...

von Theor (Gast)


Lesenswert?

Die Sache habe ich falsch bewertet. Offenbar ein Bug. Bedaure.

von HaaanSoul (Gast)


Lesenswert?

Bei mir tritt es bei einem STM32F042 auf.

und zwar beim Aufruf von
1
/**
2
  * @brief  Transmit and Receive an amount of data in blocking mode.
3
  * @param  hspi pointer to a SPI_HandleTypeDef structure that contains
4
  *               the configuration information for SPI module.
5
  * @param  pTxData pointer to transmission data buffer
6
  * @param  pRxData pointer to reception data buffer
7
  * @param  Size amount of data to be sent and received
8
  * @param  Timeout Timeout duration
9
  * @retval HAL status
10
  */
11
HAL_StatusTypeDef HAL_SPI_TransmitReceive(SPI_HandleTypeDef *hspi, 
12
uint8_t *pTxData, 
13
uint8_t *pRxData, 
14
uint16_t Size,
15
uint32_t Timeout)
16
{
17
...

dort führt die Zeile
1
hspi->Instance->DR = *((uint16_t *)hspi->pTxBuffPtr);
zu dem besagten HardFault.

Was mir in dem Zusammenhang auch noch nicht klar ist, mann kann die SPI 
auf bis zu 16Bits stellen, die HAL-Funktion erwartet aber einen *uint8_t

Theor schrieb:
> Man könnte es auch einfach bei dem Hardfault belassen. Der Anwender
> Deiner Bibliothek müsste da ja sowieso beim Testen drauf stossen. Mir
> täte es um die Laufzeit leid. Naja. Ansichtssache.

Die Laufzeit ist an der Stelle nicht so entscheidend, das Problem beim 
belassen wäre ja dann das der Nutzer erst mal wieder herausfinden müsste 
das es an der Adresse liegt, ist nicht ganz so offensichtlich.
Da wäre im einfachsten Fall eine while(1){//Du musst eine gerade 
Adressen übergeben} aus meiner Sicht noch sinnvoller.

A. F. schrieb:
> Das wäre nicht wirklich tragisch, jeder STM32 hat genug RAM, aber es
> wäre nur ein Workaround und keine Lösung des Problems.

der von mir verwendete µC hat nur 6kb RAM, also mit reichlich Speicher 
ist da nicht, wenn mann z.B. einen Buffer von 1k vorhält welchen man 
senden möchte...

von Walter T. (nicolas)


Lesenswert?

HaaanSoul schrieb:
> while(1){//Du musst eine gerade
> Adressen übergeben} aus meiner Sicht noch sinnvoller.

Hast Du denn eine Art stderr implementiert? Für solche Fälle ist das 
vorhandensein von assert() und error() schon eine feine Sache, dass man 
nicht erst mit dem Debugger nach dem Problem suchen muss (oder damit 
deutlich schneller ist).

von HaaanSoul (Gast)


Lesenswert?

Nachtrag:

der Bug ist auch bei ST beschrieben: 
https://community.st.com/s/question/0D50X00009Xkdsn/bug-stm32f0xx-hal-spi-transmit

wäre ja nett wenn sie das wenigstens in den Header der Funktionen 
schreiben würden.

von HaaanSoul (Gast)


Lesenswert?

Walter T. schrieb:
> Hast Du denn eine Art stderr implementiert? Für solche Fälle ist das
> vorhandensein von assert() und error() schon eine feine Sache, dass man
> nicht erst mit dem Debugger nach dem Problem suchen muss (oder damit
> deutlich schneller ist).

In diesem speziellen Fall sieht die Fehlerbehandlung noch etwas anders 
aus, was hier aber wirklich zu weit führen würde, es ging mir ja 
hauptsächlich um die Überprüfung gerade/ungerade :)
Grundsätzlich gebe ich dir da aber auf jeden Fall recht.

von Mark B. (markbrandis)


Lesenswert?

Theor schrieb:
> Man könnte es auch einfach bei dem Hardfault belassen. Der Anwender
> Deiner Bibliothek müsste da ja sowieso beim Testen drauf stossen. Mir
> täte es um die Laufzeit leid. Naja. Ansichtssache.

Ehrlich gesagt: Nein. Ein korrektes Funktionieren der Software steht an 
erster Stelle. Danach erst kommen Laufzeitoptimierungen. Für nicht 
genutzte Rechenzeit gibt es kein Geld zurück. ;-)

Auf jeden Fall gehört so ein Bug in den Release Notes zu der 
SW-Bibliothek dokumentiert.

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.