Forum: Mikrocontroller und Digitale Elektronik ARM Assembler - GPIO einlesen und in RAM schreiben in 2 Taktzyklen


von Mac (Gast)


Lesenswert?

Hallo Zusammen,

ich habe eine Frage an ARM-Assembler-Spezialisten:

Fuer das Einlesen der Daten von vier schnellen (4 x 40 Mbit pro Sek.) 
1-bit-ADC moechte ich, wenn moeglich, die GPIOs einer ARM-Cortex-M3-MCU 
nutzen (z.B. Silabs Precision 32, coreclockmax = 80 Mhz).

Ist es mit dieser MCU moeglich, die an einem GPIO-Port anliegenden Daten 
in maximal zwei Taktzyklen einzulesen und in das MCU-RAM zu schreiben?

Das Assembler-Programm stelle ich mir wie folgt vor:

Pseudocode:

GPIO Port 1 einlesen, byte oder word nach RAM-Speicherplatz 1 schreiben
GPIO Port 1 einlesen, byte oder word nach RAM-Speicherplatz 2 schreiben
GPIO Port 1 einlesen, byte oder word nach RAM-Speicherplatz 3 schreiben
GPIO Port 1 einlesen, byte oder word nach RAM-Speicherplatz 4 schreiben
...
GPIO Port 1 einlesen, byte oder word nach RAM-Speicherplatz 1000 
schreiben

- Maximal 2000 Taktzyklen sollte die ARM-MCU fuer die Ausfuehrung dieses 
Codes benoetigen
- 1000 bits am Stueck einlesen ist fuer meine Anwendung ausreichend

Danke!

Gruesse

Mac

von Oliver J. (skriptkiddy)


Lesenswert?

Ohne jetzt großartig in ARM-Assembler programmiert zu haben, denke ich, 
dass das nicht wird. Es existieren im im Thumb2 keine Befehle um 
Speicher in Speicher zu kopieren. Also muss man den Umweg über ein 
CPU-Register machen. Das könnte folgendermaßen aussehen:

:sample
Wert von GPIO in Register laden              (1 Takt)
Register wegspeichern (indirekte Addr.)      (1 Takt)
Pointerregister inkrementieren               (1 Takt)
Pointerregister mit Endaddresse vergleichen  (1 Takt)
Sprung zu sample wenn ungleich               (1 Takt)

Das wären schon mindestens 5 Takte. Du wolltest 2.

Gruß Oliver

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Könnte aber mit DMA gehen. Als Quelladresse den GPIO, als Zieladresse 
den RAM mit inkrement. Mit dem ADC klappt das gut, mit dem GPIO hab ichs 
noch nicht probiert.
Sowas in der Art:
1
DMA_InitTypeDef    DMA_InitStructure;
2
3
4
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
5
/* DMA1 channel1 configuration ----------------------------------------------*/
6
  DMA_DeInit(DMA1_Channel1);
7
  DMA_InitStructure.DMA_PeripheralBaseAddr =  (uint32_t)&(GPIOA->IDR);
8
  DMA_InitStructure.DMA_MemoryBaseAddr = (u32)&myResultArray;
9
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
10
  DMA_InitStructure.DMA_BufferSize = 1000;
11
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
12
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
13
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
14
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
15
  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;  // will repeat automatically
16
  DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
17
  DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
18
  DMA_Init(DMA1_Channel1, &DMA_InitStructure);
19
  /* Enable DMA1 channel1 */
20
  DMA_Cmd(DMA1_Channel1, ENABLE);

von Gerd E. (robberknight)


Lesenswert?

Am besten machst Du sowas per DMA. Schau also nach einem Controller der 
DMA hat und bei dem das auch für die GPIOs funktioniert.

Aber auch damit ist die Geschwindigkeit der GPIOs normal begrenzt und 
nicht der volle CPU-Takt. Wie schnell Du auf die GPIOs zugreifen kannst 
ist leider nicht immer ganz einfach aus den Datenblättern rauszulesen...

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Sorry, das mit dem Silabs hatte ich nicht gelesen. Mein DMA Beispiel ist 
für STM32

von Jim M. (turboj)


Lesenswert?

> Silabs Precision 32, coreclockmax = 80 Mhz

