Forum: Compiler & IDEs IO bei M68k <-> GCC


von Holm T. (Gast)


Lesenswert?

Ich versuche spaßeshalber mal über das KatCE Board mit mit 68010 und 
68230
am Port B des 68230 die Daten eines DHT11 einzulesen .. und der Kram ist 
scheinbar zu langsam. Die CPU wird mit 10,240 Mhz getaktet.

Due Hauptursache für mein Problem ist die Implementation der 
Ein-Ausgabefunktionen des verwendeten FBuG Monitors.

der PIT liegt auf ungeraden Adressen
1
#define PIT_PGCR        0x400001
2
#define PIT_PSRR        PIT_PGCR+2      /* 0x400003 */
3
#define PIT_PADDR       PIT_PSRR+2      /* 0x400005 */
4
#define PIT_PBDDR       PIT_PADDR+2     /* 0x400007 */
5
#define PIT_PCDDR       PIT_PBDDR+2     /* 0x400009 */
6
#define PIT_IVR         PIT_PCDDR+2     /* 0x40000B */
7
#define PIT_PACR        PIT_IVR+2       /* 0x40000D */
8
#define PIT_PBCR        PIT_PACR+2      /* 0x40000F */
9
#define PIT_PADR        PIT_PBCR+2      /* 0x400011 */
10
#define PIT_PBDR        PIT_PADR+2      /* 0x400013 */
11
#define PIT_PAAR        PIT_PBDR+2      /* 0x400015 */
12
#define PIT_PBAR        PIT_PAAR+2      /* 0x400017 */
13
#define PIT_PCDR        PIT_PBAR+2      /* 0x400019 */
14
#define PIT_PSR         PIT_PCDR+2      /* 0x40001B */
15
#define PIT_TCR         PIT_PSR+6       /* 0x400021 */
16
#define PIT_TIVR        PIT_TCR+2       /* 0x400023 */
17
#define PIT_CPRH        PIT_TIVR+4      /* 0x400027 */
18
#define PIT_CPRM        PIT_CPRH+2      /* 0x400029 */
19
#define PIT_CPRL        PIT_CPRM+2      /* 0x40002B */
20
#define PIT_CRH         PIT_CPRL+4      /* 0x40002F */
21
#define PIT_CRM         PIT_CRH+2       /* 0x400031 */
22
#define PIT_CRL         PIT_CRM+2       /* 0x400033 */
23
#define PIT_TSR         PIT_CRL+2       /* 0x400035 */

und ich benutze die für 8 Bit Eingaben vorgesehene Funktion get8().
1
get8 (addr)   /* returns 8 bits not sign-extended  */
2
int addr;
3
{
4
extern int asmaddr;
5
extern int asmdata;
6
7
        asmaddr = addr;
8
        asmget8();
9
        asmdata = asmdata & MASK8;
10
        return(asmdata);
11
}

die ihrerseits asmget8() aufruft
1
asmget8:        clr.l   asmdata
2
                mov.l   %a0,-(%sp)
3
                mov.l   asmaddr,%a0
4
                mov.b   (%a0),asmdata+3
5
                bpl.b   nosi8
6
                or.l    &0xffffff00,asmdata
7
nosi8:          mov.l   (%sp)+,%a0
8
                rts

Das dauert ja regelrecht Wochen bis die CPU da durch ist.
In der einfachen Lesefunktion für den DHT11 habe ich zwischen 2 Abfragen 
eine Verzögerung von ca. 40 mikrosekunden einzuhalten:
1
...
2
while(!get8(PIT_PBDR)&0x01);                    // wait for high "response"
3
        while(get8(PIT_PBDR)&0x01);                     // wait for low "Bit 0 Start"
4
        for(b=0;b<3;b++)
5
        {
6
                num = 0;
7
                for (i=0; i<8; i++)
8
                {
9
                        while(!get8(PIT_PBDR)&0x01); // wait for  L/H 
10
                        __asm volatile ("nop");
11
                        __asm volatile ("nop");
12
                        if(get8(PIT_PBDR)&0x01)      // read Data
13
                                 num |= 1<<(7-i);
14
                        while(get8(PIT_PBDR)&0x01);  // wait for  H/L
15
                }
16
                bitbuf[b]=num;
17
        }
