Beispiel #1
0
        void SendFirmwareBlock(byte[] data, int length)
        {
            int i    = 0;
            int part = 0;

            byte[] crc16;

            Console.WriteLine("sending block 0x{0:X02} 0x{1:X04} 0x{2:X04}", LastBinBlock + CurrentUpdateFiles[CurrentUpdateFileIndex].blockOffset, LastBinBlock * CurrentUpdateFiles[CurrentUpdateFileIndex].blockSize, length);

            for (i = 0; i < length; i += 8)
            {
                //build Message Id containing current part number
                LastSentFrame = new CANMessage(BuildCANId(CANMaerklinCommand.Bootloader, 0x0300) + (byte)part, new byte[] { 0x00, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00, 0x00 });
                part++;
                Array.Copy(data, i, LastSentFrame.Data, 0, 8);
                serialCAN.SendCAN(LastSentFrame);
            }

            LastSentFrame = new CANMessage(BuildCANId(CANMaerklinCommand.Bootloader, CS2AddressHash), new byte[] { 0x00, 0x00, 0x00, 0x00, 0x88, 0x00, 0x00 });
            Array.Copy(CurrentDeviceId.HexStringToByteArray(), 0, LastSentFrame.Data, 0, 4);
            Crc16Ccitt crc16Ccitt = new Crc16Ccitt(InitialCrcValue.NonZero1);

            crc16 = crc16Ccitt.ComputeChecksumBytes(data.Take(length).ToArray()).ToBigEndian();
            LastSentFrame.Data[5] = crc16[0];
            LastSentFrame.Data[6] = crc16[1];
            Console.WriteLine("block checksum 0x{0}", crc16.ByteArrayToHexString());
            serialCAN.SendCAN(LastSentFrame);
        }