Die GPIOs hängen bei diesen µCs IIRC am APB, der kann nur 40 MHz max. 
Dann wird das mit 40MBit schon recht eng, selbst mit DMA.

von Uwe (Gast)


Lesenswert?

> Fuer das Einlesen der Daten von vier schnellen (4 x 40 Mbit pro Sek.)
> 1-bit-ADC moechte ich, wenn moeglich, die GPIOs ...

Du hast also 4 x einen 40Mbit/s ADC mit seriellem Interface (z.B. SPI) ?
Du möchtest also vier serielle SPIs parallel betreiben jeden mit 
40Mbit/s ?

Schreib mal die Mega Sampels pro Sekunde hin und welches Interface die 
Dinger haben.

von Mac (Gast)


Lesenswert?

Vielen Dank für eure Antworten!

In Sachen DMA habe ich vor kurzem mal bei Micro Energy nachgefragt. Die 
haben mir mitgeteilt, dass der DMA-Transfer bei den Gecko-MCUs ca. 12-15 
Takte benötigen würde, zumindest bezogen auf die SPI-Schnittstelle. Eine 
DMA-Lösung habe ich deshalb nicht weiter verfolgt. Aber ich werde mal 
versuchen aus einem STM32-Datenblatt Angaben dazu herauszulesen.

Oliver, wenn ich Deinen Assemblercode richtig verstehe, dann hast Du 
eine kurze Schleife mit Abbruchbedingung dargestellt.
Müssten die ersten zwei Zeilen eintausend Mal hintereinander kopiert 
dann nicht zum gewünschten Ergebnis in jeweils zwei Takten führen? :

Wert von GPIO in Register laden              (1 Takt)
Register wegspeichern (RAM-Adresse 1)        (1 Takt)
Wert von GPIO in Register laden              (1 Takt)
Register wegspeichern (RAM-Adresse 2)        (1 Takt)
Wert von GPIO in Register laden              (1 Takt)
Register wegspeichern (RAM-Adresse 3)        (1 Takt)
...
Wert von GPIO in Register laden              (1 Takt)
Register wegspeichern (RAM-Adresse 1000)     (1 Takt)

Grüße

Mac

von Oliver J. (skriptkiddy)


Lesenswert?

Mac schrieb:
> Oliver, wenn ich Deinen Assemblercode richtig verstehe, dann hast Du
> eine kurze Schleife mit Abbruchbedingung dargestellt.
> Müssten die ersten zwei Zeilen eintausend Mal hintereinander kopiert
> dann nicht zum gewünschten Ergebnis in jeweils zwei Takten führen? :
>
> Wert von GPIO in Register laden              (1 Takt)
> Register wegspeichern (RAM-Adresse 1)        (1 Takt)
> Wert von GPIO in Register laden              (1 Takt)
> Register wegspeichern (RAM-Adresse 2)        (1 Takt)
> Wert von GPIO in Register laden              (1 Takt)
> Register wegspeichern (RAM-Adresse 3)        (1 Takt)
> ...
> Wert von GPIO in Register laden              (1 Takt)
> Register wegspeichern (RAM-Adresse 1000)     (1 Takt)

Wie willst du denn in einem Thumb2-Befehl eine 32 Bit Addresse codieren?
Das geht also wieder über indirekte Adressierung. Und dafür musst du 
nach jedem Transfer das Pointerregister erhöhen.

Außerdem brauchen Load- und Store-Befehle 2 Takte (eben nachgeschaut):
Wert von GPIO in Register laden              (2 Takte)

Register wegspeichern indirekt über
Pointerregister                              (2 Takte)

Pointerregister := Pointeregister + 1        (1 Takt )


Gruß Oliver

von Mac (Gast)


Lesenswert?

Hallo Uwe, die ADC haben 4 x 40 40Mbit/s und ein serielles Interface. Im 
Datenblatt wird das Interface zwar nicht SPI genannt, es scheint aber 
technisch völlig identisch zu sein. Die ADCs laufen übrigens mit der 
gleichen clock wie der ARM.

Zu Megasamples kann ich im Moment keine Aussage machen, soweit ich das 
einschätzen kann sollte das aber in Bezug auf das Interface nicht 
relevant sein, zumindest nicht in Bezug auf meine Problemstellung.

Zuerst habe ich übrigens nach ARM-Controllern mit schneller(n) 
SPI-Schnittstelle(n) gesucht, ich habe aber keine ARM-MCU mit 
40Mbit/s-SPI-Interface gefunden.

