Forum: Mikrocontroller und Digitale Elektronik Cortex M0 ROR instruktion


von Kai G. (kpl)


Lesenswert?

Hallo!

Muss gerade mal meckern, sorry :-)
Ich programmiere zum resten mal einen CM0+ in Assembler. Cortex 
M0(+)/M4F/M3 und ARM7TDMI/ARM9 hab ich bisher immer in C programmiert, 
oder höchstens mal mit inline assembler (DSP code Optimierungen)..

Dabei will ich eine kleine Bitbang seriell => Parallel Wandlungsroutine 
schreiben. Damit es deterministisch läuft, wird die Routine ins RAM 
gelinkt (Thema flash waitstates...).

Erstmal: Ich finde keine komplette Kommandoreferenz. Das, was auf der 
ARM-Seite so zu finden ist, ist doch ein Witz. Man muss sich alles aus 
mehreren Quellen zusammensuchen.

z.B. das hier: 
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0484c/CHDCICDF.html

oder das: 
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0497a/BABJCCDH.html

Keine Angaben, wie die Befehle genau arbeiten. Wann werden die PSR flags 
upgedated und nach welchen Regeln?

Schlecht informiert bin ich gerade in eine Falle getappt.

In der Annahme, dass der RORS (rotate right) Befehl genauso arbeitet, 
wie auf fast jeder anderen MCU, musste ich feststellen, dass das 
Carry-flag bei dem THUMB Befehlssatz lediglich upgedated wird, aber 
nicht bei z.B. einem rotate right um 1 Bit ins MSB geschoben wird.

Mein konkreter Code sah so aus:
                      LSRS    r2, r2, #1
                      RORS    r4, r4, r1

Das LSB von r2 (stammt von einem IO port) sollte ins MSB von r4 
geschoben werden und r4 um 1 Bit nach rechts.

Hat jemand eine Idee, wie man das gewünschte Verhalten effizient 
erreichen kann?
Also ohne aus dem 2 Zeiler ein 4 Zeiler zu machen? Das könnte ich auch 
selbst :-)

VG,

Kai

Achja, was ich sonst noch nicht so toll finde (bin von anderen MCUs 
verwöhnt):
- die meisten Befehle unterstützen nur R0-R7 als Operanden 
(low-register)
- es gibt keine schönen IF-THEN konstrukte (wie z.B. bei CM3)
- es gibt nicht sowas nettes wie SBIS / SBIC (AVR)
- Kein decrement mit check auf 0 und sprung, oder vergleichbares
Ein paar Sachen werden durch die potentiell höhere Clockrate wieder gut 
gemacht, um mal was positives zu nennen :-)

Nein, ich schreibe nicht alles in Assembler. Aber beim CM0+ wird ja 
extra damit geworben, dass man gut bitbanging IO machen kann. Daher hat 
er ja auch den single-cycle GPIO Zugriff. Was macht man meistens mit 
bitbang IO? Serielle busse in SW implementieren... Was wäre dafür 
nützlich? Richtig, ein ROR / ROL mit Carry flag, was auch REINgeshiftet 
wird.

: Bearbeitet durch User
von Kai G. (kpl)


Lesenswert?

Update:
Ein "normales" ROL sollte sich mit ADCS (Add with carry) realisieren 
lassen, indem man 2 mal dasselbe Register übergibt. Also z.B. 
R0+R0+carry rechnet.

Hilft leider nicht weiter, wenn man ein ROR braucht, da das serielle 
Protokoll LSB first schickt.

Also: Weitersuchen :(

von Saphir (Gast)


Lesenswert?

Da sieht man mal was man an seinem AVR hat... zumindest in Assembler. 
Der verwöhnt einen ja richtig :) Dach't ich mir's doch- ARM 
Programmierer sind mit dieser undurchsichtigen, komplizierten 
Architektur wirklich arm dran!

von Kai G. (kpl)


Lesenswert?

Hey, das sollte nicht in einem Bashing enden :-)

von Saphir (Gast)


Lesenswert?

Na ja, hab noch etliche Threads im Hinterkopf in denen immer behauptet 
wird ARM sei nicht komplizierter als AVR und bereits jedem Einsteiger zu 
empfehlen...

