@Arne Rossius:ISP Progger

  • Thread starter Dominik Schmidt
  • Start date
D

Dominik Schmidt

Guest
Moin Arne!

Du hast mir am 22.08. bei einem AVR Progger Problerm geholfen. Nun habe ich
da nochmal ne kleine Frage :) (Muss es leider über diesen Weg machen, denn
dein Formmailer geht irgendwie nicht.)
Und zwar kriege ich das Proggen des Speichers nicht sauber hin. Das ist
meine Funktion:
// Load Program Memory Page 0100 H000 xxxx xxxx xxxx bbbb iiii iiii
// Write H (high or low) data i to Program Memory page at word address b.
// Data low byte must be loaded before data high byte is applied within
// the same address.
// Write Program Memory Page 0100 1100 xxxx xxaa bbbb xxxx xxxx xxxx
// Write Program Memory Page at address a:b.
// i = data in a = address high bits b = address low bits
// H = 0 - Low byte, 1 - High Byte o = data out
procedure TForm1.AVRFlashSchreibenClick(Sender: TObject);
var i,j,k,l:integer;
begin
ComOpen(COMCombo.Text);
SPIInit;
// Speicher löschen
ISPInOut(172);
ISPInOut(128);
ISPInOut(0);
ISPInOut(0);
Delay(10);
l := 0; // Positionszeiger für HexEdit
for k := 0 to 3 do // \
for j := 1 to 16 do // / 16Byte Blöcke wegschreiben
begin
for i := 0 to 15 do // Puffer füllen
begin
// erst Low Byte schreiben
ISPInOut(64);
ISPInOut(0);
ISPInOut(i);
ISPInOut(hextoint(chartohex(AVRHex.GetMemory(l+1))));
// dann HighByte schreiben
ISPInOut(72);
ISPInOut(0);
ISPInOut(i);
ISPInOut(hextoint(chartohex(AVRHex.GetMemory(l))));
inc(l);
inc(l);
end;
// checken ob ein Byte aus der Page geschrieben wurde
// wenn dem so ist, kann erst die nächste Page geschrieben werden!
{ISPInOut(32); //< Hi-Byte
ISPInOut(k);
ISPInOut(j);
res := ISPInOut(0); }

// Schreibe Memory Page
ISPInOut(76);
ISPInOut(k);
ISPInOut(j*16);
ISPInOut(0);
delay(10);
//Memo1.Lines.Add('Schreibe Memory Page');
end;
CLOSECOM;
end;

Und das ist SPIInit (funzt auch sauber):
// SPI Proceduren & Funktionen
procedure SPIInit;
var i:integer;
begin
TXD(1); //
RTS(0); // Initialisierung einleiten
Delay(100);
TXD(0);
Delay(100);
TXD(1);
Delay(100);
for i:=1 to 4 do // Synchronisieren
begin
ISPInOut(172);
ISPInOut(83);
ISPInOut(0);
ISPInOut(0);
end;
end;

Er schreibt die Werte einfach nicht sauber weg. Kannst du mir mal erklären
auf was man da achten muss? Oder kannst du mir nochmal deine Funktion für
das Flashen schicken?

Grüße Dominik
 
Dominik Schmidt wrote:
Du hast mir am 22.08. bei einem AVR Progger Problerm geholfen. Nun habe ich
da nochmal ne kleine Frage :) (Muss es leider über diesen Weg machen, denn
dein Formmailer geht irgendwie nicht.)
Der Formmailer war nur falsch konfiguriert und hat nach erfolgreichem
Versenden die Hauptseite angezeigt, deine Email ist aber trotzdem nicht
angekommen. Aber but das du mich drauf hingewiesen hast, sonst hätte ich
es wohl nie gemerkt.

Und zwar kriege ich das Proggen des Speichers nicht sauber hin. Das ist
meine Funktion:
[...]
// Speicher löschen
ISPInOut(172);
ISPInOut(128);
ISPInOut(0);
ISPInOut(0);
Delay(10);
Dort habe ich 25ms Wartezeit stehen. 10ms sind nur bei 5V genug (Werte
des 90S2313).

