C-Code optimieren

OP #3039241
Hallo,

ich habe einen AVR32UC3C0512C, der einen IR-Protokollstack über einen 
8-Bit Parallelbus anspricht. Im späteren Verlauf des Projektes wird der 
µController gewechselt (kleineres Package) bei dem die Pins dann zwar am 
selben Port hängen, aber wild verstreut (reicht von Pin 4 bis Pin 27). 
Nachdem die Kommunikation und alle Routinen grundsätzlich funktionieren, 
würde ich gerne die Geschwindigkeit der Lese- und Schreibroutinen 
erhöhen. Derzeit bin ich bei Übertragungsraten von 2,7 MBit/s von 
(theoretisch) maximalen 4 MBit/s. Nachfolgend der Code, den es zu 
optimieren gilt:
1
/* IPMS Controllerpins definieren */
2
#define GPIO_IPMS_DB0  AVR32_PIN_PD11
3
#define GPIO_IPMS_DB1  AVR32_PIN_PD12
4
#define GPIO_IPMS_DB2  AVR32_PIN_PD13
5
#define GPIO_IPMS_DB3  AVR32_PIN_PD14
6
#define GPIO_IPMS_DB4  AVR32_PIN_PD15
7
#define GPIO_IPMS_DB5  AVR32_PIN_PD16
8
#define GPIO_IPMS_DB6  AVR32_PIN_PD17
9
#define GPIO_IPMS_DB7  AVR32_PIN_PD18
10

11
...
12

13
uint8_t ipms_read_reg(uint8_t address)
14
{
15
  uint8_t data = 0;
16
  uint32_t temp_bitmask = 0;
17

18
  ...
19

20
  /* Pinzustände abfragen */
21
  temp_bitmask = AVR32_GPIO.port[IPMS_DB_PORT].pvr;
22

23
  /* Byte wieder zurecht biegen */
24
  if(temp_bitmask & (1 << (GPIO_IPMS_DB0 & 0x1F)))  data |= 1;
25
  if(temp_bitmask & (1 << (GPIO_IPMS_DB1 & 0x1F)))  data |= 2;
26
  if(temp_bitmask & (1 << (GPIO_IPMS_DB2 & 0x1F)))  data |= 4;
27
  if(temp_bitmask & (1 << (GPIO_IPMS_DB3 & 0x1F)))  data |= 8;
28
  if(temp_bitmask & (1 << (GPIO_IPMS_DB4 & 0x1F)))  data |= 16;
29
  if(temp_bitmask & (1 << (GPIO_IPMS_DB5 & 0x1F)))  data |= 32;
30
  if(temp_bitmask & (1 << (GPIO_IPMS_DB6 & 0x1F)))  data |= 64;
31
  if(temp_bitmask & (1 << (GPIO_IPMS_DB7 & 0x1F)))  data |= 128;
32

33
  ...
34
}

Wie kann ich hier Taktzyklen einsparen? Vor lauter Programmierarbeit, 
habe ich gerade keine Ideen mehr :) Vielleicht liegt es auch daran, dass 
es schon spät ist.....oder früh.

Gute Nacht und vielen Dank im voraus für eure Mühen
Gast #3039246
Ist das eine datenbankspeicherplazbelegende Trollfrage, oder dein 
ernst??

Dein Bit0 fängt bei PinD11 an und Bit7 hört bei PinD18 auf. Durchweg.
du brauchst doch nur dein temp_bitmask um 11 bit nach unten verschieben 
und mit 0xff verunden.... fertig.