von Kai G. (kpl)


Lesenswert?

Jede Architektur hat ihre Vor- und Nachteile.
Ich denke in dem Fall ist das Problem, dass man durch andere MCUs 
bestimmte  Lösungsansätze gewohnt ist, die man hier anders anpacken 
muss.

von (prx) A. K. (prx)


Lesenswert?

Kai G. schrieb:
> Erstmal: Ich finde keine komplette Kommandoreferenz.

=> armv6-m architecture reference
http://infocenter.arm.com/help/topic/com.arm.doc.ddi0419c/index.html

> In der Annahme, dass der RORS (rotate right) Befehl genauso arbeitet,
> wie auf fast jeder anderen MCU

Bei 32-Bit Prozessoren arbeitet ROL/ROR normalerweise grad so wie bei 
ARM, also ohne aktive Beteiligung vom Carry. Soweit meine Kenntnis - 
welche "fast jede" kennst du, bei denen das anders ist?

Original-ARM und ARMv7-M (Cortex-M3) besitzen einen RRX Befehl für 1 Bit 
durch Carry. Mehr als 1 Bit durch Carry wird nicht oft benötigt..

> Hat jemand eine Idee, wie man das gewünschte Verhalten effizient
> erreichen kann?

Nicht beim Cortex-M0, wenn "effizient" für dich 2 Takte bedeutet.

In 3 Takten gehts aber:
   LSRS    r2, r2, #1
   ADCS    r4, r4
   RORS    r4, r4, #1

> Achja, was ich sonst noch nicht so toll finde (bin von anderen MCUs
> verwöhnt):

Wenn du dich verwöhnen lassen willst - wieso hast du dir dann mit dem 
Cortex-M0 ausgerechnet den schmalspurigsten Core ausgesucht? Das ist nun 
einmal ein Schrumpf-Core für mässige Anforderungen.

: Bearbeitet durch User
von (prx) A. K. (prx)


Lesenswert?

Kai G. schrieb:
> Achja, was ich sonst noch nicht so toll finde (bin von anderen MCUs
> verwöhnt):

Welche diese anderen MCUs erfüllt denn alle genannten Forderungen?
Also die
- mindestens 16 Register direkt adressiert,
- deine schönen IF-THEN konstrukte kennt,
- sowas nettes wie SBIS / SBIC hat,
- und auf ein decrement mit check auf 0 und sprung,
und das mit 1 Takt pro Befehl, ähnlich knappem Codebedarf und als Core 
so billig und klein, dass er es mit dem CM0 aufnehmen kann.

: Bearbeitet durch User
von Kai G. (kpl)


Lesenswert?

> => armv6-m architecture reference
> http://infocenter.arm.com/help/topic/com.arm.doc.ddi0419c/index.html

Merci!

> Bei 32-Bit Prozessoren arbeitet ROL/ROR normalerweise grad so wie bei
> ARM, also ohne aktive Beteiligung vom Carry. Soweit meine Kenntnis -
> welche "fast jede" kennst du, bei denen das anders ist?

Naja, ich habe von der 8-Bit Welt gesprochen. Die wird doch durch die 32 
Bit Controller "angegriffen". Aber auch viele 32-Bit Architekturen 
können doch ein Carry links / rechtsreinshiften.

> Original-ARM und ARMv7-M (Cortex-M3) besitzen einen RRX Befehl für 1 Bit
> durch Carry. Mehr als 1 Bit durch Carry wird nicht oft benötigt..

Klar, macht auch nicht viel Sinn mehr als 1 mal zu shiften wenn es 
komplett durchs Carry geht.

Der M0+ hat einen Prima barrelshifter, wie alle ARMs. Kann doch nicht 
viel Chipfläche kosten noch ein RRX zu realisieren.

> Nicht beim Cortex-M0, wenn "effizient" für dich 2 Takte bedeutet.

3 wären auch noch zu ertragen :-)

Also muss ich wohl mit linksshiften (ADCS) arbeiten und nachträglich mit 
einer 8-Bit Tabelle die Bitreihenfolge invertieren, zu einem Zeitpunkt 
an dem etwas mehr Zeit zur Verfügung steht. RBIT gibt es ja auch nicht.