18
...

Ich bin mit Assembler beim 68k nicht sonderlich bewandert, hat hier 
einer der Profis eine Idee wie ich das Verfahren für diesen speziellen 
Fall der Abfrage nur des Pins PB0 des PIT entscheidend beschleunigen 
kann?
Wenn es gar nicht geht muß ich halt die ganze Leseroutine in Assembler 
einfügen, allerdings muß ich da erst wieder viel lesen, ich wußte vor 
Jahren schon mal besser Bescheid :-(

Gruß,

Holm

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Und was geschieht, wenn Du auf die Assemblerkiste verzichtest?
1
uint8_t wert;
2
3
wert = *((uint8_t *) addresse);

Das sollte doch genügen; schließlich gibt es auf einem 68k keine 
speziellen I/O-Befehle, sondern nur "memory-mapped I/O".

von (prx) A. K. (prx)


Lesenswert?

Welcher Scherzkeks hat diesen Asm-Code verbrochen? Frischer PIC 
Konvertit? Auf einer 68K CPU Funktionsaufruf mit Übergabe von Parameter 
und Returnwert via globaler Variable? Und die (bekloppte) 
Vorzeichenerweiterung ist auch reichlich aufwändig geraten.

: Bearbeitet durch User
von Markus F. (mfro)


Lesenswert?

Rufus Τ. Firefly schrieb:
> Und was geschieht, wenn Du auf die Assemblerkiste verzichtest?
> uint8_t wert;
>
> wert = *((volatile uint8_t *) addresse);

Das würde ich in erster Instanz auch probieren (noch 'n volatile dazu), 
ansonsten (wenn's denn unbedingt Assembler sein soll) mal eben aus der 
Hüfte geschossen (und ungetestet):
1
#define pit_ready()  __extension__({ \
2
    char res = 0; \
3
    __asm__ __volatile__(\
4
            "           .equ    PIT_PBDR,0x400013 \n\t" \
5
            "           move.b  PIT_PBDR,%[res]   \n\t" \
6
            : [res] "=r" (res)                          \
7
            : /* no input */                            \
8
            : /* no clobber */                          \
9
        ); \
10
        res;  \
11
    })

Speziell für die etwas schräge Anbindung von 16 bit Peripherie an den 
32-Bit Bus hat der 68k den movep-Befehl. Der wird aber erst interessant, 
wenn Du mehrere Register auf einmal holen willst.

: Bearbeitet durch User
von Holm T. (Gast)


Lesenswert?

@rufus:

Es gibt aber Alignment-restriktionen die mir derzeit nicht mehr geläufig 
sind, dieses get8() legt ja das gelesene Byte in 3. Byte des Integers 
ab.

@A.K. ...Hmm.. Motorola? Jedenfalls sind die der Meinung diesen Monitor 
geschrieben zu haben...

1
MONITOR
2
3
4
Rev 1.1
5
Release Date
6
September 28,1989
7
8
9
10
                        ******** DISCLAIMER ********
11
12
The FBUG monitor is the sole property of Motorola Inc. This software may be
13
distributed in whole or in part as public domain software. This software is 
14
provided as is and in no event shall Motorola, Inc. be liable for any direct, 
15
special, incidental, or consequential damages arising out of or connected with
16
a users poseesion or use of this software package, even if Motorola has advance
17
notice of the possibility of such damages.
18
19
Comments, questions or suggestions may be directed, in writing only, to:
20
21
                Microprocessor Products Applications
22
                6501 William Cannon Drive West 0E33
23
                Austin, Texas 78735-8598

Gerade rief Einer an der fragte ob ich mal nach seiner Waschmaschine 
gucken könnte. Der Monteur der vorher reingeguckt hat diagnostizierte 
ein defektes "Steuerteil" für 270 Euro und die Maschine wäre Scheiße..

Ich komme mir nach Deiner Diagnose auch so vor wie der 
Waschmaschinenbesitzer.

BTW: das ist ne Bauknecht..


@marcus: ich werde das probieren.
>Speziell für die etwas schräge Anbindung von 16 bit Peripherie an den
>32-Bit Bus hat der 68k den movep-Befehl. Der wird aber erst interessant,
>wenn Du mehrere Register auf einmal holen willst.

..ich kann mich erinnern das bei diesem movep Befehl irgendwas mit 
geraden und ungeraden Adressen war, ich habe gelesen das die Peripherie 
auf gerade Adressen gelegt werden sollte damit man diesen Befehl 
benutzen kann. Was ist denn da dran? Die KatCe Hardware habe ich ja 
nicht erfunden...

Gruß,

Holm

von Markus F. (mfro)


Lesenswert?

Der originale Code erinnert zwar tatsächlich mehr an einen Rübenacker 
als an m68k-Assembler, es ist aber durchaus möglich, daß er bloß 
deswegen nicht tut (schließlich tat er das ja schon mal, oder?), weil 
man früher Compiler nicht mit taktisch klug eingestreuten volatile's vom 
Optimieren abhalten mußte...

Vielleicht guckst Du dir das mal unter dem Aspekt nochmal an.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Markus F. schrieb:
> Speziell für die etwas schräge Anbindung von 16 bit Peripherie an den
> 32-Bit Bus hat der 68k den movep-Befehl.

Das ist hier nicht relevant, denn hier wird ein 68010 verwendet, der 
sowieso nur einen 16-Bit-Datenbus hat.

von (prx) A. K. (prx)


Lesenswert?

Markus F. schrieb:
> 32-Bit Bus hat der 68k den movep-Befehl. Der wird aber erst interessant,
> wenn Du mehrere Register auf einmal holen willst.

Diese sehr exotische Befehl war für den Fall gedacht, in dem sich ein 
16/32 Bit breites Peripherieregister auf 2/4 Bytes eines 8-Bit Busses 
verteilt. Mit der späteren dynamischen Busbreite löste sich das Problem 
in Luft auf.

Rufus Τ. Firefly schrieb:
> Das ist hier nicht relevant, denn hier wird ein 68010 verwendet, der
> sowieso nur einen 16-Bit-Datenbus hat.

Andersrum. Ab 68020 war er überflüssig.

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


Lesenswert?

Holm Tiffe schrieb:
> @A.K. ...Hmm.. Motorola? Jedenfalls sind die der Meinung diesen Monitor
> geschrieben zu haben...

Dem Code nach zu schliessen erledigen solche Jobs heute oft 
Praktikanten.

: Bearbeitet durch User
von Markus F. (mfro)


Lesenswert?

Rufus Τ. Firefly schrieb:
> Markus F. schrieb:
>> Speziell für die etwas schräge Anbindung von 16 bit Peripherie an den
>> 32-Bit Bus hat der 68k den movep-Befehl.
>
> Das ist hier nicht relevant, denn hier wird ein 68010 verwendet, der
> sowieso nur einen 16-Bit-Datenbus hat.

Das ist zwar richtig, aber trotzdem falsch ;).

