Пример #1
0
        private async void ReadTcrtBtn_Click(object sender, EventArgs e)
        {
            if (_tapecartInfo == null)
            {
                return;
            }

            if (_readActive)
            {
                _readActive = false;                 // stop
                return;
            }

            // 2 mbyte tcrt file
            byte[] tcrtImage = new byte[0x200000 + 216];

            // select tcrt file to write

            SaveFileDialog saveFileDialog = new SaveFileDialog();

            try {
                saveFileDialog.Filter = "TCRT files|*.tcrt";
                saveFileDialog.Title  = "Select a TCRT file";

                if (saveFileDialog.ShowDialog() != DialogResult.OK)
                {
                    return;
                }

                // test if we can write this file
                File.WriteAllBytes(saveFileDialog.FileName, tcrtImage);
                File.Delete(saveFileDialog.FileName);
            }
            catch (Exception)
            {
                _logging.Warn(MODUL_NAME, "ReadTcrtBtn_Click", $"Error opening tcrt file for write '{Path.GetFileName(saveFileDialog.FileName)}'");
                TcrtInfoTb.Text = $"Error opening TCRT file for write";
                return;
            }

            TcrtFilenameTb.Text = saveFileDialog.FileName;
            string logFilename = Path.GetFileName(saveFileDialog.FileName);

            _logging.Info(MODUL_NAME, "ReadTcrtBtn_Click", $"Read file, Filename='{logFilename}' {_arduinoComm.CurrentParameter}");

            // fill header with 0xFF
            ByteArray.Fill(tcrtImage, Tapecart.HEADER_SIZE, 0xFF, Tapecart.MAX_FLASH_SIZE);

            ByteArray.WriteASCIIString(tcrtImage, 0, Tapecart.TAPECART_SIGNATURE);
            ByteArray.WriteUInt16(tcrtImage, Tapecart.OFFSET_VERSION, Tapecart.VERSION);
            // we can not determine the real tcrt size, so we assume maximum flash size
            ByteArray.WriteInt32(tcrtImage, Tapecart.OFFSET_FLASHSIZE, Tapecart.MAX_FLASH_SIZE);

            // handle loader

            if (INCL_LOADER_IN_TCRT)
            {
                tcrtImage[Tapecart.OFFSET_FLAGS] = 0x01;

                byte[] loader = _arduinoComm.ReadLoader();
                if (loader == null || loader.Length != Tapecart.LOADER_LENGTH)
                {
                    _logging.Warn(MODUL_NAME, "ReadTcrtBtn_Click", $"Error reading loader");
                    TcrtInfoTb.Text = $"Error reading loader";
                    return;
                }
                Buffer.BlockCopy(loader, 0, tcrtImage, Tapecart.OFFSET_LOADER, Tapecart.LOADER_LENGTH);
            }
            else
            {
                tcrtImage[Tapecart.OFFSET_FLAGS] = 0x00;
                // filling with 0x00 is not really neccessary but makes the TCRT file equal if you compare it to existing files
                ByteArray.Fill(tcrtImage, Tapecart.OFFSET_LOADER, 0x00, Tapecart.LOADER_LENGTH);
            }

            // read loader info

            int    loaderOffset;
            int    loaderLength;
            int    loaderCallAddr;
            string filename;

            if (!_arduinoComm.ReadLoadInfo(out loaderOffset, out loaderLength, out loaderCallAddr, out filename))
            {
                _logging.Warn(MODUL_NAME, "ReadTcrtBtn_Click", $"Error reading loader info");
                TcrtInfoTb.Text = $"Error reading loader info";
                return;
            }
            ByteArray.WriteUInt16(tcrtImage, Tapecart.OFFSET_LOADER_OFFSET, (UInt16)loaderOffset);
            ByteArray.WriteUInt16(tcrtImage, Tapecart.OFFSET_LOADER_LENGTH, (UInt16)loaderLength);
            ByteArray.WriteUInt16(tcrtImage, Tapecart.OFFSET_LOADER_CALLADDR, (UInt16)loaderCallAddr);
            ByteArray.WriteASCIIString(tcrtImage, Tapecart.OFFSET_LOADER_NAME, filename, 0x20);

            int tcrtSize = Tapecart.MAX_FLASH_SIZE;

            TcrtInfoTb.Text = $"Loader info={loaderOffset:X4}h,{loaderLength:X4}h,{loaderCallAddr:X4}h,{filename.Trim()}";
            _logging.Info(MODUL_NAME, "ReadTcrtBtn_Click", $"Loader info={loaderOffset:X4}h,{loaderLength:X4}h,{loaderCallAddr:X4}h,{filename.Trim()}");


            // read flash data

            string btnText = ReadTcrtBtn.Text;

            ReadTcrtBtn.Text     = "Cancel read";
            WriteTcrtBtn.Enabled = false;

            ReadWritePb.Minimum = 0;
            ReadWritePb.Maximum = 100;
            ReadWritePb.Step    = 1;
            ReadWritePb.Value   = 0;

            _readActive        = true;
            _readWriteCanceled = false;
            SetButtonStatus();

            await Task.Run(() =>
            {
                int flashOffset = 0;
                Crc32 calcCrc   = new Crc32();
                Stopwatch sw    = new Stopwatch();
                sw.Start();
                while (flashOffset < tcrtSize)
                {
                    if (!_readActive)
                    {                              // cancel
                        _readWriteCanceled = true; // <- must be set before invoke !!!
                        UpdateReadWriteStatus("Read canceled", Color.Red);
                        _logging.Info(MODUL_NAME, "ReadTcrtBtn_Click", $"Read canceled at {flashOffset:X6}");
                        UpdateReadWriteBar(0);
                        return;
                    }

                    byte[] page = _arduinoComm.ReadFlashPage(flashOffset);
                    if (page == null)
                    {
                        UpdateReadWriteStatus($"Error at offset={flashOffset:X6}", Color.Red);
                        _readWriteCanceled = true;
                        return;
                    }

                    calcCrc.Update(page, 0, Tapecart.BLOCK_SIZE);

                    Buffer.BlockCopy(page, 0, tcrtImage, flashOffset + Tapecart.HEADER_SIZE, Tapecart.BLOCK_SIZE);

                    flashOffset += Tapecart.BLOCK_SIZE;

                    if (flashOffset % 0x1000 == 0)
                    {
                        if (flashOffset == 0x1000)
                        {
                            Helper.ControlInvokeRequired(BrowserInfoTb, () =>
                            {
                                BrowserInfoTb.Text = TapecartBrowser.GetInfo(tcrtImage, Tapecart.HEADER_SIZE);
                            });
                        }
                        UpdateReadWriteStatus($"Reading: Offset={flashOffset:X6}h Time={Minutes(sw.ElapsedMilliseconds)}");
                        UpdateReadWriteBar(flashOffset * 100 / tcrtSize);
                    }
                }

                if (ChecksumCb.Checked)
                {
                    _logging.Info(MODUL_NAME, "ReadTcrtBtn_Click", "Checksum test...");
                    UpdateReadWriteStatus($"Checksum-Test...");
                    UInt32 crc;
                    Stopwatch sw2 = new Stopwatch();
                    sw2.Start();
                    _arduinoComm.Crc32Flash(0, (int)tcrtSize, out crc);
                    Debug.WriteLine($"crc-time={Minutes(sw2.ElapsedMilliseconds)}");
                    if (crc != calcCrc.Crc)
                    {
                        Debug.WriteLine($"checksum error calc={calcCrc.Crc:X8} flash={crc:X8}");
                        _logging.Warn(MODUL_NAME, "ReadTcrtBtn_Click", $"checksum error calc={calcCrc.Crc:X8} flash={crc:X8}");
                        UpdateReadWriteStatus($"Checksum error", Color.Red);
                        return;
                    }
                    else
                    {
                        _logging.Info(MODUL_NAME, "ReadTcrtBtn_Click", $"checksum ok {crc:X8}");
                    }
                }

                _logging.Info(MODUL_NAME, "ReadTcrtBtn_Click", $"Read finished: Offset={flashOffset:X6}h Time={Minutes(sw.ElapsedMilliseconds)}");
                UpdateReadWriteStatus($"Read finished: Offset={flashOffset:X6}h Time={Minutes(sw.ElapsedMilliseconds)}", Color.Green);
                UpdateReadWriteBar(100);
            });

            if (!_readWriteCanceled)
            {
                // write tcrt file, should write without error because we tested it before
                try {
                    File.WriteAllBytes(saveFileDialog.FileName, tcrtImage);
                }
                catch (Exception ex) {
                    _logging.Warn(MODUL_NAME, "ReadTcrtBtn_Click", $"Error writing tcrt file '{logFilename}'");
                    TcrtInfoTb.Text = $"Error writing TCRT file";
                }
            }

            _readActive        = false;
            _readWriteCanceled = true;
            ReadTcrtBtn.Text   = btnText;
            SetButtonStatus();
        }