> Wenn du dich verwöhnen lassen willst - wieso hast du dir dann mit dem
> Cortex-M0 ausgerechnet den schmalspurigsten Core ausgesucht? Das ist nun
> einmal ein Schrumpf-Core für mässige Anforderungen.

Wie üblich: Der Preis.
Wo bekomm ich sonst eine MCU mit vernünftigen Speicherausbau in 
Stückzahlen für <0.50 USD? Oder in Einzelstückzahlen aus dem Katalog für 
0.89 USD?

Und der M0+ ist nicht schlecht, auch wenn das hier anders rüberkommen 
mag.

Was mich mal interessieren würde:
Von dem Befehlssatz her ist der M0+ durchaus mit einem 8-Bitter 
vergleichbar. Es gibt wenige spezielle Vorkehrungen für 32-Bit in dem 
Befehlssatz. Man kann z.B. keine 16 oder 32 Bit immediates direkt in ein 
Register laden.
Andere Sachen fehlen halt. z.B. auch sowas wie ein STR mit automatischem 
pointer decrement/increment.
Ist die Chipfläche bei gleicher Prozesstechnologie so viel kleiner als 
z.B. bei einem AVR?

VG,

Kai

: Bearbeitet durch User
von (prx) A. K. (prx)


Lesenswert?

Kai G. schrieb:
> Aber auch viele 32-Bit Architekturen
> können doch ein Carry links / rechtsreinshiften.

Das liegt ein wenig daran, wie der Thumb Befehlssatz entstand. Nämlich 
als minimalisierte Abbildung eines einfachen in 16 Bits codierten 
Befehlssatzes auf den ARM Befehlssatz. Da RRX durch 2 Befehle ersetzt 
werden kann (ebd. ADC/ROR), sah ARM wohl keine Veranlassung, deshalb 
Bäume auszureissen.

> 3 wären auch noch zu ertragen :-)

Das Beispiel dafür hatte ich ja gezeigt.

> Also muss ich wohl mit linksshiften (ADCS) arbeiten und nachträglich mit
> einer 8-Bit Tabelle die Bitreihenfolge invertieren, zu einem Zeitpunkt
> an dem etwas mehr Zeit zur Verfügung steht.

Auch das ist ein möglicher Weg.

> Von dem Befehlssatz her ist der M0+ durchaus mit einem 8-Bitter
> vergleichbar. Es gibt wenige spezielle Vorkehrungen für 32-Bit in dem
> Befehlssatz. Man kann z.B. keine 16 oder 32 Bit immediates direkt in ein
> Register laden.

Das hängt direkt mit der Codierung zusammen und ist eine Eigenheit 
vieler Achitekturen mit fester Befehlslänge. Wenn die Daten nicht 
deutlich schmaler sind als die fix definierte Befehlsbreite, dann geht 
das schlicht und einfach nicht.

AVR und PIC/8-Bit sind insofern die Ausnahme von der Regel: Nur weil 
deren (fast) feste Befehlsbreite grösser als die Datenbreite ist, sind 
Immediates voller Breite überhaupt möglich.

Die native ARM Architektur kann es ebenso wenig wie das daraus 
entstandene Thumb. Auch Thumb2 kann es nicht in einem Befehl, sondern 
implementiert es so, wie die viele anderen 32-Bit RISCs: Ein 32-Bit 
Immediate wird aus 2 Befehlen mit je 16 Bits zusammengesetzt. Man hat 
dann die Wahl: Schnell mit 64 Bits (2 Befehle à 32 Bits) oder knapper 
aber langsamer mit 48 Bits (1 Load-Befehl mit 16 Bits, plus 1 32-Bit 
Wort im constant pool dahinter).

Bei 64-Bit Architekturen sind Immediates voller Breite erst recht 
selten. Sogar x64/AMD64 mit sehr variabler Befehlslänge codiert bei 
64-Bit Befehlen meist nur 32-Bit Immediates, ausser bei Move to 
Register.

> Andere Sachen fehlen halt. z.B. auch sowas wie ein STR mit automatischem
> pointer decrement/increment.

