コード例 #1
0
        private HexLoader(string fileName, bool bBootLoaderCode)
        {
            this.fileName = fileName;

            // Assume failure until finished loading.
            hexLoaded           = false;
            applicationRowCount = 0;
            crc = 0;

            // Parse the lines of the hex file. If the entire file is parsed successfully, set
            // hexLoaded to true to indicate the file was successfully loaded. Otherwise if
            // an unrecognized line is reached, return early with hexLoaded = false.
            string[] hexLines = System.IO.File.ReadAllLines(fileName);
            if (hexLines != null)
            {
                // Loop to load hex records from the input file. The format is as follows:
                //
                //	:BBAAAATTHHHH....HHHCC
                //
                // where:
                //
                // BB    A two digit hexadecimal byte count representing the number of data
                //       bytes that will appear on the line.
                // AAAA  A four digit hexadecimal address representing the starting address of
                //       the data record.
                // TT    A two digit record type:
                //    00 - Data record
                //    01 - End of File record
                //    02 - Segment address record
                //    04 - Linear address record
                // HH    A two digit hexadecimal data byte, presented in low byte/high byte
                //       combinations.
                // CC    A two digit hexadecimal checksum that is the two's complement of the
                //       sum of all preceding bytes in the record.
                //
                uint baseAddress      = 0;
                bool endOfFileReached = false;
                foreach (string line in hexLines)
                {
                    if (endOfFileReached)
                    {
                        return; // Failed; extra data found after end-of-file marker.
                    }
                    // Parse the line from the hex file.
                    if ((line.Length < 11) || (line[0] != ':') || ((line.Length & 1) == 0))
                    {
                        return; // Line does not have minimum length, does not start with ':', or does not have an even number of hex digits.
                    }
                    // Extract field values.
                    uint       dataByteCount  = Convert.ToUInt32(line.Substring(1, 2), 16);
                    uint       address        = Convert.ToUInt32(line.Substring(3, 4), 16);
                    RecordType recordType     = (RecordType)Convert.ToUInt32(line.Substring(7, 2), 16);
                    uint       checksumDigit  = Convert.ToUInt32(line.Substring(line.Length - 2, 2), 16);
                    byte       checksum       = (byte)(dataByteCount + (address >> 8) + (address & 0x00FF) + (uint)recordType + checksumDigit);
                    int        dataDigitIndex = 9;
                    int        dataDigitEnd   = line.Length - 2;
                    MyDebug.Assert(2 * dataByteCount == dataDigitEnd - dataDigitIndex);
                    byte[] dataBytes     = new byte[dataByteCount];
                    uint   dataByteIndex = 0;
                    while (dataDigitIndex < dataDigitEnd)
                    {
                        byte dataByte = Convert.ToByte(line.Substring(dataDigitIndex, 2), 16);
                        dataDigitIndex            += 2;
                        dataBytes[dataByteIndex++] = dataByte;
                        checksum += dataByte;
                    }

                    // The final byte is the checksum byte. All of the bytes in the string should add up to zero.
                    if (checksum != 0)
                    {
                        return; // Checksum failed.
                    }
                    switch (recordType)
                    {
                    case RecordType.Data:
                        AddData(baseAddress + address, dataBytes);
                        break;

                    case RecordType.EndOfFile:
                        endOfFileReached = true;
                        break;

                    case RecordType.SegmentAddress:
                        return;     // Unexpected record type.

                    case RecordType.LinearAddress:
                        MyDebug.Assert(address == 0);
                        baseAddress = (((uint)dataBytes[0] << 8) | dataBytes[1]) << 16;
                        break;

                    default:
                        return;     // Unexpected record type.
                    }
                }
            }

            // Hex file has loaded successfully. Calculate the row count and CRC.
            if (CalculateRowCountAndCRC(bBootLoaderCode, out applicationRowCount, out totalRowCount, out crc))
            {
                if (applicationRowCount == 0)
                {
                    throw new Exception("File contains no application data.");
                }
                hexLoaded = true; // Success!
            }
        }
