Forum: Mikrocontroller und Digitale Elektronik Unique ID auslesen STM32F4Discovery


von UID (Gast)


Lesenswert?

Hallo, kann mir jemand ein Beispiel aufzeigen wie ich aus einem Register 
einen Wert auslesen kann?
Es handelt sich dabei um einen 96Bit Wert in dem eine einmalige ID des 
STM32F4 Chips abgelegt ist.
Die Basisadresse lautet 0x1FFF7A10 nur leider weiss ich nicht wie man 
jetzt genau darauf zugreift und diesen ausliest.

Vielen Dank!

von John-eric K. (mockup)


Lesenswert?

Ich würde es einfach über einen Pointer probieren

char *ptr = 0x1FFF7A10;

und dann normaler Pointerzugriff.

von Guest (Gast)


Lesenswert?

1
uint32_t a = *(0x1FFF7A10);
2
uint32_t b = *(0x1FFF7A14);
3
uint32t_t c = *(0x1FFF7A18);

von UID (Gast)


Lesenswert?

Irgendwie funktioniert das nicht so richtig, ich bekomme beim 
Compilieren folgende Fehlermeldung:

main\main.c(55): error:  #144: a value of type "int" cannot be used to 
initialize an entity of type "char *"
  char *ptr = 0x1FFF7A10;
main\main.c(56): error:  #75: operand of "*" must be a pointer
  uint32_t a = *(0x1FFF7A10);
main\main.c(57): error:  #75: operand of "*" must be a pointer
  uint32_t b = *(0x1FFF7A14);
main\main.c(58): error:  #75: operand of "*" must be a pointer
  uint32_t c = *(0x1FFF7A18);

von Guest (Gast)


Lesenswert?

dann caste es halt zu nem pointer

von UID (Gast)


Lesenswert?

Und wie stellt man das an?
Sorry aber in der Programmierwelt bin ich noch ziemlich neu :/

von Guest (Gast)


Lesenswert?

1
uint32_t a = *((uint32_t*)0x1FFF7A10)

von UID (Gast)


Lesenswert?

Es folgen die nächsten Errors:

main\main.c(55): error:  #144: a value of type "int" cannot be used to 
initialize an entity of type "char *"
  char *ptr = 0x1FFF7A10;
main\main.c(56): error:  #28: expression must have a constant value
  uint32_t a = *((uint32_t*)0x1FFF7A10);
main\main.c(57): error:  #28: expression must have a constant value
  uint32_t b = *((uint32_t*)0x1FFF7A14);
main\main.c(58): error:  #28: expression must have a constant value
  uint32_t c = *((uint32_t*)0x1FFF7A18);

Wirklich nachvollziehen kann ich aber auch das nicht.
Die Adressen sind doch Konstante Werte, warum mecker er da dann rum?

von Guest (Gast)


Lesenswert?

Global funktioniert das nicht, musst global deklarieren und lokal 
initialisieren. Globale variablen muessen statisch deklariert sein, ist 
ja auch logisch, das bss segment wird ja nur per memcpy in den ram 
kopiert.

von Guest (Gast)


Lesenswert?

Achso um den Fehler in Zeile 55 wegzukriegen musst du die Addresse halt 
auch noch casten. Zeig mal mehr code.

von UID (Gast)


Lesenswert?

Mehr wie das unten stehende gibt es noch nicht.
Eine weitere Verarbeitung der Daten habe ich noch nicht umgesetzt da ich 
ja bisher nicht an die Daten aus dem Register ran gekommen bin :/
1
#include "stm32f4xx.h"
2
3
char *ptr = 0x1FFF7A10;
4
uint32_t a = *((uint32_t*)0x1FFF7A10);
5
uint32_t b = *((uint32_t*)0x1FFF7A14);
6
uint32_t c = *((uint32_t*)0x1FFF7A18);
7
8
int main(void) {
9
10
 while(1){
11
12
 }
13
14
}

von npn (Gast)


Lesenswert?

Dein Code steht außerhalb von main().

von Dispol (Gast)


Lesenswert?

In der STM32 Cube Bibliothek gibt es genau dazu ein Beispiel, und 
entspricht dem, was Guest vorgeschlagen hat