Platzfrage. Nicht auf dem Die, sondern im Programmcode. Solche Optionen 
sind nett, aber wenn auf die Länge des gesamten Codes eines Programms 
betrachtet nicht ganz so wichtige Operationen durch 2 Befehle ersetzt 
werden können, dann sind sie im Zielmarkt der Thumb Architektur 
verzichtbar.

Thumb entstand, weil ARM Code recht raumgreifend war und manche 
aufkommende Konkurrenz wesentlich sparsamer zu sein versprach (z.B. 
Hitachi). Es ging dabei um Platz im ROM, nicht um Laufzeit.

Das Ergebnis waren die sehr populären ARM7-Txxx Cores, die über einen 
grösseren Befehlsdekoder verfügten als ARM7 ohne -T. Weil beides 
möglich wurde. Aufgrund der Dekoderstruktur musste aber jeder Thumb 
Befehl 1:1 in einen ARM Befehl übersetzbar sein, mehr als ARM schon 
hatte ging also in Thumb per Definition nicht.

Dass Thumb Code bei sonst gleichen Rahmenbedingungen langsamer als ARM 
Code ist, war vor vorneherein einkalkuliert. Es gab ja beides, wer Tempo 
brauchte nahm nativen ARM Code, wer Platz sparen wollte nahm Thumb Code.

ARMv6-M, also die Architektur der Cortex M0/M1, zielt auf einen sehr 
einfachen Core mit moderaten Anforderungen ab und basiert direkt auf 
diesem historisch entstandenen Thumb-Teil ohne nativem ARM Befehlssatz, 
leicht erweitert. Beim Cortex M1 geht es ausserdem nicht um mm² 
Silizium, sondern um noch viel knappere FPGA-Zellen.

Parallel dazu entstand ARMv7-M basierend auf Thumb2 im Markt für mhr 
Performance bei komplexerem Core und entsprechend mehr Platz auf dem 
Die.

Man hat als Kunde die Wahl: Kleiner, billiger, langsamer, oder etwas 
grösser, teurer, schneller. Wenn der Kunde dabei die falsche Wahl 
getroffen hat, weil Geiz geil ist, dann sollte er sich selbst an die 
Nase fassen und sich nicht bei ARM beklagen.

Zum Vergleich mit AVRs: In jedem x-beliebigen Vergleich zwischen 
Architekturen wirst du in solchen Detailfragen, wie sie von dir 
betrachtet wurden, Aspekte finden, die mal die eine besser kann und mal 
die andere.

: Bearbeitet durch User
von Kai G. (kpl)


Lesenswert?

Ich mecker nicht, ich "bemerke". Mich reizt es aus wenig viel zu machen 
:-)

Wenn man sich tiefer mit beschäftigt fallen einen Tricks und 
Möglichkeiten auf die Probleme geschickt zu lösen. Wenn auch teilweise 
anders, als man es gewohnt ist.

Da ich in den letzten Tagen Abends mit einem ASM Projekt zubringe und 
ständig was dazu lerne, will ich die Aussage, dass es kein Load / Store 
mit post increment revidieren:

Die STM und LDM Instruktionen (Store / Load multiple) inkrementieren den 
Pointer (post inc)!

Nicht auf Anhieb ersichtlich, aber man kann sie auch Nutzen um nur einen 
einzelnen 32 Bit Wert zu lesen / zu schreiben und bekommt danach einen 
um 4 inkrementierten Pointer. Das ganze dauert 2 Zyklen, wie ein 
normales STR/LDR.

Also z.B. so:
  MOVS  r0, #0         <- Adresse nur zur Veranschaulichung...
  STM   r0!, {r1}      <- r0 hat danach den Wert #4

Ich habe mal probiert, ob IAR den Kniff kennt, als sowas gemacht:
  int i;
  volatile int u;
  volatile uint32_t *ptr = (uint32_t*)buf;
  for (i=0; i<u; i++)
  {
    *ptr++ = 0x12345678;
  }
Die volatiles und Variable "u" sind eingestreut, damit dem Compiler die 
Möglichkeit zum loop unrolling genommen werden.