Пример #2
0
        private async void WriteTcrtBtn_Click(object sender, EventArgs e)
        {
            if (_tapecartInfo == null)
            {
                return;
            }

            if (_writeActive)
            {
                _writeActive = false;                 // stop
                return;
            }

            // load tcrt file

            OpenFileDialog openFileDialog = new OpenFileDialog();

            byte[] tcrtImage;
            try {
                openFileDialog.Filter = "TCRT files|*.tcrt";
                openFileDialog.Title  = "Select a TCRT file";

                if (openFileDialog.ShowDialog() != DialogResult.OK)
                {
                    return;
                }

                tcrtImage = File.ReadAllBytes(openFileDialog.FileName);
            }
            catch (Exception ex)
            {
                _logging.Warn(MODUL_NAME, "WriteTcrtBtn_Click", $"Error reading '{Path.GetFileName(openFileDialog.FileName)}'");
                return;
            }

            TcrtFilenameTb.Text = openFileDialog.FileName;
            string logFilename = Path.GetFileName(openFileDialog.FileName);

            _logging.Info(MODUL_NAME, "WriteTcrtBtn_Click", $"Write file: Filename='{logFilename}' {_arduinoComm.CurrentParameter}");

            // check tcrt header

            if (ByteArray.ReadAsciiString(tcrtImage, 0x00, 16) != Tapecart.TAPECART_SIGNATURE)
            {
                _logging.Warn(MODUL_NAME, "WriteTcrtBtn_Click", $"Invalid TCRT signature, tcrt file='{logFilename}'");
                TcrtInfoTb.Text = "Invalid TCRT header";
                return;
            }

            int tcrtVersion = BitConverter.ToUInt16(tcrtImage, Tapecart.OFFSET_VERSION);

            if (tcrtVersion != 1)
            {
                _logging.Warn(MODUL_NAME, "WriteTcrtBtn_Click", $"Invalid TCRT version, tcrt file='{logFilename}'");
                TcrtInfoTb.Text = $"Invalid TCRT version {tcrtVersion}";
                return;
            }

            int tcrtSize = (int)BitConverter.ToUInt32(tcrtImage, Tapecart.OFFSET_FLASHSIZE);

            if (tcrtSize > _tapecartInfo.TotalSize || tcrtSize < 0x1000)
            {
                _logging.Warn(MODUL_NAME, "WriteTcrtBtn_Click", $"TCRT size exceeds cartridge size, tcrt file='{logFilename}'");
                TcrtInfoTb.Text = $"Invalid TCRT size {tcrtSize / 1024:X}h kB";
                return;
            }

            BrowserInfoTb.Text = TapecartBrowser.GetInfo(tcrtImage, Tapecart.HEADER_SIZE);

            // write loader

            byte[] loader;
            int    flags = tcrtImage[Tapecart.OFFSET_FLAGS];

            if ((flags & 0x01) == 0)
            {
                // loader not present, use standard loader
                _logging.Info(MODUL_NAME, "WriteTcrtBtn_Click", $"TCRT file has no loader, using standard loader");
                loader = Helper.GetEmbeddedRessource("TapecartFlasher.Resources.tapecart_loader.bin");
            }
            else
            {
                // use loader from tcrt image
                _logging.Info(MODUL_NAME, "WriteTcrtBtn_Click", $"Using TCRT file loader");
                loader = new byte[Tapecart.LOADER_LENGTH];
                Buffer.BlockCopy(tcrtImage, Tapecart.OFFSET_LOADER, loader, 0, Tapecart.LOADER_LENGTH);
            }

            byte[] installedLoader = _arduinoComm.ReadLoader();
            if (!ByteArray.CompareBytes(loader, 0, installedLoader, 0, Tapecart.LOADER_LENGTH))
            {
                // installed loader is different, write loader
                if (!_arduinoComm.WriteLoader(loader))
                {
                    _logging.Warn(MODUL_NAME, "WriteTcrtBtn_Click", $"Error writing loader, tcrt file='{logFilename}'");
                    TcrtInfoTb.Text = $"Error writing loader";
                    return;
                }
            }
            else
            {
                _logging.Info(MODUL_NAME, "WriteTcrtBtn_Click", $"Identical loader is already installed");
            }

            // write loadinfo

            int    loaderOffset   = BitConverter.ToUInt16(tcrtImage, Tapecart.OFFSET_LOADER_OFFSET);
            int    loaderLength   = BitConverter.ToUInt16(tcrtImage, Tapecart.OFFSET_LOADER_LENGTH);
            int    loaderCalladdr = BitConverter.ToUInt16(tcrtImage, Tapecart.OFFSET_LOADER_CALLADDR);
            string filename       = ByteArray.ReadAsciiString(tcrtImage, Tapecart.OFFSET_LOADER_NAME, Tapecart.LOADER_NAME_LENGTH);

            if (!_arduinoComm.WriteLoadInfo(loaderOffset, loaderLength, loaderCalladdr, filename))
            {
                _logging.Warn(MODUL_NAME, "WriteTcrtBtn_Click", $"Error writing loader info, tcrt file='{logFilename}'");
                TcrtInfoTb.Text = $"Error writing loader info";
                return;
            }

            TcrtInfoTb.Text = $"Size={tcrtSize:X6}h Loader info={loaderOffset:X4}h,{loaderLength:X4}h,{loaderCalladdr:X4}h,{filename.Trim()}";

            // write flash data

            string btnText = WriteTcrtBtn.Text;

            WriteTcrtBtn.Text   = "Cancel write";
            ReadTcrtBtn.Enabled = false;

            ReadWritePb.Minimum = 0;
            ReadWritePb.Maximum = 100;
            ReadWritePb.Step    = 1;
            ReadWritePb.Value   = 0;

            _writeActive       = true;
            _readWriteCanceled = false;
            SetButtonStatus();

            await Task.Run(() =>
            {
                int flashOffset = 0;
                Crc32 calcCrc   = new Crc32();
                Stopwatch sw    = new Stopwatch();
                sw.Start();
                while (flashOffset < tcrtSize)
                {
                    if (!_writeActive)
                    {                              // cancel
                        _readWriteCanceled = true; // <- must be set before invoke !!!
                        UpdateReadWriteStatus("Write canceled", Color.Red);
                        _logging.Warn(MODUL_NAME, "WriteTcrtBtn_Click", $"Write canceled at {flashOffset:X6}");
                        UpdateReadWriteBar(0);
                        return;
                    }

                    if (flashOffset % Tapecart.ERASE_SIZE == 0)
                    {
                        _arduinoComm.EraseFlashBlock(flashOffset);
                    }

                    if (!_arduinoComm.WriteFlashPage(tcrtImage, flashOffset + Tapecart.HEADER_SIZE, flashOffset))
                    {
                        UpdateReadWriteStatus($"Error at offset={flashOffset:X6}", Color.Red);
                        _logging.Warn(MODUL_NAME, "WriteTcrtBtn_Click", $"Error at offset={flashOffset:X6}");
                        _readWriteCanceled = true;
                        return;
                    }

                    calcCrc.Update(tcrtImage, flashOffset + Tapecart.HEADER_SIZE, Tapecart.BLOCK_SIZE);

                    flashOffset += Tapecart.BLOCK_SIZE;

                    if (flashOffset % 0x1000 == 0)
                    {
                        UpdateReadWriteBar((int)(flashOffset * 100 / tcrtSize));
                        UpdateReadWriteStatus($"Writing: Offset={flashOffset:X6}h Time={Minutes(sw.ElapsedMilliseconds)}");
                    }
                }

                if (ChecksumCb.Checked)
                {
                    _logging.Info(MODUL_NAME, "WriteTcrtBtn_Click", "Checksum test...");
                    UpdateReadWriteStatus($"Checksum-Test...");
                    UInt32 crc;
                    Stopwatch sw2 = new Stopwatch();
                    sw2.Start();
                    _arduinoComm.Crc32Flash(0, (int)tcrtSize, out crc);
                    Debug.WriteLine($"crc-time={Minutes(sw2.ElapsedMilliseconds)}");
                    if (crc != calcCrc.Crc)
                    {
                        Debug.WriteLine($"checksum error calc={calcCrc.Crc:X8} flash={crc:X8}");
                        _logging.Warn(MODUL_NAME, "WriteTcrtBtn_Click", $"checksum error calc={calcCrc.Crc:X8} flash={crc:X8}");
                        UpdateReadWriteStatus($"Checksum error", Color.Red);
                        return;
                    }
                    else
                    {
                        _logging.Info(MODUL_NAME, "WriteTcrtBtn_Click", $"checksum ok {crc:X8}");
                    }
                }

                _logging.Info(MODUL_NAME, "WriteTcrtBtn_Click", $"Write finished: Offset={flashOffset:X6}h Time={Minutes(sw.ElapsedMilliseconds)}");
                UpdateReadWriteStatus($"Write finished: Offset={flashOffset:X6}h Time={Minutes(sw.ElapsedMilliseconds)}", Color.Green);
                UpdateReadWriteBar(100);
            });


            _readWriteCanceled = true;
            _writeActive       = false;
            WriteTcrtBtn.Text  = btnText;
            SetButtonStatus();
        }