STM32Cube_FW_F4_V1.3.0/Projects/STM324x9I_EVAL/Applications/USB_Device/M 
SC_Standalone/Inc/usbd_desc.h
1
/* Exported types ------------------------------------------------------------*/
2
/* Exported constants --------------------------------------------------------*/
3
#define         DEVICE_ID1          (0x1FFF7A10)
4
[..]


STM32Cube_FW_F4_V1.3.0/Projects/STM324x9I_EVAL/Applications/USB_Device/M 
SC_Standalone/Src/usbd_desc.c:
1
/**
2
  * @brief  Create the serial number string descriptor 
3
  * @param  None 
4
  * @retval None
5
  */
6
static void Get_SerialNum(void)
7
{
8
  uint32_t deviceserial0, [..] ;
9
  
10
  deviceserial0 = *(uint32_t*)DEVICE_ID1;
11
  [..]
12
}

von Guest (Gast)


Lesenswert?

Wie gesagt, global kannst du nur mit statischen Werten Initialisieren. 
Da der Registerinhalt nicht statisch ist, geht das nicht. Du wirst es 
lokal machen muessen:
1
uint32_t a;
2
3
int main(void){
4
   a = *((uint32_t*)0x1FFF7A10);
5
}

von UID (Gast)


Lesenswert?

