Forum: Mikrocontroller und Digitale Elektronik Atmel und SRAM, timing


von Micha (Gast)


Lesenswert?

Ich hab einen Atmel mit 18,432 MHz der einen 70ns SRAM schreiben soll - 
mit Daten die per ser. Schnittstelle ankommen.

Der folgende Code funktionierte erst, nachdem ich zwischen dem runter- 
und wieder hochsetzen des /WE Signals für den SRAM das delay eingefügt 
hatte. Eine Microsekunde ist das Minimum was mit den delay 
Bibliotheksfunktionen geht. Ich würde das delay gern noch ein wenig 
reduzieren, da nebenbei auch noch eine serielle Kommunikation (ohne 
Handshake) läuft die die Daten für den RAM liefert, ich Sorge bezügl. 
Timing habe. Wie bekomme ich ein halbwegs genaues delay in der 
Größenordnung 100 Nanosekunden hin?
1
void writeByte(uint16_t Addr,uint8_t DataByte)
2
{
3
  DDRC = 0b11111111;  // set data port to output
4
  PORTA = Addr & 0xFF;     // set low addr byte
5
  PORTB = Addr >> 8;  // set high addr byte
6
  PORTC = DataByte;
7
  PORTD &= ~WE;    // put /WE signal low
8
  _delay_us(1);
9
  PORTD |= WE;    // put /WE back to high
10
}

von TSE (Gast)


Lesenswert?

Hallo,

18Mhz sind 55ns Pro Takt

Einfach zwei:
asm("nop");

solten reichen

VG

von Stefan (Gast)


Lesenswert?

Bei 10Mhz und ohne delay hättest du 100ns.
Bei 20Mhz und mit einem NOP auch.

Mit deinen 14Mhz Taktfrequenz geht nur 140ns.
1
PORTD &= ~WE;
2
asm volatile ("nop");
3
PORTD |= WE;

von Reinhard Kern (Gast)


Lesenswert?

Micha schrieb:
> der einen 70ns SRAM schreiben soll

Da dürfte eigentlich kein Delay nötig sein, der WE-Inpuls darf 
wesentlich kürzer als 100 ns sein. Du könntest aber ein oder ein paar 
Assembler-NOPs einfügen. Und aufpassen dass nichts weg optimiert wird.

Ich vermute, das Delay ist eigentlich nach dem Setzen der Daten 
notwendig.

Gruss Reinhard

von Falk B. (falk)


Lesenswert?

@ Micha (Gast)

>Ich hab einen Atmel mit 18,432 MHz der einen 70ns SRAM schreiben soll -
>mit Daten die per ser. Schnittstelle ankommen.

Warum machst du das alles per Software? Nimm lieber einen AVR mit XMEM 
Interface, dann läuft das automatisch und deutlich schneller. ATmega 
8515, ATmega64 und andere haben das. Funktioniert problemlos, wenn man 
sich an die Hinweise im Datenblatt hält.

https://www.mikrocontroller.net/articles/Speicher#Mit_XMEM-Interface

>Bibliotheksfunktionen geht. Ich würde das delay gern noch ein wenig
>reduzieren, da nebenbei auch noch eine serielle Kommunikation (ohne
>Handshake) läuft die die Daten für den RAM liefert, ich Sorge bezügl.
>Timing habe.

Nutze Interrupts für den UART.

von Stefan (Gast)


Lesenswert?

Ach, es waren ja 18Mhz. Also kommst Du auf 110ns.

von Micha (Gast)


Lesenswert?

Vielen Dank für die Tips!
Der Code ganz oben hatte ohne das delay teilweise funktioniert, mit 
gelegentlichen Aussetzter, d.h. es kamen manchmal aber nicht immer die 
richtigen Daten im SRAM an.
Das mit dem nop liest sich nach einer guten Idee. Unklar ist mir 
momentan die Bedeutung des "volatile" bei einem der beiden Vorschläge, 
diese Inline-Assembler Statement zu verwenden.

Vorschläge bezügl. uC mit Speicher-Interface, Interrupt sowie 
Hardware-Handshake für die ser. Schnittstelle machen Sinn, kommen aber 
für mich im gegebenen Kontext kurzfristig nicht in Frage (Schaltung 
schon aufgebaut, Firmware auch fast komplett).