Bei höchster Optimierungseinstellung wird die Schleife realisiert und im 
inneren steht:
STR R2, [r0]
ADDS R0, R0, #4

Auch in anderen Tests, die den Optimierer nicht beschränken, wird immer 
ein ADDS eingefügt. Spätestens, wenn die Immidiate Offset Werte nicht 
mehr ausreichen wird ein: ADDS r0, r0, #132 eingefügt.

An der Stelle könnte IAR seine Codeeffizienz doch noch etwas steigern. 
Der STM Trick ist denen wohl noch nicht eingefallen. Oder gibt es mir 
momentan nicht bekannte Nachteile? OK, ein LDM/STM wird beim M0 durch 
einen IRQ unterbrochen (nicht konfigurierbar wie z.B. beim M3), aber 
wird auch bei einem einzelnen Wert auch unterbrochen? Ist mir bei der 
vorliegenden Dokumentation nicht deutlich.

Ansonsten: Ich habe das Problem mit dem ROR so gelösst, dass ich erstmal 
ein "ROL" mache, mittels ADCS und dann an späterer Stelle ein 
Bitreversal durchführe.
Das Bitreversal braucht momentan 16 Zyklen, aber ich habe schon eine 
Idee zur Beschleunigung.

So, Zeit fürs Bett...

VG,

Kai

von (prx) A. K. (prx)


Lesenswert?

Kai G. schrieb:
> Ich habe mal probiert, ob IAR den Kniff kennt, als sowas gemacht:

Anständigen Compiler verwenden, nicht so einen Billigkram. Aus
1
void f(int *p, int n)
2
{
3
  int *q = p + n;
4
  while (p < q)
5
    *p++ = 0x12345678;
6
}
und
1
void f(int *p, int n)
2
{
3
  for (int i = 0; i < n; ++i)
4
    p[i] = 0x12345678;
5
}
wird im Kern dann
1
.L5:
2
  stmia  r0!, {r3}
3
  cmp  r1, r0
4
  bhi  .L5

: Bearbeitet durch User
von Kai G. (kpl)


Lesenswert?

Keil?

Wenn mein projekt fertig ist, werd ich mal schauen, was gcc draus macht.

Spannend, dass er es im 2. Beispiel schafft das ++i in ein postinkrement 
umzusetzen. Vermutlich fuegt er etwas vorher ein adds r0, r0, #4 ein. 
Und beeindruckend, dass er nicht jedesmal die adresse berechnet.

von (prx) A. K. (prx)


Lesenswert?

Kai G. schrieb:
> Keil?

GCC ;-]

: Bearbeitet durch User
von Kai G. (kpl)


Lesenswert?

Amüsant :-)

Dann kann ich mir den Test ja sparen. Wollte Danach sowieso auf gcc 
gehen.

von Kai G. (kpl)


Lesenswert?

Haha, hab gerade ne 2 Zyklen Lösung gefunden!

Wenns interessiert, verrat ich sie sogar :-)

von (prx) A. K. (prx)


Lesenswert?

Bitte bitte! ;-)

: Bearbeitet durch User
von Kai G. (kpl)


Lesenswert?

OK :-)
Sorry, freu mich gerade halt :-)

            LDR   r2, GPIO_DIN_REGISTER
            MOVS  r3, #0      ; in r3 landet das parallele Datenwort
Schleifchen:
            LDR   r1, [r2]    ; GPIO DIN auslesen
            ORRS  r3, r3, r1
            RORS  r3, r3, #1

            B     Schleifchen

OK, es gibt 2 Limitierungen, die bei mir kein Problem darstellen:
1.) Alle Bits, ausser Bit 0 müssen eine 0 beinhalten, damit es klappt
2.) Das parallele Register r3 muss auf jeden Fall mit 0 vorinitialisiert 
werden.

Das hat jetzt ein Weilchen gedauert...
Die Lösung ist an und für sich einfach, aber das war wieder ein Fall von 
"festgefahren sein in bekannten Lösungswegen mit anderen CPUs".

von (prx) A. K. (prx)


Lesenswert?

Kai G. schrieb:
> 1.) Alle Bits, ausser Bit 0 müssen eine 0 beinhalten, damit es klappt