Es geht beim movep-Befehl natürlich um die Anbindung von 8-Bit 
Peripherie an einen 16-Bit Datenbus (hab' ich oben schon falsch 
eingeläutet).

von Holm T. (Gast)


Lesenswert?

1
25: 00100101 0: 00000000 19: 00011001 0: 00000000 3E: 00111110 
2
Rh: 37.0   Temp: 25.0 cs:3e
3
4
25: 00100101 0: 00000000 19: 00011001 0: 00000000 3E: 00111110 
5
Rh: 37.0   Temp: 25.0 cs:3e
6
7
25: 00100101 0: 00000000 19: 00011001 0: 00000000 3E: 00111110 
8
Rh: 37.0   Temp: 25.0 cs:3e
9
10
25: 00100101 0: 00000000 19: 00011001 0: 00000000 3E: 00111110 
11
Rh: 37.0   Temp: 25.0 cs:3e
1
 num = 0;
2
                for (i=0; i<8; i++)
3
                {
4
5
                        while(!((*((volatile unsigned char *) PIT_PBDR))&0x01));
6
                        delay(10);
7
                        //__asm volatile ("nop");
8
                        if((*((volatile unsigned char *) PIT_PBDR))&0x01)
9
                                 num |= 1<<(7-i);
10
                        while((*((volatile unsigned char *) PIT_PBDR))&0x01);
11
                }
12
                bitbuf[b]=num;
13
        }


Das tut wie es aussieht, 25° sind lt. Digitalthermometer gerade 
plausibel :-)