Beispiel #2
0
        private void SerialCAN_CANMessageReceived(object sender, CANMessageReceivedEventArgs e)
        {
            int requestedBlockIndex;

            if (UpdateRunning)
            {
                switch ((CANMaerklinCommand)(e.CANMessage.Id & 0xFFFF0000UL))
                {
                case (CANMaerklinCommand.Ping):
                    Console.WriteLine("received CAN Ping {0}\n", e.CANMessage);
                    if (CurrentDeviceHash == (e.CANMessage.Id & 0x00FFFF))
                    {
                        if (!FileUpdateRunning)
                        {
                            //Ping received from update device so we expect the File update has been completed
                            Console.WriteLine("UPDATE COMPLETE");

                            UpdateCompletedAutoResetEvent.Set();
                            UpdateRunning = false;
                        }
                    }
                    break;

                case (CANMaerklinCommand.PingRsp):
                    Console.WriteLine("received CAN Ping answer from Device {0}\n", (DeviceType)(e.CANMessage.Data[0]));
                    if ((e.CANMessage.Data.Length == 8) && (e.CANMessage.Data[0] == (byte)DeviceType))
                    {
                        string deviceVersion = string.Format("{0}.{1}", e.CANMessage.Data[4], e.CANMessage.Data[5]);

                        switch ((DeviceType)e.CANMessage.Data[0])
                        {
                        case DeviceType.GB2:
                            Console.WriteLine("found Gleisbox with ID 0x{0} Version {1}\n", CurrentDeviceId, deviceVersion);
                            CurrentDeviceId   = GetDeviceIdFromCanMessage(e.CANMessage);
                            CurrentDeviceHash = e.CANMessage.Id & 0x00FFFF;
                            PingReceived      = true;
                            break;

                        case DeviceType.MS2:
                            Console.WriteLine("found MS2 with ID 0x{0} Version {1}\n", CurrentDeviceId, deviceVersion);
                            CurrentDeviceId   = GetDeviceIdFromCanMessage(e.CANMessage);
                            CurrentDeviceHash = e.CANMessage.Id & 0x00FFFF;
                            PingReceived      = true;
                            break;
                        }

                        if (IsFirmwareUpdate)
                        {
                            StartFirmwareUpdateProcedure(deviceVersion);
                        }
                        else
                        {
                            StartConfigFileSend();
                        }
                    }
                    break;

                case CANMaerklinCommand.BootloaderRsp:
                    //Firmware update process
                    if (PingReceived)
                    {
                        if (e.CANMessage.Data.Length == 8 && GetDeviceIdFromCanMessage(e.CANMessage) == CurrentDeviceId && ((e.CANMessage.Data[7] == 0x10) || (e.CANMessage.Data[7] == 0x32)))
                        {
                            Console.WriteLine("Send initial block id");
                            SendInitialBlockId(e.CANMessage);
                        }
                        else
                        {
                            /* first data block */
                            if (LastSentFrame == null || e.CANMessage.Data.ByteArrayEquals(LastSentFrame.Data) && LastBinBlock == TotalBlocksToSend)
                            {
                                Console.WriteLine("Send first data block");
                                SendFirmwareBlock(DataBytesToSendWithPadding.Skip(LastBinBlock * (int)CurrentUpdateFiles[CurrentUpdateFileIndex].blockSize).ToArray(), DataBytesToSendWithPadding.Length - TotalBlocksToSend * (int)CurrentUpdateFiles[CurrentUpdateFileIndex].blockSize);
                                LastBinBlock--;
                            }
                            else
                            {
                                //there seems to be different NACK types : 0xF1 and 0xF2
                                if (CheckFrameNack != null && e.CANMessage.Data.Length >= 5 && CheckFrameNack.Data.Length >= 5 &&
                                    e.CANMessage.Id == CheckFrameNack.Id && e.CANMessage.Data.Take(4).ToArray().ByteArrayEquals(CheckFrameNack.Data.Take(4).ToArray()) &&
                                    (e.CANMessage.Data[4] == 0xF1 || e.CANMessage.Data[4] == 0xF2)
                                    )
                                {
                                    Console.WriteLine("Aiiee got NACK. Aborting");
                                    UpdateCompletedAutoResetEvent.Set();
                                    UpdateRunning = false;
                                }

                                //MS2 may use 0x0000 as hash -> compare CheckFrameBlockId full 8 bytes
                                if (CheckFrameBlockId != null && e.CANMessage.Data.ByteArrayEquals(CheckFrameBlockId.Data))
                                {
                                    SendFirmwareBlock(DataBytesToSendWithPadding.Skip(LastBinBlock * (int)CurrentUpdateFiles[CurrentUpdateFileIndex].blockSize).ToArray(), (int)CurrentUpdateFiles[CurrentUpdateFileIndex].blockSize);
                                    //firmware flashing has to be sent in reversed order
                                    LastBinBlock--;
                                }

                                //MS2 may use 0x0000 as hash -> compare CheckFrame full 8 bytes
                                if (CheckFrame != null && e.CANMessage.Data.Length == CheckFrame.Data.Length && e.CANMessage.Data.Take(5).ToArray().ByteArrayEquals(CheckFrame.Data.Take(5).ToArray()))
                                {
                                    if ((LastBinBlock >= 0))
                                    {
                                        SendNextBlockId((byte)(LastBinBlock + CurrentUpdateFiles[CurrentUpdateFileIndex].blockOffset));
                                    }
                                    else
                                    {
                                        if (DeviceType == DeviceType.MS2)
                                        {
                                            Console.WriteLine("Reboot MS2 - be patient...");
                                            //end of update
                                            LastSentFrame = new CANMessage(BuildCANId(CANMaerklinCommand.Bootloader, CS2AddressHash), new byte[] { 0x00, 0x00, 0x00, 0x00, 0xf5 });
                                            Array.Copy(CurrentDeviceId.HexStringToByteArray(), 0, LastSentFrame.Data, 0, 4);
                                            serialCAN.SendCAN(LastSentFrame);
                                            Thread.Sleep(1000);
                                            //soft reset
                                            LastSentFrame = new CANMessage(BuildCANId(CANMaerklinCommand.Bootloader, CS2AddressHash), new byte[] { 0x00, 0x00, 0x00, 0x00, 0x11 });
                                            Array.Copy(CurrentDeviceId.HexStringToByteArray(), 0, LastSentFrame.Data, 0, 4);
                                            serialCAN.SendCAN(LastSentFrame);
                                            Thread.Sleep(13000);

                                            //Start updating MS2 files
                                            StartConfigFileSend();
                                        }
                                        else
                                        {
                                            Console.WriteLine("UPDATE COMPLETE");

                                            UpdateCompletedAutoResetEvent.Set();
                                            UpdateRunning = false;
                                        }
                                    }
                                }
                            }
                        }
                    }
                    break;

                case CANMaerklinCommand.ConfigDataQuery:
                    //Send/Update CONFIG DATA

                    if (e.CANMessage.Data.ByteArrayToHexString() == "6666666666666666")
                    {
                        if (RequestedConfigNameData.EndsWith("ver"))
                        {
                            if (AckconfigFileRequestFrame != null)
                            {
                                serialCAN.SendCAN(AckconfigFileRequestFrame);
                            }

                            //Send config data

                            LastBinBlock = 0;
                            PrepareCS2FileVersionInfoToSend(CurrentUpdateFiles[CurrentUpdateFileIndex]);
                            byte[] fileSizeBytes = BitConverter.GetBytes(FileLength).ToBigEndian();
                            Array.Copy(fileSizeBytes, LastSentFrame.Data, 4);
                            Crc16Ccitt crc16Ccitt = new Crc16Ccitt(InitialCrcValue.NonZero1);
                            LastSentFrame.Id = BuildCANId(CANMaerklinCommand.ConfigDataStream, e.CANMessage.Id & 0x00FFFF);
                            var crc16 = crc16Ccitt.ComputeChecksumBytes(DataBytesToSendWithPadding).ToBigEndian();
                            LastSentFrame.Data[4] = crc16[0];
                            LastSentFrame.Data[5] = crc16[1];
                            Console.WriteLine("block checksum 0x{0}", crc16.ByteArrayToHexString());
                            serialCAN.SendCAN(LastSentFrame);

                            //send all data
                            for (int i = 0; i < DataBytesToSendWithPadding.Length; i += 8)
                            {
                                LastSentFrame.Data = new byte[8];
                                Array.Copy(DataBytesToSendWithPadding, i, LastSentFrame.Data, 0, 8);
                                serialCAN.SendCAN(LastSentFrame);
                            }
                            Console.WriteLine("Data sent.");
                        }
                    }
                    else if (e.CANMessage.Data.ByteArrayToHexString().Substring(6) == "0000000000" && int.TryParse(Encoding.ASCII.GetString(e.CANMessage.Data).Trim('\0'), out requestedBlockIndex))
                    {
                        FileUpdateRunning = true;
                        if (!string.IsNullOrEmpty(RequestedConfigNameData))
                        {
                            Console.WriteLine("Request file {0} block {1}", RequestedConfigNameData, requestedBlockIndex);

                            byte[] bytesToSend = DataBytesToSendWithPadding.Skip(requestedBlockIndex * CurrentUpdateFiles[CurrentUpdateFileIndex].blockSize).Take(CurrentUpdateFiles[CurrentUpdateFileIndex].blockSize).ToArray();
                            //check if requested block is last block
                            if (DataBytesToSendWithPadding.Length / CurrentUpdateFiles[CurrentUpdateFileIndex].blockSize == requestedBlockIndex)
                            {
                                FileUpdateRunning = false;
                            }

                            byte[] fileSizeBytes = BitConverter.GetBytes(bytesToSend.Length).ToBigEndian();

                            //Prepare messages for later sending (FFFFFF... message)
                            AckconfigFileRequestFrame    = e.CANMessage.Clone();
                            AckconfigFileRequestFrame.Id = BuildCANId(CANMaerklinCommand.ConfigDataQueryRsp, CS2AddressHash);
                            serialCAN.SendCAN(AckconfigFileRequestFrame);

                            Array.Copy(fileSizeBytes, LastSentFrame.Data, 4);
                            Crc16Ccitt crc16Ccitt = new Crc16Ccitt(InitialCrcValue.NonZero1);
                            LastSentFrame.Id = BuildCANId(CANMaerklinCommand.ConfigDataStream, e.CANMessage.Id & 0x00FFFF);
                            var crc16 = crc16Ccitt.ComputeChecksumBytes(bytesToSend).ToBigEndian();
                            LastSentFrame.Data[4] = crc16[0];
                            LastSentFrame.Data[5] = crc16[1];
                            Console.WriteLine("block checksum 0x{0}", crc16.ByteArrayToHexString());
                            Thread.Sleep(100);
                            serialCAN.SendCAN(LastSentFrame);

                            //send block
                            LastSentFrame.Id = BuildCANId(CANMaerklinCommand.ConfigDataStream, e.CANMessage.Id & 0x00FFFF);
                            for (int i = 0; i < bytesToSend.Length; i += 8)
                            {
                                LastSentFrame.Data = new byte[8];
                                Array.Copy(bytesToSend, i, LastSentFrame.Data, 0, 8);
                                serialCAN.SendCAN(LastSentFrame);
                            }
                        }
                    }
                    else
                    {
                        RequestedConfigNameData = Encoding.ASCII.GetString(e.CANMessage.Data).Trim('\0');
                        CurrentUpdateFileIndex  = Array.FindIndex(ms2_update_data, x => x.versionName == RequestedConfigNameData);
                        if (Array.Exists(ms2_update_data, x => x.versionName == RequestedConfigNameData))
                        {
                            //CS2 version string request
                            Console.WriteLine("Request .CS2 fileinfo {0}", RequestedConfigNameData);
                            CurrentUpdateFileIndex = Array.FindIndex(ms2_update_data, x => x.versionName == RequestedConfigNameData);
                            LastSentFrame          = new CANMessage(BuildCANId(CANMaerklinCommand.ConfigDataStream, CS2AddressHash), new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 });

                            //Prepare messages for later sending (FFFFFF... message)
                            AckconfigFileRequestFrame    = e.CANMessage.Clone();
                            AckconfigFileRequestFrame.Id = BuildCANId(CANMaerklinCommand.ConfigDataQueryRsp, CS2AddressHash);
                        }
                        else if (Array.Exists(ms2_update_data, x => x.name == RequestedConfigNameData))
                        {
                            //File data request
                            Console.WriteLine("Request file {0}", RequestedConfigNameData);
                            CurrentUpdateFileIndex = Array.FindIndex(ms2_update_data, x => x.name == RequestedConfigNameData);
                            ReadFirmwareFile(CurrentUpdateFiles[CurrentUpdateFileIndex], false);
                            LastSentFrame = new CANMessage(BuildCANId(CANMaerklinCommand.ConfigDataStream, CS2AddressHash), new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 });

                            AckconfigFileRequestFrame    = e.CANMessage.Clone();
                            AckconfigFileRequestFrame.Id = BuildCANId(CANMaerklinCommand.ConfigDataStreamRsp, CS2AddressHash);
                        }
                        else
                        {
                            Console.WriteLine("Couldn't find requested file {0}", RequestedConfigNameData);
                        }
                    }
                    break;

                default:
                    break;
                }
            }
        }