Bit 0 muss nicht unbedingt sein, jedes anderes tut es auch. Aber es ist 
schon ziemlich speziell, dass diese Randbedingung akzeptabel ist.

von Kai G. (kpl)


Lesenswert?

Ja, stimmt schon. Bei mir liegt halt das serielle Signal auf Bit 0. Weil 
ich ja mit einem rechtsshift das Bit ins Carry übertragen wollte.

So speziell ist die Bedingung garnicht. Es sind nicht alle GPIO Bits von 
dem Port in dem Package herausgeführt. Ich verliere also keine 15, bzw. 
31 IO pins.

von Roland E. (roland0815)


Lesenswert?

Kai G. schrieb:
> Update:
> Ein "normales" ROL sollte sich mit ADCS (Add with carry) realisieren
> lassen, indem man 2 mal dasselbe Register übergibt. Also z.B.
> R0+R0+carry rechnet.
>
> Hilft leider nicht weiter, wenn man ein ROR braucht, da das serielle
> Protokoll LSB first schickt.
>
> Also: Weitersuchen :(

Verstehe ich jetzt nicht. Dann setzt man ein Bit im UART, und der 
eingehende Bitstrom wird anders herum interpretiert. Da brauchts keinen 
Rechenschritt für.

von Kai G. (kpl)


Lesenswert?

@Roland: Es geht nicht um eine UART.

: Bearbeitet durch User
von Roland E. (roland0815)


Lesenswert?

Der OP geht aus irgend einem Grund davon aus, dass man immer das Carry 
bei einem Rotate braucht. Das ist aber (so pauschal[1]) Käse. Wozu soll 
ich denn ein 33.Bit brauchen (nichts anderes ist der Carry bei einer 
32Bit CPU) wenn ich die 32 vorhandenen Bits nur rotieren/schieben will.
Wenn mich das Carry interessiert lese ich es vor dem Rotieren aus.

Wobei ich mich mit dem "Thumb-Befehlssatz" der Cortex nie 
auseinandergesetzt habe, da ich bisher keinen praktischen Nutzen daraus 
ziehen konnte.

Wobei ich dem OP auch unterstelle, nicht richtig geschaut zu haben, denn 
auf der ersten von ihm verlinkten Seite ist (ua) das komplette 
Instruction-Set alle Cortex-M aufgeführt. Inklusive des M0.

http://infocenter.arm.com/help/topic/com.arm.doc.dui0662a/DUI0662A_cortex_m0p_r0p0_dgug.pdf

Dort ist auch beschrieben, dass die Schiebebreite (also die Nutzung des 
Carry) mit einer Option angegeben wird.

Roland
[1]Viele CPUs haben einen zusätzlichen Rotier/Schiebebefehl der durchs 
Carry schiebt/rotiert.

von Kai G. (kpl)


Lesenswert?

Roland, es ist doch schon alles geklärt :-)

von (prx) A. K. (prx)


Lesenswert?

Roland Ertelt schrieb:
> Dort ist auch beschrieben, dass die Schiebebreite (also die Nutzung des
> Carry) mit einer Option angegeben wird.

Bei keiner Shift-Operation des CM0[+] wird das Carry als Input-Operand 
verwendet (nur ADC/SBC), unabhängig von der Anzahl Stellen. Das gibts 
nur ab CM3 oder im ursprünglichen ARM.

von Roland E. (roland0815)


Lesenswert?

Ja, dass du einen Würgaround für deinen Carry-Zwang gefunden hast, habe 
ich gesehen.

Er ist nur gar nicht nötig, weil du eigentlich nicht durchs Carry 
schieben musst. Ich verstehe dein Problem so, dass du auf irgend einem 
Port ein Bit bekommst, welches du (per Software) auf einer anderen 
Stelle wieder haben willst.

Das kannst du schieben, sinnvoller Weise den kürzeren Weg, oder per 
Bittest erkennen und ins Zielregister addieren.

PS: Nach der von der ARM-Seite kommenden Instructionset für den M0 
berücksichtigen alle Schiebebefehle das Carry je nach Wunsch mit. 
Stattdessen wird dann halt das LSB weggeworfen. Das Bit mehr im 
Barrelshifter hätte wohl ein Vermögen gekostet... :-D