>Der originale Code erinnert zwar tatsächlich mehr an einen Rübenacker
>als an m68k-Assembler, es ist aber durchaus möglich, daß er bloß
>deswegen nicht tut (schließlich tat er das ja schon mal, oder?), weil
>man früher Compiler nicht mit taktisch klug eingestreuten volatile's vom
>Optimieren abhalten mußte...

>Vielleicht guckst Du dir das mal unter dem Aspekt nochmal an.

Naja .. hmm ... wie ich schon schrieb, der Code ist mir momentan nicht 
gerade eingängig.
Allerdings hat das file unterschiedliche Defines für die verschiedenen 
Prozessortypen.A Ich denke aber auch das das Ding alles andere als 
fertig
war, ich weiß noch, das ich die Stackframe Geschichte für den 68010 
anpassen mußte, Nach einem Trap hat der Debugger den 68010 als 68000 
behandelt was schief gehen muß. Das ist aber irgendwann Mitte der 90er 
gewesen als ich das das letzte Mal angefaßt hatte...

Der FBUG gefiel mir von verschiedenen Monitoren/Debuggern die für 68k
damals zur Verfügung standen am besten und als Ossi haben mir diese CPUs 
besser gefallen als das Zeug was mir bis dahin über den Weg gelaufen 
war,
allerdings sind die doch ganz schön komplex. Heute ist das Zeug so 
veraltet das es keinen mehr interessiert. Bei mir ist das auch nur ein 
nostalgischer Anfall und ich stehe noch lange nicht so in der Materie 
das ich da nennenswert verbessern könnte, was wiederum der Grund ist, 
warum ich mir einen Cross-GCC gebastelt habe.
BTW: Der gcc braucht da irgendwo auch noch Arbeit. Trotz der Tatsache 
das ich den mit --with-cpu=m68000 konfiguriert hatte steht in seiner 
libgcc rotzfrech 68020 code drin wenn man nicht explizit den Pfad 
-L/home/holm/cross/m68k/lib/gcc/m68k-elf/4.6.2/m68000 angibt, 
normalerweise sollte der dann der default sein.

Gruß,

Holm

von Markus F. (mfro)


Lesenswert?

Holm Tiffe schrieb:
> ..ich kann mich erinnern das bei diesem movep Befehl irgendwas mit
> geraden und ungeraden Adressen war, ich habe gelesen das die Peripherie
> auf gerade Adressen gelegt werden sollte damit man diesen Befehl
> benutzen kann. Was ist denn da dran? Die KatCe Hardware habe ich ja
> nicht erfunden...

Das muß so.

mit movep kannst Du vier Registerinhalte in einem Langwort und in einem 
Rutsch auf einmal übertragen, die geraden Adressen werden dabei 
übersprungen.

von Holm T. (Gast)


Lesenswert?

Aha. Interessant, ich gucke mir das an.

>es ist aber durchaus möglich, daß er bloß
>deswegen nicht tut (schließlich tat er das ja schon mal, oder?), weil
>man früher Compiler nicht mit taktisch klug eingestreuten volatile's vom
>Optimieren abhalten mußte...


..nicht tut ist falsch. Das geht schon, aber es vergehen Äonen ehe ich 
zu der Information komme ob nun das Bit gesetzt ist oder nicht, die Zeit 
habe ich da gerade nicht. Den DHT11 habe ich da auch gestern erst 
angespaxt, der war vorher noch nie dran. Ich spiele doch nur mit der 
Platine.

@A.K.:
>Dem Code nach zu schliessen erledigen solche Jobs heute oft
>Praktikanten.

Ich war mir nun echt nicht mehr sicher, habe aber das alte Original file 
noch mal ausgewickelt:
1
asmput8:        mov.b   asmdata+3,([asmaddr])
2
                rts
3
4
asmput16:       mov.w   asmdata+2,([asmaddr])
5
                rts
6
7
asmput32:       mov.l   asmdata,([asmaddr])
8
                rts
9
10
asmget8:        clr.l   asmdata
11
                mov.b   ([asmaddr]),asmdata+3
12
                bpl.b   nosi8
13
                or.l    &0xffffff00,asmdata
14
nosi8:          rts
15
16
asmget16:       clr.l   asmdata
17
                mov.w   ([asmaddr]),asmdata+2