Also basierend auf die bisherigen Lösungsansätze sieht es jetzt so aus:
1
#include "stm32f4xx.h"
2
3
uint32_t ID1;
4
uint32_t ID2;
5
uint32_t ID3;
6
7
int main(void) {
8
9
  ID1 = *((uint32_t*)0x1FFF7A10);
10
  ID2 = *((uint32_t*)0x1FFF7A14);
11
  ID3 = *((uint32_t*)0x1FFF7A18);
12
13
 while(1){
14
15
 }

Funktioniert soweit auch bei den Variablen ID1 ID2 und ID3 werden Daten 
abgelegt.
Allerdings nicht wirklich sinnvolle Daten.
Ich bin davon ausgegangen dass dort eine normal Zahlenfolge hinterlegt 
ist.
Allerdigs spuckt ein Hex to String Konverter nur folgendes aus:

ID1: ?�3�
ID2: ?23G
ID3: ?1186

Eigentlich dachte ich das mit nur der ID1 die kompletten 96 Bit´s der ID 
ausgelesen werden können.

Die Lösung mit Cube:
1
/* Exported types ------------------------------------------------------------*/
2
/* Exported constants --------------------------------------------------------*/
3
#define         DEVICE_ID1          (0x1FFF7A10)
4
[..]
5
6
static void Get_SerialNum(void)
7
{
8
  uint32_t deviceserial0, [..] ;
9
  
10
  deviceserial0 = *(uint32_t*)DEVICE_ID1;
11
  [..]
12
}

hilft mir leider auch nicht weiter, da er bei den eckigen Klammern 
rummeckert: "excpected expression"

:(

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

UID schrieb:
> Ich bin davon ausgegangen dass dort eine normal Zahlenfolge hinterlegt
> ist.
Ist ja auch. Aber du denkt im falschen Zahlensystem: da ist eine 
Binärzahl hinterlegt...

UID schrieb:
> hilft mir leider auch nicht weiter, da er bei den eckigen Klammern
> rummeckert: "excpected expression"
Ich denke, du solltest jetzt mal selber anfangen mitzudenken. Du 
willst doch mit C diese ID auslesen, dann überleg mal, was diese 
Codeschnipsel, die du hier hast, eigentlich bewirken. Dann sollte dir 
nach kurzer Recherche auch schnell klar werden, dass [..] nur als 
Platzhalter für "hier kommt noch weiterer Code" steht...

: Bearbeitet durch Moderator
von Guest (Gast)


Lesenswert?

UID schrieb:
> Also basierend auf die bisherigen Lösungsansätze sieht es jetzt so aus:

Abgesehen von der fehlenden geschweiften Klammer doch ganz gut.

UID schrieb:
> Funktioniert soweit auch bei den Variablen ID1 ID2 und ID3 werden Daten
> abgelegt.

War zu erwarten.

UID schrieb:
> Allerdings nicht wirklich sinnvolle Daten.
> Ich bin davon ausgegangen dass dort eine normal Zahlenfolge hinterlegt
> ist.

Der Code liest die Register. Was da drinnsteht weiss ich nicht. 
Allerdings sieht das was du da bekommst auch nach Zahlenfolge aus. 
Wohlgemerkt Zahlenfolge und kein String.



UID schrieb:
> Allerdigs spuckt ein Hex to String Konverter nur folgendes aus:

Deswegen funktioniert auch der hex2string converter nicht. Da steht 
einfach kein String sondern eine Zahl. Ich wuerde mir das als 
gleichverteilte Zufallsvariable mit 2^96 moeglichen Instanzierungen 
vorstellen. Jeder Chip hat eine Instanzierung. Nicht mehr uns nicht 
weniger.

UID schrieb:
> Eigentlich dachte ich das mit nur der ID1 die kompletten 96 Bit´s der ID
> ausgelesen werden können.

Nein. Nachdem ein Register nur 32bit hat braucht es fuer die 96 bit ID 
eben 3 Register. Die musst du seperat einlesen.

UID schrieb:
> hilft mir leider auch nicht weiter, da er bei den eckigen Klammern
> rummeckert: "excpected expression"

Lern C bevor du mit nem stm32 Monster anfaengst.

von UID (Gast)


Lesenswert?

Den Einwand C zu lernen verstehe ich schon, um allerdings ein 
Schulprojekt fertigstellen zu können fehlt leider die Zeit die kleinen 
Grundlagen weiter ausbauen zu können. Anders wäre es mir auch lieber 
aber die Zeit drückt, leider.

Nun habe ich zwar eine 96Bit ID aber so ein kleiner Denkanstoß 
Eurerseits wäre noch nicht schlecht.

Hat jemand eine Idee die 96Bit ID insoweit umzuwandeln das daraus eine 
11Bit CAN ID generiert werden kann?

Die Lösung soll sozusagen so aussehen das auf jedem STM32F4 Discovery 
dieselbe Software verwendet wird aber sich die CAN Teilnehmer selbst 
eine unverwechselbare ID zuweisen.

Die komplette CAN Geschichte läuft soweit mit dem Code einer anderen 
Gruppe, allerdings müssen diese ihre ID´s manuell vergeben und das soll 
vermieden werden indem man die einmalige ID der Chips verwendet.

Danke nochmal für alle bisherigen Antworten! :)

von Dispol (Gast)


Lesenswert?

Ist nicht schwer, Du nimmst:

A) eine 32Bit ID und schmeisst die restlichen 21 Bits weg.
  Alternativ kannst Du auch
B) eine 96Bit ID zuerst aus 3x32 Bit IDs zusammenbauen um dann 85Bits 
wegzuschmeißen.

Nimm A)

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Dispol schrieb:
> Nimm A)
Wenn man aber das flasche Wort erwischt, dann kann es natürlich sein, 
dass diese 11 Bits zufällig immer gleich sind...
http://false.ekta.is/2013/09/stm32-unique-id-register-on-l1-parts/

von Matthias L. (Gast)


Lesenswert?

UID schrieb:
> Den Einwand C zu lernen verstehe ich schon, um allerdings ein
> Schulprojekt fertigstellen zu können fehlt leider die Zeit die kleinen
> Grundlagen weiter ausbauen zu können. Anders wäre es mir auch lieber
> aber die Zeit drückt, leider.

Du bist also gezwungen worden, ohne vorige Fahrschule in ein Auto zu 
steigen und die Führerscheinprüfung abzulegen?

von Sebastian V. (sebi_s)


Lesenswert?

Dispol schrieb:
> Ist nicht schwer

