コード例 #1
0
        static void Run(string[] args)
        {
            bool esp32mode = false;

            if (esp32mode)
            {
                Console.WriteLine("ESP32 image tool v1.1 [http://sysprogs.com/]");
            }
            else
            {
                Console.WriteLine("ESP8266 image tool v1.1 [http://sysprogs.com/]");
            }

            if (args.Length < 1)
            {
                PrintUsage();
                return;
            }

            string        port = null;
            string        bootloader = null;
            int           otaPort = 0;
            int           baud = 115200;
            bool          erase = false;
            List <string> files = new List <string>();
            string        frequency = null, mode = null, size = null;

            for (int i = 0; i < args.Length; i++)
            {
                if (args[i] == "--esp32")
                {
                    esp32mode = true;
                }
                else if (args[i] == "--boot")
                {
                    if (i >= (args.Length - 1))
                    {
                        throw new Exception("--boot must be followed by the bootloader image");
                    }
                    bootloader = args[++i];
                }
                else if (args[i] == "--program")
                {
                    if (i >= (args.Length - 1))
                    {
                        throw new Exception("--program must be followed by port number");
                    }
                    port = args[++i];
                    if ((i + 1) < args.Length && !args[i + 1].StartsWith("-"))
                    {
                        baud = int.Parse(args[++i]);
                    }
                }
                else if (args[i] == "--mode")
                {
                    if (i >= (args.Length - 1))
                    {
                        throw new Exception("--mode must be followed by FLASH mode");
                    }
                    mode = args[++i];
                }
                else if (args[i] == "--size")
                {
                    if (i >= (args.Length - 1))
                    {
                        throw new Exception("--size must be followed by FLASH mode");
                    }
                    size = args[++i];
                }
                else if (args[i] == "--freq")
                {
                    if (i >= (args.Length - 1))
                    {
                        throw new Exception("--freq must be followed by FLASH mode");
                    }
                    frequency = args[++i];
                }
                else if (args[i].ToLower() == "--ota")
                {
                    if (i >= (args.Length - 1))
                    {
                        throw new Exception("--OTA must be followed by port number");
                    }
                    otaPort = int.Parse(args[++i]);
                }
                else if (args[i] == "--erase")
                {
                    erase = true;
                }
                else
                {
                    files.Add(args[i]);
                }
            }

            ESP8266BinaryImage.IESPxxImageHeader hdr;
            if (esp32mode)
            {
                var hdr2 = new ESP8266BinaryImage.ESP32ImageHeader(frequency, mode, size);
                Console.WriteLine("FLASH Parameters:");
                Console.WriteLine("\tFrequency: " + DumpEnumValue(hdr2.Frequency));
                Console.WriteLine("\tMode: " + DumpEnumValue(hdr2.Mode));
                Console.WriteLine("\tSize: " + DumpEnumValue(hdr2.Size));
                hdr = hdr2;
            }
            else
            {
                var hdr2 = new ESP8266BinaryImage.ESP8266ImageHeader(frequency, mode, size);
                Console.WriteLine("FLASH Parameters:");
                Console.WriteLine("\tFrequency: " + DumpEnumValue(hdr2.Frequency));
                Console.WriteLine("\tMode: " + DumpEnumValue(hdr2.Mode));
                Console.WriteLine("\tSize: " + DumpEnumValue(hdr2.Size));
                hdr = hdr2;
            }

            if (otaPort != 0)
            {
                OTAServer.ServeOTAFiles(otaPort, (ESP8266BinaryImage.ESP8266ImageHeader)hdr, files.ToArray());
                return;
            }

            foreach (var elf in files)
            {
                string pathBase = Path.ChangeExtension(elf, ".").TrimEnd('.');
                List <ProgrammableRegion> regions = new List <ProgrammableRegion>();

                Console.WriteLine("Processing " + elf + "...");

                using (var elfFile = new ELFFile(elf))
                {
                    string status;
                    if (esp32mode)
                    {
                        var img = ESP8266BinaryImage.MakeESP32ImageFromELFFile(elfFile, (ESP8266BinaryImage.ESP32ImageHeader)hdr);

                        string fn = pathBase + "-esp32.bin";
                        using (var fs = new FileStream(fn, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite))
                        {
                            img.Save(fs);
                            regions.Add(new ProgrammableRegion {
                                FileName = fn, Offset = 0x10000, Size = (int)fs.Length
                            });
                        }
                    }
                    else
                    {
                        int appMode = ESP8266BinaryImage.DetectAppMode(elfFile, out status);
                        Console.WriteLine(status);

                        if (appMode == 0)
                        {
                            var img = ESP8266BinaryImage.MakeNonBootloaderImageFromELFFile(elfFile, (ESP8266BinaryImage.ESP8266ImageHeader)hdr);

                            string fn = pathBase + "-0x00000.bin";
                            using (var fs = new FileStream(fn, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite))
                            {
                                img.Save(fs);
                                regions.Add(new ProgrammableRegion {
                                    FileName = fn, Offset = 0, Size = (int)fs.Length
                                });
                            }

                            foreach (var sec in ESP8266BinaryImage.GetFLASHSections(elfFile))
                            {
                                fn = string.Format("{0}-0x{1:x5}.bin", pathBase, sec.OffsetInFLASH);
                                using (var fs = new FileStream(fn, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite))
                                {
                                    fs.Write(sec.Data, 0, sec.Data.Length);
                                    regions.Add(new ProgrammableRegion {
                                        FileName = fn, Offset = (int)sec.OffsetInFLASH, Size = sec.Data.Length
                                    });
                                }
                            }
                        }
                        else
                        {
                            string fn;
                            var    hdr2 = (ESP8266BinaryImage.ESP8266ImageHeader)hdr;
                            var    img  = ESP8266BinaryImage.MakeBootloaderBasedImageFromELFFile(elfFile, hdr2, appMode);

                            if (bootloader == null)
                            {
                                Console.WriteLine("Warning: no bootloader specified. Skipping bootloader...");
                            }
                            else
                            {
                                if (!File.Exists(bootloader))
                                {
                                    throw new Exception(bootloader + " not found. Cannot program OTA images.");
                                }

                                byte[] data = File.ReadAllBytes(bootloader);
                                data[2] = (byte)hdr2.Mode;
                                data[3] = (byte)(((byte)hdr2.Size << 4) | (byte)hdr2.Frequency);
                                fn      = string.Format("{0}-boot.bin", pathBase);
                                File.WriteAllBytes(fn, data);

                                regions.Add(new ProgrammableRegion {
                                    FileName = fn, Offset = 0, Size = File.ReadAllBytes(fn).Length
                                });
                            }

                            fn = string.Format("{0}-user{1}.bin", pathBase, appMode);
                            using (var fs = new FileStream(fn, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite))
                            {
                                img.Save(fs);
                                regions.Add(new ProgrammableRegion {
                                    FileName = fn, Offset = (int)img.BootloaderImageOffset, Size = (int)fs.Length
                                });
                            }
                        }
                    }
                }

                if (port != null)
                {
                    using (var serialPort = new SerialPortStream(port, baud, System.IO.Ports.Handshake.None)
                    {
                        AllowTimingOutWithZeroBytes = true
                    })
                    {
                        ESP8266BootloaderClient client = new ESP8266BootloaderClient(serialPort, 50, null);
                        Console.WriteLine("Connecting to bootloader on {0}...", port);
                        client.Sync();
                        if (erase)
                        {
                            Console.WriteLine("Erasing FLASH...");
                            client.EraseFLASH();
                            Console.WriteLine("FLASH erased. Please restart your ESP8266 into the bootloader mode again.\r\nPress any key when done...");
                            Console.ReadKey();
                            client.Sync();
                        }
                        foreach (var region in regions)
                        {
                            DateTime start = DateTime.Now;
                            Console.WriteLine("Programming " + Path.GetFileName(region.FileName) + "...");
                            var tracker = new ProgressTracker(region);
                            client.BlockWritten += tracker.BlockWritten;
                            client.ProgramFLASH((uint)region.Offset, File.ReadAllBytes(region.FileName));
                            client.BlockWritten -= tracker.BlockWritten;
                            Console.WriteLine("\rProgrammed in {0} seconds        ", (int)(DateTime.Now - start).TotalSeconds);
                        }
                    }
                }
                else
                {
                    int fileNameLen = Path.GetFileName(args[0]).Length + 10;
                    Console.WriteLine("\r\nCreated the following files:");

                    Console.WriteLine("File".PadRight(fileNameLen) + " FLASH Offset  Size");
                    foreach (var region in regions)
                    {
                        Console.WriteLine(Path.GetFileName(region.FileName).PadRight(fileNameLen) + " " + string.Format("0x{0:x8}    {1}KB", region.Offset, region.Size / 1024));
                    }
                }
            }
        }