コード例 #2
0
        private bool CalculateRowCountAndCRC(bool bBootLoaderCode,
                                             out uint applicationRowCount, out uint totalRowCount, out ushort crc)
        {
            applicationRowCount = 0;
            totalRowCount       = 0;
            crc = 0;

            uint startAllowableRowIndex;
            uint endAllowableRowIndex;

            if (bBootLoaderCode)
            {
                startAllowableRowIndex = FirstBootLoaderRowIndex;
                endAllowableRowIndex   = EndBootLoaderRowIndex;
            }
            else
            {
                startAllowableRowIndex = FirstApplicationRowIndex;
                endAllowableRowIndex   = LastAllowableApplicationRow;
            }

            MyDebug.Assert(BlankRow.Length == BytesPerRow);
            uint currentRowIndex = 0;
            uint rowIndex;

            byte[] row;
            bool   bFirst        = true;
            CRC    crcCalculator = new CRC();

            while (EnumerateRows(bFirst, out row, out rowIndex))
            {
                bFirst = false;
                totalRowCount++;
                MyDebug.Assert(row.Length == BytesPerRow);
                MyDebug.Assert(rowIndex >= currentRowIndex); // Failure indicates a bug in EnumerateRows().

                // The CRC calculation does not include flash memory above the user program flash
                // memory area, as defined in chapter 3 of the dsPIC33FJXXXMCX06/X08/X10 Motor
                // Control Family datasheet. Skip any such data.
                if (rowIndex >= LastAllowableApplicationRow)
                {
                    MyDebug.Assert((rowIndex == 0x1F000) || IsBlank(row)); // Only the single processor configuration row is expected.
                    continue;
                }

                // Take care of any rows that are skipped in the hex file.
                while (currentRowIndex < rowIndex)
                {
                    // Ignore blank rows in the protected area. They are not included in the CRC calculation.
                    if ((currentRowIndex < FirstPageAllowableRows) || (currentRowIndex >= startAllowableRowIndex))
                    {
                        // Assume the skipped row is all 0xFF's.
                        crcCalculator.addBuffer(BlankRow);
                    }
                    currentRowIndex++;
                }

                if ((rowIndex < FirstPageAllowableRows) ||
                    ((rowIndex >= startAllowableRowIndex) && (rowIndex < endAllowableRowIndex)))
                {
                    // Update the CRC with this row.
                    crcCalculator.addBuffer(row);
                }
                else
                {
                    // Code was specified for the protected areas. If the specified code is
                    // something other than all FF's, fail the hex loading.
                    foreach (byte rowByte in row)
                    {
                        if (rowByte != 0xFF)
                        {
                            throw new Exception("File contains flash data in a protected page.");
                        }
                    }
                }

                currentRowIndex++;
            }

            if (currentRowIndex > startAllowableRowIndex)
            {
                applicationRowCount = currentRowIndex - startAllowableRowIndex;
            }
            crc = crcCalculator.crc;

            return(true);
        }