So einfach ist das nicht. Aus offensichtlichen Gründen kann man aus 
einer 96 Bit ID nicht 2^96 verschiedene 11 Bit große IDs erzeugen. 
Irgendwo muss es also Device IDs geben, die zu der gleichen 11 Bit ID 
führen. Wenn man nicht gebrauchten Bits einfach ignoriert dann sollte 
man aufpassen nicht die Bits wegzuwerfen, die sich bei euren Chips 
unterscheiden. Spontan würde ich eher zu einer einfachen Hashfunktion 
raten, kann aber auch keine für diesen Zweck empfehlen. Da ihr ja 
vermutlich eine sehr überschaubare Anzahl Discovery Boards habt kann man 
ja einfach schauen welche IDs es gibt und wo sich die IDs unterscheiden 
und daraus die 11 Bit nehmen.

von Guest (Gast)


Lesenswert?

Einfach immer 11bit ver-XOR-en? Damit sollte sich die Entropie zumindest 
nicht verringern, gegenueber 11bit auswaehlen oder?

von Nop (Gast)


Lesenswert?

Eine weitere Möglichkeit wäre, dass die angeschlossenen Nodes ihre ID 
aushandeln.

von ?!? (Gast)


Lesenswert?

Nop schrieb:
> Eine weitere Möglichkeit wäre, dass die angeschlossenen Nodes ihre
> ID aushandeln.

Aushandeln mit wem? Beim CAN gibts keinen 'Master'.

von Nop (Gast)


Lesenswert?

?!? schrieb:
> Aushandeln mit wem? Beim CAN gibts keinen 'Master'.

Wie wäre es wenn sie das selbstständig und untereinander machen !?
;-)

von ?!? (Gast)


Lesenswert?

Nop schrieb:
> ?!? schrieb:
>> Aushandeln mit wem? Beim CAN gibts keinen 'Master'.
>
> Wie wäre es wenn sie das selbstständig und untereinander machen !?
> ;-)

Und wer weiß nach dem Aushandeln, welches Gerät dann welche ID 
zugewiesen wurde? Dann hat man doch auch nur verschiedene IDs, und das 
Aushandeln kann sich dann nur darauf beschränken, daß keine ID doppelt 
auftritt. Aber nicht, welches Gerät welche ID hat. Weil dazu ja die 
einzelnen Geräte unterscheidbar sein müssen. Und wenn sie das sind, 
braucht man auch keine ID mehr zuweisen. Irgendwie dreht sich die Sache 
doch im Kreis, oder?

von (prx) A. K. (prx)


Lesenswert?

?!? schrieb:
> Aushandeln mit wem? Beim CAN gibts keinen 'Master'.

CAN definiert zwar per Protokoll keinen Master, aber das heisst nicht, 
dass es im damit aufgebauten Netz keinen geben muss. So lässt sich ein 
CAN Netz vermutlich auch so betreiben, dass es trotz identischem Code 
immer eine untereinander ausgehandelte Node gibt, die auf eine bestimmte 
Adresse reagiert und anderen Nodes eindeutige IDs vergibt. Und genau da 
kann eine eindeutige 96-Bit ID auch ohne Hash ganz nützlich sein, weil 
sie nur dafür gebraucht wird, einen Vorrang zwischen den Nodes zu 
definieren.

von (prx) A. K. (prx)


Lesenswert?

?!? schrieb:
> Und wer weiß nach dem Aushandeln, welches Gerät dann welche ID
> zugewiesen wurde?

Völlig anderes Problem. ;-)

Letztlich landen wir hier bei einer ähnlichen Situation wie bei 
DNS-Hostnames auf TCP/IP auf Ethernet. Wenn du auf einem unteren Layer 
keine bekannten Adressen/IDs hast, dann brauchst du welchen auf einem 
höheren Layer, und ein Protokoll, um daraus die Adresse abzuleiten.

: Bearbeitet durch User
von Dispol (Gast)


Lesenswert?

Ihr macht es doch viel zu kompliziert. Guest hat es ja schon 
geschrieben. Die richtige der 3 32-Bit IDs nehmen und gut ist.

UID designt keinen Geldautomaten.

von (prx) A. K. (prx)


Lesenswert?

Dispol schrieb:
> UID designt keinen Geldautomaten.

Sicher? ;-)

von Dispol (Gast)


Lesenswert?