18
                bpl.b   nosi16
19
                or.l    &0xffff0000,asmdata
20
nosi16:         rts
21
22
asmget32:       mov.l   ([asmaddr]),asmdata
23
                rts
24
25
putmpu:         
26
                mov.l   ([RUSP]),%d0

das sieht so ziemlich genauso aus. Ich wars also nicht.
Ich nehme gerne Vorschläge zur Verbesserung entgegen, vielleicht braucht 
das ja Jemand Anders nochmal. Ich schmeiße das Ergebnis gerne auf meine 
Webseite.

Du solltest auch ein Bisschen nachsichtig sein, "heute" ist arg relativ 
wenn man sich das Datum in der Quelle anguckt: 28.9.1989!

Gruß,

Holm

von (prx) A. K. (prx)


Lesenswert?

Holm Tiffe schrieb:
> das sieht so ziemlich genauso aus. Ich wars also nicht.

Hatte auch nicht angenommen. Der Asm-Code ist freilich fubar, da lohnt 
es sich nicht, irgendwas zu verbessern, solange man nicht auf Register 
für Parameter umstellt. Also statt dem ASM Kram gleich in C:
1
int get8 (int addr)   /* returns 8 bits not sign-extended  */
2
{
3
  return *(volatile uint8_t *)addr;
4
}
wenn der Compiler schon ANSI C frisst. ;-)

Oder noch einfacher
1
#define PIT_BASE        0x400001
2
#define PIT_PSRR        (*(volatile uint8_t *)(PIT_BASE+2))    /* 0x400003 */
und im Code ohne Aufruf direkt PIT_PSRR verwenden.

> Du solltest auch ein Bisschen nachsichtig sein, "heute" ist arg relativ
> wenn man sich das Datum in der Quelle anguckt: 28.9.1989!

Dachte ich mir, bei K&C C. Aber vielleicht gab es damals auch schon 
Praktikanten.

Mein Kommentar war etwas verunglückt. Ich meinte damit, das Beispielcode 
aus heutiger Zeit, wie in der STM32 Library, teilweise genauso 
verbrochen aussieht.

: Bearbeitet durch User
von Holm T. (Gast)


Lesenswert?

Bei den PIT Adressen funktioniert das, beim LCD aber nicht.
Da ist ein 44780 Teil an 0xc04000 (ctrl) und 0xc04002 (daten)
dran, diesmal interessanterweise gerade Adressen.
Muß ich die Dinger als 16 Bit deklarieren?


Sorry, ist mir jetzt schon zu spät zum denken... ich knalle mich jetzt 
vor die Glotze und penne sicher ein...

Gruß,

Holm

von (prx) A. K. (prx)


Lesenswert?

Holm Tiffe schrieb:
> Bei den PIT Adressen funktioniert das, beim LCD aber nicht.

Weshalb nicht?

> Da ist ein 44780 Teil an 0xc04000 (ctrl) und 0xc04002 (daten)
> dran, diesmal interessanterweise gerade Adressen.
> Muß ich die Dinger als 16 Bit deklarieren?

Nein, grad so wie oben. Nur eben mit den anderen Adressen.

von Holm T. (Gast)


Lesenswert?

Bin noch da...aber ich weiß es nicht. Ich werde morgen mal mit dem 
Debugger nachsehen was der da so treibt. Ich melde mich.

Gruß,

Holm

von Holm T. (Gast)


Lesenswert?

...es lag an dieser Routine, die war vorher 3 Zeilen kürzer:
1
void lcdbusy()
2
{
3
uint8_t ch;
4
5
        ch=LCD_CTRL;
6
        __asm volatile ("nop");
7
        __asm volatile ("nop");
8
        __asm volatile ("nop");
9
        while(LCD_CTRL & 0x80);
10
}


:-)

Gruß,

Holm

von Eric (Gast)


Lesenswert?

Holm Tiffe schrieb:

> for (i=0; i<8; i++)
> {
>     ...
>     num |= 1<<(7-i);
>     ...
> }

Hm, loop invertieren und schon spart man sich den (7-i) ...
1
i = 7;
2
do {
3
    ...
4
    num |= 1<<i;
5
    ...
6
} while (i-- != 0);

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.