Forum: Mikrocontroller und Digitale Elektronik RS232 Signal (Bootloader) PIC24H CCS Compiler


von Bubba L. (pic24h)


Lesenswert?

Guten Morgen liebes Forum,

ich bin noch ein Neuling auf diesem Gebiet, also bitte nicht übel 
nehmen.

Wir verwende einen PIC24HJ256GP610 und haben zur Zeit an der Uni das 
Projekt "Flashen eines Mikrocontrollers". Dazu sollen wir einen 
Bootloader verwenden. Dieser läuft soweit.

Meine Frage nun. Gibt es eine Funktion (für den CCS Compiler), die 
erkennt ob eine Verbindungen (über eine serielle Schnittstelle RS232) zu 
einem PC/Laptop besteht? So dass der Bootloader nur dann startet wenn er 
die verbindung erkennt und ein neues Programm flasht. Ansonsten sollte 
das daraufliegend programm gestartet werden.

Vielen Dank im Voraus

von Björn P. (bjrn_g)


Lesenswert?

Hallo,

hast du den Bootloader selbst geschrieben?
Ist der Bootloader Bestandteil des eigentlichen Programms (wie im CCS 
Wizard üblich) oder ein eigenständiges Programm am Anfang oder Ende des 
Programmspeichers?

Ich verwende für meine PIC18 (meist 18F4xk22) eine leicht angepasste 
Variante des TinyBootloaders. Welcher sich am Ende des Programmspeichers 
befindet und nur beim Starten/Resetten des Controllers ausgeführt wird.

Ergo: um den Bootloader auszuführen muss der PIC mit reset_cpu(); neu 
gestartet werden und wenn dann innerhalb eines Zeitfensters der passende 
Befehl ('K') vom Host kommt, wird die neue Hex-File übernommen.

------------------------------------------------------------------------ 
-------

Wie soll denn bei dir der Upload funktionieren?
Mittels Terminal? Oder hast du dafür ein Programm?

Wenn der Bootloader eine offene COM-Schnittstelle detektieren soll, 
müsste auf der anderen Seite (Host) eine Antwort generiert werden.

An welcher Stelle soll denn die COM-Schnittstelle abgefragt werden? 
Einmalig beim Start oder zyklisch?

von Bubba L. (pic24h)


Lesenswert?

Vielen Danke für die ausführliche Antwort Björn.

Als Grundlage haben wir den Beispielbootloader (Dateiname: 
ex_pcd_bootloader.c) von CCS verwendet. Diese Bindet 2 Header Files (die 
vom Chip und eine für die speicherverwaltung) und noch eine loader_pcd.c 
ein. Das Programm ist ein eigenständiges Programm und liegt laut 
linkerlist im Bereich 0x200 und  0x64A, also beginnt am Anfang.

Beim betätigten und halten eines Buttons während man den Mikrocontroller 
resetet, startet den Bootloader. Das aufspielen eins Programms läuft 
ohne Probleme. Nach dem erfolgreichen aufspielen reseted sich der 
Mikrocontroller wieder von selbst und startet das Programm.

Wir benutzen das Programm "SIOW - Serial Input/Output Monitor" 
(siow.exe) von CCS um Programme auf den PIC zu laden. Aber dieses planen 
wir am ende vom Projekt durch ein selbstgeschriebenes zu ersetzen.

D.h. unser Programm müsste eine Antwort senden, damit der PIC die COM 
Schnittstelle erkennt.

Die COM-Schnittstelle soll nur einmalig beim Start (für einige Sekunden 
lang) abgefragt werden. Wenn z.B. 5 Sekunden lang keine Nachricht kommt, 
dann soll der Bootloader beendet werden und das Programm gestartet 
werden.

Wir benutzen den CCS Compiler und der TinyBootloader wurde ja mit einem 
anderen Compiler geschrieben wenn ich mich nicht irre,oder?

von Björn P. (bjrn_g)


Lesenswert?

Der TinyBootloader wurde in ASM geschrieben und ist somit auch mit dem 
CCS-Compiler kompatibel.

Wenn weiterhin der CCS-Bootloader verwendet werden soll, musst du 
herausfinden, welche Kommunikation er mit SIOW für den Upload einer 
neuen Firmware erwartet.
Wie lange bleibt denn der Controller aktuell im Bootloader, wenn er 
nicht mit SIOW verbunden ist?

Im Grunde muss doch nur, wenn keine zusätzlichen Features gefordert 
sind, die Kommunikation von SIOW kopiert werden.

[EDIT]
Ich gehe mal davon aus, dass du die "loader_pcd.c" des CCS-Compilers 
verwendest.
Habe mir gerade mal den Code angeguckt und er scheint kein Befehl vor 
der Hex-File zu erwarten. Er liest einfach nur die Hex-File (muss im 
INTEL-Hex-Format sein) und prüft sie auf Checksumme etc.

Demnach sollte es ja möglich sein jedes x-beliebige Terminalprogramm 
anstelle von SIOW zu verwenden. Probiere das mal aus, dann weißt, du, 
was dein selbst geschriebenes Programm mehr können muss oder nicht. ;)