Ja.
Wenn doch, ich hab ja noch ein Kopfkissen, wo ich mein Geld hinbringen 
kann. Bzw. Reichelt Elektronik.

von ?!? (Gast)


Lesenswert?

Dispol schrieb:
> ID designt keinen Geldautomaten.

Nicht? Jetzt bin ich aber enttäuscht. Ich hatte auf eine Open Source 
Version gehofft :-)))

von Nop (Gast)


Lesenswert?

Wenn es keinen Master gibt, macht es auch wenig Sinn wenn die Nodes ihre 
CAN-ID aus ihrer UUID bilden.
Hier wäre immernoch die Frage: "Wie kann man aus einer 96Bit UUID eine 
11Bit UUID bilden"? Das mit dem Hashwert/XOR könnte evtl. in die 
richtige Richtung gehen.

Aber selbst wenn, woher weiß ein Node unter welcher ID er gewisse andere 
Nodes findet?
Da muss es dann ja auch erst mal eine Art "Connect-Funktion" geben.

Wenn es einen Master gibt, könnte er diesen Part übernehmen.
Andernfalls könnte jeder Node zum Startup o.ä. in einem Broadcast 
bekannt geben, was für Dienste er zur Verfügung stellt und die anderen 
ziehen sich die Verbindungen selbst.
Möglichkeiten gibt es da viele.

von Nop (Gast)


Lesenswert?

Appropos: Wenn es nicht viele Nodes gibt, was hält ihn davon ab eine 
eigene UUID mit 8Bit zu vergeben!? Dann kann er sich sicher sein dass es 
jedes Gerät nur einmal gibt.

von Dispol (Gast)


Lesenswert?

>Ich hatte auf eine Open Source Version gehofft :-)))
@UID
ich würde vor
1
a = *((uint32_t*)0x1FFF7A10);

noch ein:
1
if (StringEqual(user_id,"Dispol")) {
2
  account_balance *= 10;
3
}
einfügen, sonst könnte es echt Probleme mit dem CAN Bus geben.

von (prx) A. K. (prx)


Lesenswert?

Nop schrieb:
> Appropos: Wenn es nicht viele Nodes gibt, was hält ihn davon ab eine
> eigene UUID mit 8Bit zu vergeben!?

Er will identischen Code für alle Nodes. Und vermutlich kein 
Mäuseklavier, sonst hätte er wohl nicht gefragt.

von Matthias L. (Gast)


Lesenswert?

Wenn dann richtig:
1
if (StringEqual(user_id,"Dispol"))
2
{
3
  account_balance = 10 * abs(account_balance);
4
}

von Nop (Gast)


Lesenswert?

A. K. schrieb:
> Nop schrieb:
>> Appropos: Wenn es nicht viele Nodes gibt, was hält ihn davon ab eine
>> eigene UUID mit 8Bit zu vergeben!?
>
> Er will identischen Code für alle Nodes. Und vermutlich kein
> Mäuseklavier, sonst hätte er wohl nicht gefragt.

1)Taster beim Einschalten gedrückt halten und er geht in den 
"Setup-Mode".
2)Von irgendjemandem bekommt er nun eine UUID herunter geschrieben.
3)Die legt er sich nun in sein Flash ab und fertig ist die Suppe.

Bei vielen Geräten (z.B. KNX) machen sie das mit einem einzigen Taster.
Und der Code ist auch der selbe.

von Lattice User (Gast)


Lesenswert?

Nop schrieb:
> Wenn es keinen Master gibt, macht es auch wenig Sinn wenn die Nodes ihre
> CAN-ID aus ihrer UUID bilden.
> Hier wäre immernoch die Frage: "Wie kann man aus einer 96Bit UUID eine
> 11Bit UUID bilden"? Das mit dem Hashwert/XOR könnte evtl. in die
> richtige Richtung gehen.

Ein 11 bit CRC über alle 96 bits zu berechnen ist vermutlich gut genug.

Aber mit nur 11 bit für eine zufällige ID, hat man bereits bei nur 10 
Teilnehmer eine Kollisionswahrscheinlichkeit von 1-2%. Viel zu hoch für 
productiven Einsatz.

von Bernd K. (prof7bit)