// erst Low Byte schreiben
ISPInOut(64);
ISPInOut(0);
^
Da gehört das High-Byte der Adresse hin, sonst kannst du nur 256 Words
programmieren.

ISPInOut(i);
ISPInOut(hextoint(chartohex(AVRHex.GetMemory(l+1))));
^^^^^^^^^
Wenn das Ergebnis dieser Funktion nicht char ist, was dann?

// dann HighByte schreiben
ISPInOut(72);
ISPInOut(0);
^
siehe oben

ISPInOut(hextoint(chartohex(AVRHex.GetMemory(l))));
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Hast du dir die Ergebnisse dieser Konversionen mal ausgeben lassen und
überprüft?


ISPInOut(k);
ISPInOut(j);
Verstehe ich nicht. Was haben die Variablen damit zu tun? Vor allem,
weil j (Low-Byte) ja von 1 bis 16 läuft (sollte es nicht 0-255 sein?).

// Schreibe Memory Page
Page? Was meinst du damit? Normalerweise kann man die Words nur einzeln
schreiben (also 2 Byte, dann warten).

ISPInOut(76);
Was ist das für ein Befehl?

for i:=1 to 4 do // Synchronisieren
Wo synchronisierst du da was? Du sendest einfach 4x das gleiche:

begin
ISPInOut(172);
ISPInOut(83);
ISPInOut(0);
ISPInOut(0);
end;
Im Datenblatt des 2313 steht das hier:
| The serial programming instructions will not work if the communication
| is out of synchronization. When in sync, the second byte ($53) will
| echo back when issu-ing the third byte of the Programming Enable
| instruction. Whether the echo is correct or not, all four bytes of the
| instruction must be transmitted. If the $53 did not echo back, give SCK
| a positive pulse and issue a new Programming Enable instruction. If the
| $53 is not seen within 32 attempts, there is no functional device
| connected.

Wo prüfst du das Echo 53? Und wo gibst du den Puls auf SCK, wenn es
nicht kommt?

Oder kannst du mir nochmal deine Funktion für das Flashen schicken?
Falls du da durchblickst:

'Datei öffnen, Endlosschleife bis Dateiende erreicht:
Open FileName For Input As 1
Do Until EOF(1)
Line Input #1, Record
If Left(Record, 1) = ":" And Len(Record) > 10 Then
'Hexfile-Zeilen-Header von Hex nach Dezimal konvertieren
Length = CLng("&H" & Mid(Record, 2, 2))
Offset = CLng("&H" & Mid(Record, 4, 4))
RecType = CLng("&H" & Mid(Record, 8, 2))
If RecType = 0 Then
'Daten im Hexfile an den Controller senden (eine Hexfile-Zeile)
For A = 0 To Length - 1
Form1.lblStatus = "Programming [" & Right("0000" & Hex((Offset + A) \ 2), 4) & "]"
DoEvents
Data = CLng("&H" & Mid(Record, 10 + 2 * A, 2)) 'Wert des Bytes
Addr = (Offset + A) \ 2 'Adresse im Controller
High = (Offset + A) And 1 'High-Byte oder Low-Byte?
If Data <> &HFF Then '0xFF braucht nicht programmiert zu werden
WriteFlash Data, Addr, High
'wenn das Byte 7F ist, warten, sonst pollen bis der richtige Wert gelesen wird
If InStr("7F", Hex(Data)) Then
DELAY 5
Else
Start = Timer
Failed = False
Do While ReadFlash(Addr, High) <> Data
If Timer - Start > 0.5 Then
'Timeout nach 0.5s erfolglosem warten
Failed = True
Exit Do
End If
Loop
If Failed Then Exit Do
End If
End If
Next
ElseIf RecType = 1 Then
'Dateiende-Makierung im Hexfile
Exit Do
End If
End If
Loop
Close

