Hallo,
kann mir jemand sagen bzw Code zur Vefügung stellen, wie man einen Array
per Bitbanding anspricht?
Ich habe eine Art FAT in einem EEPROM, lese diese ein in
uint8_t ee_fat[1024];
wobei jedes Bit einen benutzten Sektor abbildet. 8 Bit sind also 8
"Sektoren". Die Adresse der Daten berechne ich dann aus der Bitposition.
Wäre nur schön, wenn man den ganzen Array oben als ein Bitfeld hätte.
Ich habe leider nur Makros, für 32 Bit Variablen und die sind nicht ganz
so trivial.
Was fehlt wäre sowas wie testbit(ee_fat,1234)
Oder gibt es sowas wie:
struct {
unsigned int data:8760; // 8760 Bits
}
vermutlich eher weniger, meine Bitfelder sind auf elementare Typen
begrenzt.
Gruss,
Christian
Spricht nichts gegen..... sieht gut aus, probiere ich mal aus!
ee_fat [index / entrySize] = (ee_fat [index / entrySize] & ~(1 << bit))
| (value << bit);
Nicht ganz einfach zu verstehen... erst Bit löschen mit & ~(.. , dann
das neue mit ODER danach einmaskieren?
Geht das hier auch noch eleganter?
1
/* Bit setzen */
2
LED_BitStream|=(uint64_t)(1ull<<pos);
3
/* 1 Bit evtl. blinken lassen */
4
if(blink)
5
/* Setze korrespondierende Position im Blink Stream */
Christian J. schrieb:> Nicht ganz einfach zu verstehen... erst Bit löschen mit & ~(.. , dann> das neue mit ODER danach einmaskieren?
Ja genau.
> Geht das hier auch noch eleganter?
Geht auch, aber je nach Hardware kann es sein dass if-else-Konstrukte
langsamer sind (wg. Pipeline & Branch-Prediction) als eine scheinbar
kompliziertere Arithmetik. Kannst du ja einfach ausprobieren.
Christian J. schrieb:> Spricht nichts gegen..... sieht gut aus, probiere ich mal aus!>> ee_fat [index / entrySize] = (ee_fat [index / entrySize] & ~(1 << bit))> | (value << bit);>> Nicht ganz einfach zu verstehen... erst Bit löschen mit & ~(.. , dann> das neue mit ODER danach einmaskieren?
Naja, der grosse Vorteil vom Bit Banding IST ja eben, dass die Operation
auf dem Bit "atomisch" ist, d.h. wenn Du ein Bit über seinen Alias
manipulierst, bleiben die anderen Bits im selben 32 Bit Wert unberührt.
Du musst Dich also nicht mit Maskenoperationen herumschlagen.
Allerdings kannst Du durch funktionale Abstraktion die Maskenoperationen
in den "traditionellen" Implementationen von Bitfeldern so einkapseln,
dass Du sie genau an einer Stelle machen musst. Dann sind die Bitfelder
so ziemlich gleichwertig... ausser... es gibt nebenläufigen Zugriff auf
die Bitfelder (in dem Fall hilft Dir die Ununterbrechbarkeit der
Operation beim Bit Banding, Nebenläufigkeitsprobleme zu umschiffen).
Obacht: Bei Bitbanding sollte "ee_fat" als "volatile" deklariert werden,
da der Compiler nicht weiss, dass die Bitbanding-Operationen darauf
Einfluss haben.
Sollte ungefähr so mit Bitbanding funktionieren, ungetestet.
Jo, danke!
Ich probiers heute abend dann mal aus am uC. Geht auch mehr um den Spass
an der Sache als einen echten Nutzwert da stündliche Wettermessdaten
abzuspeichern. Kann man auch aus Datenbanken abfragen wie die Werte wann
wo waren.
temp schrieb:> ist es so was was du meinst?
Genau so geht das beim STM32, der hat extra Bitbanding Adressen um auf
dem RAM einzelne Bits lesen/schreiben zu können.
Da braucht man nichts ausmaskieren/rechnen/zuweisen, das geht direkt.
Markus M. schrieb:> Genau so geht das beim STM32, der hat extra Bitbanding Adressen um auf> dem RAM einzelne Bits lesen/schreiben zu können.
Das weiss ich :-) Es geht ja auch granuliert manuell aber damit geht es
eben programmiertechnisch einfacher.
Diesen Trümmer habe ich gesucht:
#define BitBandMemAddr(addr, bitnum) ((volatile uint32_t*)(0x22000000 +
(((uint32_t)(addr) & 0xFFFFF) << 5) + ((bitnum) << 2)))
Markus M. schrieb:> Da braucht man nichts ausmaskieren/rechnen/zuweisen, das geht direkt.
Umrechnen muss der Prozessor schon, nämlich die normale Byteadresse des
Arrays in die Bitadresse des Spiegeladressraums. Aber man kann sich
aussuchen wann man das tut. So sieht es jedenfalls eleganter aus:
Dr. Sommer schrieb:> Optimierungen eingeschaltet?! Die Division sollte eigentlich> wegoptimiert werden.
Dann kann ich nicht mehr debuggen, weil der Source Code nicht mit dem
Bin File übereinstimmt. Man kann keine BPs mehr setzen und der Codefluss
ist chaotisch.
Christian J. schrieb:> Selbst ohne Optimierung ist das extrem schmal aber leider nicht debugbar> Und leider funktioniert es auch nicht.
Mein Code bezieht sich auf einen STM32F103C8 und da funtioniert das. Hab
das eben nochmal in Debugger betrachtet. Leider hast du uns nicht
verraten was du für einen Chip hast. Ob der Bitbang Bereich bei deiner
CPU auch an 0x22000000 losgeht kann ich nicht in der Glaskugel lesen.
Das der Code kurz wird ist ja genau das was damit erreicht werden soll.
Aber die Doku dazu sollte man sich schon reinziehen.
A. K. schrieb:> Mach> volatile uint32_t *ba = (uint32_t*)BitBandMemAddr(&ee_fat,0);> draus
Passt! Stimmt! Läuft! :-) Kotmäßig erheblich kürzer als das maskieren,
nur 4 Befehle pro Bitsetzen, ohne Optimierung.
temp schrieb:> Nochmal gegoogelt. Alle M3 und M4 sollten das auf dieser Adress haben.> M0 hat es überhaupt nicht.
Klappt auch ja jetzt, hatte falsch gecastet.
Jungs, ihr seit spitze! :-)
Christian J. schrieb:> Dann kann ich nicht mehr debuggen, weil der Source Code nicht mit dem> Bin File übereinstimmt. Man kann keine BPs mehr setzen und der Codefluss> ist chaotisch.
Geht schon, ist etwas fummeliger. Wenn du die Optimierungen nicht nutzt,
beschwer dich nicht dass der Code ineffizient ist. Aus der Division
sollte ein Bitshift werden, aus dem Modulo ein "and". Wenn das
unoptimierte Programm nicht in den Flash passt, nimmt man einen größeren
Chip für das Debuggen und einen kleineren (in den das optimierte
Programm passt) für die Serie. Falls man keine Serie produziert, braucht
man auch nicht am Flash zu sparen.
Dr. Sommer schrieb:> Geht schon, ist etwas fummeliger. Wenn du die Optimierungen nicht nutzt,> beschwer dich nicht dass der Code ineffizient ist.
In der Release Version ist natürliuch alles eingeschaltet, die ist auch
20kb kürzer als die Debug Version. Nein, man kann nicht debuggen, Embitz
schmiert sogar komplett ab, wenn man es versucht. Wenn der Code nicht
zeile für zeile dem Kompilat entspricht ist Ende. Und ist ja nur Hobby,
habe ja jetzt 128kb mit dem OCD Debugger und dem patch aus dem C103RB
heraus geholt. Die haben ja alle 128kb statt 64. Schalte ich LTO ab und
noch so eine Option bläst der Code auf 110kb auf und der geht noch rein.
Christian J. schrieb:> Nein, man kann nicht debuggen, Embitz> schmiert sogar komplett ab, wenn man es versucht. Wenn der Code nicht> zeile für zeile dem Kompilat entspricht ist Ende.
Oy. Eclipse und GDB können das. Versuch mal -Og, das ist ein Kompromiss
zwischen Debugbarkeit und Optimierung. Für Hobby kann man auch einfach
einen F4 nehmen, die haben z.B. 1 MB, da braucht man sich gar keine
Sorgen um Programmspeicher machen. Kostet ein paar Euro mehr und spart
ein paar graue Haare.
Ja, hat der Master auch, den 429er aber bei dem hier muss ich etwas
knausern mit dem Platz.... packe das aber jetzt auch wieder weg und
widme mich er Reparatur echter Hardware zum Anfassen, die auch glimmt
und glüht und vor allem sehr schwer ist :-)
-Og klappt echt gut und ist sogar nur 4 kb größer als das Minimum.
Code ist echt atomar:
1
(87)staticstorage_tDataToSafe[24];/* Datenspeicher für 24h Stunden */
Dr. Sommer schrieb:> Oy. Eclipse und GDB können das. Versuch mal -Og,
Könntest Du mir mal zeigen wie -Og definiert ist? In der offiziellen GNU
Doku finde ich das nicht.
Markus schrieb:> Platz?> Diese F407 Board hier könnte noch auf Deine Platine passen:> Ebay-Artikel Nr. 122444767496
Kenne ich. Ich habe die Masterplatine mit dem 407 gemacht, einfach ein
Disko Board drauf gesteckt, wo ich diverses vorher abgelötet habe, da
ich es nicht brauche. Und etliches an Peripherie dran gebaut. Das wuchs
immer mehr. Da nutze ich einiges mehr an SPIs und I2Cs, bzw auch die 180
kb Ram. Aber für die kleinen Dinge reichen die 103 aus. Schnell muss
nichts sein und Platz genug ist auch da. Habe 4 Timer im Einsatz, 2 als
PWM, beide SPIs, eine I2C und noch die CRC Einheit, sowie die RTC und
die Backup Register.
Christian J. schrieb:> Könntest Du mir mal zeigen wie -Og definiert ist? In der offiziellen GNU> Doku finde ich das nicht.
Ich schon:
https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html
-Og
Optimize debugging experience. -Og enables optimizations that do not
interfere with debugging. It should be the optimization level of choice
for the standard edit-compile-debug cycle, offering a reasonable level
of optimization while maintaining fast compilation and a good debugging
experience.