Mw E. schrieb:> Was willste denn damit bezwecken?>> Ansonsten das Array einer LInkerscript Section zuweisen und diese> Secteion im LInkerscript fest platzieren.
Kannst du das genauer erklären? Gibt es eine Referenz für das
Atmel Studio 7, wo ich das nachlesen kann?
oder Du weist einem Zeiger die Adresse des Array zu:
unsigned char *object;
object=0x100;
dann kannst Du darüber, wie gewohnt drauf zugreifen:
object[12]='H';
Was soll sich denn an der Adresse 0x100 befinden? RAM? Oder ein
Registersatz? Jedenfalls einfach einer Zeigervariablen eine Adresse
zuweisen ist zu 99,9% falsch.
Sorry, meine Frage ist schlecht formuliert. Vor allem habe ich vergessen
zu erwähnen, dass das ARRAY eine feste Adresse im SRAM bekommen soll.
Ein Array ist 0x120 Bytes lang. Dieses Array soll an eine feste Adresse
im SRAM (ATMega328, 0x200 bis 0x31F) gelegt werden. Wie kann ich das mit
dem Atmel Studio 7 erreichen?
das ist mal eine interessante Frag, die mich auch interessieren würde.
Warum eigentlich immer diese blöden Fragen auch dem Wozu!?
Der Grund ist doch völlig wurscht
Stefan schrieb:> Warum eigentlich immer diese blöden Fragen auch dem Wozu!?
Weil die Frage zusammen mit der Tatsache, daß der TO mit den bereits
gegebenen Antworten offensichtlich nicht so richtig was anzufangen
wußte, mit recht großer Wahrscheinlichkeit letztendlich auf die
(einfachere) Frage "wie schieße ich mir am besten selbst ins Knie"
rausläuft.
Jemanden mit einem "wozu" hiervon abhalten zu wollen, ist doch nett,
oder?
Weil es sich bei solchen "Anforderungen" i.d.R. um einen Disignfehler
handelt.
Sowas wird ja nur dann gebraucht, wenn man von ausserhalb der
Anwendung auf den Speicher zugreifen und hart codierte Adressen
verwenden muss.
Die Frage ist also, warum man solche hart platzierten Objekte braucht,
und die Frage stellt sich um so mehr, als es keine einfache Möglichkeit
gibt, das mit GCC + Binutils zu erreichen.
Einen Zeiger mit der gewünschten Adresse zu initialisieren ist
jedenfalls falsch, denn das legt kein Objekt an, reserviert keinen
Speicher und initialisiert das Objekt auch nicht.
In eine eigene Section legen und per --section-start die Section
irgendwohin legen ist auch keine Lösung, da Section möglicherweise mit
anderes Sections überlappt.
Ergo: Es braucht ein angepasstes Linker Description File, wo man einen
entsprechenden MEMROY eintrag hinzufügt und die zugehörige
Output-Section an die gewünschte Adresse legt. In die Input-Section
legt man dann das gewünschte Objekt bzw. eine Input-Section, die man dem
Objektzugewiesen hat.
Dokumentiert ist das in den Binutils, nicht in XX Studio:
http://sourceware.org/binutils/docs-2.27/ld/Scripts.html
Markus F und Johann L habens auf den Punkt gebracht.
Es gibt GCC Attribute um eine Variable zu alignen
(zB L1 Tabellen für die MMU oder ARM Exception Vektoren)
aber nicht um diese an eine feste Adresse zu packen.
Warum das wohl so ist? -> Weils keiner braucht und es eher schlechte
Üraxis ist sowas überhaupt zu benötigen in einem Programm.
Daher meine Frage warum der Threadersteller diese feste Platzierung
braucht, denn da findet sich dann sicherlich eine bessere/andere Lösung.
Ansonsten ist hier der GNU LInker erklärt und wie man dort Sections
platziert:
https://www.eecs.umich.edu/courses/eecs373/readings/Linker.pdf
Eine Variable wird dann mit dem GCC Attribut Section einer LInkerscript
Section zugewiesen:
https://gcc.gnu.org/onlinedocs/gcc-3.2/gcc/Variable-Attributes.html
Das kann manchmal trotzdem sinnvoll sein. Vielleicht nicht im RAM, aber
zumindest im EEPROM.
Spätestens, wenn man per Bootloader z.B. Firmwareupdates einspielen
kann, wäre es durchaus wünschenswert, wenn der Inhalt des EEPROMs aus C
heraus immer noch da zu finden ist, wo er vorher war.
Üblicherweise löst man das behelfsmäßig, indem man nur eine einzige
struct im EEPROM anlegt und innerhalb dieser dann die Daten platziert
und dafür sorgt, dass kein Padding eingefügt wird. Andernfalls wäres
nämlich blöd, wenn der Linker bei einem Build die Reihenfolge im EEPROM
verändert...
Nase schrieb:> Das kann manchmal trotzdem sinnvoll sein. Vielleicht nicht im RAM, aber> zumindest im EEPROM.>> Spätestens, wenn man per Bootloader z.B. Firmwareupdates einspielen> kann, wäre es durchaus wünschenswert, wenn der Inhalt des EEPROMs aus C> heraus immer noch da zu finden ist, wo er vorher war.
Was aber nicht ausreichend ist, denn selbst wenn EEMEM noch da liegt wo
es vorher lag (was immer der Fall ist, es sei denn man änder
Linkerscript o.ä.) gibt dir niemand die Zusicherung, dass der Linker
aller Objekte an die gleichen Adressen lokatiert wie zuvor.
> Üblicherweise löst man das behelfsmäßig, indem man nur eine einzige> struct im EEPROM anlegt und innerhalb dieser dann die Daten platziert> und dafür sorgt, dass kein Padding eingefügt wird.
Das ist die einzige robuste Lösung (neben händischem Lokatieren im
Linkerskript o.ä.)
> Andernfalls wäres nämlich blöd, wenn der Linker bei einem Build> die Reihenfolge im EEPROM verändert...
was irgendwie die Frage nach wie vor nicht ebantwortet wie üblich in
diesem Forum!
Vielleicht will ich ja ein Ram Defragmentierungtool scheiben und msus
daher wissen oder ich möchte es einfach nur so machen das ist doch
völlig wurscht!!
Stefan schrieb:> Vielleicht will ich ja ein Ram Defragmentierungtool scheiben und msus> daher wissen oder ich möchte es einfach nur so machen das ist doch> völlig wurscht!!
Der Threadersteller heißt Jochen und nicht Stefan, also willst du hier
garnichts!
Stefan schrieb:>was irgendwie die Frage nach wie vor nicht ebantwortet wie üblich in>diesem Forum!
Lesen verlernt?
Die eigentliche Frage habe ich schon längst beantwortet, geh wieder
zurück in deine Trollhöhle.
Warum ist das in diesem Forum eigentlich in fast jedem Thread so, dass
es nach kurzer Zeit mit Beschimpfungen losgeht. Es ist schon
"einzigartig" hier ...
abgesehen davon das es mich ebenfalls interessiert..ist die
Kommunikation hier wie bereits erwähnt einfach nur genial .-)
Ich kenne kein anderes Forum wo die Menschen dermaßen unsozial
miteinander kommunizieren, das es hier schon fast wieder witzig ist :-)
Und die meisten hier sind auch noch stolz drauf :-O)
Also ich will ja mal nicht auf denjenigen zeigen wer hier direkt zu
Anfang was von "blöden Fragen" geschrieben hat ;)
Schade, dass die Gäste ihre Negativbewertungen nicht sehen.
findest Du die Frage den intelligent?
Ist ja auch wurscht, das Thema wurde beantwortet und weitere
Diskussionen sind hinfällig..
Und mit Deinem Tonfall in dem Post davor sparre ich mir weitere
Kommentare und verfolge das jetzt auch nicht weiter
hier..traurig..traurig..sag ich nur
Jeder hat mal klein angefangen: deswegen finde ich, dass es keine dummen
(ernstgemeinten) Fragen gibt!
Das Problem liegt hier m.E. auf beiden Seiten:
- es gibt Fragesteller, die keine Hilfe zur Selbsthilfe wollen, sondern
eine Lösung.
- es gibt Antworter, die jeder Frage / Rückfrage als Provokation
empfinden bzw. als Plattform für ihre sehr einseitigen Ansichten.
Beides zeugt von mangelndem Respekt. Der Ton macht die Musik.
Insgesamt ist das schade, denn ich finde schon, dass hier ein Menge
Sachkenntnis zusammen kommt. Leider werden allerdings wegen des
Umgangtons viele ihre Konsequenzen ziehen.
Vielleicht sollte darauf hingewiesen werden, dass es DIE Lösung nicht
gibt. Je nachdem, welcher Lösungsansatz gewählt wird, ist es z.B. nicht
egal, ob die Adresse am Anfang oder am Ende des RAM liegt oder
mittendrin.
Johann L. schrieb:> Weil es sich bei solchen "Anforderungen" i.d.R. um einen Disignfehler> handelt.
Ich hab sowas auch schonmal gebraucht, allerdings nicht auf AVR, sondern
auf STM32. Sinn der Sache war, daß ich ein großes struct ins Backup-RAM
legen wollte, um dort Daten über einen Stromausfall hinweg zu sichern.
Außerdem sollte auch das komplette Backup-RAM genullt werden können, und
einen RAM-Test wollte ich dafür auch noch haben.
Also einfach einen Pointer auf die Basisadresse zeigen lassen und je
nach Anwendungsfall (Daten sichern, RAM nullen/testen) geeignet casten,
fertig. Hätte man natürlich auch mit dem Linkerfile machen können, aber
weniger Herumgecaste wäre das auch nicht geworden.
Nop schrieb:> Johann L. schrieb:>> Weil es sich bei solchen "Anforderungen" i.d.R. um einen Disignfehler>> handelt.>> Ich hab sowas auch schonmal gebraucht, allerdings nicht auf AVR, sondern> auf STM32. Sinn der Sache war, daß ich ein großes struct ins Backup-RAM> legen wollte, um dort Daten über einen Stromausfall hinweg zu sichern.> Außerdem sollte auch das komplette Backup-RAM genullt werden können, und> einen RAM-Test wollte ich dafür auch noch haben.>> Also einfach einen Pointer auf die Basisadresse zeigen lassen und je> nach Anwendungsfall (Daten sichern, RAM nullen/testen) geeignet casten,> fertig. Hätte man natürlich auch mit dem Linkerfile machen können, aber> weniger Herumgecaste wäre das auch nicht geworden.
Es geht eher darum, dass das "Backup-RAM" (SRAM2 / CCRAM?) dann nicht
mehr vernünftig genutzt werden kann. Legt man für das RAM eigene
Sections an, so kann man es ohne schlechtes Gewissen auch für .data und
.bss nutzen.
Portable ist der Pointer Code übrigens auch nicht. Ohne Eintrag in den
Linker hast du keine globalen Symbole am Anfang und Ende des RAM. Wenn
jetzt ein anderer Prozessor mit weniger Speicher verwendet wird, dann
nullt der Pointer ohne Code Anpassung in nicht zugelassene Adressen,
usw. usf.
Vincent H. schrieb:> Es geht eher darum, dass das "Backup-RAM" (SRAM2 / CCRAM?) dann nicht> mehr vernünftig genutzt werden kann.
Kann es so oder so nicht, weil es nur 4kB sind, die auch noch in einem
eigenen Adreßblock liegen, also nicht kontinuierlich zum normalen RAM.
Von den 4kB brauche ich so etwa 3.8kB für Backupzwecke. Da ist also
ohnehin nichts mehr, was ich noch mit Verlinkung nutzen kann.
Ganz abgesehen davon, daß man das Backup-RAM vor dem Zugriff ohnehin
erstmal mit Registerbefehlen freischalten muß (und danach wieder
verriegeln kann), und bei sowas habe ich kein Vertrauen in
Compiler-Automatismen. Lieber manuell, dann weiß ich, daß es richtig
gemacht ist.
> Legt man für das RAM eigene> Sections an, so kann man es ohne schlechtes Gewissen auch für .data und> .bss nutzen.
Ja, könnte man machen. Für andere Sachen wie das CCM mache ich das auch
so, weil ich da diverse Variablen reinlege über Variablen-Attribute mit
den Sections. Das muß man dnn schon ausknobeln, welche Variablen wo noch
reinpassen, weil das auch nicht kontinuierlich zum normalen SRAM ist Das
geht aber gut per Linker.
> Portable ist der Pointer Code übrigens auch nicht. Ohne Eintrag in den> Linker hast du keine globalen Symbole am Anfang und Ende des RAM.
Der Anfang des RAM ist einfach seine Basisadresse, und die nächsten 4kB
sind eben das RAM.
> Wenn> jetzt ein anderer Prozessor mit weniger Speicher verwendet wird, dann> nullt der Pointer ohne Code Anpassung in nicht zugelassene Adressen,
Mit einem anderen Prozessor müßte ich sowieso die unterste Schicht neu
portieren, und nebst diversen Registeradressen und Bitmasken ist genau
im Headerfile des Treibers auch die Basisadresse des RAM drin.
Sollten auf dem anderen Prozessor wesentlich weniger als 4kB Backup-RAM
vorhanden sein, würde das Backup-Feature in der jetztigen Form aus
Applikationssicht ohnehin nicht mehr funktionieren.
Vincent H. schrieb:> Portable ist der Pointer Code übrigens auch nicht.
Sind feste RAM-Adressen nie. Daher fand ich das Beispiel völlig OK.
Leider hat sich der UP ja verabschiedet und Stefan jede sachliche
Diskussion zerschlagen.
Dennoch an den UP: Das "Warum" entscheidet über den pragmatischen Weg.
Wenn das RAM zusätzlich ist und dem Linker z.B. unbekannt, ist der
Pointer einfach und ausreichend.
Wenn Du den Linker kennst und beherrschst, oder kennenlernen willst, ist
die Lösung über eine eigene Section sauber und ebenso einfach.
Wenn Du den Linker nicht kennst, und es nur wenige Bytes vorher oder
nachher gibt, auf die Du verzichten kannst, reicht eine kleine Änderung
im Linker-Skript-File.
Wenn es nur darum geht, dass zwei unabhängig voneinander kompilierte
Codes damit arbeiten sollen, gibt es auch vielfältige Lösungen.
Ich weiß der Thread ist schon älter...
Allerdings ist genau die Speicherverwaltung des Compilers der Grund
warum ich immernoch mit Assembler arbeite.
Ich bräuchte auch so eine feste Speicherzuordnung.
Der Grund ist ganz einfach.
Ich tausche Daten mit dem PC aus.
Dabei schickt momentan der PC die Adresse und Länge und der AVR schickt
die Werte aus dem Ram von der Adresse zurück.
Das ganze würde ich eventuell noch umstellen und ganze Ram Bereiche per
DMA an den PC schicken.
Dazu muß aber der PC wissen, welche Daten an welcher Adresse stehen.
Die Lösung mit dem Linker und der Section habe ich gelesen.
Offensichtlich gibt es keine einfachere Lösung.
Aber vielleicht gibt es eine andere Lösung für meine Datenübertragung?
Ich will einfach nur Daten im Ram vom PC aus lesen und schreiben.
Außerdem müssen einige Daten vom Ram zusätzlich im Eeprom gespeichert
werden damit sie nach Stromausfall nicht verloren gehen.
Jetzt bin ich mal gespannt ob ich konstruktive Kommentare Lesen darf :-)
Kannst du nicht einfach mit nm/objdump/libbfd oder sowas die Addressen
der interessanten Symbole abfragen?
Ich würde dem Compiler nur vorschreiben, wo etwas hingepackt wird, wenn
es gar nicht anders geht. Ansonsten degradiert man sich selbst
freiwillig dazu, Arbeit zu machen, die der Linker innerhalb von
Millisekunden wahrscheinlich besser erledigt.
Für sowas denkt man sich Protokolle aus (oder nutzt fertige), aber man
schreibt nicht wild im Speicher des Controllers rum.
Aber so wie die Frage aufgebaut ist -> Trollfrage -> ignorieren
Wenn es nur ein paar interessante Symbole wären, dann würde ich es so
machen.
Es handelt sich aber um über 400 Variablen (ca. 800 Byte) im Ram, die
zum PC übertragen werden und ca. 200 Byte die im Eeprom gesichert
werden.
Dann ist die Abfrage aller Variable eher unsinning.
Was macht der Compiler wenn ich alle Variablen in eine einzige Strutur
packe?
Liegen die Variablen dann ab der Startadresse der Struktur
zusammenhängend im RAM?
In dem Fall könnte ich ja die ganze Structur übertragen.
Mw E. schrieb:> Für sowas denkt man sich Protokolle aus (oder nutzt fertige)
Ich habe ja ein Protokoll für den Datenaustausch.
Danach stellt der PC eine Datenanforderung nach einem fest vorgegeben
Protokoll mit Informationen welche Daten gelesen / geschrieben werden
sollen.
Der AVR reagiert darauf und schickt eine Antwort ebenfalls in einem
festen Protokoll.
> aber man schreibt nicht wild im Speicher des Controllers rum.
Wie soll ich sonst Parameter am PC ändern können ohne im Speicher rum zu
schreiben?
> Aber so wie die Frage aufgebaut ist -> Trollfrage -> ignorieren
Wer hier der Troll ist frag ich mich auch gerade...
Also tue mir ein gefallen und ignoriere einfach diesen Thread!
Gad Z. schrieb:> Mw E. schrieb:>> Für sowas denkt man sich Protokolle aus (oder nutzt fertige)
...
> Wer hier der Troll ist frag ich mich auch gerade...> Also tue mir ein gefallen und ignoriere einfach diesen Thread!
Recht hat er in dem Punkte, dass es zweifellos eleganter ist, statt mit
irgendwelchen Addressen direkt nach benannten Symbolen zu fragen. Ob das
realisierbar ist, ist natürlich wieder eine andere Frage: kostet ja
einiges an Speicher...
zer0 schrieb:> Gad Z. schrieb:>> Mw E. schrieb:>>> Für sowas denkt man sich Protokolle aus (oder nutzt fertige)> ...>> Wer hier der Troll ist frag ich mich auch gerade...>> Also tue mir ein gefallen und ignoriere einfach diesen Thread!>> Recht hat er in dem Punkte, dass es zweifellos eleganter ist, statt mit> irgendwelchen Addressen direkt nach benannten Symbolen zu fragen. Ob das> realisierbar ist, ist natürlich wieder eine andere Frage: kostet ja> einiges an Speicher...
Klar ist es eleganter mit Symbolen aber bei der Datenmenge wohl kaum
machbar.
Außerdem lag die Priorität darauf möglichst kurze Protokole zu haben da
die Daten sehr schnell übertragen werden müssen.
Der AVR hat aber noch ganz andere Sachen zu tun als nur die
Datenanforderungen vom PC abzuarbeiten.
Also ist es schon aus Performancegründen mit Symbolen nicht machbar,
ganz abgesehen vom zusätzlichen Speicherbedarf.
Gad Z. schrieb:> Was macht der Compiler wenn ich alle Variablen in eine einzige Strutur> packe?> Liegen die Variablen dann ab der Startadresse der Struktur> zusammenhängend im RAM?
Das auf jeden Fall, du musst dann nur auf dem PC aufpassen, die selben
alignment-Regeln, gleich große Datentypen usw. zu verwenden.
zer0 schrieb:> Das auf jeden Fall, du musst dann nur auf dem PC aufpassen, die selben> alignment-Regeln, gleich große Datentypen usw. zu verwenden.
Danke für die Antwort.
das klingt ja schonmal gut.
Es ist logisch das der PC die gleichen Reihenfolge und Datentypen haben
muß.
Aber im PC habe ich ein Programm geschrieben in dem es eine
Konfigurationsliste gibt wo eben auch die Adressen drin stehen vom
AVR-RAM.
Ich könnte also jetzt eine Structur im AVR machen mit allen ca. 400
Symbolen und die Structur dann per DMA direkt an den PC schicken.
Und der PC weiß dann anhand der Konfigurationsliste, welcher Wert an
welcher Stelle in dem Datenstrom liegt.
Der Schreibzugriff auf den AVR ist zwar so nicht möglich, aber da könnte
ich mir noch eine art CASE Anweisung schreiben, die nur das angeforderte
Symbol verändert da der PC immer nur einen Wert ändern darf und nie
mehrere gleichzeitig.
Außerdem werden die schreibbaren Parameter sowieso noch zusätzlich in
den Eprom gespeichert, was sowieso nur einzeln geht.
Gad Z. schrieb:> Ich könnte also jetzt eine Structur im AVR machen mit allen ca. 400> Symbolen und die Structur dann per DMA direkt an den PC schicken.> Und der PC weiß dann anhand der Konfigurationsliste, welcher Wert an> welcher Stelle in dem Datenstrom liegt.
Über die offizielle Definition von DMA will ich jetzt nichts gesagt
haben, aber: Wenn du einen portablen Header mit der struct schreibst,
kennt man die Offsets der einzelnen Attribute genau. D.h. man kann
einfach den empfangenen Speicherblock auf den struct-Datentyp casten und
die Dinger auslesen. Genau so kann man dann auch bei frei wählbaren
Schreibaddressen einfach einen einzelnen Wert auf dem Controller per
Protokoll poken: Man kennt die Basis-Addresse der struct, kennt Offset
und Größe des Attributes und kennt dann daher auch die Zieladdresse auf
dem Controller.
Was mich aber stutzig macht, ist, dass du jetzt doch wieder
zurückruderst:
Gad Z. schrieb:> Der Schreibzugriff auf den AVR ist zwar so nicht möglich, aber da könnte> ich mir noch eine art CASE Anweisung schreiben, die nur das angeforderte> Symbol verändert da der PC immer nur einen Wert ändern darf und nie> mehrere gleichzeitig.
Wenn du also eine Symboltabelle z.B. der Form
unterbringen kannst und willst (ist ja bei 400 Feldern schon ein wenig
Arbeit), dann wäre es vermutlich eine ernsthafte Überlegung wert. Wenn
die Einträge in der Tabelle alphabetisch sortiert sind, sind die per
binary-search relativ schnell zu durchsuchen (wobei relativ echt
"relativ" heißt: Im Vergleich zum einfachen Addressen-Poking ist der
Aufwand trotzdem enorm).
Ich würde aber für so eine Konstruktion einiges an Speicher einplanen.
Für 'nen ATtiny ist das eher nichts!
Danke für die Antwort.
zer0 schrieb:> Über die offizielle Definition von DMA will ich jetzt nichts gesagt> haben, aber: Wenn du einen portablen Header mit der struct schreibst,> kennt man die Offsets der einzelnen Attribute genau. D.h. man kann> einfach den empfangenen Speicherblock auf den struct-Datentyp casten und> die Dinger auslesen. Genau so kann man dann auch bei frei wählbaren> Schreibaddressen einfach einen einzelnen Wert auf dem Controller per> Protokoll poken: Man kennt die Basis-Addresse der struct, kennt Offset> und Größe des Attributes und kennt dann daher auch die Zieladdresse auf> dem Controller.> Was mich aber stutzig macht, ist, dass du jetzt doch wieder> zurückruderst:
Da hast du völlig Recht!
Aber ich rudere nicht zurück sondern es ist einfach von der PC Software
so vorgegeben, das immer nur ein Symbol geändert werden darf.
Diese Änderung wird dann als Schreibanforderung an den AVR geschickt und
der schreibt die Daten in den RAM und gleich noch in den Eprom damit sie
remantent sind.
Danach quittiert der AVR die Schreibanforderung an den PC.
Demzufolge macht es keine Sinn alle zu schreiben wenn nur ein Wert
geändert wurde.
Außerdem prüfe ich vor jedem Eprom Schreibzugriff ob der Wert im Eprom
überhaupt geschrieben werden muß. Schließlich haben ja Eproms eine recht
begrenzte Anzahl an Schreibzyklen.
Wenn ich den Schreibzugriff auch über die Structur mache, dann würde ich
ja immer alle Symbole überschreiben, was von den Werten her egal wäre
aber von den Schreibzyklen des Eproms eben nicht.
>> Wenn du also eine Symboltabelle z.B. der Form>
> unterbringen kannst und willst (ist ja bei 400 Feldern schon ein wenig> Arbeit), dann wäre es vermutlich eine ernsthafte Überlegung wert. Wenn> die Einträge in der Tabelle alphabetisch sortiert sind, sind die per> binary-search relativ schnell zu durchsuchen (wobei relativ echt> "relativ" heißt: Im Vergleich zum einfachen Addressen-Poking ist der> Aufwand trotzdem enorm).> Ich würde aber für so eine Konstruktion einiges an Speicher einplanen.> Für 'nen ATtiny ist das eher nichts!
Momentan habe ich einen Mega1284P im Einsatz.
Der hat schon keine Speicherprobleme mehr selbst wenn ich den Code
aufblasen wurde.
Aber der läuft noch mit Assembler.
ich denke aber darüber nach auf einen XMega umzusteigen unter anderem um
den DMA zu nutzen für die Datenübertragung und damit dem AVR selber
etwas mehr Ressourcen zu geben und nicht so viel zu "verschwenden" für
Datenübertragungen.
zer0 schrieb:> Wenn du also eine Symboltabelle> unterbringen kannst und willst (ist ja bei 400 Feldern schon ein wenig> Arbeit), dann wäre es vermutlich eine ernsthafte Überlegung wert.
Die Parametertabelle ist ja in der PC Software und die gibt es ja jetzt
schon (siehe Anhang).
> Wenn die Einträge in der Tabelle alphabetisch sortiert sind, sind die per> binary-search relativ schnell zu durchsuchen (wobei relativ echt> "relativ" heißt: Im Vergleich zum einfachen Addressen-Poking ist der> Aufwand trotzdem enorm).
Die Auswertung der Daten richtet sich nach verschiedenen Kriterien.
Je nachdem welche Ansicht angewählt ist, werden nur die sichtbaren
Symbole aktualisiert.
Aber wie gesagt, der Teil ist ja schon fertig.
> Ich würde aber für so eine Konstruktion einiges an Speicher einplanen.> Für 'nen ATtiny ist das eher nichts!
Ich denke garnichtmal das der Speicherbedarf so viel wäre.
Im Endeffekt ist es eine Case Anweisung für ca. 150 schreibbare Symbole.
Der PC müsste dann bei der Schreibanforderung statt der Adresse eine ID
schicken und in der Case Anweisung würde ich anhand der ID das
entsprechende Symbol beschreiben.
Ja, mach wie du meinst!
Frei wählbare Schreibzugriffe sind natürlich eine klaffende
Sicherheitslücke sonder gleichen, weil der PC den Controller dann
einfach völlig kaputt patchen kann. Vor allem, wenn das EEPROM gleich
mit versaut wird.
Wenn man aber auf den Zug aufspringt braucht man auch ganz schnell noch
Wertebereichsprüfungen, checks auf logische Stimmigkeit zwischen
mehreren Werten (was heißt: man muss dann ggf. doch mehrere auf einmal
Schreiben können) und und und.
Kommt auf den Use-Case und damit auf die konkreten Anforderungen an.
Wenn du mich fragst: "Kann man das und das machen?" antworte ich ja
zunächst nur, ob das geht oder nicht und unterstelle damit einfach mal,
dass du dir über die Konsequenzen im Klaren bist.
Freie oder ungeprüft Schreibzugriffe in einen Controller einzubauen, der
schwere Maschinerie steuert oder sowas, dürfte hart an der Grenze zur
Fahrlässigkeit liegen...
zer0 schrieb:> Ja, mach wie du meinst!>> Frei wählbare Schreibzugriffe sind natürlich eine klaffende> Sicherheitslücke sonder gleichen, weil der PC den Controller dann> einfach völlig kaputt patchen kann. Vor allem, wenn das EEPROM gleich> mit versaut wird.
Klar kann man damit den Controller bzw dessen Funktionen auch
abschießen.
Aber es handelt sich hier um ein privates Projekt welches nur ich nutze.
Und wenn der Controller abgeschossen werden würde und totale
fehlfunktionen hätte, dann würde es allerschlimmstenfalls zu einem
Getriebeschaden an meinem Go-Kart kommen.
> Wenn man aber auf den Zug aufspringt braucht man auch ganz schnell noch> Wertebereichsprüfungen, checks auf logische Stimmigkeit zwischen> mehreren Werten (was heißt: man muss dann ggf. doch mehrere auf einmal> Schreiben können) und und und.
Werteüberprüfungen auf Gültigkeit sind in der PC Software drin.
Das ergibt sich ja schon aus dem Datentyp und ob es signed oder unsigned
ist.
Außerdem bediene ja nur ich die Software.
>> Kommt auf den Use-Case und damit auf die konkreten Anforderungen an.> Wenn du mich fragst: "Kann man das und das machen?" antworte ich ja> zunächst nur, ob das geht oder nicht und unterstelle damit einfach mal,> dass du dir über die Konsequenzen im Klaren bist.>> Freie oder ungeprüft Schreibzugriffe in einen Controller einzubauen, der> schwere Maschinerie steuert oder sowas, dürfte hart an der Grenze zur> Fahrlässigkeit liegen...
Übrigens kann ich selbst bei einer Siemens Steuerung Parameter vom PC
aus so verbiegen das die Steuerung nicht mehr funktioniert bzw.
Servoantriebe zu schwingen beginnen und schlimmstenfalls mechanische
schäden verursachen können.
Außerdem geht es ja nicht um eine schwere Maschine sondern nur um einen
Shifter für mein eigenen Go-Kart.
Also was soll die Frage nach der Sicherheit?
Gad Z. schrieb:> Übrigens kann ich selbst bei einer Siemens Steuerung Parameter vom PC> aus so verbiegen das die Steuerung nicht mehr funktioniert bzw.> Servoantriebe zu schwingen beginnen und schlimmstenfalls mechanische> schäden verursachen können.
Ja, das ist aber DEREN Problem. Ein Geschäftsmann kalkuliert dann ggf.
eben wie eine Versicherung:
So und so viel Profit durch Einsparung der 50 Cent extra für
Wertebereichsprüfungen
vs./-
so und so viel Verlust durch Schadenersatzforderungen/Garantie im Falle
des Falles
=
(JA = +) / (NEIN = -)
Wenn es sowieso niemanden in Gefahr bringt würde ich mit den Offsets
arbeiten - Wozu die Arbeit, IDs zu mappen?
Aber wie gesagt: Mach, wie du das haben willst oder was es dir an Arbeit
wert ist.
zer0 schrieb:> Gad Z. schrieb:>> Übrigens kann ich selbst bei einer Siemens Steuerung Parameter vom PC>> aus so verbiegen das die Steuerung nicht mehr funktioniert bzw.>> Servoantriebe zu schwingen beginnen und schlimmstenfalls mechanische>> schäden verursachen können.>> Ja, das ist aber DEREN Problem. Ein Geschäftsmann kalkuliert dann ggf.> eben wie eine Versicherung:> So und so viel Profit durch Einsparung der 50 Cent extra für> Wertebereichsprüfungen> vs./-> so und so viel Verlust durch Schadenersatzforderungen/Garantie im Falle> des Falles> => (JA = +) / (NEIN = -)>
Ok wenn man es aus der geschäftlichen ebene sieht...
War aber nicht das Thema.
>> Wenn es sowieso niemanden in Gefahr bringt würde ich mit den Offsets> arbeiten - Wozu die Arbeit, IDs zu mappen?> Aber wie gesagt: Mach, wie du das haben willst oder was es dir an Arbeit> wert ist.
Wie soll ich es mit Offsets einfacher machen als mit ID's
Der Punkt ist doch das ich einzelne Elemente der Structur ab und zu
beschreiben will.
Wie soll ich dann das Symbol finden zu einem Offset?
Oder kann man bei GCC direkt auf die Structur + Offset zugreifen?
Wenn ja, wie? Ist doch kein Array.
Gad Z. schrieb:> zer0 schrieb:>> Gad Z. schrieb:>>> Übrigens kann ich selbst bei einer Siemens Steuerung Parameter vom PC>>> aus so verbiegen das die Steuerung nicht mehr funktioniert bzw.>>> Servoantriebe zu schwingen beginnen und schlimmstenfalls mechanische>>> schäden verursachen können.>>>> Ja, das ist aber DEREN Problem. Ein Geschäftsmann kalkuliert dann ggf.>> eben wie eine Versicherung:>> So und so viel Profit durch Einsparung der 50 Cent extra für>> Wertebereichsprüfungen>> vs./->> so und so viel Verlust durch Schadenersatzforderungen/Garantie im Falle>> des Falles>> =>> (JA = +) / (NEIN = -)>>> Ok wenn man es aus der geschäftlichen ebene sieht...> War aber nicht das Thema.>>>> Wenn es sowieso niemanden in Gefahr bringt würde ich mit den Offsets>> arbeiten - Wozu die Arbeit, IDs zu mappen?>> Aber wie gesagt: Mach, wie du das haben willst oder was es dir an Arbeit>> wert ist.>> Wie soll ich es mit Offsets einfacher machen als mit ID's> Der Punkt ist doch das ich einzelne Elemente der Structur ab und zu> beschreiben will.> Wie soll ich dann das Symbol finden zu einem Offset?> Oder kann man bei GCC direkt auf die Structur + Offset zugreifen?> Wenn ja, wie? Ist doch kein Array.
Das Symbol zu einem Offset wirst du so NICHT finden. Aber man kann die
Addresse zu einem Symbol berechnen.
1
structDaten{
2
floatfeld1;
3
floatfeld2;
4
};
5
6
/* das hier ist ein pointer, der nur zur address-berechnung verwendet wird.
7
0xadd2 ist die Addresse der Struct auf dem Controller. */
8
Daten*datenOnController=(Daten*)0xadd2;
9
10
void*addr=&(datenOnController->feld2);
Ob das Sinn macht, kommt wieder auf deinen use-case an.
zer0 schrieb:> Das Symbol zu einem Offset wirst du so NICHT finden. Aber man kann die> Addresse zu einem Symbol berechnen.>
1
>structDaten{
2
>floatfeld1;
3
>floatfeld2;
4
>};
5
>
6
>/* das hier ist ein pointer, der nur zur address-berechnung verwendet
7
> wird.
8
> 0xadd2 ist die Addresse der Struct auf dem Controller. */
9
>Daten*datenOnController=(Daten*)0xadd2;
10
>
11
>void*addr=&(datenOnController->feld2);
12
>
> Ob das Sinn macht, kommt wieder auf deinen use-case an.
Da hast du aber in deinem ersten Kommentar folgendes dazu geschrieben :
zer0 schrieb:> Kannst du nicht einfach mit nm/objdump/libbfd oder sowas die Addressen> der interessanten Symbole abfragen?
Also wozu eine Adresse zu einem Symbol berechnen wenn ich ohnehin den
Sybolnamen brauche?
Außerdem war ja mein problem das ich die daten vom PC kommend im AVR dem
richtigen Symbol zuordnen muß um darauf zu schreiben.
In deinem beispiel also das Symbol "feld2"
ich hätte jetzt eben so eine simple Case gemacht, nur eben mit ca 150
cases...
switch( receive_ID )
{
case 0x01:
Daten.feld1 = receive_Value
case 0x02:
Daten.feld2 = receive_Value
}
Oder habe ich da was total falsch verstanden?
Muß dazu sagen das ich wenig C-Erfahrung habe :-(
Deshalb frage ich ja hier so blöd um abzuschätzen ob es in C überhaupt
geht und ob sich der Aufwand lohnt.
Gad Z. schrieb:> Also wozu eine Adresse zu einem Symbol berechnen wenn ich ohnehin den> Sybolnamen brauche?
Ja, wenn du den brauchst auf dem Controller...
Mit objdump kannst du dir einfach zu jeder Variable im Programm die
Addresse ausgeben lassen. Zusammen mit dem "bliebig Schreiben und
Lesen"-Protokoll kann man damit also in ganz genereller Weise alles
mögliche auf dem Ding schreiben und lesen - könnte man in eine generelle
GUI packen, wo man dann alle Variablen mit aktuellen Werten sieht und
ändern kann.
Und das OHNE jede Variable einzeln irgendwo aufzuzählen.
Restringierter wird das natürlich mit den festen IDs.
Das sieht vom Prinzip her richtig aus. Kann man so machen.
(Allerdings fehlt ein "break" in den cases, aber das hättest du sicher
noch bemerkt :)
Ich würde zwar aus unbestimmten Gründen eine Symboltabelle als array im
Programm präferieren, aber cases funktionieren ganz bestimmt auch.
zer0 schrieb:> Gad Z. schrieb:>> Also wozu eine Adresse zu einem Symbol berechnen wenn ich ohnehin den>> Sybolnamen brauche?>> Ja, wenn du den brauchst auf dem Controller...> Mit objdump kannst du dir einfach zu jeder Variable im Programm die> Addresse ausgeben lassen. Zusammen mit dem "bliebig Schreiben und> Lesen"-Protokoll kann man damit also in ganz genereller Weise alles> mögliche auf dem Ding schreiben und lesen - könnte man in eine generelle> GUI packen, wo man dann alle Variablen mit aktuellen Werten sieht und> ändern kann.> Und das OHNE jede Variable einzeln irgendwo aufzuzählen.
Genau den Symbolnamen brauche ich nicht sondern Zugriff auf Variablen
mit Hilfe der Adresse.
Aber laut diesem Thread geht das doch bei C nicht weil der Compiler
selber die Adressverwaltung macht.
Daher die Sache mit der Struktur um wenigstens die Reihenfolge der
Variablen im Speicher vorgeben zu können.
> Restringierter wird das natürlich mit den festen IDs.> Das sieht vom Prinzip her richtig aus. Kann man so machen.> (Allerdings fehlt ein "break" in den cases, aber das hättest du sicher> noch bemerkt :)
Ja der Break fehlt..... ich war zu faul es richtig zu tippen :-)
Sollte nur als beispiel dienen, aber danke für den Tip.
>> Ich würde zwar aus unbestimmten Gründen eine Symboltabelle als array im> Programm präferieren, aber cases funktionieren ganz bestimmt auch.
Sorry aber ich stehe auf dem Schlauch.
Was meinst du mit einer Symboltabelle als Array?
Ein Array hat doch nur ein Symbol und den Arrayindex...
Harry L. schrieb:> foo[i] = 42; // the answer of all your questions :-D
1
Fehler: assignment to expression with array type
2
foo[i] = 42; // the answer of all your questions :-D
3
^
Muesste so sein:
1
for(uint8_ti=0;i<ARRAY_SIZE;i++){
2
(*foo)[i]=42;// the answer of all your questions :-D
3
}
Darueber hinaus ist das aber trotzdem kacke, denn:
1
my_fucking_data_t*foo=0x1234;
Hier wird ein Pointer erzeugt, der einfach auf die Speicheradresse
0x1234 zeigt, ohne das dort ein gueltiges Objekt existiert. Du weisst
aber gar nicht, was an dieser Speicheradresse liegt, geschweige denn, ob
diese Adresse (und die nachfolgenden) ueberhaupt frei sind.
Moeglicherweise waechst einmal der Stack ueber diese Adresse rueber, und
schon sind alle deine Werte fuer den Eimer. Oder andersrum, du schreibst
einfach Werte im Stack kaputt.
Damit ist unvorhersehbares Programmverhalten vorprogrammiert.
Kaj G. schrieb:> Hier wird ein Pointer erzeugt, der einfach auf die Speicheradresse> 0x1234 zeigt, ohne das dort ein gueltiges Objekt existiert.
Ja natürlich ist sowas bescheuert, aber das war die Ausgangsfrage.
Der Code compiliert bis auf 1 Warnung hier übrigens problemlos.
Harry L. schrieb:> Ja natürlich ist sowas bescheuert
Dann poste nicht so einen Muell.
Harry L. schrieb:> aber das war die Ausgangsfrage.
Nein. Die Frage war:
Wie legt man ein Objekt an eine bestimmte Stelle, und nicht,
wie man einen Zeiger auf eine bestimmte Adresse zeigen laesst.
Es gibt da einen nicht unerheblichen Unterschied, aber was
langweile ich hier mit Details...
Harry L. schrieb:> Der Code compiliert bis auf 1 Warnung hier übrigens problemlos.
Glaub ich dir nicht.
1
#include<stdint.h>
2
3
#define ARRAY_SIZE 10
4
5
typedefuint8_tmy_data_t[ARRAY_SIZE];
6
7
my_data_t*foo=0x1234;// Memory-Adress 0x1234
8
9
voidmain(void)
10
{
11
uint8_ti;
12
for(i=0;i==ARRAY_SIZE;i++)
13
foo[i]=42;// the answer of all your questions :-D
14
}
1
$ gcc --version
2
gcc (GCC) 7.1.1 20170630
1
$ gcc -std=c99 -o main test.c
2
test.c:7:18: Warnung: Initialisierung erzeugt Zeiger von Ganzzahl ohne Typkonvertierung [-Wint-conversion]
3
my_data_t *foo = 0x1234; // Memory-Adress 0x1234
4
^~~~~~
5
test.c: In Funktion »main«:
6
test.c:13:16: Fehler: Zuweisung an Ausdruck von Arraytyp
7
foo[i] = 42; // the answer of all your questions :-D
Und selbst wenn es compilieren sollte (was es nicht tut), beinhaltet
dein Code immernoch folgende Probleme:
1) Die Laufbedingung der Schleife ist falsch. Die Schleife wird nie
durchlaufen und wegoptimiert (wenn es denn compilieren wuerde)
2) Die Zuweisung in der Schleife ist falsch (Fehler: Zuweisung an
Ausdruck von Arraytyp). foo ist ein Pointer auf ein Array, also ein
Pointer auf einen Pointer. Du vergisst die Dereferenzierung des ersten
Pointer. Erst wenn du foo dereferenzierst -> (*foo) kannst du mit dem
Index gueltig darauf zugreifen -> (*foo)[i]
Der AVR-GCC 5.3.0 ist die aelteste Version die ich gerade hier hab, und
da compiliert das auch schon nicht.
Ausgangsfrage:
Jochen schrieb:> Wie kann ich ein ARRAY an eine feste Adresse legen? Zum> Programmieren> verwende ich ATMEL Studio 7.>> So einfach geht es leider nicht:>> unsigned char object[maxobject] absolute 0x100;Oliver S. schrieb:> Der implizite Teil der Ausgangsfrage "..., und zwar so, daß das auch> funktioniert", ist dir halt entgangen.
Und was soll das sein?
Ich hab eher den Eindruck, daß du da irgendwas hinein interpretieren
möchtest, was da nicht steht.....
So, wie ich das gepostet hab, macht das genau das Gewünschte.
Ob das auch sinnvoll ist, steht auf einem ganz anderen Blatt
Harry L. schrieb:> So, wie ich das gepostet hab, macht das genau das Gewünschte.
Nein, macht es nicht, weil das Programm damit abstürzen wird.
Compilerbarkeit ist eine notwendige Bedingung für ein korrekt
funktionierendes Programm, aber keine hinreichende. Generationen von
Programmierern haben das inzwischen ausreichend bewiesen...
Du hast den ersten kleinen Teil der Aufgabe gelöst, wie man einem
pointer eine konstanten Wert zuweist. Den größeren Problemteil der
Frage, wie man ein Array an eine feste Adresse im SRam eines AVRs (oder
jedes anderen Mikrocontrollers) legt, so daß das am Ende auch
funktioniert, hast du weder beantwortet, noch überhaupt verstanden.
Oliver
Nachtrag:
Wenn das Array am Anfang des SRam liegen darf, dann liefert
http://www.nongnu.org/avr-libc/user-manual/mem_sections.html
den fehlenden Teil der Antwort.
Wenns dagegen irgendwo mittendrinn oder am Ende platziert sein soll,
dann ist händisches editieren der linkerskripts erforderlich.
Oliver
Oliver S. schrieb:> Harry L. schrieb:>> So, wie ich das gepostet hab, macht das genau das Gewünschte.>> Nein, macht es nicht, weil das Programm damit abstürzen wird.> Compilerbarkeit ist eine notwendige Bedingung für ein korrekt> funktionierendes Programm, aber keine hinreichende. Generationen von> Programmierern haben das inzwischen ausreichend bewiesen...>> Du hast den ersten kleinen Teil der Aufgabe gelöst, wie man einem> pointer eine konstanten Wert zuweist. Den größeren Problemteil der> Frage, wie man ein Array an eine feste Adresse im SRam eines AVRs (oder> jedes anderen Mikrocontrollers) legt, so daß das am Ende auch> funktioniert, hast du weder beantwortet, noch überhaupt verstanden.>> Oliver
Herr im Himmel!
Ich gebs auf!
Natürlich stürzt das ab.
So what....
Die Frage wurde beantwortet.
Ich bin hier raus....
Würde auch gerne wissen wie das funktioniert weil wenn man testen will
welche Speicherberiech in einem Mikrocontroller eventuell buggy sind
sollte man ja direkt mal irgendwo in die Hardware schreiben können ohne
(wie am anfang vom thread) als doofi bezeichnet zu werden.VIelleicht
gibts in zwischen ne header mit funktion?
standardfratze schrieb:> wenn man testen will welche Speicherberiech in einem Mikrocontroller> eventuell buggy sind
… dann nimmt man einen Zeiger, statt irgendeinen uralten Thread
auszugraben.
Aber wer sagt dir denn dann, dass der Programmspeicher mit dem Programm,
das den Speicher testen soll, nicht auch "buggy" sein könnte? In aller
Regel sind solche Tests nur sehr wenig sinnvoll.