Cytuj:
---Joseph Yiu – The Definitive Guide to the Arm Cortex – M3
Wondrous though the STM32 (ARM Cortex M3) might be, it makes something of a meal of atomic access individual bits in a memory. The technique used is called bit-banding. Although it is simple enough in concept and pretty friendly to the assembly language programmer, it is easy enough to get lost in C. Or Should That Be at C?
So why would you want atomic access that individual bits? Consider a single bit used as a flag in your program. Perhaps you have a data buffer and the interrupt service routine That looks after it sets a bit in a memory location to signal That it is full. A higher level function sees the bit set and does something about it, then resets the bit. the problem of Is That this is just one in a whole bit memory word of 32 bits and, then modify it you need to read the word, change the bit and write back the word. What happens if some other changes they interrupt function of the other bits in That word after you read it but before you wrote back the modified version? When you write back your version, it will put all the bits back to how they were before you started THUS destroying a piece of information. In this particular case, it is recommended to use a bit -band call directly in the main function. This prevents damage to the variables, but it does not mean that this is happening forever. However, you can be tempted to call outside the main internal function, there may be a growth in code size and the method can work, however, will prawiodłowo less effective. This is not the fault somehow silicon, and the imperfections of GCC.
You can solve this issue; generally by using an entire variable for each dry flag. At best this will use up a whole byte for each flag and so wastes memory. That small and not be a problem for you and If that is the case then That will work out just fine. Things are not so easy if you wanted to keep All These flags neatly together in a single location as a status word That might get sent to a host or recorded in a log.
This kind of thing happens all the time in the peripheral control registers. Take the USART for example. The CTS flag goes high and an interrupt handler as part of its job, wants to reset the flag. Do not ask me why, it just does. Meantime, you just received a byte and the RXNE flag is set it Indicate That there is data waiting. But the CTS handler is in the middle of a read-modify-write cycle. It has read the status register and is in the process of clearing the CTS flag. When it writes the result back, the flag will be RXNE cleared and the arrival of the character could go un-noticed.
OK, so I just invented all that. The point is, the peripheral registers need care in a small setting and clearing bits and the safest way to do that in both cases is through bit-banding. Why? because the changes are atomic. That is, they happen is the single bits in a cycle and can not be interrupted. THUS, there will never be an occasion the where you read a bit Which can be modified by some other code before you get to write it back out.
Right, so, how is it done? 8051 programmers had a rich set of bit set / reset instruction to all that could accommodate this very neatly. then again, the 8051 had a tiny address space and a suitably simple architecture.
On the STM32, some magic is worked internally so That each bit in a pre-defined memory range can be Addressed as another location in a kind of virtual address space somewhere else. So, for example, the 32 bit value stored at address 0x20000000 Appears also as 32 sequential memory locations starting at 0x22000000. There are two regions of memory That have bit-band alias regions. First there is a 1Mbyte SRAM region from 0x20000000 - 0x20100000 is the where each bit and byte aliases to address in the range 0x22000000 - 0x23FFFFFF. Then there is the peripheral space from 0x40000000 - 0x40100000 Which is aliased in the same way to the range 0x42000000 - 0x43FFFFFF.
Using this scheme, a read or write to memory location 0x22000000 is the same as a read or write to the least bit of SRAM significant_coeff_flag location 0x20000000. I have no intention of going through the whole thing.
Niemniej nie stanowi to jakiegoś dużego problemu prawda ... ??
Ot warto wiedzieć że takie coś może mieć miejsce ...
Problemem mogą tez być biblioteki C .. które zawierają makra stanowiące translację adresów warto się przyjrzeć jak to wygląda w przestrzeni pamięci SRAM:
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.
Nie są może zbyt intuicyjne w obsłudze, nawet gdy wiesz co robią. Niemniej zdaniem J.Yiu tworzą bałagan i się z tym zgadzam. Warto pójść jego tropem i zdefiniować je tak jak proponuje dodatkowo:
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.
Korzystanie z tych makr jak widać jest bardzo proste:
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.
Tu widać że korzystanie z makra varGetBit z Lvalue można zastosować do przypisania:
język c
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.
Oczywiście koledze
doman należy się też małe wyjaśnienie, w korzystaniu z bit-bandu wcale nie chodzi o szybkość jak mu się wydaje, która jest wymierna jak sam zaobserwował zależnie od miejsca wywołania, ale o wygodę,
Kompilator nie może wiedzieć gdzie zmienne będą przechowywane podczas generowania kodu ale będzie mógł "zobaczyć" niektóre z obliczeń dokonywanych podczas wykonywania programu. Jeśli więc użyjesz metody wskaźnika jak w przykładzie wyżej, obliczenie aliasu adresu odbędzie się tylko raz, i będziesz w stanie dobrać się do zmiennych bitowych sprawnie i wygodnie prawda ??
Jeśli chcesz dostępu do bitów rejestrów peryferyjnych zrob to ta samo, pamiętając o różnych rejestrach bazowych
Dlatego niema powodu dla którego nie można by sobie zdefiniować odpowiedniego makra które się odniesie do określonego bitu w rejestrze pod znanym adresem.
Właśnie w tym wypadku otrzymasz adresy wyliczone wstępnie przez kompilator i kod będzie najbardziej efektywny bo adresy rejestrów peryferyjnych będą znane już na poziomie kompilacji.
Tak więc kolego
wwojtek, pamiętałem że coś takiego właśnie czytałem stąd taka a nie inna interpretacja
zadałeś sobie sporo trudu , ale powierzchowne przeglądanie to nie to samo co czynne czytanie wtedy można więcej wyłapać i zapamiętać. co wcale nie oznacza że nie masz racji. I nie musisz się oburzać i unosić ... ja tylko wskazałem że takie coś może mieć miejsce.
z pozdrowieniami
<Prawdziwy akt odkrycia nie polega na odnajdywaniu nowych lądów,lecz na patrzeniu na stare w nowy sposób. Marcel Proust ?? <chyba dobrze pamiętam ?>