/// <summary> /// Function to transmit the UBL and application for flash /// </summary> private static Boolean TransmitAPP() { Byte[] imageData; UARTBOOT_Header ackHeader = new UARTBOOT_Header(); try { // Now Send the application image that will be written to flash Console.WriteLine("Sending the Application image"); imageData = FileIO.GetFileData(cmdParams.APPFileName); ackHeader.magicNum = ((UInt32)MagicFlags.UBL_MAGIC_BIN_IMG); ackHeader.startAddr = cmdParams.APPStartAddr; ackHeader.byteCnt = (UInt32)imageData.Length; ackHeader.loadAddr = cmdParams.APPLoadAddr; if (!TransmitImage(imageData, ackHeader)) { return(false); } // ^^^DONE\0 that indicates that application flashing is complete if (!SerialIO.waitForSequence(" DONE\0", "BOOTUBL\0", MySP, true)) { return(false); } return(true); } catch (ObjectDisposedException e) { Console.WriteLine(e.StackTrace); throw e; } }
/// <summary> /// Function to transmit the application code via the SLT, which is now /// running on the device. This code is specific to the supplied SLT. /// If the the TI supplied SLT is modified or a different boot loader is /// used, this code will need to be modified. /// </summary> private static Boolean TransmitImage(Byte[] imageData, UARTBOOT_Header ackHeader) { try { Console.WriteLine("Waiting for SENDIMG sequence..."); if (!SerialIO.waitForSequence("SENDIMG\0", "BOOTUBL\0", MySP, cmdParams.verbose)) { return(false); } Console.WriteLine("SENDIMG received. Returning ACK and header for image data..."); // Output 36 Bytes for the ACK sequence and header // 8 bytes acknowledge sequence = " ACK\0" MySP.Write(" ACK\0"); // 8 bytes of magic number MySP.Write(String.Format("{0:X8}", ackHeader.magicNum)); // 8 bytes of binary execution address = ASCII string of 8 hex characters MySP.Write(String.Format("{0:X8}", ackHeader.startAddr)); // 8 bytes of data size = ASCII string of 8 hex characters MySP.Write(String.Format("{0:X8}", ackHeader.byteCnt)); // 8 bytes of binary load address = ASCII string of 8 hex characters MySP.Write(String.Format("{0:X8}", ackHeader.loadAddr)); // 4 bytes of constant zeros = "0000" MySP.Write("0000"); Console.WriteLine("ACK command sent. Waiting for BEGIN command... "); // Wait for the ^^BEGIN\0 sequence if (!SerialIO.waitForSequence(" BEGIN\0", "BOOTUBL\0", MySP, cmdParams.verbose)) { return(false); } Console.WriteLine("BEGIN commmand received. Sending the image data..."); // Send the image data MySP.Write(imageData, 0, (Int32)ackHeader.byteCnt); Console.WriteLine("Image data sent. Waiting for DONE..."); // Wait for first ^^^DONE\0 to indicate data received if (!SerialIO.waitForSequence(" DONE\0", "BOOTUBL\0", MySP, cmdParams.verbose)) { return(false); } Console.WriteLine("DONE received. All bytes of image data received..."); } catch (ObjectDisposedException e) { Console.WriteLine(e.StackTrace); throw e; } return(true); }
/// <summary> /// Send command and wait for erase response. (NOR and NAND global erase) /// </summary> private static Boolean TransmitErase() { try { // ^^^DONE\0 that indicates command was executed successfully if (!SerialIO.waitForSequence(" DONE\0", "BOOTUBL\0", MySP, true)) { return(false); } } catch (ObjectDisposedException e) { Console.WriteLine(e.StackTrace); throw e; } return(true); }
//********************************************************************************** //********************************************************************************** #region Code for UART interfacing thread /// <summary> /// The main function of the thread where all the cool stuff happens /// to interface with the device /// </summary> public static void WorkerThreadStart() { switch (cmdParams.CMDMagicFlag) { case MagicFlags.SLT_MAGIC_LOADIMAGE_IRAM: { TransmitAppToIRAM(); break; } case MagicFlags.SLT_MAGIC_LOADIMAGE_DDR: { // Send SLT and the app to DDR TransmitSLTAndApp(); // Wait for second ^^^DONE that indicates SLT is done if (!SerialIO.waitForSequence(" DONE\0", "BOOTUBL\0", MySP, true)) { throw new Exception("Final DONE not returned. Operation failed."); } break; } default: { Console.WriteLine("Command not recognized!"); break; } } // Clean up any embedded files we extracted EmbeddedFileIO.CleanUpEmbeddedFiles(); // Everything worked, so change boolean status workerThreadSucceeded = true; }
/// <summary> /// Function used to handle the -load2DDR command-line option private static void TransmitSLTAndApp() { // Local Variables for holding file data Byte[] imageData; UARTBOOT_Header ackHeader = new UARTBOOT_Header(); // Extract the embedded SLT EmbeddedFileIO.ExtractFile(System.Reflection.Assembly.GetExecutingAssembly(), "slt_" + devString + ".bin", true); // Read the extracted embedded SLT data that we will transmit imageData = FileIO.GetFileData("slt_" + devString + ".bin"); ackHeader.startAddr = 0x0100; // Default for SLT ackHeader.byteCnt = (UInt32)imageData.Length; ackHeader.loadAddr = 0x0020; // Not used here, but this what the RBL uses TransmitUBL(imageData, ackHeader); // Sleep in case we need to abort Thread.Sleep(200); // Code to perform specified command try { BOOTUBLSEQ1: // Send the UBL command // Clear input buffer so we can start looking for BOOTUBL MySP.DiscardInBuffer(); Console.WriteLine("\nWaiting for SLT on the " + devString + "..."); // Wait for the UBL on the device to send the ^BOOTUBL\0 sequence if (!SerialIO.waitForSequence("BOOTUBL\0", "BOOTUBL\0", MySP, true)) { goto BOOTUBLSEQ1; } Console.WriteLine("BOOTUBL commmand received. Returning CMD and command..."); // 8 bytes acknowledge sequence = " CMD\0" MySP.Write(" CMD\0"); // 8 bytes of magic number MySP.Write(((UInt32)cmdParams.CMDMagicFlag).ToString("X8")); Console.WriteLine("CMD value sent. Waiting for DONE..."); // Wait for ^^^DONE letting us know the command was accepted if (!SerialIO.waitForSequence(" DONE\0", "BOOTUBL\0", MySP, cmdParams.verbose)) { goto BOOTUBLSEQ1; } Console.WriteLine("DONE received. Command was accepted."); // Local Variables for reading APP file imageData = FileIO.GetFileData(cmdParams.APPFileName); ackHeader.startAddr = cmdParams.APPStartAddr; // App entry point ackHeader.loadAddr = cmdParams.APPLoadAddr; // App load address ackHeader.byteCnt = (UInt32)imageData.Length; // App byte cnt if (!TransmitImage(imageData, ackHeader)) { goto BOOTUBLSEQ1; } } catch (Exception e) { if (e is ThreadAbortException) { Thread.Sleep(1000); } else { Console.WriteLine(e.Message); } return; } }
/// <summary> /// Function to transmit the application code via the SLT, which is now /// running on the device. This code is specific to the supplied SLT. /// If the the TI supplied SLT is modified or a different boot loader is /// used, this code will need to be modified. /// </summary> private static Boolean TransmitImage(Byte[] imageData, UARTBOOT_Header ackHeader) { ProgressBar progressBar; UInt32 blockCnt; try { Console.WriteLine("Waiting for SENDIMG sequence..."); if (!SerialIO.waitForSequence("SENDIMG\0", "BOOTUBL\0", MySP, cmdParams.verbose)) { return(false); } Console.WriteLine("SENDIMG received. Returning ACK and header for image data..."); // Output 36 Bytes for the ACK sequence and header // 8 bytes acknowledge sequence = " ACK\0" MySP.Write(" ACK\0"); // 8 bytes of binary execution address = ASCII string of 8 hex characters MySP.Write(String.Format("{0:X8}", ackHeader.startAddr)); // 8 bytes of data size = ASCII string of 8 hex characters MySP.Write(String.Format("{0:X8}", ackHeader.byteCnt)); // 8 bytes of binary load address = ASCII string of 8 hex characters MySP.Write(String.Format("{0:X8}", ackHeader.loadAddr)); // 4 bytes of constant zeros = "0000" MySP.Write("0000"); Console.WriteLine("ACK command sent. Waiting for BEGIN command... "); // Wait for the ^^BEGIN\0 sequence if (!SerialIO.waitForSequence(" BEGIN\0", "BOOTUBL\0", MySP, cmdParams.verbose)) { return(false); } Console.WriteLine("BEGIN commmand received."); // Send the image data progressBar = new ProgressBar(); progressBar.Update(0.0, "Sending Image data..."); blockCnt = ackHeader.byteCnt / 128; for (int i = 0; i < (blockCnt * 128); i += 128) { MySP.Write(imageData, i, 128); progressBar.Percent = (((Double)(i + 1)) / ackHeader.byteCnt); } // Write last (possibly partial) block MySP.Write(imageData, (Int32)(blockCnt * 128), (Int32)(ackHeader.byteCnt - (blockCnt * 128))); progressBar.Update(100.0, "Image data sent."); Console.WriteLine("Waiting for DONE..."); // Wait for first ^^^DONE\0 to indicate data received if (!SerialIO.waitForSequence(" DONE\0", "BOOTUBL\0", MySP, cmdParams.verbose)) { return(false); } Console.WriteLine("DONE received. All bytes of image data received..."); } catch (ObjectDisposedException e) { Console.WriteLine(e.StackTrace); throw e; } return(true); }
/// <summary> /// Function to Transmit the UBL via the device ROM Serial boot /// </summary> private static void TransmitUBL(Byte[] imageData, UARTBOOT_Header ackHeader) { // Local Variables for building up output StringBuilder UBLsb; CRC32 MyCRC; ProgressBar progressBar; Int32 blockCnt; UBLsb = new StringBuilder(imageData.Length * 2); // Read the data from the UBL file into the appropriate structures for (int i = 0; i < imageData.Length; i += sizeof(UInt32)) { UBLsb.AppendFormat("{0:X8}", System.BitConverter.ToUInt32(imageData, i)); } // Create CRC object and use it to calculate the UBL file's CRC // Note that this CRC is not quite the standard CRC-32 algorithm // commonly in use since the final register value is not XOR'd // with 0xFFFFFFFF. As a result the CRC value returned here // will be the bitwise inverse of the standard CRC-32 value. MyCRC = new CRC32(0x04C11DB7, 0xFFFFFFFF, 0x00000000, true, 1, CRCType.ONESHOT, CRCCalcMethod.LUT); ackHeader.crcVal = MyCRC.CalculateCRC(imageData); ackHeader.byteCnt = (UInt32)imageData.Length; try { BOOTMESEQ: Console.WriteLine("\nWaiting for the " + devString + "..."); // Wait for the device to send the ^BOOTME/0 sequence if (SerialIO.waitForSequence(" BOOTME\0", " BOOTME\0", MySP, cmdParams.verbose)) { Console.WriteLine("BOOTME commmand received. Returning ACK and header..."); } else { goto BOOTMESEQ; } // Output 28 Bytes for the ACK sequence and header // 8 bytes acknowledge sequence = " ACK\0" #if (DM35x_REVB || DM36x_REVA) MySP.Write(" ACK"); #else MySP.Write(" ACK\0"); #endif // 8 bytes of CRC data = ASCII string of 8 hex characters MySP.Write(ackHeader.crcVal.ToString("X8")); // 4 bytes of UBL data size = ASCII string of 4 hex characters (3800h = 14336d) MySP.Write(ackHeader.byteCnt.ToString("X4")); // 4 bytes of start address = ASCII string of 4 hex characters (>=0100h) MySP.Write(ackHeader.startAddr.ToString("X4")); // 4 bytes of constant zeros = "0000" MySP.Write("0000"); Console.WriteLine("ACK command sent. Waiting for BEGIN command... "); // Wait for the BEGIN sequence if (SerialIO.waitForSequence(" BEGIN\0", " BOOTME\0", MySP, true)) { Console.WriteLine("BEGIN commmand received. Sending CRC table..."); } else { goto BOOTMESEQ; } // Send the 1024 byte (256 word) CRC table progressBar = new ProgressBar(); progressBar.Update(0.0, "Sending CRC table..."); for (int i = 0; i < MyCRC.Length; i++) { MySP.Write(MyCRC[i].ToString("x8")); progressBar.Percent = (((Double)(i + 1)) / MyCRC.Length); } progressBar.Update(100.0, "CRC table sent."); Console.WriteLine("Waiting for DONE..."); // Wait for the first DONE sequence if (SerialIO.waitForSequence(" DONE\0", " BOOTME\0", MySP, cmdParams.verbose)) { Console.WriteLine("DONE received. Sending the UBL..."); } else { goto BOOTMESEQ; } // Send the contents of the UBL file (as hex text) progressBar = new ProgressBar(); progressBar.Update(0.0, "Sending UBL..."); blockCnt = UBLsb.Length / 128; for (int i = 0; i < (blockCnt * 128); i += 128) { MySP.Write(UBLsb.ToString(i, 128)); progressBar.Percent = (((Double)(i + 1)) / UBLsb.Length); } // Write last (possibly partial) block MySP.Write(UBLsb.ToString(blockCnt * 128, UBLsb.Length - (blockCnt * 128))); progressBar.Update(100.0, "UBL sent."); // Wait for the second DONE sequence if (SerialIO.waitForSequence(" DONE\0", " BOOTME\0", MySP, cmdParams.verbose)) { Console.WriteLine("DONE received. UBL was accepted."); } else { goto BOOTMESEQ; } Console.WriteLine("UBL transmitted successfully.\n"); } catch (ObjectDisposedException e) { Console.WriteLine(e.StackTrace); throw e; } }
//********************************************************************************** //********************************************************************************** #region Code for UART interfacing thread /// <summary> /// The main function of the thread where all the cool stuff happens /// to interface with the device /// </summary> public static void WorkerThreadStart() { Boolean status; // Try transmitting the first stage boot-loader (UBL) via the RBL try { String srchStr; Byte[] imageData; UARTBOOT_Header ackHeader = new UARTBOOT_Header(); if (cmdParams.UBLFlashType == FlashType.NAND) { srchStr = "sft_" + devString + "_nand.bin"; } else { srchStr = "sft_" + devString + "_nor.bin"; } // Extract the embedded SLT EmbeddedFileIO.ExtractFile(System.Reflection.Assembly.GetExecutingAssembly(), srchStr, true); // Read the extracted embedded SFT data that we will transmit imageData = FileIO.GetFileData(srchStr); ackHeader.startAddr = 0x0100; // Default for SFT ackHeader.loadAddr = 0x0020; // Not used here, but this what the RBL uses ackHeader.byteCnt = (UInt32)imageData.Length; TransmitUBL(imageData, ackHeader); } catch (Exception e) { if (e is ThreadAbortException) { Thread.Sleep(1000); } else { Console.WriteLine(e.Message); } return; } // Sleep in case we need to abort Thread.Sleep(200); // Code to perform specified command try { BOOTUBLSEQ1: // Clear input buffer so we can start looking for BOOTUBL MySP.DiscardInBuffer(); Console.WriteLine("\nWaiting for SFT on the " + devString + "..."); // Wait for the SFT on the device to send the ^BOOTUBL\0 sequence if (!SerialIO.waitForSequence("BOOTUBL\0", "BOOTUBL\0", MySP, true)) { goto BOOTUBLSEQ1; } Console.WriteLine("BOOTUBL commmand received. Returning CMD and command..."); // 8 bytes acknowledge sequence = " CMD\0" MySP.Write(" CMD\0"); // 8 bytes of magic number MySP.Write(((UInt32)cmdParams.CMDMagicFlag).ToString("X8")); Console.WriteLine("CMD value sent. Waiting for DONE..."); if (!SerialIO.waitForSequence(" DONE\0", "BOOTUBL\0", MySP, true)) { goto BOOTUBLSEQ1; } Console.WriteLine("DONE received. Command was accepted."); // Take appropriate action depending on command switch (cmdParams.CMDMagicFlag) { case MagicFlags.UBL_MAGIC_NAND_FLASH: { status = TransmitUBLandAPP(); break; } case MagicFlags.UBL_MAGIC_NOR_FLASH: { status = TransmitUBLandAPP(); break; } case MagicFlags.UBL_MAGIC_NOR_FLASH_NO_UBL: { status = TransmitAPP(); break; } case MagicFlags.UBL_MAGIC_NOR_ERASE: { status = TransmitErase(); break; } case MagicFlags.UBL_MAGIC_NAND_ERASE: { status = TransmitErase(); break; } default: { Console.WriteLine("Command not recognized!"); status = false; break; } } if (!status) { goto BOOTUBLSEQ1; } } catch (Exception e) { if (e is ThreadAbortException) { Thread.Sleep(1000); } else { Console.WriteLine(e.Message); } return; } // Wait for ^^^DONE that indicates SFT is exiting and so can this host program if (!SerialIO.waitForSequence(" DONE\0", "BOOTUBL\0", MySP, true)) { throw new Exception("Final DONE not returned. Operation failed."); } // Clean up any embedded files we extracted EmbeddedFileIO.CleanUpEmbeddedFiles(); // Everything worked, so change boolean status workerThreadSucceeded = true; }