von Stefan (Gast)


Lesenswert?

Ohne volatile darf der Compiler das nop weg optimieren, wenn er meint, 
dass es nicht gebraucht wird. Volatile verhindert das.

von Stefan E. (sternst)


Lesenswert?

Und so nebenbei:

Micha schrieb:
> Eine Microsekunde ist das Minimum was mit den delay
> Bibliotheksfunktionen geht.

Nö.

Micha schrieb:
> Wie bekomme ich ein halbwegs genaues delay in der
> Größenordnung 100 Nanosekunden hin?

1
_delay_us(0.1);
Das wird in deinem Fall zu zwei NOPs.

von Micha (Gast)


Lesenswert?

wow - das ist interessant!
Hab noch nie in die Header-Definition von _delay_us geschaut, immer 
angenommen dass da nur eine Ganzzahl als Argument geht. Jetzt sehe ich 
dass das Argument von Typ double ist.

von Micha (Gast)


Lesenswert?

nachdem ich endlich zu Hause war und es ausprobieren konnte:

funktioniert wirklich! _delay_us kann mit einer gebrochenen Zahl als 
Argument verwendet werden. Da wär ich allein NIEMALS drauf gekommen.

Für mich galt immer die felsenfeste 'IMPLICIT ASSUMPTION' dass _delay_us 
ein Ganzzahl-Argument erwartet. Möglicher Grund: bei Microcontrollern 
wie den Atmels hat man normalerweise fast nie was mit Fliesskomma-Zahlen 
zu tun.

Was mich ausserdem begeistert: dass das Statement _delay_us(0.1) 
offenbar schon zu Compile-Zeit umgesetzt wird und nicht erst zur 
Laufzeit - dann wär es ja ziemlich gaga, trotzdem beeindruckend dass ein 
moderner Compiler das so hinbekommt...

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


Lesenswert?

Micha schrieb:
> dass das Statement _delay_us(0.1)
> offenbar schon zu Compile-Zeit umgesetzt wird und nicht erst zur
> Laufzeit

Deswegen sollte man die _delay_nn() Routinen auch nicht mit einer 
Variablen als Argument aufrufen.

von c-hater (Gast)


Lesenswert?

Micha schrieb:

> Für mich galt immer die felsenfeste 'IMPLICIT ASSUMPTION' dass _delay_us
> ein Ganzzahl-Argument erwartet. Möglicher Grund: bei Microcontrollern
> wie den Atmels hat man normalerweise fast nie was mit Fliesskomma-Zahlen
> zu tun.

Das Lustige ist: Das bekommt er hier auch nicht. Alles, was mit dieser 
Float-Zahl passiert, passiert bereits zur Compile-Zeit.

> Was mich ausserdem begeistert: dass das Statement _delay_us(0.1)
> offenbar schon zu Compile-Zeit umgesetzt wird und nicht erst zur
> Laufzeit - dann wär es ja ziemlich gaga

Im konkreten Fall wäre es (außer für die Codegröße) scheißegal, nichts 
eignet sich schließlich besser zum Bremsen als 
Fließkommazahlen-Berechnungen.

> trotzdem beeindruckend dass ein
> moderner Compiler das so hinbekommt...

Das hat mit modernem Compiler oder nicht rein garnichts zu tun. Das 
hängt nur am Vorhandensein und der Mächtigkeit eines Präprozessors. Geht 
also z.B. in Assembler ganz genauso.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

c-hater schrieb:
> Micha schrieb:
>> trotzdem beeindruckend dass ein
>> moderner Compiler das so hinbekommt...
>
> Das hat mit modernem Compiler oder nicht rein garnichts zu tun. Das
> hängt nur am Vorhandensein und der Mächtigkeit eines Präprozessors. Geht
> also z.B. in Assembler ganz genauso.

Nö, ein Präprozessor alleine reicht hier nicht.  Wenn da steht

 x = 1.2 * 3.4

rechnet der Präprozessor nämlich nix, das muß vom Compiler kommen.

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.