Untitled

 avatar
unknown
plain_text
5 months ago
12 kB
2
Indexable
 public class PROMFlasher
 {
     private const int CmdUnlock = 0x556E6C6B;  // Unlock command
     private const int CmdErase = 0x45726173;   // Erase command
     private const int CmdProgram = 0x50726F67; // Program command
     private const int CmdStartAddress = 0x5341; // Start Address command
     private const int CmdEndAddress = 0x45; // End Address command

     //Check for bit 7 of the program status register. A value of 1 indicates Program ready.
     private const int ProgramEraseControllerStatusMask = 0x000003FC;
     private const int ProgrammerStatusReady = 0x00000200;

     // Check bit 4 of program status register. A value of 1 indicates error.
     private const int ProgramErrorStatusMask = 0x00000040;
     private const int ProgramStatusError = 0x00000040;

     // Bit 0 of the FPGA status register. If set indicates FIFO is full.
     private const int FifoFullStatusMask = 0x00000001;
     private const int FifoFullValue = 0x00000001;

     // Bit 1 of the FPGA status register.
     private const int ProgReadyBitMask = 0x00000002;
     private const int ProgReadyValue = 0x00000002;

     // The default timeout when waiting for the programmer status in msec.
     // Change here to increase or decrease the waiting period.
     //jcpm 50000 was ok for smaller FPGA (315T), but 60000 is needed for larger FPGA (475T)
     private const int DefaultTimeoutForStatusCheckInMs = 60000;

     // Number of successive words prograamed before checking programmer status.
     // Each word is 32 bits.
     private const int ProgramChunkSizeInWords = 16;

     // Start and End addresses of the PROM, used for erasing all blocks.
     private const int StartAddressForPROMErase = 0x000000;
     private const int EndAddressForPROMErase = 0x7E0000;

     private string _statusMsg = string.Empty;

     public int _UpgradePercentage;
     /// <summary>
     /// Initializes a new instance of the <see cref="PROMFlasher"/> class.
     /// </summary>
     public PROMFlasher()
     {
     }

     /// <summary>
     /// Flashes the PROM.
     /// </summary>
     /// <param name="filename">Name of the file with entire path.</param>
     /// <returns>Status of PROM flashing</returns>
     public bool FlashPROM(MCSFile mcsFile)
     {
         // Set up for programming
         if (!this.SetUpForProgramming(mcsFile))
         {
             // Set up failed.
             return false;
         }

         // program PROM.
         if (!this.Program(mcsFile))
         {
             return false;
         }

         return true;
     }

     /// <summary>
     /// Sets up for programming.
     /// </summary>
     /// <param name="mcsFile">The MCS file.</param>
     /// <returns>Ststus of set up.</returns>
     private bool SetUpForProgramming(MCSFile mcsFile)
     {
         // Check Prg_Ready bit status.
         if (!this.CheckPrgReadyAndWait(PROMFlasher.DefaultTimeoutForStatusCheckInMs))
         {
             return false;
         }

         // Set the start and end addresses and unlock the PROM.
         this.SetStartAndEndAddress(mcsFile.StartAddress, mcsFile.EndAddress);

         // Write Unlock Command to Buffer
         FPGACommunicationHandler.FPGAInstance.WriteToFPGARegister(AnoleAPIConstants.BASE_ADDRESS, AnoleAPIConstants.FLASH_DATA_REGISTER, PROMFlasher.CmdUnlock);

         // Write Erase Command to Buffer
         FPGACommunicationHandler.FPGAInstance.WriteToFPGARegister(AnoleAPIConstants.BASE_ADDRESS, AnoleAPIConstants.FLASH_DATA_REGISTER, PROMFlasher.CmdErase);

         // Write Program Command to Buffer.
         FPGACommunicationHandler.FPGAInstance.WriteToFPGARegister(AnoleAPIConstants.BASE_ADDRESS, AnoleAPIConstants.FLASH_DATA_REGISTER, PROMFlasher.CmdProgram);
         return true;
     }

     /// <summary>
     /// Sets the start and end addresses.
     /// </summary>
     /// <param name="mcsFile">The MCS file.</param>
     private void SetStartAndEndAddress(int startAddress, int endAddress)
     {
         StringBuilder startAddressCmdString = new StringBuilder();
         startAddressCmdString.AppendFormat("{0:X4}", PROMFlasher.CmdStartAddress);
         startAddressCmdString.AppendFormat("{0:X4}", startAddress);

         // Write StartAddr to Buffer
         FPGACommunicationHandler.FPGAInstance.WriteToFPGARegister(AnoleAPIConstants.BASE_ADDRESS, AnoleAPIConstants.FLASH_DATA_REGISTER, Convert.ToInt32(startAddressCmdString.ToString(), 16));

         // Build end address command string
         StringBuilder endAddressCmdString = new StringBuilder();
         endAddressCmdString.AppendFormat("{0:X2}", PROMFlasher.CmdEndAddress);
         endAddressCmdString.AppendFormat("{0:X6}", endAddress);

         // Write EndAddr to Buffer
         FPGACommunicationHandler.FPGAInstance.WriteToFPGARegister(AnoleAPIConstants.BASE_ADDRESS, AnoleAPIConstants.FLASH_DATA_REGISTER, Convert.ToInt32(endAddressCmdString.ToString(), 16));
     }

     /// <summary>
     /// Programs the PROM.
     /// </summary>
     /// <param name="mcsFile">The MCS file.</param>
     /// <returns>
     /// Status of programming. <c>true</c> if successful; otherwise <c>false</c>.
     /// </returns>
     private bool Program(MCSFile mcsFile)
     {

         System.Threading.Thread.Sleep(500);
         // Start writing data for programming.
         int wordCounter = 0;
         double TotalWordsSentToFPGA = 0;
         _UpgradePercentage = 0;
         foreach (UInt32 dataWord in mcsFile.DataInWords)
         {

             if (wordCounter < PROMFlasher.ProgramChunkSizeInWords)
             {
                 // Chunksize of words not written yet. Continue writing without status check.
                 FPGACommunicationHandler.FPGAInstance.WriteToFPGARegister(AnoleAPIConstants.BASE_ADDRESS, AnoleAPIConstants.FLASH_DATA_REGISTER, (int)dataWord);
                 wordCounter++;
                 TotalWordsSentToFPGA++;
             }
             else
             {
                 if (!this.CheckAndWaitForProgramReadyAndProgramError(PROMFlasher.DefaultTimeoutForStatusCheckInMs))
                 {
                     // First time this is failing
                     System.Threading.Thread.Sleep(5000);
                     if (!this.CheckAndWaitForProgramReadyAndProgramError(PROMFlasher.DefaultTimeoutForStatusCheckInMs))
                     {
                         return false;
                     }
                 }

                 // Wait for FIFO availability if it is full.
                 if (!this.CheckFifoFullStatusAndWait(PROMFlasher.DefaultTimeoutForStatusCheckInMs))
                 {
                     return false;
                 }
                 wordCounter = 0;
                 TotalWordsSentToFPGA++;

                 // Write the next word.
                 FPGACommunicationHandler.FPGAInstance.WriteToFPGARegister(AnoleAPIConstants.BASE_ADDRESS, AnoleAPIConstants.FLASH_DATA_REGISTER, (int)dataWord);
		wordCounter++;
             }
              _UpgradePercentage = (int)((TotalWordsSentToFPGA / (mcsFile.DataInWords.Count))* 100 );
         }
         _UpgradePercentage = (int)((TotalWordsSentToFPGA / (mcsFile.DataInWords.Count)) * 100);
         // Final check for programming completed.
         int statusWord = -1;
         FPGACommunicationHandler.FPGAInstance.ReadFromFPGARegister(AnoleAPIConstants.BASE_ADDRESS, AnoleAPIConstants.FLASH_COMMAND_REGISTER, ref statusWord);
         
         // Check Program error.
         if ((Convert.ToInt32(statusWord) & PROMFlasher.ProgramErrorStatusMask) == PROMFlasher.ProgramStatusError)
         {
             return false;
         }
         return true;
     }

     /// <summary>
     /// Checks the and wait for programmer ready status.
     /// </summary>
     /// <param name="timeout">The timeout in milliseconds.</param>
     /// <returns>Status of the check. <c>true</c> if programmer is ready; <c>false</c>If the wait timed out.</returns>
     private bool CheckAndWaitForProgramReady(int timeout)
     {
         int statusWord = -1;
         bool isStatusReady = false;
         bool isTimedOut = false;
         Stopwatch timer = new Stopwatch();
         timer.Start();
         while ((!isStatusReady) && (!isTimedOut))
         {
             FPGACommunicationHandler.FPGAInstance.ReadFromFPGARegister(AnoleAPIConstants.BASE_ADDRESS, AnoleAPIConstants.FLASH_COMMAND_REGISTER, ref statusWord);

             isStatusReady = ((Convert.ToInt32(statusWord) & PROMFlasher.ProgramEraseControllerStatusMask) == PROMFlasher.ProgrammerStatusReady);
             isTimedOut = (timer.ElapsedMilliseconds > timeout);
         }

         // return status.
         if (isTimedOut)
         {
             // Timed out before programmer was ready.
             return false;
         }             
         
         return true;
     }

     /// <summary>
     /// Checks the and wait for ready status and program error.
     /// </summary>
     /// <param name="timeout">The timeout.</param>
     /// <returns>Status of check for Program Ready</returns>
     private bool CheckAndWaitForProgramReadyAndProgramError(int timeout)
     {
         int statusWord = -1;
         bool isStatusReady = false;
         bool isTimedOut = false;
         Stopwatch timer = new Stopwatch();
         timer.Start();
         while ((!isStatusReady) && (!isTimedOut))
         {
             FPGACommunicationHandler.FPGAInstance.ReadFromFPGARegister(AnoleAPIConstants.BASE_ADDRESS, AnoleAPIConstants.FLASH_COMMAND_REGISTER, ref statusWord);

             isStatusReady = ((Convert.ToInt32(statusWord) & PROMFlasher.ProgramEraseControllerStatusMask) == PROMFlasher.ProgrammerStatusReady);
             isTimedOut = (timer.ElapsedMilliseconds > timeout);

             System.Threading.Thread.Sleep(5);
             // Check Program error.
             if ((Convert.ToInt32(statusWord) & PROMFlasher.ProgramErrorStatusMask) == PROMFlasher.ProgramStatusError)
             {
                 return false;
             }
         }
         // return status.
         if (isTimedOut)
         {
             return false;
         } 
       
         return true;
     }

     /// <summary>
     /// Checks the PRG_Ready bit and waits for it to be set.
     /// </summary>
     /// <param name="timeOut">The time out.</param>
     /// <returns>Satus of wait</returns>
     private bool CheckPrgReadyAndWait(int timeOut)
     {
         int statusWord = -1;
         bool isProgReady = false;
         bool isTimedOut = false;
         Stopwatch timer = new Stopwatch();
         timer.Start();

         while (!isProgReady && !isTimedOut)
         {
             FPGACommunicationHandler.FPGAInstance.ReadFromFPGARegister(AnoleAPIConstants.BASE_ADDRESS, AnoleAPIConstants.FLASH_COMMAND_REGISTER, ref statusWord);

             isProgReady = (statusWord & PROMFlasher.ProgReadyBitMask) == PROMFlasher.ProgReadyValue;
             isTimedOut = timer.ElapsedMilliseconds > timeOut;
         }
        
         if (isTimedOut)
         {
             return false;
         }

         return true;
     }

     /// <summary>
     /// Checks the FIFO full status and waits for it to be reset.
     /// </summary>
     /// <returns>Satus of wait</returns>
     private bool CheckFifoFullStatusAndWait(int timeOut)
     {
         int statusWord = -1; 
         bool isFifoAvailable = false;
         bool isTimedOut = false;
         Stopwatch timer = new Stopwatch();
         timer.Start();
         while (!isFifoAvailable && !isTimedOut)
         {
             FPGACommunicationHandler.FPGAInstance.ReadFromFPGARegister(AnoleAPIConstants.BASE_ADDRESS, AnoleAPIConstants.FLASH_COMMAND_REGISTER, ref statusWord);

             isFifoAvailable = (statusWord & PROMFlasher.FifoFullStatusMask) != PROMFlasher.FifoFullValue;
             isTimedOut = timer.ElapsedMilliseconds > timeOut;
         }

         if (isTimedOut)
         {
             return false;
         }
         return true;
     }
 }
Editor is loading...
Leave a Comment