Du hast dir echt nichtmal eine Minute lang gedanken gemacht, wie man die 
Bitfummelei vereinfachen könnte, oder? :-( Das ist demütigend für jeden 
der hier antworten soll -.-
OP #3039254
> Im späteren Verlauf des Projektes wird der
> µController gewechselt (kleineres Package) bei dem die Pins dann zwar am
> selben Port hängen, aber wild verstreut (reicht von Pin 4 bis Pin 27).

Hier steht, dass es sich später nicht mehr so verhält wie im 
Codeschnipsel! Dass es zurzeit so geht, wie du es vorschlägst, ist mir 
klar.
#3039255
Tarek T. schrieb:
> Hier steht, dass es sich später nicht mehr so verhält wie im
> Codeschnipsel! Dass es zurzeit so geht, wie du es vorschlägst, ist mir
> klar.

Hier kann aber keiner in die Zukunft sehen und daher eher schlecht einen 
Vorschlag machen, wie Code, der später mal entstehen wird, optimiert 
werden könnte.
OP #3039257
Es geht mir auch eher um einen generellen Hinweis. Aber vielleicht 
sollte ich mal ein Beispiel reinstellen. Das momentane Design sieht 
folgende Pinbelegung vor:
1
  /* IPMS Controllerpins definieren */
2
  #define GPIO_IPMS_DB0  AVR32_PIN_PD11
3
  #define GPIO_IPMS_DB1  AVR32_PIN_PD13
4
  #define GPIO_IPMS_DB2  AVR32_PIN_PD14
5
  #define GPIO_IPMS_DB3  AVR32_PIN_PD21
6
  #define GPIO_IPMS_DB4  AVR32_PIN_PD27
7
  #define GPIO_IPMS_DB5  AVR32_PIN_PD28
8
  #define GPIO_IPMS_DB6  AVR32_PIN_PD29
9
  #define GPIO_IPMS_DB7  AVR32_PIN_PD30
Gast #3039265
Da es sich um 8bit handelt, würde ich die bytes per Tabelle übersetzen. 
Das sollte der uc3 ressourcentechnisch noch frei haben. Vermute ich mal.

mfg
#3039292
Tarek T. schrieb:
> Wie kann ich hier Taktzyklen einsparen?

Was kommt denn bisher hinten raus? Müsste sowas wie
  BLD  ...
  ORNE ...
sein, pro Bit.

Wird hier vielleicht keine grosse Rolle spielen, ist aber generell 
beachtenswert: Bei einer 32-Bit RISC-CPU sind lokale Variablen kleiner 
als 32 Bits summarum ineffizient.
#3039389
A. K. schrieb:
> Bei einer 32-Bit RISC-CPU sind lokale Variablen kleiner
> als 32 Bits summarum ineffizient.

Merkbaren Overhead wird das kaum geben.
Wenn der Compiler erkennt, daß Bit 8..31 nicht geändert werden, wird der 
Code gleich groß sein.
Nur bei einem möglichen Überlauf wird er zum Schluß ein "& 0xFF" 
anfügen.
#3039410
Johann L. schrieb:
> ein ästhetisches Problem
Vermute ich auch...

Tarek T. schrieb:
> /* Pinzustände abfragen */
Der Kommentar ist redundant. Wer sieht nicht, dass in der Folgezeile ein 
paar Pins eingelesen werden?

Tarek T. schrieb:
> /* Byte wieder zurecht biegen */
Das seh ich auch, dass da was zurechtgebogen-bitgefummelt wird.
Was ist der Zweck der Aktion?
Wenn dir das im Laufcode zu hässlich aussieht, schreib doch eine kleine 
Funktion, die dir das Pin-Einlesen/Zurechtbiegen erledigt. Oder eine 
Inline-Funktion oder ein Makro...

mfg mf
Gast #3039430
> bei dem die Pins dann zwar am selben Port hängen, aber wild verstreut

Dann machst du ein mal einen Zugriff
1
temp_bitmask = AVR32_GPIO.port[IPMS_DB_PORT].pvr;
und codierst ein mal um
1
temp_bitmask = umcodier_tabelle[temp_bitmask];
dann sind die Bits dort wo du sie hinhaben willst.

Die Tabelle ist 256 Bytes lang,
du tauscht also die lange Laufzeit deines Programmstücks
1
if(temp_bitmask & (1 << (GPIO_IPMS_DB0 & 0x1F)))  data |= 1;
2
if(temp_bitmask & (1 << (GPIO_IPMS_DB1 & 0x1F)))  data |= 2;
3
if(temp_bitmask & (1 << (GPIO_IPMS_DB2 & 0x1F)))  data |= 4;
4
if(temp_bitmask & (1 << (GPIO_IPMS_DB3 & 0x1F)))  data |= 8;
5
if(temp_bitmask & (1 << (GPIO_IPMS_DB4 & 0x1F)))  data |= 16;
6
if(temp_bitmask & (1 << (GPIO_IPMS_DB5 & 0x1F)))  data |= 32;
7
if(temp_bitmask & (1 << (GPIO_IPMS_DB6 & 0x1F)))  data |= 64;
8
if(temp_bitmask & (1 << (GPIO_IPMS_DB7 & 0x1F)))  data |= 128;
gegen den Speicherplatz den die Tabelle benötigt
space vs. speed trade off
(die man übrigens von einem Hilfsprogramm erzeugen lässt,
bei viel RAM auch zu Beginn des Programms vom Programm
selbst erzeugen lassen kann
1
uint8_t umcodier_tabelle[256];
2
for(i=0;i<256;i++)
3
{
4
  temp_bitmask = i; data = 0;
5
  if(temp_bitmask & (1 << (GPIO_IPMS_DB0 & 0x1F)))  data |= 1;
6
  if(temp_bitmask & (1 << (GPIO_IPMS_DB1 & 0x1F)))  data |= 2;
7
  if(temp_bitmask & (1 << (GPIO_IPMS_DB2 & 0x1F)))  data |= 4;
8
  if(temp_bitmask & (1 << (GPIO_IPMS_DB3 & 0x1F)))  data |= 8;
9
  if(temp_bitmask & (1 << (GPIO_IPMS_DB4 & 0x1F)))  data |= 16;
10
  if(temp_bitmask & (1 << (GPIO_IPMS_DB5 & 0x1F)))  data |= 32;
11
  if(temp_bitmask & (1 << (GPIO_IPMS_DB6 & 0x1F)))  data |= 64;
12
  if(temp_bitmask & (1 << (GPIO_IPMS_DB7 & 0x1F)))  data |= 128;
13
  umcodier_tabelle[i] = data;
14
}

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 13 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.