Untitled
unknown
plain_text
a year ago
12 kB
4
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