Grüße

Mac

von Oliver J. (skriptkiddy)


Lesenswert?

Mac schrieb:
> Hallo Uwe, die ADC haben 4 x 40 40Mbit/s
Welche ADCs sind das denn?

von Mac (Gast)


Lesenswert?

Oliver J. schrieb:
> Wie willst du denn in einem Thumb2-Befehl eine 32 Bit Addresse codieren?
> Das geht also wieder über indirekte Adressierung. Und dafür musst du
> nach jedem Transfer das Pointerregister erhöhen.
>
> Außerdem brauchen Load- und Store-Befehle 2 Takte (eben nachgeschaut):
> Wert von GPIO in Register laden              (2 Takte)
>
> Register wegspeichern indirekt über
> Pointerregister                              (2 Takte)
>
> Pointerregister := Pointeregister + 1        (1 Takt )

Ah, ok. Ich hab von Thumb2 leider keine Ahnung. Dann kann ich diese 
Lösungsmöglichkeit wohl abschreiben.

Vielen Dank!

Grüße

Mac

von Mac (Gast)


Lesenswert?

Oliver J. schrieb:
> Mac schrieb:
>> Hallo Uwe, die ADC haben 4 x 40 40Mbit/s
> Welche ADCs sind das denn?

So doof es auch ist, ich darf leider nicht ins Details gehen, wegen NDA 
und Arbeitgeber.

Grüße

Mac

von Oliver J. (skriptkiddy)


Lesenswert?

Mac schrieb:
> NDA
> und Arbeitgeber.
WTF? Du wirst doch wohl den Typen des ADC nennen dürfen.

von Max (Gast)


Lesenswert?

man könnte auch die 4 bits des adc stapeln, also 4 bit ins high-nibble 
und 4-bit ins low-nibble, mit ein paar externen ICs solltes gehn, is aba 
hald mehraufwand, vmtl. wär mehr takt billiger oder in sonderfällen eine 
CPLD, die lacht dann auch bei 100 MHz noch...

von Andreas B. (andreas_b77)


Lesenswert?

Man muss sich ja nicht auf einen Wert pro Schleifendurchlauf 
beschränken. Bei mehreren kann man STM mit Post-Inkrement verwenden, das 
ist günstiger als einzelne ST. Etwa:
1
    ldr    r0,[r7]
2
    ldr    r1,[r7]
3
    ldr    r2,[r7]
4
    ldr    r3,[r7]
5
    ldr    r4,[r7]
6
    ldr    r5,[r7]
7
    stmia  r6!,{r0,r1,r2,r3,r4,r5}
(So sind ausschließlich 16 Bit Opcodes verwendet.)

Ich hab aber nicht nachgeschaut, ob das von den Zyklen wirklich 
günstiger ist.

von Jim M. (turboj)


Lesenswert?

> SPI-Schnittstelle(n) gesucht, ich habe aber keine ARM-MCU mit
> 40Mbit/s-SPI-Interface gefunden.

LPC1769 müsste in die Richtung kommen. Die Schnittstellen heissen da 
SSP, das sind schnelle SPI Schnittstellen (die legacy SPI braucht 12 
Clockzyklen bei diesem µC und fällt damit aus). Mit den SSPs ist SPI als 
Master bis CCLK/2 möglich; Die Port Pins gehen IIRC aber nur bis 50MHz. 
Die sind auch DMA fähig.

von Mac (Gast)


Lesenswert?

Vielen Dank für die weiteren Hinweise!

Max, durch Deinen CPLD-Hinweis habe ich mal in diese Richtung und FPGA 
gegoogelt und bin dann bei IGLOO Nano hängengeblieben. Da die Teile ev. 
geeignet und auch verfügbar sind, werde ich in dieser Richtung wohl 
erstmal weitermachen.

Jim, der LPC1769 klingt auch interessant. I.S. Gehäusegröße trifft er 
zwar nicht ganz meine Anforderungen, aber ev. gibts da auch noch 
kleinere Brüder.

Grüße

Mac

von Uwe (Gast)


Lesenswert?

Jup darauf wollte ich auch hinaus (CPLD) als ich fragte ob er vier SPI 
parallel betreiben möchte.

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.