コード例 #3
0
        private void AddData(uint address, byte[] dataBytes)
        {
            // A page contains 512 instruction words (1536 bytes) but has an address space range
            // of 1024 from the processor's point of view, but 2048 from the .hex file's point of
            // view. Although each instruction is 24 bits, they are specified in 32 bits, so they
            // will be stored in pageList as 32 bits.
            MyDebug.Assert((address & 3) == 0);          // Address must be multiple of 4 for 16-bit processor.
            MyDebug.Assert((dataBytes.Length & 3) == 0); // Data is expected in 4-byte words for 16-bit processor.
            uint dataWords               = (uint)dataBytes.Length / 4;
            uint wordIndex               = address / 4;
            uint pageIndex               = wordIndex / InstructionWordsPerPage;
            uint dstWordIndex            = wordIndex % InstructionWordsPerPage;
            uint srcByteIndex            = 0;
            uint srcByteEndIndex         = (uint)dataBytes.Length;
            uint srcByteEndIndexNextPass = 0;

            // If the byte series overlaps pages, restrict the number of bytes that will be copied
            // on the first pass.
            if (dstWordIndex + dataWords > InstructionWordsPerPage)
            {
                srcByteEndIndexNextPass = srcByteEndIndex;
                srcByteEndIndex        -= 4 * (dstWordIndex + dataWords - InstructionWordsPerPage);
            }

            // The following loops one or two times depending on if the data overlaps a page boundary.
            while (true)
            {
                // Find the page for the specified address. If it hasn't yet been created, allocate
                // it now and initialize its contents to all 0xFFs.
                UInt32[] page = (UInt32[])pageList[pageIndex];
                while (page == null)
                {
                    page = new UInt32[InstructionWordsPerPage];
                    for (int i = 0; i < page.Length; i++)
                    {
                        page[i] = 0x00FFFFFF; // Only 24 bits are actually stored.
                    }
                    pageList.Add(pageIndex, page);
                }

                // Add the new data from srcByteIndex to srcByteEndIndex to its destination page.
                while (srcByteIndex < srcByteEndIndex)
                {
                    UInt32 word = 0;
                    for (int i = 0; i < 32; i += 8)
                    {
                        word |= (UInt32)dataBytes[srcByteIndex++] << i;
                    }
                    MyDebug.Assert(word < 0x01000000);

                    // If any word is specified multiple times in the .hex file, make sure they
                    // always specify the same value.
                    MyDebug.Assert((page[dstWordIndex] == 0x00FFFFFF) || (page[dstWordIndex] == word));
                    page[dstWordIndex++] = word;
                }

                // Break out of the loop if all of the data has been saved.
                if (srcByteEndIndexNextPass == 0)
                {
                    break;
                }

                // The data byte series overlaps two pages. Set up for the next page and loop to
                // copy to the second page.
                pageIndex++;
                dstWordIndex            = 0;
                srcByteEndIndex         = srcByteEndIndexNextPass;
                srcByteEndIndexNextPass = 0;
            }
        }
        /// <summary>
        /// Overide method RS232Port.OnMessageReceived(). This is called by the base class when a complete
        /// inbound message has been received.
        /// </summary>
        /// <param name="message">full message receive to sort and process</param>
        public override void OnMessageReceived(string message)
        {
            const string completionTag = "Tunnel|";
            const string asyncEventTag = "AsyncEvent|";

            if (message.StartsWith(completionTag))
            {
                // MyDebug.Assert(completionPacket == null,"Error in OnMessageReceived 1");

                int    dstBytes            = (message.Length - completionTag.Length) / 2;
                byte[] newCompletionPacket = new byte[dstBytes];
                int    srcIndex            = completionTag.Length;
                uint   dstIndex            = 0;
                while (srcIndex < message.Length)
                {
                    newCompletionPacket[dstIndex++] = (byte)Convert.ToUInt32(message.Substring(srcIndex, 2), 16);
                    srcIndex += 2;
                }
                MyDebug.Assert(dstIndex == dstBytes, "Error in OnMessageReceived 2");

                completionPacket = newCompletionPacket;
                if (completionEvent != null)
                {
                    completionEvent.Set();
                }
            }
            else if (message.StartsWith(asyncEventTag))
            {
                int    dstBytes            = 2 + (message.Length - asyncEventTag.Length) / 2;
                byte[] newAsyncEventPacket = new byte[dstBytes];
                int    srcIndex            = asyncEventTag.Length;
                ushort command             = (ushort)CommandType.PBCMD_AsyncEvent;
                newAsyncEventPacket[0] = (byte)(command & 0xFF);
                newAsyncEventPacket[1] = (byte)((command >> 8) & 0xFF);
                uint dstIndex = 2;
                while (srcIndex < message.Length)
                {
                    newAsyncEventPacket[dstIndex++] = (byte)Convert.ToUInt32(message.Substring(srcIndex, 2), 16);
                    srcIndex += 2;
                }
                MyDebug.Assert(dstIndex == dstBytes, "Error in OnMessageReceived 3");

                lock (lockObj)
                {
                    asyncEventQueue.Enqueue(newAsyncEventPacket);
                }
                if (asyncEventEvent != null)
                {
                    asyncEventEvent.Set();
                }
            }
            else if (message.StartsWith("PowerOFF"))
            {
                int    dstBytes            = 10;
                byte[] newAsyncEventPacket = new byte[dstBytes];
                int    srcIndex            = asyncEventTag.Length;
                ushort command             = (ushort)CommandType.PBCMD_AsyncEvent;
                newAsyncEventPacket[0] = (byte)(command & 0xFF);
                newAsyncEventPacket[1] = (byte)((command >> 8) & 0xFF);
                uint dstIndex = 2;
                newAsyncEventPacket[dstIndex++] = (byte)Convert.ToUInt32("FF", 16);
                srcIndex += 2;
                newAsyncEventPacket[dstIndex++] = (byte)Convert.ToUInt32("FF", 16);
                srcIndex += 2;

                lock (lockObj)
                {
                    asyncEventQueue.Enqueue(newAsyncEventPacket);
                }
                if (asyncEventEvent != null)
                {
                    asyncEventEvent.Set();
                }
            }
            else if (message.StartsWith("PowerON"))
            {
                int    dstBytes            = 10;
                byte[] newAsyncEventPacket = new byte[dstBytes];
                int    srcIndex            = asyncEventTag.Length;
                ushort command             = (ushort)CommandType.PBCMD_AsyncEvent;
                newAsyncEventPacket[0] = (byte)(command & 0xFF);
                newAsyncEventPacket[1] = (byte)((command >> 8) & 0xFF);
                uint dstIndex = 2;
                newAsyncEventPacket[dstIndex++] = (byte)Convert.ToUInt32("EE", 16);
                srcIndex += 2;
                newAsyncEventPacket[dstIndex++] = (byte)Convert.ToUInt32("EE", 16);
                srcIndex += 2;
                lock (lockObj)
                {
                    asyncEventQueue.Enqueue(newAsyncEventPacket);
                }
                if (asyncEventEvent != null)
                {
                    asyncEventEvent.Set();
                }
            }
            else
            {
                if (inboundMessageQueue != null)
                {
                    inboundMessageQueue.Enqueue(message);
                    if (inboundMessageEvent != null)
                    {
                        inboundMessageEvent.Set();
                    }
                }
            }
        }