Man möge mir die Anfrage verzeihen (weil ich noch absoluter Newbie im
Umgang mit PADAUK in Verbindung mit SDCC bin).
Vllt. weiß ja Philipp Klaus K. einen Rat für mich oder kann mir etwas
erläutern: bisher habe ich in Programmen, wenn es evtl. knapp mit dem
Ram war (nicht Padauk) "einfach" den verfügbaren Speicherplatz
abgefragt, das kann ich mit den (sehr) kleinen PFS154
nicht.
Also mache ich mich über das Map-File des SDCC her (schlicht weil ich 30
oder 40 Byte mehr Ram benötige).
In meinem Programm habe ich eine Funktion:
1
// mir ist bewusst, dass das Registerarray 32 Byte Ram frisst, aber das geht leider nicht anderst
Warum ist das so?
Interpretiere ich hier etwas falsch ? Ich hätte im besten Fall 4 Bytes
vermutet, 2 für den Parameter und 2 für die Rücksprungadresse (wobei ich
eigentlich annehme, dass eine Rücksprungadresse auf dem Stack liegt und
hierfür nicht extra Ram reserviert wird).
Interpretiere ich das falsch und es werden gar keine 8 Bytes reserviert
und wenn ich das nicht falsch interpretiere wie kann ich Abhilfe
schaffen?
--------------------------------------
Wenn ich mein Programm nur mit globalen Variablen schreibe funktioniert
das Programm aber es ist natürlich höchst unschön (und ich will das
eigentlich nicht mit mehr globalen Variablen machen als notwendig).
Gruß,
Ralph
Keine Möglichkeit, dir den erzeugten Assemblercode der Funktion
anzusehen (du könntest erschrecken was er alles macht), schliesslich ist
der Padauk fast ein PIC und genau so ungeeignet für C.
MaWin schrieb:> Keine Möglichkeit, dir den erzeugten Assemblercode der Funktion> anzusehen
ich habe mir ihn angesehen...
MaWin schrieb:> der Padauk fast ein PIC und genau so ungeeignet für C.
Das würde ich so nicht unterschreiben. Allerdings hat auch niemand
gesagt dass dieses ein "komfortabler" Controller ist und ich kenne deine
Abneigung den Padauk mittels C programmieren zu wollen (genau so wie du
abgeneigt bist, die kleinen PIC in C coden zu wollen).
Hier geht es mir auch nicht darum den in Assembler programmieren zu
wollen (das Programm das mir vorschwebt funktioniert in Assembler
schon), es geht mir darum, ein kleines Framework für den Padauk in C zu
machen, egal ob das für jemanden Sinn macht oder nicht und für mich
auszuloten, was in C machbar ist und was nicht.
Kleinere Dinge die in C machbar sind, werde ich hier dann sicher nicht
in Assembler erledigen, schlicht deshalb, weil sie schneller erledigt
sind.
Ich mag hier auch garantiert nicht eine Diskussion C vs. Assembler
aufmachen wie sie hier schon einmal stattgefunden hat, sondern es ging
mir schlichtweg darum, wie ich in C RAM-Speicher sparen kann, vor allem
in Verbindung mit dem SDCC (den ich gut finde und ich froh bin, dass es
diesen gibt).
Wenn ich in C keine Lösungen für mich finde, werde ich bestimmte Dinge
mit dem Padauk in C eben nicht machen.
Hier ging es vor allem darum, warum für eine Parameterübergabe eines
16-Bit Integers 8 Byte RAM benötigt werden, in einer anderen Funktion,
die einem Int-Array einen Wert beschreibt sogar 32 Byte belegt werden
(was für mich eben deshalb tragisch ist, weil der Controller nur 128
Byte Ram hat).
Im Übrigen gilt für mich: erlaubt ist, was funktioniert (was heißt, dass
ich in meinem Falle wohl mit globalen Variablen arbeiten werde und die
Programmfunktionen in eine *.h *.c Kombination stecke in der die
globalen Variable nicht "öffentlich" gemacht werden. Schön ist zwar
anderst, aber so funktioniert es dann eben.
-----------------------------
By the way: das momentane "Projekt" erstellt aus dem Padauk ein kleines
UKW-Radio mit RDA5807 Chip und Software I2C. Das Radio ist schon
ansprechbar und ich kann einen Sender und eine Lautstärke schon fest
einstellen. Das ganze soll mit 3 Tasten gesteuert werden und als Anzeige
fungieren 20 LED's als Leuchtband, die mittels Charlieplexing
angesprochen werden. Charlieplexing funktioniert auch, nur geht mir eben
in Kombination von allem genau der RAM aus (und im konkreten Falle um
genau 27 Byte).
Funktionsfähige Teile in C mittels Padauk sind:
- Nutzung 16-Bit Timer als Reload-Overflow
- einfacher Notenparser, gespeichert in einem String, der diese mittels
Rechteckfrequenzen abspielen kann (im Stile einfacher Melodiegrußkarten)
- serielle Schnittstelle mit uart_putchar UND uart_getchar
- eigenem abgespecktem printf (logischerweise OHNE float-Unterstützung)
- I2C
- serielle Schieberegister (74HC595 / HEF 4094)
- generellen Abstraktionslayer für die GPIO Pins
Und das alles, damit man eben auf die Schnelle ein Progrämmchen bei
Bedarf auf dem Padauk "hinrotzen" kann.
Ob das alles einen Sinn macht ist hier nicht die Frage (denn das ist es
bei einem Hobby sicher nie), für mich ist das einfach faszinierend dass
ein derart billiger Controller die Syntax von C verstehen kann, selbst
dann, wenn der Code nicht sooooooo zwingend effizient ist.
So kann ich, zumindest bei Verwendung von Bitbanging, zwischen den
einzelnen Controllern hin und her springen wie ich das mag.
Ralph S. schrieb:> ich habe mir ihn angesehen...
Na dann müsstest du doch jedes verwendete Datenbyte sehen.
Nein, ich programmiere gerne in C, finde aber schon den code den GCC für
den AVR erzeugt grausam.
Ralph S. schrieb:> Ich mag hier auch garantiert nicht eine Diskussion C vs. Assembler> aufmachen wie sie hier schon einmal stattgefunden hat, sondern es ging> mir schlichtweg darum, wie ich in C RAM-Speicher sparen kann, vor allem> in Verbindung mit dem SDCC (den ich gut finde und ich froh bin, dass es> diesen gibt).>> Wenn ich in C keine Lösungen für mich finde, werde ich bestimmte Dinge> mit dem Padauk in C eben nicht machen.Ralph S. schrieb:> Wenn ich mein Programm nur mit globalen Variablen schreibe funktioniert> das Programm aber es ist natürlich höchst unschön (und ich will das> eigentlich nicht mit mehr globalen Variablen machen als notwendig).
Ich kann deine Herangehensweise nicht wirklich verstehen. Diese Padauk's
sin wirklich KLEINE Plattformen, da sollte man bereit sein, deren
begrenzte Ressourcen sinnvoll zu verwenden und eben nicht hochtrabend
irgendwelche C-Programmierer-Regeln als wichtiger zu erachten als die
Plattform, die man zu programmieren gedenkt.
Also, es ist absolut NICHT "höchst unschön", auf dieser Plattform
vornehmlich oder gar nur mit globalen Variablen zu arbeiten. Das ist
die platzsparendste Version von allen. Und wenn es damit funktioniert,
wie du ja schriebest, dann ist aus meiner Sicht die Sache final
erledigt.
Bedenke mal, daß du auf diesen µC eben recht wenig RAM hast. Also
überlege es dir gut, WAS du mit den Dingern anstellen willst - denn wenn
du partout und NUR in C programmieren willst, dann kriegst du eben nicht
anähernd soviel dort hinein, wie das in Assembler (und eigenem Können)
möglich wäre. Dann bleibt dir nur eines: einen größeren Chip nehmen.
Ich für meinen Teil kenne das alles in- und auswendig, schließlich
benutze ich schon fast 30 Jahre lang PIC's - die ich jedoch in Assembler
programmiere. Muß man eben wollen und können.
Nun hat Padauk seine Chips zwar bei den PIC's abgeguckt, aber eben
zwecks Kostenminimierung umgemodelt: Peripherie abgespeckt, das Meiste
davon braucht man bei den angedachten Einsatzzwecken (Flackerkerzen,
piepsende Grußpostkarten, billigster Schnickschnack aller Art) sowieso
nicht, dafür die innere Struktur in Richtung C getrimmt (Stack in den
RAM, ADD/SUB mit Carry und so weiter). Das hatte dann Konsequenzen für
die Hardwareregister, die zwecks Freimachen von RAM in ein Extrasegment
IO verlagert werden mußten, das wiederum machte spezielle
Zugriffstbefehle notwendig und so weiter. Dazu dann eine Mini-IDE für
das Programmieren in einem etwas abgespeckten C - das hatte triftige
Gründe.
Diese Padauk-Chips sind in ihrer Art tatsächlich sehr konsequent auf das
Billigst-Segment getrimmt: nicht nur der Chip und die Funktionalität
darauf sind dafür optimiert, sondern auch die Programmierung: Leute, die
nur etwas C können und sonst nix anderes, gibt es wie Sand am Meer - und
sie sind billige Arbeitskräfte. Gute Assemblerprogrammierer sind
hingegen eher rar. Wenn also eine Firma Billigs-Schnickschnack damit
bauen will, dann dürfen die Programmierer auch nicht viel kosten.
Wenn man sich das alles mal durch den Kopf gehen läßt, dann kann man zu
Padauk nur "Chapeau!" sagen. Sie haben das alles konsequent und richtig
durchgezogen.
Und jetzt kommen Leute wie du und wollen mit dem SDCC dort hineinbrummen
und dabei ihre gelernten Prämissen aufrecht erhalten wie z.B. deine
Bemerkung über globale Variablen. Wenn das Boot und der Teich zum drauf
schwimmen nicht zueinander passen - was ist dann daran als falsch zu
bemängeln?
W.S.
Kuddel schrieb:> W.S. schrieb:>> Du hast den Deppen-Apostroph gut drauf. Dafür ist dein Beitrag> ziemlicher Mist.
Weiß nicht, warum man da jetzt mit dem Deppen-Apostroph-Kram
polemisieren muss, ich fand den Betrag von W.S. sehr gut und treffend.
Solche Einschränkungen gab es bei den PIC12-Compilern von CSS vor 15
Jahren auch. Man war doch froh, dass es überhaupt C für die Dinger gab,
der Code sah ganz gut aus und konnte mit den Einschränkungen leben.
Kuddel schrieb:> Du hast den Deppen-Apostroph gut drauf. Dafür ist dein Beitrag> ziemlicher Mist.
Zumindest beweist du, dass du nichts von ihm verstanden hast.
Aber wo liegt er denn falsch? Gut, den zweiten Teil mit den
Programmierern hätte er weglassen können aber das hier ist ein Forum und
kein Uploadportal für Dissertationen.
W.S. schrieb:> Und jetzt kommen Leute wie du und wollen mit dem SDCC dort hineinbrummen> und dabei ihre gelernten Prämissen aufrecht erhalten wie z.B. deine> Bemerkung über globale Variablen.
... darum gehts doch gar nicht und gerlernt habe ich vor 40 Jahren auf
einem 8080 in Maschinensprache, bei Controllern mit 8048 angefangen und
wie viele dann auf MCS-51 ... natürlich alles in Assembler... und
irgendwann einmal mußte ich dienstlich PIC16F84 verwenden (für einen
Temperaturdatenlogger). Sogar Teile von PC Programmen hab ich in ASM
gemacht (damals auch sogenannte TSR). Pascal, Delphi und C kamen erst
sehr viel später. Von daher "denke" ich eher in Maschinensprache als in
C, nur programmiere ich in Maschinensprache nur noch dann, wenn ich muß.
Summa summarum: es geht nicht darum, etwas partout in C machen zu wollen
(beim Reload des 16-Bit Timers mußt du bspw. -noch- das Register mit
Inline-ASM füttern weil SDCC momentan den Zugriff noch nicht für dieses
einzige 16-Bit Register implementiert hat).
Es geht schlicht darum, etwas (für andere und mich) bereit zu stellen,
mit dem schnelle Lösungen trotz dieser extrem dünnen Resourcen machbar
sind. Das ganze bitte wieder verwendbar.
------------------------------------
Bei meinem ursprünglichen Problem hab ich mittlerweile 30 Byte RAM
einsparen können (mit aus meiner Sicht der Dinge immer noch unschönem
C), aber funktioniert, im Stile von (hinzuzulinkende C-Datei):
1
uint8_t aktvolume = 7;
2
uint8_t tmpvolume;
3
4
// überall im Programm kann die aktvolume geändert werden...
5
6
void setvolume(void)
7
{
8
volume_register= aktvolume;
9
}
10
11
void scandown(void)
12
{
13
tmpvolume= aktvolume;
14
aktvolume= 0; // Ton während Scan aus
15
setvolume();
16
// hier Sendersuchlauf
17
aktvolume= tmpvolume;
18
setvolume();
19
}
Das witzige hierbei ist, dass für einen solchigen Code Unmengen an
Programmierer den Kopf schütteln werden, dass man das in C eben so nicht
macht, sondern eben mit call by value oder call by reference. Beide
Methoden verschlingen aber mehr Speicher, mit den globalen Variablen
hier wurden in diesem Stile 12 Byte eingespart (normalerweise schüttelt
man darüber den Kopf, weil 12 Byte nicht die Menge sind, aber wenn man
insgesamt nur 128... ).
Das ganze kommt mir vom Stil dann auch eher in Richtung ASM vor, bei dem
man vor einem Call ein Register oder eine Speicherstelle beschreibt und
dann eben diese in der aufgerufenen Funktion auswertet.
Ich glaube, gerade W.S. ist der erste, wenn er solchen Code sieht, der
als erster schreit, dass man das so nicht macht.
------------------------------------------------
Im Moment kämpfe ich jedoch mit anderen Dingen, bspw. warum ein
read-modify-writeback auf die Register für die GPIO nicht so
funktioniert wie ich das haben möchte.
Konfiguriere ich einen Portpin mittels:
PADIER |= 1 << bitnr;
PAC &= ~(1 << bitnr);
als Eingang, so wird mit dir Konifguration zerschossen, sobald ich auf
Port A einen weiteren Pin als Ausgang verwenden möchte, so dass ich die
Initialisierung vor dem Lesen eines Pins erneut durchführen muss.
Mir sind da einige Dinge eben noch suspekt (oder besser unklar) und
suche hierfür eben den besten Weg.
... und an W.S. noch einmal:
Ja, ich habe in grauer Vorzeit einmal, mit PIC16F84 eine Berechnung mit
natürlichem Logarithmus in Assembler machen müssen bei gleichzeitiger
Aufaddierung der auf das Minigerätchen eingewirkten Wärmemenge...
Sowas will ich nie wieder machen müssen, in meiner Erinnerung war dieses
die scheuslichste Programmierarbeit, die ich je gemacht habe.
> Sowas will ich nie wieder machen müssen, in meiner Erinnerung war dieses> die scheuslichste Programmierarbeit, die ich je gemacht habe.
Die Einstellung Teile ich zwar nicht so ganz, kann sie aber immerhin
nachvollziehen. Was ich aber nicht verstehe warum man sich dann privat
mit so einem Mickercontroller mit OTP abgibt. Als Firma die dann
1Million davon kauft kann ich das verstehen, aber privat gibt man einmal
1Euro mehr aus und hat danach eine sehr viel spassigeres leben.
Was WS geschrieben hat stimmt schon..
Olaf
Ralph S. schrieb:> (weil ich noch absoluter Newbie im> Umgang mit PADAUK in Verbindung mit SDCC bin)
Dann ist es natürlich besonders "klug", einen MC zu nehmen, der nur
wenige Ressourcen hat und den nur sehr wenige kennen.
Keiner, der bisher geantwortet hat (mich eingeschlossen), kennt diesen
Chip.
Man kann sich das Leben auch künstlich schwer machen. Viel Spaß dabei.
Wie ja schon gesagt wurde, sollte aus dem Assemblerlisting hervorgehen,
wofür der RAM genau benutzt wird.
Wenn ich Hilfe bräuchte, würde ich MCs nehmen, die weit verbreitet und
gut in C programmierbar sind, z.B. AVR oder 8051.
Peter D. schrieb:> Dann ist es natürlich besonders "klug", einen MC zu nehmen, der nur> wenige Ressourcen hat und den nur sehr wenige kennen.
Er schreibt aber doch, dass er 40 Jahre Programmiererfahrung hat. Wenn
er jetzt mal was mit Padauk machen will ist er ja automatisch am Anfang
Newbie. Oder wie machst Du das?
Wenn dein Programm C8x conform ist, dann kann ich dies mal durch den
smallC durchlaufen lassen und dir den Ressourcenverbrauch auf Padauk
mitteilen, ist aber kein vollwertiger C wie sdcc.
Harald schrieb:> Oder wie machst Du das?
Ich habe ja noch nicht mal die MCs ausgeschöpft, die ich kenne. Daher
habe ich keinerlei Bedarf nach weiteren 8-Bittern.
Man will sich ja nicht rückentwickeln, sondern weiter entwickeln. D.h.
irgendwas machen, was die bisherigen Chips noch nicht oder nur sehr
umständlich können.
Man kauft sich ja auch nicht das neue Auto schlechter als das alte.
Ralph S. schrieb:> Das witzige hierbei ist, dass für einen solchigen Code Unmengen an> Programmierer den Kopf schütteln werden, dass man das in C eben so nicht> macht
D.h. als abschreckendes Beispiel, diesen MC lieber nicht zu nehmen.
Gut zu wissen.
Peter D. schrieb:> Ralph S. schrieb:>> Das witzige hierbei ist, dass für einen solchigen Code Unmengen an>> Programmierer den Kopf schütteln werden, dass man das in C eben so nicht>> macht>> D.h. als abschreckendes Beispiel, diesen MC lieber nicht zu nehmen.> Gut zu wissen.
Also ich finde die auch interessant (aber nur um zu sehen, was man auch
einem 3ct Controller so rausholen kann). Du musst den ja nicht nehmen.
Aber dürfen andere das dann auch nicht bzw. hier Fragen stellen?
Ralph S. schrieb:> Von daher "denke" ich eher in Maschinensprache als in> C, nur programmiere ich in Maschinensprache nur noch dann, wenn ich muß.>> Summa summarum: es geht nicht darum, etwas partout in C machen zu wollen
Also erstens sind wir uns nach deinen Worten dann doch ähnlicher, als
angenommen und zweitens frag ich mich, was dann deine Worte
Ralph S. schrieb:> Wenn ich in C keine Lösungen für mich finde, werde ich bestimmte Dinge> mit dem Padauk in C eben nicht machen.
bedeuten sollen. Ich lese das so: "entweder geht der Chip in C zu
programmieren oder ich will ihn nicht benutzen."
Und obendrein hast du ja geschrieben, daß deine Firmware funktioniert
und reinpaßt, wenn du die Variablen alle global machst. Da ist das
Problem doch erledigt, also wozu dann all die Aufregung?
Ist es dir wichtiger, globale Variablen zu vermeiden und stattdessen mit
einem Haufen an Funktionsargumenten zu arbeiten oder gar 'static' zu
benutzen, als die Grenzen des vorliegenden Chips zu beachten? Siehe:
"Wenn ich mein Programm nur mit globalen Variablen schreibe funktioniert
das Programm aber es ist natürlich höchst unschön" Ich würde da aber
ganz schnell meine Prioritäten neu ordnen. Und ich finde globale
Variablen durchaus nicht höchst unschön. Wer lehrt die Leute denn sowas?
Nochwas:
Ich hab jetzt nicht all die HW-Register dieser Chips auswendig gelernt,
aber wenn ich mal ganz kühn von den PIC auf die Padauk schließe, dann
kommt mir deine Quelle etwas verschwenderisch vor. Ich mach da mal ein
paar Anmerkungen:
1
uint8_taktvolume=7;// wozu überhaupt eine Variable erzeugen?
2
uint8_ttmpvolume;// dito
3
4
// wozu diese Funktion überhaupt schreiben?
5
// so wie es aussieht, hält 'volume_register' den Volumewert
6
// ja ohnehin. Man kann das (sehr wahrscheinlich) als normale
7
// Variable benutzen.
8
voidsetvolume(void)
9
{
10
volume_register=aktvolume;
11
}
12
// wäre wohl eher als Inline machbar, etwa so:
13
inlinevoidsetvolume(unsignedcharw)
14
{volume_register=w;}
15
16
17
18
// ohne inneren Funktionsaufruf
19
// dafür aber mit einer Variablen auf dem Stack
20
voidscandown(void)
21
{unsignedchartmp;// hier mal lokal
22
23
tmp=volume_register;
24
volume_register=0;// Ton während Scan aus
25
// hier Sendersuchlauf
26
volume_register=tmp;
27
}
28
29
// Alternativlösung mit einer Universal-Temporär-Variablen, die
30
// man an anderen Stellen eben auch benutzt. Das braucht Obacht,
31
// daß man die nicht gedankenlos mehrfach geschachtelt benutzt
32
33
unsignedchartemphudel;// quasi Mädchen für alles
34
35
voidscandown(void)
36
{temphudel=volume_register;
37
volume_register=0;// Ton während Scan aus
38
// hier Sendersuchlauf
39
volume_register=temphudel;
40
}
Ich sag's mal so: Die Gepflogenheiten auf dem PC sind das eine, das
Bedenken der Eigenheiten solcher kleinen µC's sind etwas ganz anderes.
Gepflogenheiten kann man ändern oder mal auslassen, eine vorliegende
Plattform kann man hingegen nicht ändern.
W.S.
Harald schrieb:> Aber dürfen andere das dann auch nicht bzw. hier Fragen stellen?
Ich wollte nur darauf hinweisen, daß man sich dann nicht über das
Ausbleiben von zielführenden Antworten wundern sollte.
Mehr nicht.
Ralph S. schrieb:> Ja, ich habe in grauer Vorzeit einmal, mit PIC16F84 eine Berechnung mit> natürlichem Logarithmus in Assembler machen müssen bei gleichzeitiger> Aufaddierung der auf das Minigerätchen eingewirkten Wärmemenge...>> Sowas will ich nie wieder machen müssen, in meiner Erinnerung war dieses> die scheuslichste Programmierarbeit, die ich je gemacht habe.
Tja, da sind wir uns dann doch SEHR unähnlich:
Ich hatte damals (Anfang der 90er) von Microchip nur den PICALC als
Assembler. OK, das war ein eher scheußliches Tool. Also hatte ich mir
kurzerhand meinen Assembler für die PIC's selber geschrieben.
Und da ich auch für meßtechnische Zwecke Gleitkomma brauche, hab ich mir
auch mein Gleitkommapaket für diese PIC selbe geschrieben. Später hab
ich das auf 32 Bit Mantisse umgeschrieben, weil ich für meinen
Taschen-Frequenzzähler mehr als nur 24 Bit Mantisse brauchte. Ich kann
sowas und wenn ich es brauche, schreibe ich mir das eben selber, wenn
mir das Vorhandene nicht gefällt.
Die ganze Architektur der PIC ist für Assembler gemacht und ich finde,
sie hat in diesem Punkte eine Eleganz, die man bei stupiden
Load-Modify-Store Architekturen eben nicht hat. Ich mag das und du hast
dich offensichtlich innerlich dagegen gesträubt. Tja, kann man nix
machen.
W.S.
Peter D. schrieb:> Man will sich ja nicht rückentwickeln, sondern weiter entwickeln. D.h.> irgendwas machen, was die bisherigen Chips noch nicht oder nur sehr> umständlich können.> Man kauft sich ja auch nicht das neue Auto schlechter als das alte.
Bla Bla natürlich.
Manche brauchen wenn sie älter werden keine Schwanzverlängerung mehr,
sondern sind mit dem Kleinwagen zufrieden.
Und andere finden es interessant was man mit kleinen billigen uC machen
kann während andere den rPi einsetzen.
Lass ihn also machen. Warum er sich aber verweigert, den
compilererzeugten Assemblercode anzusehen, weiss ich auch nicht,
ebensowenig wie ich wüsste was an einer handvoll globaler Variablen
schlecht ist.
Peter D. schrieb:> Keiner, der bisher geantwortet hat (mich eingeschlossen), kennt diesen> Chip.
Peter, sieh das mal etwas genereller. Wir hatten vor Jahren das große
Plattform-Sterben, weil die Cortexe so ziemlich alles Andere
plattgemacht hatten. Keine NEC, keine Fujitsu, keine Mitsubishi, keine
Hitachi, keine Mips in ESS-Chips mehr.
Ich finde das überhaupt nicht gut, denn ich weiß, daß Monokulturen immer
auf lange Sicht etwas übles sind. Und genau aus DIESEM Grunde finde ich
im Prinzip das Auftauchen dieser kleinen billigen Chips durchaus
begrüßenswert.
Das könnte eine Bereicherung des Marktes sein. Allerdings gibt es ernste
Widerhaken dabei: der Hersteller hat zwar die Assembler-Mnemonics
veröffentlicht, die jeweiligen Maschinencodes jedoch nicht. Er hat auch
nicht die Programmieralgorithmen für die Chips veröffentlicht.
Das ist ein wirklich ERNSTER Grund, die Finger davon zu lassen.
Nun haben einige Enthusiasten auf eigene Faust dies herausbaldowert, was
an sich lobenswert ist, aber es fehlt noch immer eine Dokumentation all
dessen, was da herausgefunden wurde. Stattdessen gibt es einiges an über
die Zeit angehäuften Unterlagen unterschiedlichen Erkenntnisstandes,
dito Quellen, dito Fragmenten, was aber salopp gesagt alles nur
dahingerotzt ist.
Es gibt auch einen Programmierdongle dafür, der in Serie produziert
wird, als ich das letzte Mal dort reingeschaut hatte, war grad die 2.
Charge in Produktion. Aber auch dort sind zwar Quellen und Schaltung per
Git veröffentlicht (die Quellen durchaus professionell geschrieben),
jedoch wiederum völlig kommentarlos und ohne Dokumentation. Ist fast wie
bei einem obfuscated Java-Modul. Das ist dann ebenso wenig der
Verbreitung förderlich wie das Benehmen des Herstellers.
Ich kann verstehen, daß die Jagd nach dem, was der Hersteller
verschweigt, für interessierte Programmierer sehr reizvoll ist. Ich kann
es auch verstehen, wenn Leute aus der Verschwiegenheit des Herstellers
ein Geschäft machen und Programmiertools dafür verkaufen wollen und
deshalb nicht interessiert sind, die Essentials dediziert zu
dokumentieren.
Ja, es gibt da einiges außerhalb von Padauk, aber das heißt noch lange
nicht, daß das ein Beitrag zur Beförderung der Popularität dieser Chips
ist. Und wenn sich da im Verständnis der Beteiligten nichts ändert, dann
bleibt das Ganze eben nur eine Rand-Episode.
Ich selbst hatte durchaus mit dem Gedanken gespielt, meine GK-Lib auf
die Padauk's umzusetzen, damit man dort auch mal kleinere Meßgeräte etc.
machen kann. Aber ich mache sowas nicht, ohne zuvor eine ordentliche
Dokumentation des Pferdes zu haben, das da geritten werden soll.
W.S.
> Also ich finde die auch interessant (aber nur um zu sehen, was man auch> einem 3ct Controller so rausholen kann). Du musst den ja nicht nehmen.
Also so wie GO auf einem 6x6 Feld zu spielen? :-)
Ich kann ja verstehen das sich arme Schweine damit beschaeftigen muessen
welche die blinkenen Weihnachtbaeume fuer die Grabbelkiste bei Aldi
entwickeln muessen und wenn mich mein Chef mit Geld bewirft damit ich
meine Zeit damit vertute auch okay. Aber wieso ich meine Freizeit mit so
einem ollen Kram vertueddeln soll ist mir ein Raetzel.
Olaf
Olaf schrieb:> Ich kann ja verstehen das sich arme Schweine damit beschaeftigen muessen> welche die blinkenen Weihnachtbaeume fuer die Grabbelkiste bei Aldi> entwickeln muessen und wenn mich mein Chef mit Geld bewirft damit ich> meine Zeit damit vertute auch okay. Aber wieso ich meine Freizeit mit so> einem ollen Kram vertueddeln soll ist mir ein Raetzel
Tja, warum beschäftigen sich Leute überhaupt mit Mikrocontrollern, wo es
doch so schöne Supercomputer gibt die in der Cloud alles viel besser und
schneller berechnen, mit einfachster "1 Klick Homepage Generator"
Programmierung.
Ich glaube, du verstehst eh eher wenig von der Welt.
> Konfiguriere ich einen Portpin mittels:>> PADIER |= 1 << bitnr;> PAC &= ~(1 << bitnr);>> als Eingang, so wird mit dir Konifguration zerschossen, sobald ich auf> Port A einen weiteren Pin als Ausgang verwenden möchte, so dass ich die> Initialisierung vor dem Lesen eines Pins erneut durchführen muss.
Daraus sollte SDCC eigentlich SET1 / SET0-Befehle generieren. Hast Du
Dir das Listing schon einmal angschaut?
Tim . schrieb:>> PADIER |= 1 << bitnr;>> PAC &= ~(1 << bitnr);>....> Daraus sollte SDCC eigentlich SET1 / SET0-Befehle generieren.
Das ist ja eben eines der vielen traurigen Details bei solchen Chips:
sowas wie C kann eben nicht den Möglichkeiten des Chips entsprechen.
Weitaus angenehmer wäre es, wenn man solche Bits tatsächlich als Boolean
Variablen deklarieren könnte und dann
MeinPadier=false;
schreiben könnte. Im Maschinenbefehl sind ja beide Dinge drin:
Byteadresse und Bitnummer, das macht zusammen ne Bitadresse.
W.S.
W.S. schrieb:> Weitaus angenehmer wäre es, wenn man solche Bits tatsächlich als Boolean> Variablen deklarieren könnte und dann>> MeinPadier=false;>> schreiben könnte. Im Maschinenbefehl sind ja beide Dinge drin:> Byteadresse und Bitnummer, das macht zusammen ne Bitadresse.
So etwas erlaubt C ja auch mit bitfield-structs. Funktioniert aktuell im
SDCC mit dem Padauk aber noch nicht.
https://sourceforge.net/p/sdcc/bugs/3070/
MaWin schrieb:> Warum er sich aber verweigert, den> compilererzeugten Assemblercode anzusehen, weiss ich auch nicht,
Heeey, ich hatte oben schon geschrieben gehabt, dass ich das gemacht
habe ... und auch die Stellen gefunden, wo optimiert werden konnte und
auch Teile, wie W.S. das beschrieben hatte, Teile davon dann als Inline
gemacht.
Insgesamt wurden 30 Byte eingespart.
By the way: Das Radio mit PFS150 und RDA5807 funktionert jetzt mit
aktivierbarem Sendersuchlauf und einstellbare Lautstärke sehr gut.
Tim . schrieb:>> Konfiguriere ich einen Portpin mittels:>>>> PADIER |= 1 << bitnr;>> PAC &= ~(1 << bitnr);>>>> als Eingang, so wird mit dir Konifguration zerschossen, sobald ich auf>> Port A einen weiteren Pin als Ausgang verwenden möchte, so dass ich die>> Initialisierung vor dem Lesen eines Pins erneut durchführen muss.>> Daraus sollte SDCC eigentlich SET1 / SET0-Befehle generieren. Hast Du> Dir das Listing schon einmal angschaut?
Hab ich gemacht und er macht etwas anderes als "erwartet". Allerdings
bin ich mit noch nicht ganz sicher ob ich nicht irgendwo einen Bug in
meinen Macros eingebaut habe, als Abstraktionsschicht sind bei mir für
PAC PBC und PADIER PBDIER diese zusammengefasst im Stile von
1
#define mask1 (1 << 1)
2
#define mask2 (1 << 2)
3
4
#define PA1_output_init() (PAC |= mask1)
5
#define PA1_set() (PA |= mask1)
6
#define PA1_clr() (PA &= ~mask1)
7
8
// Input mit eingeschalteten Pull-Up Widerstaenden
Wie gesagt, ich schau es mir noch einmal genauer an und wenn das nicht
klappt, werde ich einen Weg über Inline Assembler finden. Wenn der
Fehler nicht bei mir liegt, werde ich diesbezüglich mich noch einmal
melden.
---------------------------------------------
Olaf schrieb:> Aber wieso ich meine Freizeit mit so> einem ollen Kram vertueddeln soll ist mir ein Raetzel.
... einfach weil das Spaß macht (vllt. bin ich ja auch massochistisch
veranlagt und weiß das noch nicht). Der Reiz hier ist dann tatsächlich:
Geiz ist geil und "mal sehen mit wie wenig man auskommen kann".
Die Bauteile des Radios kosten (ohne PCB) im Moment (inkl. der
Widerstände, Kondensatoren, LED's und Uhrenquarz) 42 Cent.
So etwas reizt mich einfach ohne einen großen Sinn zu machen.
... ich werde die Tage den Code einstellen und ein Foto vom Steckbrett,
wenn es sauberer gesteckt ist.
Das Radio kann UKW Radioempfänger empfangen :-) :-) :-)
Grundsätzlich ist das Radio in der Qualität ja abhängig vom RDA5807, der
ist hier auch schon hinlänglich besprochen worden.
Für mich ging es darum, das von meinen STM8 und AVR-Versionen auf den
Padauk zu portieren.
Der RDA5807 ist eigentlich schon kein "Chip" mehr, er benötigt lediglich
einen Uhrenquarz um zu funktionieren und die Steuersignale mittels I2C.
Ursprünglich wollte ich dem Teil noch eine 20 Digit
LED-Leuchtbandanzeige mittels Charlieplexing geben, aber das hatte im
ursprünglichen Entwurf wegen des RAM-Mangels nicht geklappt gehabt
(sollte jetzt zwar realisierbar sein, aber die Motivation ist jetzt
nicht mehr so groß).
Das Radio hat 8 LED als Leuchtbandanzeige auf der am linken Rand das
untere Ende des Empfangbereichs (88 MHz) und am rechten Rand das oberen
Ende (107 MHz) angezeigt wird (oder je nach eingestelltem Sender dann
dazwischen) und eine LED zur Anzeige, welcher Modus aktiv ist.
Das Radio hat 3 Tasten: "MODE" "<<" und ">>".
Mit MODE kann zwischen Sendersuchlauf und Lautstärkeeinstellung
getoggelt werden (Modus-LED an = Lautstärkeeinstellung).
Taste auf "<<" verringert die Lautstärke, ">>" erhöht sie. Es gibt 16
Lautstärkestufen und die eingestellte Lautstärke wird auf den LED's als
Leuchtband angezeigt.
Im Modus Sendersuchlauf bewirkt ein Druck auf "<<" einen Suchlauf in
Richtung unteres Frequenzband. Während der Suche blinkt die Modus-LED.
Ein Druck auf ">>" startet einen Suchlauf in Richtung oberes Ende des
Frequenzbandes.
Am Ausgang des Empfängerchips (RDA5807) ist ein kleiner
Brückenverstärker HXJ8002 / FM8002 mit Vdd= +5V angeschlossen der lt.
Datenblatt eine Leistung von 1 W true rms haben soll (zumindest dürfte
die Kühlung auf meinen Adapterplatinen nicht ausreichend genug sein).
Ein sehr einfaches, aber normales Radio eben.
Das Radio ist für mich als solches abgeschlossen, als nächstes steht die
Fehlersuche bei evtl. Bugs der GPIO Anschlüsse an und parallel dazu
werde ich mich ab morgen mit dem integrierten Komparator beschäftigen um
damit einen "Software-ADC" wie das Atmel seiner Zeit für einen
ATtiny2313 vorgeschlagen hatte (hmmm, sind diese alten App-Notes noch
irgendwo verfügbar, ich finde diese nicht auf der microchip Seite).
Im Endeffekt wird dann daraus evtl. ein VU-Meter wie das hier im Forum
mit einem ATtiny13 vorgestellt wurde:
Beitrag "VU-Meter mit Attiny13a statt LM3916"
Okay, vielen Dank für die ausführliche Beschreibung! Das mit der
Leuchtbandanzeige ist ja ganz fein! Ich will Dir den Mut nicht nehmen,
aber wusstest Du von der RDA5807FP Variante, da kann man Sender- und
Lautstärketasten direkt anschließen, also komplett ohne uC. Dann
natürlich auch keine Leuchtbandanzeige. FP gibt es meines Wissens nur im
SO16 Package.
Harald schrieb:> aber wusstest Du von der RDA5807FP Variante, da kann man Sender- und> Lautstärketasten direkt anschließen
kenne ich, auch wenn ich noch keinen in den Fingern gehabt habe.
Grundsätzlich finde ich den (für mich) aber eher uninteressant, weil da
dann nur grob die Originalapplikation nachgebaut wird.
Mit I2C Schnittstelle und anderem Controller als Padauk, kannst du dann
eben die Anzeige verbessern (als Lehrprojekt hatte ich mal was gemacht
gehabt mit SPI-Display und STM8, der dann eben auch freie Senderspeicher
hatte und beim Wiedereinschalten den zuletzt eingestellten Sender und
die Lautstärke restauriert hatte, außerdem war da zwischen Empfängerchip
und Verstärker noch ein über den Controller einstellbares
Klangregelnetzwerk (Bass / Höhe) drin, dass das ganze als Radio
komfortabler macht. Bauteilekosten hier waren dann eher am Display fest
zu machen als an der Kombination µC - RDA5807
Ralph S. schrieb:>> Laut map-file des SDCC benötigt die Funktion für das Argument 8 Byte> (Speicher von 0x3F bis 0x46 (inklusive):>> Listing map-File> ---------------->>
>> Warum ist das so?>> Interpretiere ich hier etwas falsch ? Ich hätte im besten Fall 4 Bytes> vermutet, 2 für den Parameter und 2 für die Rücksprungadresse (wobei ich> eigentlich annehme, dass eine Rücksprungadresse auf dem Stack liegt und> hierfür nicht extra Ram reserviert wird).>> Interpretiere ich das falsch und es werden gar keine 8 Bytes reserviert> und wenn ich das nicht falsch interpretiere wie kann ich Abhilfe> schaffen?
In .map sind nicht alle Variablen aufgelistet, sondern nur solche, die
auch einen Namen haben. Namenlose temporäre Variablen sind dort nur aus
dem Eintrag zur Größe ersichtlich.
Aus der Größe der Lücke von _rda5807_setvol_PARM_1 bis zum nächsten
Eintrag kann man also nicht die Größe von _rda5807_setvol_PARM_1
erkennen.
Wenn es allzu knapp wird mit dem Speicher, wäre es naheliegend, einen µC
mit mehr Speicher zu nehmen, z.b. den PFS173.
Philipp
Tim . schrieb:> W.S. schrieb:>> Weitaus angenehmer wäre es, wenn man solche Bits tatsächlich als Boolean>> Variablen deklarieren könnte und dann>>>> MeinPadier=false;>>>> schreiben könnte. Im Maschinenbefehl sind ja beide Dinge drin:>> Byteadresse und Bitnummer, das macht zusammen ne Bitadresse.>> So etwas erlaubt C ja auch mit bitfield-structs. Funktioniert aktuell im> SDCC mit dem Padauk aber noch nicht.>> https://sourceforge.net/p/sdcc/bugs/3070/
Gewöhnliche C bitfields (also im normalen Speicher) gehen. Und dort sind
sie nützlich, um RAM zu sparen, was ja gerade bei den kleinen Padauk-µC
nützlich ist.
Was aber in SDCC noch nicht geht (und außerhalb des C-Standard liegt),
sind bit-fields an I/O-Adressen (außer natürlich bei Architekturen mit
I/O im normalen Adressraum, wie stm8).
Philipp
Ralph S. schrieb:> uint16_t rda5807_reg[16];>> ...>> void rda5807_setvol(uint16_t volume)> {> rda5807_reg[5]=(rda5807_reg[5] & 0xFFF0) | volume;> rda5807_writereg(5);> }> [/code]
Wenn ich das mit aktuellem SDCC kompiliere (unter der Annahme, dass
rda5807_writereg ein void rda5807_writereg(uint_least8_t) ist), werden
für diese Funktion 4 Bytes an RAM verwendet: 2 Byte für den Parameter, 2
Byte für die temporären Variablen, die nicht in Registern abgelegt
werden.
Das sollte sich das aber durch kleine Verbesserungen an SDCC auf 2 Byte
reduzieren lassen (wozu alle temporären Variablen in Register müssten,
und dann nur noch der Parameter RAM bräuchte). Wenn ich Zeit finde,
werde ich mir das genauer anschauen.
Philipp
Ralph S. schrieb:> Vergessen habe:>> Compilerflags sind:>> --std-sdcc11 --opt-code-size>> Kann ich hier etwas ändern, Flashspeicher habe ich noch etwas
Reentrante Funktionen sind deutlich größer und langsamer, sparen aber
RAM.
Einzelne Funktionen lassen sich per __reentrant reentrant machen, aber
es gibt auch --stack-auto, um das global zu machen (allerdings braucht
man bei --stack-auto auch eine mit --stack-auto kompilierte
Standardbibliothek, was bei SDCC nicht für alle Ports mitgeliefert wird
- bei den Padauk bisher nur für pdk15).
Philipp
Philipp Klaus K. schrieb:> wozu alle temporären Variablen in Register müssten,> und dann nur noch der Parameter RAM bräuchte
Um das mal deutlich zu sagen: auf diesen Chips gibt es keine Register
außer dem W (PIC) bzw. A (Padauk). Bei Padauk kommt für Argumente und
lokale Variablen ansonsten nur noch der Stack in Frage, aber der geht ja
ohnehin vom spärlichen RAM ab.
Das Grundprinzip dieser Architektur ist, daß man Operationen an
Variablen direkt in der Variablen vornimmt. Es sind eben keine
Load-Modify-Store Architekturen.
W.S.
W.S. schrieb:> Philipp Klaus K. schrieb:>> wozu alle temporären Variablen in Register müssten,>> und dann nur noch der Parameter RAM bräuchte>> Um das mal deutlich zu sagen: auf diesen Chips gibt es keine Register> außer dem W (PIC) bzw. A (Padauk). Bei Padauk kommt für Argumente und> lokale Variablen ansonsten nur noch der Stack in Frage, aber der geht ja> ohnehin vom spärlichen RAM ab.>> Das Grundprinzip dieser Architektur ist, daß man Operationen an> Variablen direkt in der Variablen vornimmt. Es sind eben keine> Load-Modify-Store Architekturen.>> W.S.
SDCC verwendet das Byte an Adresse 0 als Pseudoregister P. Aus Sicht des
Registerallokators gibt es damit zwei Register zu je einem Byte. Und im
Falle der obigen Funktion sollte es durch leichte Verbesserungen an SDCC
möglich sein, dass auch noch die letzte zur Zeit im RAM liegende
16-Bit-Variable je zur Hälfte in A und P abgelegt wird.
Beim Stack sind hier zwei Aspekte zu bedenken: 1) es fehlt an
effizienten Instruktionen für den Zugriff darauf, wodurch bei Verwendung
des Stacks für Variablen der Code groß und langsam wird. 2) Variablen
auf dem Stack lassen sich effizienter speichern, da 2a) nur die der
gerade aufgerufenen Funktionen wirklich dort liegen und 2b) SDCC dort
einen besseren Allokator verwendet.
Ein kurzer Überblick über die Padauk-µC als Zielarchitektur für C, und
eine ein paar Daten, wieviel besser die Padauk wären, wenn man
effizienter auf den Stack zugreifen könnte:
https://arxiv.org/abs/2010.04633
Philipp
Philipp Klaus K. schrieb:> Aus der Größe der Lücke von _rda5807_setvol_PARM_1 bis zum nächsten> Eintrag kann man also nicht die Größe von _rda5807_setvol_PARM_1> erkennen.
Das wußte ich nicht, vielen Dank für die Info.
Philipp Klaus K. schrieb:> Wenn es allzu knapp wird mit dem Speicher, wäre es naheliegend, einen µC> mit mehr Speicher zu nehmen, z.b. den PFS173.
Es geht ja mittlerweile auch mit dem PFS154, mit dem PFS173 ging es
früher :-)
Philipp Klaus K. schrieb:> Das sollte sich das aber durch kleine Verbesserungen an SDCC auf 2 Byte> reduzieren lassen (wozu alle temporären Variablen in Register müssten,> und dann nur noch der Parameter RAM bräuchte). Wenn ich Zeit finde,> werde ich mir das genauer anschauen.
... das finde ich das Sensationelle am Forum und am SDCC-Team, dass sie
sich solche Dinge dann tatsächlich anschauen, vielen Dank
Ralph S. schrieb:> Philipp Klaus K. schrieb:>> Das sollte sich das aber durch kleine Verbesserungen an SDCC auf 2 Byte>> reduzieren lassen (wozu alle temporären Variablen in Register müssten,>> und dann nur noch der Parameter RAM bräuchte). Wenn ich Zeit finde,>> werde ich mir das genauer anschauen.>> ... das finde ich das Sensationelle am Forum und am SDCC-Team, dass sie> sich solche Dinge dann tatsächlich anschauen, vielen Dank
In SDCC 4.0.4 #11926 wird die Funktion nun zumindest auf meinem Debian
GNU/Linux testing System keine temporären Variablen im RAM mehr, so dass
nur noch die 2 Byte für den Parameter benötigt werden.
Philipp
VERRÜCKT !!!
-----------------------------------
Ich konnte zwar SDCC 4.0.4 #11926 nicht ausprobieren, weil als Snapshot
auf http://sdcc.sourceforge.net/snap.php "nur" #11925 zum download
liegt, aaaaaaaber das Ergebnis ist schon "krass":
Ein und dasselbe Programm (hier das Radio) mit beiden Versionen (4.0.3
#11879 und 4.0.4 #11925) übersetzt:
----------------------------------------------------------------
SDCC 4.0.3 #11879
Area Addr Size Decimal
Bytes (Attributes)
-------------------------------- ---- ---- -------
----- ------------
DATA 00000002 00000048 = 72.
bytes (REL,CON)
Area Addr Size Decimal
Bytes (Attributes)
-------------------------------- ---- ---- -------
----- ------------
CODE 00000046 0000084A = 2122.
bytes (REL,CON)
Zu flashende Words im Hexfile sind: 1110
----------------------------------------------------------------
SDCC 4.0.4 #11925
Area Addr Size Decimal
Bytes (Attributes)
-------------------------------- ---- ---- -------
----- ------------
DATA 00000002 00000036 = 54.
bytes (REL,CON)
Area Addr Size Decimal
Bytes (Attributes)
-------------------------------- ---- ---- -------
----- ------------
CODE 00000046 000007F4 = 2036.
bytes (REL,CON)
Zu flashende Words im Hexfile sind: 1067
---------------------------------------------------------------
Das Einsparen von RAM-Speicher finde ich schon klasse (18 Bytes
angesichts der Tatsache, dass man insgesamt nur 128 hat), dass dabei der
Code dann auch noch um 43 Words kleiner geworden ist... Respekt.
Natürlich funktioniert die Firmware des Radios mit beiden Versionen
übersetzt identisch.
Vielen Dank
Ralph S. schrieb:> Ich konnte zwar SDCC 4.0.4 #11926 nicht ausprobieren, weil als Snapshot> auf http://sdcc.sourceforge.net/snap.php "nur" #11925 zum download> liegt, aaaaaaaber das Ergebnis ist schon "krass":>> Ein und dasselbe Programm (hier das Radio) mit beiden Versionen (4.0.3> #11879 und 4.0.4 #11925) übersetzt:
In 4.0.4 #11925 sind auch schon die meisten Verbesserungen enthalten
(insbesondere die für & und |). 4.0.4 #11926 bringt demgegenüber nur
Verbesserungen für ^ und einen Bugfix.