Hallo, weiss zufällig jemand wie man das Bitbanding für _Bool Variablen nutzen kann? Ich kann wohl ein Bit über #defines definieren aber das liegt dann eben an einer festen Adresse. Mit fällt auf Anhieb nur ein einen Bit Struct zu definieren: typedef bitfeld { _Bool flag_1:1; _Bool flag_2:1; _Bool flag_2:1; ... } __attribute_packed(()) bitfeld_t; Dabei erzeugt der Compiler aber einiges mehr an Code für den Zugriff. Und da verliessen sie ihn auch schon.
Knifflig. Lokale Variablen werden gern in Registern aufbewahrt, damit geht es überhaupt nicht. Theoretisch wäre es möglich, wenn sie auf dem Stack liegen. Aber dann müsste man ihre Adresse kennen um die in die BitBand Adresse umzurechnen. Das ist in C irgendwie nicht vorgesehen. Bleiben globale Variablen. Dazu könnte man im Linker Script zwei Sections anlegen, eine im RAM für die Bits und eine für den zugehörigen Bereich in der BitBand Region. In dieser Section legt man die Bool-Variablen als int an (sie haben 32 Bit, können aber nur die Werte 0 und 1 annehmen). Damit kann man mit einfachen, schnellen 32-Bit-Zugriffen einzelne Bits lesen und schreiben. Der Zugriff auf das RAM ist angeblich ein echter, unteilbarer read-modify-write Zyklus. Stimmt das wirklich, auch bei einem Fault während die Floating Point Register gerettet werden (oder noch schlimmeren Sachen)? Auf die Section im RAM sollte man wahrscheinlich nicht selbst zugreifen. Wie würde man mit C-Mitteln die richtige Zuordnung der beiden Sections machen?
Christian J. schrieb: > weiss zufällig jemand wie man das Bitbanding für _Bool Variablen nutzen > kann? Ich kann wohl ein Bit über #defines definieren aber das liegt dann > eben an einer festen Adresse. > > Mit fällt auf Anhieb nur ein einen Bit Struct zu definieren: > > typedef bitfeld { > > _Bool flag_1:1; > _Bool flag_2:1; > _Bool flag_2:1; > ... > > } __attribute_packed(()) bitfeld_t; Irgendwie passt das nicht zusammen. Beim Bitbanding bekommt ja gerade jedes Bit eines Registers ein eigenes Byte (bzw. sogar mehrere) zugewiesen (und nicht nur ein Bit). Auszug aus dem Handbuch des F407: 2.3.3 Bit banding The Cortex™-M4F memory map includes two bit-band regions. These regions map each word in an alias region of memory to a bit in a bit-band region of memory. Writing to a word in the alias region has the same effect as a read-modify-write operation on the targeted bit in the bit-band region. In the STM32F4xx devices both the peripheral registers and the SRAM are mapped to a bitband region, so that single bit-band write and read operations are allowed. The operations are only available for Cortex™-M4F accesses, and not from other bus masters (e.g. DMA). A mapping formula shows how to reference each word in the alias region to a corresponding bit in the bit-band region. The mapping formula is: bit_word_addr = bit_band_base + (byte_offset x 32) + (bit_number × 4) where: – bit_word_addr is the address of the word in the alias memory region that maps to the targeted bit – bit_band_base is the starting address of the alias region – byte_offset is the number of the byte in the bit-band region that contains the targeted bit – bit_number is the bit position (0-7) of the targeted bit Example The following example shows how to map bit 2 of the byte located at SRAM address 0x20000300 to the alias region: 0x22006008 = 0x22000000 + (0x300*32) + (2*4) Writing to address 0x22006008 has the same effect as a read-modify-write operation on bit 2 of the byte at SRAM address 0x20000300. Reading address 0x22006008 returns the value (0x01 or 0x00) of bit 2 of the byte at SRAM address 0x20000300 (0x01: bit set; 0x00: bit reset). Also eher ausrechen als Structs verwenden...
eagle user schrieb: > Damit kann man mit einfachen, schnellen 32-Bit-Zugriffen einzelne Bits > lesen und schreiben. Der Zugriff auf das RAM ist angeblich ein echter, > unteilbarer read-modify-write Zyklus. Stimmt das wirklich, auch bei > einem Fault während die Floating Point Register gerettet werden (oder > noch schlimmeren Sachen)? > Es ist beim BitBanding gar keine read-modify-write mehr sondern nur noch ein einzelner (atomarer) write. Dafür das die restlichen Bits in ruhe gelassen werden sorgt hier die Hardware > Auf die Section im RAM sollte man wahrscheinlich nicht selbst zugreifen. > Wie würde man mit C-Mitteln die richtige Zuordnung der beiden Sections > machen? So ganz verstehe ich nicht was du mit deinen zwei Sectionen meinst? An den BitBandig Adressen befindet sich kein RAM. Der ARM hat nur einen einzigen Linearen Adressraum für alles gemeinsam auf dem immer gleich zugegriffen werden kann ganz egal ob unter einer bestimmten Adresse Flash, RAM, Register, I/O oder sonstwas gemappt ist.
Irgendwer schrieb: > Es ist beim BitBanding gar keine read-modify-write mehr sondern nur noch > ein einzelner (atomarer) write. Dafür das die restlichen Bits in ruhe > gelassen werden sorgt hier die Hardware das glaube ich nicht, tim... Das Ziel ist ein beliebiges Wort im normalen RAM, das ist 32 Bit breit. Woher soll diese Hardware die restlichen 31 Bit kennen, ohne sie vorher zu lesen? Auch dann, wenn die Daten keinen Umweg durch die CPU nehmen, weil es eine Spezial-Hardware direkt am Bus gibt. >> Auf die Section im RAM sollte man wahrscheinlich nicht selbst zugreifen. >> Wie würde man mit C-Mitteln die richtige Zuordnung der beiden Sections >> machen? > So ganz verstehe ich nicht was du mit deinen zwei Sectionen meinst? Die Section im RAM braucht man, damit der Linker diesen Bereich nicht für andere Daten benutzt. Außerdem braucht man die RAM Adressen, damit man sie in BitBanding Adressen umrechnen kann. Die BitBandig Section braucht man nicht, auf diese Adressen kann man natürlich mit beliebigen C-Mitteln zugreifen. Aber ich finde
1 | int __attribute__((section(".bitband"))) foo; |
schöner als #define.
eagle user schrieb: > das glaube ich nicht, tim... Das Ziel ist ein beliebiges Wort im > normalen RAM, das ist 32 Bit breit. Woher soll diese Hardware die > restlichen 31 Bit kennen, ohne sie vorher zu lesen? Auch dann, wenn die > Daten keinen Umweg durch die CPU nehmen, weil es eine Spezial-Hardware > direkt am Bus gibt. Richtig. Es ist immer noch ein read-modify-write Zyklus, allerdings atomar ausgeführt (was einem das Sperren der Interrupts bei Bitmanipulationen erspart).
eagle user schrieb: > C-Mitteln zugreifen. Aber ich findeint > __attribute__((section(".bitband"))) foo; schöner als #define Ich weiss wie das technisch funktioniert aber wie man das nun in C umsetzt, daran hapert es. Der Bitband Bereich kann zb im Debugger nicht angezeigt werden. Klar kann ich da Variablen reinlegen mit #definde (volatile) (*adresse)..... aber die bügelt der Compiler ggf. über. Und wie man das Linker File umschreibt weiss ich nicht. Es nützt natürlich auch nichts, wenn für jedes Bit ein Riesenaufwand an Umrechnung passieren muss. Aber ich habe derzeit ein kleines Problem 320x240 Bits unterzubringen in einem 20kb Chip. Die Beispiele im Netz geben immer absolute Adressen als Ziel an aber "dynamische" zb globale Variablen, dazu findet sich nichts. Es entsteht ja erst die Variable an Platz x, dazu muss sie noch in den Bitband Bereich bewegt werden durch eine section und dann erfolgt der Zugriff über die Bitband Alias Adressen. edit: Sorry, glaube das ist Müll. Das ganze SRAM ist ja als Bitband abgebildet, d.h. jedes Bit meiner 20kb ab 0x20000000 lässt sich in eine 32 Bit Adresse "weit oben" umrechnen. Und über die erreiche ich dann jedes Bit. So legt man zb nur einen Array an char abc[32] und hat dann 32*8 Adressen oben zur Verfügung um auf die Bits zuzugreifen. Über uint8_t *ptr = &abc kriegt man die Adresse des Arrays raus. Diese Alias Adressen müssten nur gut verpackt werden, so dass zb ein Array entstünde, der [256] Elemente hat, vom Typ Bit ist und schreibt man in array[100] rein wird tatsächlich nur das eine Bit gesetzt. Mal durchgrübeln... kann ja nicht so schwer sein.... https://searchcode.com/codesearch/view/17574679/
Christian J. schrieb: > Das ganze SRAM ist ja als Bitband abgebildet, d.h. jedes Bit meiner > 20kb ab 0x20000000 lässt sich in eine 32 Bit Adresse "weit oben" > umrechnen. Und über die erreiche ich dann jedes Bit. So legt man > zb nur einen Array an char abc[32] und hat dann 32*8 Adressen oben > zur Verfügung um auf die Bits zuzugreifen. genau so. > Über uint8_t *ptr = &abc kriegt man die Adresse des Arrays raus. > Diese Alias Adressen müssten nur gut verpackt werden, so dass zb ein > Array entstünde, der [256] Elemente hat, vom Typ Bit ist und schreibt > man in array[100] rein wird tatsächlich nur das eine Bit gesetzt. Naja, nach der Umrechnung von ptr auf die BitBand Adresse hast du ja einen int Pointer auf array[0]. Damit kannst du doch alles machen.
eagle user schrieb: > Naja, nach der Umrechnung von ptr auf die BitBand Adresse hast du ja > einen int Pointer auf array[0]. Damit kannst du doch alles machen. #define BITBAND_ALIAS_ADDRESS(addr, bit) \ ((volatile uint32_t*)((((uint32_t)(addr) & 0xF0000000) + 0x02000000) \ +((((uint32_t)(addr)&0xFFFFF)*32)\ +( (uint32_t)(bit)*4)))) Alsoooooo.... mal aus der Hüfte geschossen: uint32_t ptr = BITBAND_ALIAS_ADDRESS(myarray, 0) Mit * oder &, müsste ich erst kompilieren. Mit *(ptr++) würde ich dann die Elemente als Bit vorfinden und hätte die Pixel meines Displays, statt auf 76.kb, dann auf 320x240 Bit = 9600 Bytes. Natürlich uimgerechnet auf 2D Array mit x,y. Cool... direkt mal ausprobieren heute abend. der GDB Debugger streikt leider im Bitbandbereich, "cannot read memory".
Christian J. schrieb: > Mit fällt auf Anhieb nur ein einen Bit Struct zu definieren: Das ist hier der grundfalsche Gedanke per se. Also: manche Hersteller haben für manche µC etwas eingeführt, was man mit Bitbanding bezeichnen kann, aber das ist erstens nur ein Schlagwort und zweitens nicht überall implementiert, also relativ unportabel. Hintergrund ist, daß die einzelnen Bits der allgemeinen Port-Register nicht in einem 8, 16 oder 31 Bit Portregister angesprochen werden (was man parallel zum Bitbanding aber trotzdem immer noch tun kann), sondern es ist irgendwo im Adreßbereich des µC ein Hardware-Array angeordnet, das aus einzelnen Boolean-Variablen besteht und hinter jeder derartigen Variablen steckt ein einzelnes Port-Bein. Damit kann man einzelne Portbeine separat als Boolean-Variablen ansprechen (0 oder 1). Ob allerdings so eine Variable 8 oder 16 oder 32 Bit groß ist, also ob man sie als bool oder longbool oder weiß der Geier ansprechen muß, kann nur das RefMan klären. Je nachdem, wie gut du beim Formulieren von #define Konstrukten bist, kannst du dir diese Arrays von Hardwareregistern selber definieren oder du benutzt dazu ne kleine Assemblerquelle, aus der heraus du diese Arrays exportierst. Dann eben in deinen C-Quellen extern longbool Port_A_Pins[32]; oder so ähnlich. W.S.
setzt ein bit:
1 | void set_bit(uint32_t* addr, const int bit) { *((volatile uint32_t*)(32 * (((uint32_t)addr) - 0x20000000) + 0x22000000 + 4 * bit)) = 1; } |
Das Ziel muss als volatile deklariert sein, ansonsten ist nicht sicher dass das Programm das gleich mitbekommt wenn per bitband manipuliert wird. Der Zugriff auf die Speicherstelle erfolgt mit der selben Breite wie der Zugriff auf die Alias-Region. Schreibzugriffe erfolgen auch als read-modify-write, die bits sind also nicht wirklich separat ansprechbar. Sinn macht das hauptsächlich um sich ein disablen von interrupts zu sparen, eventuell wirds beim manipulieren von einzelnen bits auch etwas schneller und oder kleiner als die herkömmliche methode.
Also, https://searchcode.com/codesearch/view/17574679/ das hier läuft bei mir nicht :-( volatile uint32_t foo; volatile uint32_t *adress; WRITE_BITBANDING(foo,0,1); foo wird nicht 1. adress = BITBAND_ALIAS_ADDRESS(foo,0); Hard Fault Error. Tja...
Das klappt :-) void set_bit(uint32_t* addr, const int bit) { *((volatile uint32_t*)(32 * (((uint32_t)addr) - 0x20000000) + 0x22000000 + 4 * bit)) = 1; } ergibt: (48) set_bit(&foo,0); 0800123E ldr r0, [pc, #364] ; (0x80013ac <main+372>) 08001240 movs r1, #0 08001242 bl 0x8001210 <set_bit>
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.