C-Optimieren für weniger Assambler Zyklen..



  • Hallo FReaks,

    ich bin an Microcontroller Programmierung mit C dran.. und will folgenden Code optimeren:

    67:                	lOld=lNew;
      04BE  804170     mov.w 0x082e,0x0000
      04C0  804181     mov.w 0x0830,0x0002
      04C2  8841E0     mov.w 0x0000,0x083c
      04C4  8841F1     mov.w 0x0002,0x083e
    68:                	lNew= ((((unsigned long)TMR3<<16 ) | TMR2));
      04C6  800850     mov.w 0x010a,0x0000
      04C8  200001     mov.w #0x0,0x0002
      04CA  DD01C0     sl 0x0000,#0,0x0006
      04CC  200002     mov.w #0x0,0x0004
      04CE  800830     mov.w 0x0106,0x0000
      04D0  200001     mov.w #0x0,0x0002
      04D2  710000     ior.w 0x0004,0x0000,0x0000
      04D4  718081     ior.w 0x0006,0x0002,0x0002
      04D6  884170     mov.w 0x0000,0x082e
      04D8  884181     mov.w 0x0002,0x0830
    69:                	if(lNew > lOld){
      04DA  804172     mov.w 0x082e,0x0004
      04DC  804183     mov.w 0x0830,0x0006
      04DE  8041E0     mov.w 0x083c,0x0000
      04E0  8041F1     mov.w 0x083e,0x0002
      04E2  510F80     sub.w 0x0004,0x0000,[0x001e]
      04E4  598F81     subb.w 0x0006,0x0002,[0x001e]
      04E6  340011     bra les, 0x00050a
    70:                		lDiff= 1000000000/((lNew-lOld)*33.9);
      04E8  804172     mov.w 0x082e,0x0004
      04EA  804183     mov.w 0x0830,0x0006
      04EC  8041E0     mov.w 0x083c,0x0000
      04EE  8041F1     mov.w 0x083e,0x0002
      04F0  510000     sub.w 0x0004,0x0000,0x0000
      04F2  598081     subb.w 0x0006,0x0002,0x0002
      04F4  07FE45     rcall 0x000180
      04F6  2999A2     mov.w #0x999a,0x0004
      04F8  242073     mov.w #0x4207,0x0006
      04FA  07FE6D     rcall 0x0001d6
      04FC  BE0100     mov.d 0x0000,0x0004
      04FE  26B280     mov.w #0x6b28,0x0000
      0500  24E6E1     mov.w #0x4e6e,0x0002
      0502  07FE9D     rcall 0x00023e
      0504  07FEDE     rcall 0x0002c2
      0506  884200     mov.w 0x0000,0x0840
      0508  884211     mov.w 0x0002,0x0842
    

    ihr seht immer die C-Anweidungen und der dafür generierte Assambler code eines PIC 30F4011 Mircocipts... ich weis leider nich in wie weit der Compiler den coder schon optimiert hat, und von assambler hab ich kaum ahnung.. könnt ihr mir da was optimieren???

    EDIT: das ganze sind ca 50 Zyklen.. wäre cool wenn man da 10-20 zyklen rausholen könnte;) Das problem ist, das der code für die impulsmessung bei input capture Timer sind. Und um so länger der code um wenger hoch kan die frequenz sein die man messen kann..



  • 1. benutz keine 'longs' sondern mach alles mit 'int'
    2. bei *33.9 ist der eine operand ein 'double'. eventuell besser: *339/10
    3. versuch die multiplikationen und divisionen durch shifts und additionen zu ersetzen.
    🙂



  • hey du, ich muss leider long nehmen, weil dieser 32bit groß ist , und ints nur 16bit 🙂 ich habe nun

    das

    lNew= ((((unsigned long)TMR3<<16 ) | TMR2));
    

    mit

    ((unsigned int*)&lNew)[0]= TMR2;
    ((unsigned int*)&lNew)[1]= TMR3;
    

    erstetzt 3 zyklen weniger;)



  • BorisDieKlinge schrieb:

    hey du, ich muss leider long nehmen, weil dieser 32bit groß ist , und ints nur 16bit

    long ist nur bequemlichkeit. wenn du den code umbaust, kommst du bestimmt ohne longs aus. und guck dir mal an wohin diese ganzen 'rcalls' gehen. das sind bestimmt alles in allem viel mehr taktzyklen, als die von dir geschätzen "50".
    🙂



  • achso, ging davon aus das eine zeile ein zyklus ist;) sorry ich kenn mich da nich aus... hmm... könnt ihr mir mal ein bsp. machen wie ich das nur mit ints lösehn könnte?? 👍 ein kleiner ansatz wäre nic hschlecht



  • du kriegst ja diese grossen werte, weil du TMR3 und TMR2 zusammenschiebst, ne? kannste die nicht getrennt behandeln? also z.b. wenn TMR3 grösser ist als vorher, dann ist der gesamtwert grösser. ist er gleich, dann noch TMR2 überprüfen. auch dieses: *lDiff= 1000000000/((lNew-lOld)33.9) kann man doch bestimmt als lDiff=lNew-lOld abkürzen (um rcalls an der stelle zu vermeiden) und man könnte auch die multiplikation und die division später, in einem zeitunkritischen pfad machen.
    aber guck auch mal da: http://www.piclist.com/techref/microchip/math/index.htm
    🙂



  • 1. Aber echt hey...

    lDiff= 1000000000/((lNew-lOld)*33.9)
    

    .. die berechnung könnte ich echt später machen, is mir zuerst gar nich in den sinn gekommen:)

    2. Hmm.. wäre denn

    unsigned int iOld2,iOld3,iNew2,iNew3,iDiff2,iDiff3;
    
    iOld2= iNew2;
    iOld3= iNew3;
    
    iNew2= TMR2;
    iNew3= TMR3;
    
    iDiff2= iOld2-iNew2;
    iDiff3= iOld3-iNew3;
    
    //Zeit(un)kritischer abschnitt
    
    if(iNew2 > iOld2 && iNew3 > iOld3){
    unsigned long lDiff= 1000000000/((((unsigned long)iDiff<<3) | iDiff2)*33.9);
    }
    

    aquvalent zu:

    unsigned long iOld,iNew,iDiff;
    
    lOld=lNew;
    
    lNew= ((((unsigned long)TMR3<<16 ) | TMR2));
    
    if(lNew > lOld){
    //Zeit(un)kritischer abschnitt
    lDiff= 1000000000/((lNew-lOld)*33.9);
    

    }

    ????



  • ^^ du musst natürlich überträge beachten. aber warum probierst du's nicht einfach aus? fängst ja schon an wie 'hasso' aus dem c-forum.
    🙂



  • *Diff= 1000000000/((lNew-lOld)33.9);
    und da mach mal die 'double'-konstante weg. nimm denn zähler mal 10 und mach aus der 33.9(double) eine 339 (integer) und - schwupps - brauch der compiler keine fliesskommaroutinen mehr aufzurufen.
    🙂



  • @16bit freak.. ja ich werds versuchen;) 😋

    @erweiterungsfreak: Das kann ich nich tun! Würd ich den wert "1000000000" mit 10 multiplizieren, hätte ich 10 Milliareden.. kann aber nur 32Bit variablen anlegen als max 4,3 milliarden;)

    🤡



  • das läst sich sogar wunderbar optimieren.

    1.000.000.000 / ((lNew-lOld)*33.9)

    ((1.000.000.000 / 339) * 10 ) / (lNew-lOld)

    wobei der erste teil sogar konstant ist und extern berechnet werden könnte.

    29.498.525 / (lNew-lOld)

    ggf ist noch eine Fehlerbetrachtung zu machen. Meine optimierung würde dir bei der konstante 5 klauen. 29.498.525 zu 29.498.520 wobei da der Fehler zum orginalergebnis bei 1.7 * 10-7 liegt.

    gruss



  • Respekt.. hätte ich auch selber drauf kommen können;) aber vieelen dank 🕶

    YEAHH... jetzt kann ich schon 90Khz statt 30khz messen;)


Anmelden zum Antworten