Function ReadFlash(ByVal Addr As Integer, ByVal High As Boolean) As Byte
X = Send(&H20 - 8 * High) '0x20 für Low-Byte (High=0), 0x28 für High-Byte (High=-1)
X = Send(Addr \ 256) 'High- & Low-Bytes der Adresse
X = Send(Addr Mod 256)
ReadFlash = Send(&H0) 'Byte aus dem Flash lesen und zurückgeben
End Function

Sub WriteFlash(ByVal Data As Byte, ByVal Addr As Integer, ByVal High As Boolean)
X = Send(&H40 - 8 * High)
X = Send(Addr \ 256)
X = Send(Addr Mod 256)
X = Send(Data)
End Sub


Gruß,
Arne
 
"Arne Rossius" <ArneRossius@despammed.com> wrote i

Moin !

Dort habe ich 25ms Wartezeit stehen. 10ms sind nur bei 5V genug (Werte
des 90S2313).
Ok, das kann ich ändern. Das Löschen funzt aber. Das kann ich ja auslesen.

So und nun eben zu der generellen Programierung des Tiny26 (den wir ja
nutzen).
Im Datenblatt steht das:
Data Polling Flash
When a page is being programmed into the Flash, reading an address location
within
the page being programmed will give the value $FF. At the time the device is
ready for a
new page, the programmed value will read correctly. This is used to
determine when the
next page can be written. Note that the entire page is written
simultaneously and any
address within the page can be used for polling. Data polling of the Flash
will not work
for the value $FF, so when programming this value, the user will have to
wait for at least
tWD_FLASH before programming the next page. As a chip-erased device contains
$FF in
all locations, programming of addresses that are meant to contain $FF, can
be skipped.
See Table 59 for tWD_FLASH value.

Daraus lese ich, das ich mittels
Load Program Memory Page 0100 H000 xxxx xxxx xxxx bbbb iiii iiii
erstmal 16 Words in den Controller laden muss. Das High und Low Byte wird
dabei durch H unterschieden. Wenn ich dann die 16 Words oder 32 Bytes im
Controller habe, dann kann ich das wegschreiben.
So, die Page in den Controller bringen macht dieser Teil:

for i := 0 to 15 do // Puffer füllen
begin
// erst Low Byte schreiben
ISPInOut(64);
ISPInOut(0);
ISPInOut(i);
ISPInOut(hextoint(chartohex(AVRHex.GetMemory(l+1))));
delay(5);
// dann HighByte schreiben
ISPInOut(72);
ISPInOut(0);
ISPInOut(i);
ISPInOut(hextoint(chartohex(AVRHex.GetMemory(l))));
delay(5);
inc(l);
inc(l);
end;

Dazu hast du geschrieben:
// erst Low Byte schreiben
ISPInOut(64);
ISPInOut(0);
^
Da gehört das High-Byte der Adresse hin, sonst kannst du nur 256 Words
programmieren.
Das verstehe ich nicht, denn das wäre ja gegen das Datenblatt (Load Program
Memory Page 0100 H000 xxxx xxxx xxxx bbbb iiii iiii)

ISPInOut(hextoint(chartohex(AVRHex.GetMemory(l+1))));
Die Funktion ist sauber. Das Ergebnis ist ein Integer was ich auch brauche.
Das habe ich geprüft.

So, wenn ich nun also eine Page im Speicher habe, dann kann ich die mittels:
Write Program Memory Page 0100 1100 xxxx xxaa bbbb xxxx xxxx xxxx
in den Controller schreiben lassen (bzw. der macht das dann selber).

Und dafür ist dann dieser Teil zuständig:
l := 0; // Positionszeiger für HexEdit
for k := 0 to 3 do // \
for j := 1 to 16 do // / 16Byte Blöcke wegschreiben
begin
for i := 0 to 15 do // Puffer füllen
begin
// Puffer füllen siehe oben !
end;
// Schreibe Memory Page
ISPInOut(76);
ISPInOut(k);
ISPInOut(j*16);
ISPInOut(0);
delay(10);
//Memo1.Lines.Add('Schreibe Memory Page');
end;