コード例 #2
0
ファイル: OTAServer.cs プロジェクト: whinis/BSPTools
        public static void ServeOTAFiles(int port, ESP8266BinaryImage.ESP8266ImageHeader hdr, params string[] elfFiles)
        {
            TcpListener listener = new TcpListener(port);

            byte[]     buffer = new byte[1024];
            OTAImage[] images = new OTAImage[2];

            foreach (var fn in elfFiles)
            {
                if (fn != null)
                {
                    using (var elfFile = new ELFFile(fn))
                    {
                        string status;
                        int    appMode = ESP8266BinaryImage.DetectAppMode(elfFile, out status);
                        if (appMode == 0)
                        {
                            Console.WriteLine(fn + " is not an OTA ELF file. Skipping...");
                            continue;
                        }

                        var img = ESP8266BinaryImage.MakeBootloaderBasedImageFromELFFile(elfFile, hdr, appMode);
                        using (var ms = new MemoryStream())
                        {
                            img.Save(ms);
                            images[appMode - 1].Data = ms.ToArray();
                            images[appMode - 1].File = fn;
                        }
                    }
                }
            }


            Console.WriteLine($"Ready to serve the following files:");
            Console.WriteLine($"APP1: {images[0].File ?? "(none)"}");
            Console.WriteLine($"APP2: {images[1].File ?? "(none)"}");
            Console.WriteLine($"Waiting for connection on port {port}...");
            listener.Start();
            for (;;)
            {
                using (var sock = listener.AcceptSocket())
                {
                    Console.WriteLine($"Incoming connection from {(sock.RemoteEndPoint as IPEndPoint).Address}");

                    StringBuilder requestBuilder = new StringBuilder();
                    while (!requestBuilder.ToString().Contains("\r\n\r"))
                    {
                        int done = sock.Receive(buffer);
                        requestBuilder.Append(Encoding.UTF8.GetString(buffer, 0, done));
                    }

                    string   request = requestBuilder.ToString();
                    string[] parts   = request.Split(' ');
                    if (parts.Length < 3)
                    {
                        throw new Exception("Invalid HTTP request: " + request);
                    }

                    string url = parts[1];
                    Console.WriteLine("Received request for " + url);
                    int otaIndex = (url.ToLower().Contains("user2") ? 1 : 0);
                    if (images[otaIndex].Data == null)
                    {
                        throw new Exception($"No OTA image for app{otaIndex + 1} is provided. Please check your linker scripts.");
                    }

                    string reply = string.Format("HTTP/1.0 200 OK\r\nContent-Type: application/octet-stream\r\nContent-Length: {0}\r\n\r\n", images[otaIndex].Data.Length);
                    var    r     = Encoding.UTF8.GetBytes(reply);
                    sock.Send(r);

                    if (parts[0] == "GET")
                    {
                        Console.Write($"Serving {Path.GetFileName(images[otaIndex].File)}...\r\n");

                        using (var ms = new MemoryStream(images[otaIndex].Data))
                        {
                            int totalDone = 0;
                            for (;;)
                            {
                                int done = ms.Read(buffer, 0, buffer.Length);
                                if (done == 0)
                                {
                                    break;
                                }
                                sock.Send(buffer, done, SocketFlags.None);
                                totalDone += done;

                                int percent  = (int)((totalDone * 100) / ms.Length);
                                int progress = percent / 5;
                                Console.Write($"\r[{new string('#', progress).PadRight(20)}] {percent}%");
                            }
                        }
                        Console.WriteLine("\r\nFile sent successfully\n");
                        break;
                    }
                }
            }
            listener.Stop();
        }