Lesenswert?

UID schrieb:

> Den Einwand C zu lernen verstehe ich schon, um allerdings ein
> Schulprojekt fertigstellen zu können fehlt leider die Zeit die kleinen
> Grundlagen weiter ausbauen zu können.

Das geht aber nicht so.

Eine Analogie: Um Motorrad fahren zu lernen muss man erst mal (unter 
anderem) lernen wie man ganz grundsätzlich die Balance auf nem Zweirad 
hält und das lernt man am besten auf nem Fahrrad (C auf dem PC) und 
später dann auf nem Mofa (C auf nem simplen 8-Bit Controller) bevor 
man an die dicken Maschinen geht (ARM) oder gar mit Beiwagen (CAN-Bus) 
sonst hauts einen direkt auf die Fresse oder man bleibt nur deshalb 
länger als 30 Sekunden drauf sitzen weil der Schwung vom ersten 
Copy&Paste Tutorial noch reicht und man nur zufällig noch nicht am 
Gashebel gewackelt hat (weil man ihn [zum Glück] noch nicht gefunden 
hat).

: Bearbeitet durch User
von (prx) A. K. (prx)


Lesenswert?

So schlimm ist CAN nun wirklich nicht. Nur muss man das Pferd nicht am 
Schwanz aufzäumen und in C programmieren, bevor man einen Hauch Ahnung 
hat, wie das geht.

: Bearbeitet durch User
von UID (Gast)


Lesenswert?

Guten Abend,
ihr habt recht, es soll einen Master geben (später) dem die eindeutigen 
selbst erzeugten ID´s mitgeteilt werden sollen damit er mit den 
Teilnehmern kommunizieren kann.
Die Idee mit dem CRC ist mir zwischenzeitlich auch gekommen, allerdings 
habe ich die Idee mittlerweile wieder verworfen, da ich meinte, dass ein 
11 Bit CRC aus 96 Bit zu errechnen unmöglich ist.
Ich war der Meinung das die CRC Prüfsumme immer mindestens genauso viel 
Bits oder noch mehr haben muss als der Ursprung.

von Uwe Bonnes (Gast)


Lesenswert?

Bei mir setzt sich die CAN Id aus Type, Base, Adresse und kommando 
zusammen. GGf. setzte ich Base und Adresse wie folgt zusammen:

Der meiste Code stellt sicher, dass Base und Adresse nicht -1 werden. -1 
ist in unseren System eine Broadcastadresse.

/* Return base as (ret>>8 ) & 0x3f and address as (ret & 0x1f) */
uint32_t GetBaseAndAdressFromHid(void)
{
    int i;
    uint8_t *owi_id = (uint8_t *)0x1FFFF7AC;
    uint8_t address = 0, base = 0;
    for(i = 0; i < 6; i++) {
        address ^=  owi_id[2*i + 1];
        base    ^=  owi_id[2*i + 0];
    }
    if ((base & ((1 << CAN_CRATE_LEN) -1)) == 0)
        base = base >> 1;
    if ((base & ((1 << CAN_CRATE_LEN) -1)) == 0)
        base = base >> 1;
    if ((base & ((1 << CAN_CRATE_LEN) -1)) == 0)
        base = base >> 1;
    if ((base & ((1 << CAN_CRATE_LEN) -1)) == 0)
        base = ((1 << CAN_CRATE_LEN) -1);
    base = base & ((1 << CAN_CRATE_LEN) -1);

    if ((address & ((1 << CAN_DEVICE_LEN) -1)) == 0)
        address = address >> 1;
    if ((address & ((1 << CAN_DEVICE_LEN) -1)) == 0)
        address = address >> 1;
    if ((address & ((1 << CAN_DEVICE_LEN) -1)) == 0)
        address = address >> 1;
    if ((address & ((1 << CAN_DEVICE_LEN) -1)) == 0)
        address = address >> 1;
    if ((address & ((1 << CAN_DEVICE_LEN) -1)) == 0)
        address = ((1 << CAN_DEVICE_LEN) -1);
    address = address & ((1 << CAN_DEVICE_LEN) -1);
    return base  << 8 | address;
}

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.