RoboterNetz.de Foren-Übersicht Leiton Werbung
 Home  •  Forum  •  Suchen •  Mitgliederliste  •  RN-Landkarte  •  Ränge  •  Statistik  •  Download •  Album  •  Links  •  Kalender  •  Letzte Themen
 RN-Wissen Artikelbereich  •  Mitarbeiter  •  Benutzergruppen  •  Chat  •  Registrieren  •  FAQ  •  Profil  •  log in, Nachrichten zu lesen  •  Login
Kalender 
Nächstes Thema anzeigen
Vorheriges Thema anzeigen
Neues Thema eröffnenNeue Antwort erstellen
Vorheriges Thema anzeigen Dieses Thema einem Freund schickenZeige Benutzer, die dieses Thema gesehen habenDieses Thema als Textdatei speichernPrintable versionlog in, Nachrichten zu lesen Nächstes Thema anzeigen
Autor Nachricht
HermannSW

Fleißiges Mitglied
Fleißiges Mitglied




Anmeldungsdatum: 18.12.2006
Beiträge: 195
Wohnort: Eberbach

germany.gif
Beitrag Verfasst am: 12.04.2007, 08:12 Antworten mit ZitatNach oben

Hi,

ich habe gestern die neue Asurolib v270rc3 installiert.

An dem Programm zum Dumpen (ausgeben) des EEPROM-Inhaltes des Asuro in ein Terminalprogramm stellte ich dann fest, daß ein einfaches NeuÜbersetzen die Anzahl der Seiten (pages), welche auf den Asuro geflashed werden, von 27 auf 17 reduzierte. Nun erwachte mein sportlicher Ehrgeiz und ich wollte es so klein wie möglich kriegen, damit EEPROM_dump.hex nicht nur ein nützliches, sondern auch ein schnelles Tool ist. Das waren die Schritte für die Größe von EEPROM_dump.hex:
  • mit Asurolib v270rc2: 27 pages
  • mit Asurolib v270rc3: 17 pages
  • nur UartPutc (ohne SerWrite): 14 pages
  • Weglassen der asuro.c im Makefile (!): 5 pages
  • weiteres tuning: 4 pages
Weiter ging es nicht mehr, aber 4 pages sind auch schnell geflashed.

So sieht ein Output von EEPROM_dump.hex im Terminalprogramm aus, einfach 32 Zeilen â 16 bytes hexadezimal (das EEPROM hat eine Größe von 512 bytes):
000102030405060708090A0B0C0D0E0F
101112131415161718191A1B1C1D1E1F
202122232425262728292A2B2C2D2E2F
303132333435363738393A3B3C3D3E3F
404142434445464748494A4B4C4D4E4F
505152535455565758595A5B5C5D5E5F
606162636465666768696A6B6C6D6E6F
707172737475767778797A7B7C7D7E7F
808182838485868788898A8B8C8D8E8F
909192939495969798999A9B9C9D9E9F
A0A1A2A3A4A5A6A7A8A9AAABACADAEAF
B0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF
C0C1C2C3C4C5C6C7C8C9CACBCCCDCECF
D0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF
E0E1E2E3E4E5E6E7E8E9EAEBECEDEEEF
F0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF
000102030405060708090A0B0C0D0E0F
101112131415161718191A1B1C1D1E1F
202122232425262728292A2B2C2D2E2F
303132333435363738393A3B3C3D3E3F
404142434445464748494A4B4C4D4E4F
505152535455565758595A5B5C5D5E5F
606162636465666768696A6B6C6D6E6F
707172737475767778797A7B7C7D7E7F
808182838485868788898A8B8C8D8E8F
909192939495969798999A9B9C9D9E9F
A0A1A2A3A4A5A6A7A8A9AAABACADAEAF
B0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF
C0C1C2C3C4C5C6C7C8C9CACBCCCDCECF
D0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF
E0E1E2E3E4E5E6E7E8E9EAEBECEDEEEF
F0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF


Als Anhang gibt es EEPROM_dump.hex.txt zum direkten Flashen (.hex ist leider keine erlaubte Dateiendung für Attachments, einfach in .hex umbenennen), hier ist der Quelltext (nicht vergessen, asuro.c im makefile auszukommentieren #SRC += asuro.c):
#include <avr/eeprom.h>

void UartPutc (unsigned char zeichen)
{
  UCSRB  = 0x08;                        // enable transmitter
  UCSRA |= 0x40;                        // clear transmitter flag
  while (!(UCSRA & 0x20))               // wait for empty transmit buffer
    ;
  UDR = zeichen;
  while (!(UCSRA & 0x40))               // Wait for transmit complete flag (TXC)
    ;
}

unsigned char map(unsigned char x) { return ( (x<10) ? '0'+x : 'A'+(x-10) ); }

int main(void)
{
  unsigned int u;

  for(u=0; u<0x0200; ++u)
  { 
    unsigned char ch = eeprom_read_byte((uint8_t*) u);

    UartPutc(map(ch >> 4));
    UartPutc(map(ch & 0x0F));

    if ((u & 0x0F) == 0x0F)
    {
      UartPutc('\r');
      UartPutc('\n');
    }
  }   

  while (1);

  return 0;
}
Da die Asurolib nicht benutzt wird, musste natürlich UartPutc(), die einzige aus der Asurolib benötigte Routine, in den Quelltext hineinkopiert werden. Hier nun die Ausgabe von avr-objdump aus dem Make-Prozeß (C-Quelltext und Assembler gemischt):
test.elf:     file format elf32-avr

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
  0 .text         000000ce  00000000  00000000  00000094  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  1 .data         00000000  00800060  000000ce  00000162  2**0
                  CONTENTS, ALLOC, LOAD, DATA
  2 .bss          00000000  00800060  000000ce  00000162  2**0
                  ALLOC
  3 .noinit       00000000  00800060  00800060  00000162  2**0
                  CONTENTS
  4 .eeprom       00000000  00810000  00810000  00000162  2**0
                  CONTENTS
  5 .stab         000003e4  00000000  00000000  00000164  2**2
                  CONTENTS, READONLY, DEBUGGING
  6 .stabstr      000005d7  00000000  00000000  00000548  2**0
                  CONTENTS, READONLY, DEBUGGING
Disassembly of section .text:

00000000 <__vectors>:
   0:   12 c0          rjmp   .+36        ; 0x26
   2:   2b c0          rjmp   .+86        ; 0x5a
   4:   2a c0          rjmp   .+84        ; 0x5a
   6:   29 c0          rjmp   .+82        ; 0x5a
   8:   28 c0          rjmp   .+80        ; 0x5a
   a:   27 c0          rjmp   .+78        ; 0x5a
   c:   26 c0          rjmp   .+76        ; 0x5a
   e:   25 c0          rjmp   .+74        ; 0x5a
  10:   24 c0          rjmp   .+72        ; 0x5a
  12:   23 c0          rjmp   .+70        ; 0x5a
  14:   22 c0          rjmp   .+68        ; 0x5a
  16:   21 c0          rjmp   .+66        ; 0x5a
  18:   20 c0          rjmp   .+64        ; 0x5a
  1a:   1f c0          rjmp   .+62        ; 0x5a
  1c:   1e c0          rjmp   .+60        ; 0x5a
  1e:   1d c0          rjmp   .+58        ; 0x5a
  20:   1c c0          rjmp   .+56        ; 0x5a
  22:   1b c0          rjmp   .+54        ; 0x5a
  24:   1a c0          rjmp   .+52        ; 0x5a

00000026 <__ctors_end>:
  26:   11 24          eor   r1, r1
  28:   1f be          out   0x3f, r1   ; 63
  2a:   cf e5          ldi   r28, 0x5F   ; 95
  2c:   d4 e0          ldi   r29, 0x04   ; 4
  2e:   de bf          out   0x3e, r29   ; 62
  30:   cd bf          out   0x3d, r28   ; 61

00000032 <__do_copy_data>:
  32:   10 e0          ldi   r17, 0x00   ; 0
  34:   a0 e6          ldi   r26, 0x60   ; 96
  36:   b0 e0          ldi   r27, 0x00   ; 0
  38:   ee ec          ldi   r30, 0xCE   ; 206
  3a:   f0 e0          ldi   r31, 0x00   ; 0
  3c:   02 c0          rjmp   .+4         ; 0x42

0000003e <.do_copy_data_loop>:
  3e:   05 90          lpm   r0, Z+
  40:   0d 92          st   X+, r0

00000042 <.do_copy_data_start>:
  42:   a0 36          cpi   r26, 0x60   ; 96
  44:   b1 07          cpc   r27, r17
  46:   d9 f7          brne   .-10        ; 0x3e

00000048 <__do_clear_bss>:
  48:   10 e0          ldi   r17, 0x00   ; 0
  4a:   a0 e6          ldi   r26, 0x60   ; 96
  4c:   b0 e0          ldi   r27, 0x00   ; 0
  4e:   01 c0          rjmp   .+2         ; 0x52

00000050 <.do_clear_bss_loop>:
  50:   1d 92          st   X+, r1

00000052 <.do_clear_bss_start>:
  52:   a0 36          cpi   r26, 0x60   ; 96
  54:   b1 07          cpc   r27, r17
  56:   e1 f7          brne   .-8         ; 0x50
  58:   12 c0          rjmp   .+36        ; 0x7e

0000005a <__bad_interrupt>:
  5a:   d2 cf          rjmp   .-92        ; 0x0

0000005c <UartPutc>:
#include <avr/eeprom.h>

void UartPutc (unsigned char zeichen)
{
  5c:   98 2f          mov   r25, r24
  UCSRB  = 0x08;                        // enable transmitter
  5e:   88 e0          ldi   r24, 0x08   ; 8
  60:   8a b9          out   0x0a, r24   ; 10
  UCSRA |= 0x40;                        // clear transmitter flag
  62:   5e 9a          sbi   0x0b, 6   ; 11
  while (!(UCSRA & 0x20))               // wait for empty transmit buffer
  64:   5d 9b          sbis   0x0b, 5   ; 11
  66:   fe cf          rjmp   .-4         ; 0x64
    ;
  UDR = zeichen;
  68:   9c b9          out   0x0c, r25   ; 12
  while (!(UCSRA & 0x40))               // Wait for transmit complete flag (TXC)
  6a:   5e 9b          sbis   0x0b, 6   ; 11
  6c:   fe cf          rjmp   .-4         ; 0x6a
    ;
}
  6e:   08 95          ret

00000070 <map>:

unsigned char map(unsigned char x) { return ( (x<10) ? '0'+x : 'A'+(x-10) ); }
  70:   8a 30          cpi   r24, 0x0A   ; 10
  72:   10 f4          brcc   .+4         ; 0x78
  74:   80 5d          subi   r24, 0xD0   ; 208
  76:   01 c0          rjmp   .+2         ; 0x7a
  78:   89 5c          subi   r24, 0xC9   ; 201
  7a:   99 27          eor   r25, r25
  7c:   08 95          ret

0000007e <main>:

int main(void)
{
  7e:   cf e5          ldi   r28, 0x5F   ; 95
  80:   d4 e0          ldi   r29, 0x04   ; 4
  82:   de bf          out   0x3e, r29   ; 62
  84:   cd bf          out   0x3d, r28   ; 61
  unsigned int u;

  for(u=0; u<0x0200; ++u)
  86:   c0 e0          ldi   r28, 0x00   ; 0
  88:   d0 e0          ldi   r29, 0x00   ; 0
  { 
    unsigned char ch = eeprom_read_byte((uint8_t*) u);
  8a:   ce 01          movw   r24, r28
  8c:   18 d0          rcall   .+48        ; 0xbe
  8e:   18 2f          mov   r17, r24

    UartPutc(map(ch >> 4));
  90:   82 95          swap   r24
  92:   8f 70          andi   r24, 0x0F   ; 15
  94:   ed df          rcall   .-38        ; 0x70
  96:   e2 df          rcall   .-60        ; 0x5c
    UartPutc(map(ch & 0x0F));
  98:   1f 70          andi   r17, 0x0F   ; 15
  9a:   81 2f          mov   r24, r17
  9c:   e9 df          rcall   .-46        ; 0x70
  9e:   de df          rcall   .-68        ; 0x5c

    if ((u & 0x0F) == 0x0F)
  a0:   ce 01          movw   r24, r28
  a2:   8f 70          andi   r24, 0x0F   ; 15
  a4:   90 70          andi   r25, 0x00   ; 0
  a6:   0f 97          sbiw   r24, 0x0f   ; 15
  a8:   21 f4          brne   .+8         ; 0xb2
    {
      UartPutc('\r');
  aa:   8d e0          ldi   r24, 0x0D   ; 13
  ac:   d7 df          rcall   .-82        ; 0x5c
      UartPutc('\n');
  ae:   8a e0          ldi   r24, 0x0A   ; 10
  b0:   d5 df          rcall   .-86        ; 0x5c
  b2:   21 96          adiw   r28, 0x01   ; 1
  b4:   82 e0          ldi   r24, 0x02   ; 2
  b6:   c0 30          cpi   r28, 0x00   ; 0
  b8:   d8 07          cpc   r29, r24
  ba:   38 f3          brcs   .-50        ; 0x8a
    }
  }   

  while (1);
  bc:   ff cf          rjmp   .-2         ; 0xbc

000000be <eeprom_read_byte>:

  return 0;
}
  be:   e1 99          sbic   0x1c, 1   ; 28
  c0:   fe cf          rjmp   .-4         ; 0xbe
  c2:   9f bb          out   0x1f, r25   ; 31
  c4:   8e bb          out   0x1e, r24   ; 30
  c6:   e0 9a          sbi   0x1c, 0   ; 28
  c8:   99 27          eor   r25, r25
  ca:   8d b3          in   r24, 0x1d   ; 29
  cc:   08 95          ret
Wie man schön sehen kann, ist Alles recht kompakt, bis 0x5c gibt es C-Compiler-Kram, danach UartPutc(), und der Rest des Programms bis 0xbe, und angehängt eeprom_read_byte() aus der AVR-Library.


Hier noch eine Frage an die Entwickler der Library:
Warum klappt UartPutc() ohne Aufruf von Init() aus der Asurolib?
Wird der Asuro etwa schon vom BootLoader auf 2400bps eingestellt?
Der Code aus Init() wird ja gerade nicht ausgeführt:
...
void Init (
  void)
{
  /*
    Timer2, zum Betrieb mit der seriellen Schnittstelle, fuer die
    IR-Kommunikation auf 36 kHz eingestellt.
  */
  TCCR2 = (1 << WGM20) | (1 << WGM21) | (1 << COM20) | (1 << COM21) | (1 << CS20);
  OCR2  = 0x91;                         // duty cycle fuer 36kHz
  TIMSK |= (1 << TOIE2);                // 36kHz counter

  /*
    Die serielle Schnittstelle wurde waerend der Boot-Phase schon
    programmiert und gestartet. Hier werden die Parameter auf 2400 1N8 gesetzt.
  */
  UCSRA = 0x00;
  UCSRB = 0x00;
  UCSRC = 0x86; // 1 Stop Bit | No Parity | 8 Data Bit
  UBRRL = 0xCF; // 2400bps @ 8.00MHz
...



Last, but not least, hier noch ein Programm, welches den EEPROM-Inhalt auf ein definiertes Muster setzt:
#include <asuro.h>

#include <avr/eeprom.h>

int main (void)
{
  unsigned int u;
  long t0,t1,t2,tmax;
  unsigned char ch;

  Init();

  tmax = 0;
  t0 = t1 = Gettime();

  for(u=0x0000; u<0x0200; ++u)
  {
    eeprom_write_byte((uint8_t*)u,(unsigned char)(u&0xff));

    t2 = Gettime();

    if (t2-t1>tmax)
      tmax=t2-t1;

    t1=t2;
  }

  t2 = Gettime();

  SerPrint("\r\naverage time for writing 1 byte to eeprom: ");
  PrintLong((1000*(t1-t0))/512);
  SerPrint("us\r\n");

  SerPrint("maximal time for writing 1 byte to eeprom: ");
  PrintLong(tmax);
  SerPrint("ms\r\n");

  ch = 0x00;

  t0 = Gettime();

  for(u=0x0000; u<0x0200; ++u)
    ch ^= eeprom_read_byte((uint8_t*)u);

  t1 = Gettime();

  SerPrint("average time for reading 1 byte from eeprom: ");
  PrintLong((1000*(t1-t0))/512);
  SerPrint("us\r\n");

  SerPrint("control value (should be 0): ");
  PrintInt((int)ch);
  SerPrint("\r\n");

  while (1);
   
  return 0;
}


Das Programm bestimmt noch nebenbei die durchschnittlichen Zeiten für Lesen/Schreiben von/auf EEPROM, hier der Output von 4 Läufen:
average time for writing 1 byte to eeprom: 8355us
maximal time for writing 1 byte to eeprom: 9ms
average time for reading 1 byte from eeprom: 3us
control value (should be 0): 0

average time for writing 1 byte to eeprom: 8306us
maximal time for writing 1 byte to eeprom: 9ms
average time for reading 1 byte from eeprom: 3us
control value (should be 0): 0

average time for writing 1 byte to eeprom: 8308us
maximal time for writing 1 byte to eeprom: 9ms
average time for reading 1 byte from eeprom: 5us
control value (should be 0): 0

average time for writing 1 byte to eeprom: 8302us
maximal time for writing 1 byte to eeprom: 9ms
average time for reading 1 byte from eeprom: 3us
control value (should be 0): 0


Also Lesen eines Bytes 3-5µs, Schreiben eines Bytes 8.3ms, also mehr als 3 Größenordnungen langsamer ...


Noch ein Tipp für die Nutzer von Hyperterminal:
Zeilen, die nach oben aus dem Screen rausrutschen, werden zumindest in meinem Hyperterminal verunstaltet, wenn man nach oben scrolled.
Deshalb vor Start von EEPROM_dump.hex auf dem Asuro nicht Vergessen, den Terminal-Output mittles "Transfer-->Capture Text" (habe gerade kein dt. Hyperterminal griffbereit) in eine Datei zu sichern. Hinterher "Transfer-->Capture Text-->Stop" nicht vergessen.

_________________
Gruß, Hermann.
myIrAsuro.Image
Offline Benutzer-Profile anzeigen E-Mail senden Website dieses Benutzers besuchen
m.a.r.v.i.n

Roboter Genie
Roboter Genie




Anmeldungsdatum: 24.07.2005
Beiträge: 1073
Wohnort: Berlin

germany.gif
Beitrag Verfasst am: 12.04.2007, 09:24 Antworten mit ZitatNach oben

Hallo Hermann,

sehr interessant, deine Untersuchung. Mit dem EEPROM habe ich mich bisher noch gar nicht beschäftigt.

Zu deiner Frage (obwohle ich den Quellcode des Bootloaders nicht kenne). Ja, die UART wird bereits im Bootloader initialisiert. Muß ja so sein, sonnte würde das Flashen nicht funktionieren.

Zur Codegröße. Das Optimum wäre es, jede Funktion einzeln in eine Datei ablegen, und daraus die LIB übersetzen. Noch kleiner geht es nur noch in Assembler. Beim weglassen der asuro.c darf man aber auch kein Sleep oder Msleep aufrufen, weil die Timer ISR auch nicht eingebunden wird.

_________________
Gruß m.a.r.v.i.n

Homepages:
http://www.asurowiki.de
http://www.robotfreak.de/blog
Offline Benutzer-Profile anzeigen Website dieses Benutzers besuchen
Beiträge vom vorherigen Thema anzeigen:      
Neues Thema eröffnenNeue Antwort erstellen
Vorheriges Thema anzeigen Dieses Thema einem Freund schickenZeige Benutzer, die dieses Thema gesehen habenDieses Thema als Textdatei speichernPrintable versionlog in, Nachrichten zu lesen Nächstes Thema anzeigen



 Gehe zu:   



Nächstes Thema anzeigen
Vorheriges Thema anzeigen
Du kannst keine Beiträge in dieses Forum schreiben.
Du kannst auf Beiträge in diesem Forum nicht antworten.
Du kannst deine Beiträge in diesem Forum nicht bearbeiten.
Du kannst deine Beiträge in diesem Forum nicht löschen.
Du kannst an Umfragen in diesem Forum nicht mitmachen.
Du kannst Dateien in diesem Forum nicht posten
Du kannst Dateien in diesem Forum nicht herunterladen




Die große Community für Robotik-, Mikrocontroller- und Elektronik Bastler als auch Experten
 Roboternetz RSS2.0 News Feed
Alle Zeiten sind GMT + 1 Stunde