Die For Schleife mit k füllt diesen Bereich aus:
Write Program Memory Page 0100 1100 xxxx xxaa bbbb xxxx xxxx xxxx
^^
also die beiden a
Die for Schleife mit j füllt den Bereich mit b aus aber so: ISPInOut(j*16);

Page? Was meinst du damit? Normalerweise kann man die Words nur einzeln
schreiben (also 2 Byte, dann warten).
Nein, denn wenn ich das richtig lese, dann muss man beim Tiny26 Pages
schreiben (=32 Byte)

ISPInOut(76);
Was ist das für ein Befehl?
Write Program Memory Page 0100 1100 xxxx xxaa bbbb xxxx xxxx xxxx
0100 1100 = 76

Wo synchronisierst du da was? Du sendest einfach 4x das gleiche:
Schon klar. Aber ich weiss, das ich beim Tiny nach 2x senden die 53
empfange.
Somit gehe ich auf Seite Sicher und schicke das 4x. Dann muss ich nicht
extra auf 53h abfragen :)
Aber das funzt ja auch bei allen anderen Operationen.

Ich vermute das mir dann deine Funktionen nicht viel nützen, weil das
Programmieren anders geht als beim Tiny.

Hast du trotzdem noch eine Idee??

Greetz Dominik
 
Dominik Schmidt wrote:
Page? Was meinst du damit? Normalerweise kann man die Words nur einzeln
schreiben (also 2 Byte, dann warten).
Nein, denn wenn ich das richtig lese, dann muss man beim Tiny26 Pages
schreiben (=32 Byte)
Da musste ich mir jetzt erst mal das Datenblatt vom Tiny26 besorgen, du
hast recht, da ist alles ganz anders. Ich muss jetzt erst mal verstehen,
wie die das im Datenblatt genau meinen, scheint etwas komlizierter zu
sein als das Wordweise programmieren.

Write Program Memory Page
^^^^
Deshalb stand der nicht im Datenblatt vom 2313 drin.
Übrigens gibt es im Datenblatt vom Tiny26 noch einen "Read Program
Memory" Befehl (ohne Page), nicht aber für Write.

Schon klar. Aber ich weiss, das ich beim Tiny nach 2x senden die 53
empfange.
Auch das ist beim Tiny26 anders als ich dachte, hier muss man einen Puls
auf Reset geben, nicht auf SCK, um zu synchronisieren.

Somit gehe ich auf Seite Sicher und schicke das 4x. Dann muss ich nicht
extra auf 53h abfragen :)
Solltest du trotzdem tun, sonst weißt du nie, ob dein Controller
überhaupt gemerkt hat, dass du ihn programmieren willst.

Ich vermute das mir dann deine Funktionen nicht viel nützen, weil das
Programmieren anders geht als beim Tiny.
Hast du trotzdem noch eine Idee??
Bau' dir den Sercon2 Mini doch einfach mal auf, ist ja nicht
kompliziert, und probiere, ob es mit meiner Software nicht doch
funktioniert. Vielleicht ist der Tiny26 ja abwärtskompatibel, so dass du
erst mal "normal" programmieren könntest und dir keine Gedanken über
Pages machen musst.


Gruß,
Arne
 
"Arne Rossius" <ArneRossius@despammed.com> wrote

Bau' dir den Sercon2 Mini doch einfach mal auf, ist ja nicht
kompliziert, und probiere, ob es mit meiner Software nicht doch
funktioniert. Vielleicht ist der Tiny26 ja abwärtskompatibel, so dass du
erst mal "normal" programmieren könntest und dir keine Gedanken über
Pages machen musst.
Das nützt nix. Der kann nur über die Pages programmiert werden.
Sonst hätte ich es schon lange am drehen.

btw. Kann ich mal deine Mailadresse bekommen, dann kann man sich
doch etwas schneller austauschen. Zumal es ja um Programmierung geht ...