: Bearbeitet durch User
von Kai G. (kpl)


Lesenswert?

Roland. Du hast Recht:

Wollte ich nur ein einzelnes Bit nach dem Auslesen des GPIO Port 
Registers an einer anderen Stelle haben, würd ich nicht den Aufstand 
machen.
Liess am besten nochmal den 1. Post.

Der Praktische Nutzen des von mir gewünschten ROR ist in meinem 
Anwendungsfall durchaus gegeben und mit der erwähnten 2-Zyklen Lösung 
gelösst. Die praktische Implementierung sieht leicht anders aus und ich 
kann jetzt in nur 2 Zyklen pro Bit (+Branch) einen seriellen Bitstrom 
NRZ dekodieren und seriell => Parallel wandeln.

In dem von Dir verlinkten PDF stehen z.B. nirgendwo die Anzahl der 
Instruktionszyklen erwähnt, weder in der Befehlszusammenfassung, noch in 
der jeweils ausführlichen Beschreibung der Befehle. In dem ARM CM0+ TRM 
stehen hingegen die Zyklen, aber nicht die modifizierten xPSR Flags. 
Suboptimal, wenn man immer aus mehreren Quellen zusammensuchen muss. Ich 
weiss, warum das bei ARM so ist, aber es störte mich halt.
Aber auch das ist geklärt: Ich habe mir mittlerweile eine eigene 
handliche 2 DINA4 Seiten grosse Befehlsreferenz erstellt, die sich als 
sehr nützlich herausgestellt hat.

VLG,

Kai

von Gerd E. (robberknight)


Lesenswert?

Kai G. schrieb:
> Ich habe mir mittlerweile eine eigene
> handliche 2 DINA4 Seiten grosse Befehlsreferenz erstellt, die sich als
> sehr nützlich herausgestellt hat.

Magst Du Dir hier posten oder ins Wiki stellen? Dann können sich auch 
andere die dumme Hin- und Herspringerei zwischen den Dokumenten sparen.

von Roland E. (roland0815)


Lesenswert?

Kai G. schrieb:
> Roland. Du hast Recht:
>
> Wollte ich nur ein einzelnes Bit nach dem Auslesen des GPIO Port
> Registers an einer anderen Stelle haben, würd ich nicht den Aufstand
> machen.
>

Natürlich willst du genau das. Halt mehrmals hintereinander. Du bastelst 
dir einen Mux, weil du aus irgend einem Grund den eingebauten in der 
UART nicht benutzen kannst/willst.

Im Normalfall brauchst du dazu

Schleife
           Port lesen
           Und Portregister, Maske
           Add Portregister, Zielregister -> Zielregister
           Zielregister eins schieben/rotieren
           Endprüfung
           Sprung
           Zielregister Bündig rotieren.
           ggf Maske drüber.

Um einen BCD oder ähnlichen Mehrbitcode < Portbreite aus dem Port zu 
lesen gehts sogar noch einfacher:
           Port lesen
           Register Bit 0..31 schieben
           Und Maske drüberlegen um den Müll auszunullen.
fertig.

Nirgendwo wird das Carry benötigt.

Ich verstehe halt dein Problem mit dem Carry gerade nicht. Da die 
Arbeitsregister 32Bit breit sind, und die I/O-Register auch kannst du es 
während der Operation ignorieren. Schon dein MOVS ist übertrieben. Ein 
MOV reicht völlig, da du offenbar keine "Zero-Prüfung" machst.

Roland

: Bearbeitet durch User
von (prx) A. K. (prx)


Lesenswert?

Roland Ertelt schrieb:
> Schon dein MOVS ist übertrieben. Ein
> MOV reicht völlig, da du offenbar keine "Zero-Prüfung" machst.

Diese Aufregung darüber aber auch, weil völlig irrelevant.

von Kai G. (kpl)


Lesenswert?

@Gerd: Ich werd es hochladen!

@Roland: Ich bin glücklich und zufrieden. Es gibt keinen Grund sich 
aufzuregen :-)

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
Noch kein Account? Hier anmelden.