von Bubba L. (pic24h)


Lesenswert?

Dann werd ich mir den TinyBootloader auch mal anschauen.

Cool, vielen Dank für deine Antwort. Werde es mir am Montag gleich mal 
anschauen, da ich den ccs compiler leider nur an der Uni benutzen kann. 
Ich werde dann am Montag Berichten was daraus geworden ist :)

Wünsch dir ein schönes Wochenende

von Bubba L. (pic24h)


Lesenswert?

Ich bekomme es irgendwie net hin...mach sowas zum ersten mal :(

Habe in C# ein Programm geschrieben. Aber es überträgt kein Hex File auf 
den Pic. Bootloader startet und wartet auf eine hex Datei.

Naja hier mal mein code zur Dateiübertragung. Hab mir mehrere Programme 
angeschaut und versucht es zum laufen zu bringen, aber ohne erfolg. Die 
meisten erklärungen, waren nur zur Übertragung von einer Hex Linie.
1
private void btn_hexFileSearch_Click(object sender, EventArgs e)
2
        {
3
            OpenFileDialog hexFileSearch = new OpenFileDialog();
4
            hexFileSearch.Filter = "Hex Files (*.hex)|*.hex|All files (*.*)|*.*";
5
6
            if (hexFileSearch.ShowDialog() == DialogResult.OK)
7
            {
8
                path = hexFileSearch.FileName;
9
                txtBox_hexFile.Text = hexFileSearch.FileName;
10
            }
11
        }
12
13
        private void btn_download_Click(object sender, EventArgs e)
14
        {
15
            if (File.Exists(path))
16
            {
17
                byte[] array = ReadConvertHexFile(path);
18
                if (array.Length > 0)
19
                {
20
                    DialogResult result = MessageBox.Show("Flashvorgang starten ? ", "Flasch", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
21
                    if (result == System.Windows.Forms.DialogResult.Yes)
22
                    {
23
                        txtBox_SeriellOut.AppendText("Sende Daten bitte warten..." + "\r\n");
24
                        for (int i = 0; i < array.Length; i++)
25
                        {
26
                            try
27
                            {
28
                                if (serialPort1.IsOpen)
29
                                {
30
                                    if (array[i] == ':') txtBox_SeriellOut.AppendText("#");
31
                                    serialPort1.Write(array, i, 1);
32
                                }
33
                                else
34
35
                                    MessageBox.Show("Schnittstelle ist nicht verbunden");
36
                            }
37
                            catch (Exception ex)
38
                            {
39
                                MessageBox.Show(ex.Message.ToString(), "Fehler in serieller Schnittstelle");
40
                            }
41
                        }
42
                        txtBox_SeriellOut.AppendText("\r\n" + "Daten gesendet, bitte warten" + "\r\n");
43
                    }
44
                }
45
            }
46
            else
47
                MessageBox.Show("Datei existiert nicht ! Abbruch des Flash Vorganges");
48
        }
49
50
        private byte[] ReadConvertHexFile(string path) //static
51
        {
52
            string complete = string.Empty;
53
            string hilfsstring = string.Empty;
54
            int i = 0;
55
            int bytes = 0;
56
            using (StreamReader sr = new StreamReader(path, Encoding.Default))
57
            {
58
                while (sr.Peek() != -1)
59
                {
60
                    hilfsstring = sr.ReadLine();
61
                    complete += hilfsstring;
62
                    i++;
63
                    txtBox_SeriellOut.AppendText(i.ToString() + ". Zeile gelesen :  " + hilfsstring + "\r\n");
64
                    // auswertung  hexfile größe 
65
                    bytes += Int32.Parse(hilfsstring.Substring(1, 2), System.Globalization.NumberStyles.HexNumber);
66
                }
67
            }
68
            txtBox_SeriellOut.AppendText("Anzahl Bytes :  " + bytes.ToString() + "\r\n");
69
            if (bytes > 6144)
70
            {
71
                DialogResult result = MessageBox.Show("Warnung : Flashdatei ist größer als 6144 bytes !\r\n Flash abbrechen ?", "Warung", MessageBoxButtons.YesNo);
72
                if (result == System.Windows.Forms.DialogResult.Yes)
73
                    complete = string.Empty;
74
                // abbruch oder weiter 
75
            }
76
            return Encoding.ASCII.GetBytes(complete);
77
        }

von Björn P. (bjrn_g)


Lesenswert?

Hallo, sorry ich lag die letzten Tage flach^^

Hast du mal versucht, ob ein stinknormales Terminalprogramm (Terminal, 
HTerm etc.) mit dem Bootloader kompatibel ist?
SOllte es ja eigentlich, weil der CCS-Bootloader kein Feedback auf ein 
Startzeichen sendet.

Habe mich jetzt nochmal etwas genauer mit dem CCS-Bootloader 
beschäftigt.

1. zu deinem Programm:
Ich vermisse irgendwie das Öffnen des COM-Ports und die 
Port-Einstellungen:
1
                        if (serialPort1 == null)
2
                        {
3
                            serialPort1 = new SerialPort("COM7", 57600, Parity.None, 8);
4
                            serialPort1.Handshake = Handshake.XOnXOff;
5
                        }
6
                        while ((!serialPort1.IsOpen) && (tries < 10))
7
                        {
8
                            serialPort1.Open();
9
                            tries++;
10
                        }
11
                        if (tries == 10)
12
                        {
13
                            MessageBox.Show("Schnittstelle ist nicht vorhanden");
14
                            return;
15
                        }

2. Der PCD-Bootloader verwendet Software-Handshake XonXoff!
Dies sendet er entweder nach dem Einlesen einer Zeile (du kannst also 
mit \r arbeiten) oder wenn der interne Buffer voll ist (was vermieden 
werden sollte).

Das heißt:
 - eine Zeile aus der Hex-File lesen
 - prüfen, ob Device zuletzt ein Xon gesendet hatte
 - wenn nein: auf Xon warten (mit Timeout)
 - eine Zeile via WriteLine rausschicken
 - Xoff müsste von Device gesendet werden (andernfalls ein Error)
 - beginne von vorn


ferdisch...

von Björn P. (bjrn_g)


Lesenswert?

Anmerkung:

Der PCD-Bootloader sendet sogar noch ein ACK nach jeder Zeile (siehe 
loader_pcd.c Zeile 206), wenn diese korrekt war (Format und Checksumme).

Ergo muss die Kommunikation wie folgt aussehen:

solange nicht EOF
- Lese Zeile aus Hex-File
- Schreibe Zeile auf SerialPort
- Prüfe auf Xoff (0x13) --> Exception wenn unerwartetes Zeichen oder 
Timeout
- warte auf ACK  (0x06) --> Exception wenn unerwartetes Zeichen oder 
Timeout
- Prüfe auf Xon (0x11) --> Exception wenn unerwartetes Zeichen oder 
Timeout

Btw:
Ja, das Öffnen des Comports war oben etwas dirty... am Besten in ein 
try-catch verpacken

von Bubba L. (pic24h)


Lesenswert?

Danke für die Antwort und ich hoffe dir geht es wieder besser.

> Hast du mal versucht, ob ein stinknormales Terminalprogramm (Terminal,
> HTerm etc.) mit dem Bootloader kompatibel ist?
> SOllte es ja eigentlich, weil der CCS-Bootloader kein Feedback auf ein
> Startzeichen sendet.

Also ich habe es mit HTerm 0.8.1 versucht, aber leider erfolglos.

- Habe den richtigen Port ausgewählt, Baud eingestellt und die ganzen
  Data- Stop- Bits etc.

-Connected und es zeigte mir den Bootloadertext an, dass es auf einen 
Download wartet

- dann auf input control und send file angeklickt und die hex datei 
ausgewählt

- Hex Datei wurde übertragen, aber das Programm startete nicht. 
Bootloader lies sich aber noch starten

Habe es dann mit der siow.exe probiert und da klappt es ohne probleme. 
Programm lies sich starten und der Bootloader auch noch aufrufen. Andere 
Programme konnte ich auch wieder aufspielen ohne Probleme.

Vielleicht scheint, dass Programm von CCS noch etwas zu machen?


> Habe mich jetzt nochmal etwas genauer mit dem CCS-Bootloader
> beschäftigt.
>
> 1. zu deinem Programm:
> Ich vermisse irgendwie das Öffnen des COM-Ports und die
> Port-Einstellungen:
>                         if (serialPort1 == null)
>                         {
>                             serialPort1 = new SerialPort("COM7", 57600,
> Parity.None, 8);
>                             serialPort1.Handshake = Handshake.XOnXOff;
>                         }
>                         while ((!serialPort1.IsOpen) && (tries < 10))
>                         {
>                             serialPort1.Open();
>                             tries++;
>                         }
>                         if (tries == 10)
>                         {
>                             MessageBox.Show("Schnittstelle ist nicht
> vorhanden");
>                             return;
>                         }

Ich habe einen Button erstellt gehabt, der zu Beginn gleich eine 
Verbindung mit dem Port herstellt, die ich hier nicht geposted hatte. 
Die Verbindung mit dem Port funktionierte. Habe auch per Echo die 
gesendeten Strings wieder zurück erhalten.



> 2. Der PCD-Bootloader verwendet Software-Handshake XonXoff!
> Dies sendet er entweder nach dem Einlesen einer Zeile (du kannst also
> mit \r arbeiten) oder wenn der interne Buffer voll ist (was vermieden
> werden sollte).


>Ergo muss die Kommunikation wie folgt aussehen:
>
>solange nicht EOF
>- Lese Zeile aus Hex-File
>- Schreibe Zeile auf SerialPort
>- Prüfe auf Xoff (0x13) --> Exception wenn unerwartetes Zeichen oder
>Timeout
>- warte auf ACK  (0x06) --> Exception wenn unerwartetes Zeichen oder
>Timeout
>- Prüfe auf Xon (0x11) --> Exception wenn unerwartetes Zeichen oder
>Timeout

Ich probiere es gleich nochmal aus :)

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.