Kanst mir ja einfach eben ne Mail an schmidom<at>web.de schiggn.

Greetz Dominik
 
Moin !

Es ist gelöst und funzt nun. Ich hatte zwei kleine Fehler in der Routine ...

Trotzdem Danke für deine Hilfe!

Grüße Dominik
 
Dominik Schmidt wrote:
"Arne Rossius" <ArneRossius@despammed.com> wrote:

Daraus lese ich, das ich mittels
Load Program Memory Page 0100 H000 xxxx xxxx xxxx bbbb iiii iiii
erstmal 16 Words in den Controller laden muss. Das High und Low Byte wird
dabei durch H unterschieden. Wenn ich dann die 16 Words oder 32 Bytes im
Controller habe, dann kann ich das wegschreiben.
So, die Page in den Controller bringen macht dieser Teil:

for i := 0 to 15 do // Puffer füllen
begin
// erst Low Byte schreiben
ISPInOut(64);
ISPInOut(0);
ISPInOut(i);
ISPInOut(hextoint(chartohex(AVRHex.GetMemory(l+1))));
delay(5);
// dann HighByte schreiben
ISPInOut(72);
ISPInOut(0);
ISPInOut(i);
ISPInOut(hextoint(chartohex(AVRHex.GetMemory(l))));
delay(5);
inc(l);
inc(l);
end;
Das sieht gut aus. Im Zweifel wuerde ich aber noch High-Byte first
probieren. Ich bin da mit dem mega161 schon mal auf der Schnauze
geflogen weil der es andersherum haben wollte als der mega103.

ISPInOut(hextoint(chartohex(AVRHex.GetMemory(l+1))));

Die Funktion ist sauber. Das Ergebnis ist ein Integer was ich auch brauche.
Das habe ich geprüft.
Wobei mich wundert, dass du "GetMemory(l+1)" machst um das Low-Byte zu
lesen. Auf einer Little Endian (Intel) Maschine haette ich dort das
High-Byte erwartet.

So, wenn ich nun also eine Page im Speicher habe, dann kann ich die mittels:
Write Program Memory Page 0100 1100 xxxx xxaa bbbb xxxx xxxx xxxx
in den Controller schreiben lassen (bzw. der macht das dann selber).

Und dafür ist dann dieser Teil zuständig:
l := 0; // Positionszeiger für HexEdit
for k := 0 to 3 do // \
for j := 1 to 16 do // / 16Byte Blöcke wegschreiben
begin
for i := 0 to 15 do // Puffer füllen
begin
// Puffer füllen siehe oben !
end;
// Schreibe Memory Page
ISPInOut(76);
ISPInOut(k);
ISPInOut(j*16);
ISPInOut(0);
delay(10);
//Memo1.Lines.Add('Schreibe Memory Page');
end;

Die For Schleife mit k füllt diesen Bereich aus:
Write Program Memory Page 0100 1100 xxxx xxaa bbbb xxxx xxxx xxxx
^^
also die beiden a
Die for Schleife mit j füllt den Bereich mit b aus aber so: ISPInOut(j*16);
Es geht also mit aabbbb=000001 los - und hier sehe ich ein Problem: Da
die j-Schleife bei 1 loslaeuft wird mit Page 1 statt mit Page 0
begonnen. Bei j=16 gibt es einen Integer-Overflow weil 16*16 nicht mehr
in ein Byte passt ... das MSB geht also verloren und es bleibt 0 uebrig
=> Jetzt wird Page 0 geschrieben. IMHO werden die Pages also in der
Reihenfolge 1..15,0,17..31,16,33,etc. geschrieben, was wohl nicht
erwuenscht ist.


Micha
--
Wenn man schon Gefangener seines eigenen Geistes ist, kann man sich
wenigstens seine Zelle vernuenftig moeblieren.

Sir Peter Ustinov
 

Welcome to EDABoard.com

Sponsor

Back
Top