mirror of
https://github.com/saymrwulf/xous-core.git
synced 2026-11-15 08:30:02 +00:00
emulation: MX66UM1G45G: add BackingFile property
The `BackingFile` property can be set to a file path in order to make flash writes persist across runs. Signed-off-by: Sean Cross <sean@xobs.io>
This commit is contained in:
parent
406737ebf3
commit
210d0c7fe3
1 changed files with 102 additions and 0 deletions
|
|
@ -5,6 +5,7 @@
|
|||
// Full license text is available in 'licenses/MIT.txt'.
|
||||
//
|
||||
using System;
|
||||
using System.IO;
|
||||
using Antmicro.Renode.Core.Structure.Registers;
|
||||
using Antmicro.Renode.Exceptions;
|
||||
using Antmicro.Renode.Logging;
|
||||
|
|
@ -139,6 +140,85 @@ namespace Antmicro.Renode.Peripherals.SPI
|
|||
return 0;
|
||||
}
|
||||
|
||||
private string InternalBackingFileName;
|
||||
private FileStream InternalBackingFile;
|
||||
public string BackingFile
|
||||
{
|
||||
get { return InternalBackingFileName; }
|
||||
set
|
||||
{
|
||||
// If the user passes an empty string, don't do anything.
|
||||
if (string.IsNullOrEmpty(value))
|
||||
{
|
||||
this.Log(LogLevel.Error, "Unconfiguring backing file");
|
||||
if (InternalBackingFile != null)
|
||||
{
|
||||
InternalBackingFile.Close();
|
||||
}
|
||||
InternalBackingFileName = null;
|
||||
InternalBackingFile = null;
|
||||
return;
|
||||
}
|
||||
|
||||
// Ensure the path name is fully-qualified, using the current working
|
||||
// directory if necessary.
|
||||
if (System.IO.Path.IsPathRooted(value))
|
||||
{
|
||||
InternalBackingFileName = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
InternalBackingFileName = System.IO.Path.Combine(Environment.CurrentDirectory, value);
|
||||
}
|
||||
try
|
||||
{
|
||||
this.Log(LogLevel.Debug, "Trying to load or create backing file {0}", InternalBackingFileName);
|
||||
InternalBackingFile = new FileStream(InternalBackingFileName, FileMode.OpenOrCreate, FileAccess.ReadWrite);
|
||||
// Assume that if the length is 0, then the file was just created and we need
|
||||
// to copy RAM into the newly-created file.
|
||||
if (InternalBackingFile.Length == 0)
|
||||
{
|
||||
this.Log(LogLevel.Debug, "Backing file {0} was created, dumping {1} bytes of ROM to backing file", InternalBackingFileName, underlyingMemory.Size);
|
||||
// 4096 is a safe size, since that is the page size.
|
||||
byte[] copyBuffer = new byte[4096];
|
||||
var currentOffset = 0;
|
||||
for (currentOffset = 0; currentOffset < underlyingMemory.Size; currentOffset += copyBuffer.Length)
|
||||
{
|
||||
underlyingMemory.ReadBytes(currentOffset, copyBuffer.Length, copyBuffer, 0);
|
||||
InternalBackingFile.Write(copyBuffer, 0, copyBuffer.Length);
|
||||
}
|
||||
}
|
||||
// If the length is NOT 0, read data from the backing file
|
||||
else
|
||||
{
|
||||
this.Log(LogLevel.Debug, "Backing file {0} was loaded, restoring {1} bytes (vs ROM: {2}) of ROM from file", InternalBackingFileName, InternalBackingFile.Length, underlyingMemory.Size);
|
||||
InternalBackingFile.Seek(0, SeekOrigin.Begin);
|
||||
// 4096 is a safe size, since that is the page size.
|
||||
byte[] copyBuffer = new byte[4096];
|
||||
var currentOffset = 0;
|
||||
for (currentOffset = 0;
|
||||
(currentOffset < underlyingMemory.Size) && (currentOffset < InternalBackingFile.Length);
|
||||
currentOffset += copyBuffer.Length)
|
||||
{
|
||||
InternalBackingFile.Read(copyBuffer, 0, copyBuffer.Length);
|
||||
underlyingMemory.WriteBytes(currentOffset, copyBuffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
if (InternalBackingFile != null)
|
||||
{
|
||||
InternalBackingFile.Close();
|
||||
}
|
||||
InternalBackingFileName = null;
|
||||
InternalBackingFile = null;
|
||||
throw new RecoverableException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public MappedMemory UnderlyingMemory => underlyingMemory;
|
||||
|
||||
private void AccumulateAddressBytes(byte addressByte, DecodedOperation.OperationState nextState)
|
||||
|
|
@ -537,6 +617,11 @@ namespace Antmicro.Renode.Peripherals.SPI
|
|||
var length = (int)Math.Min(SegmentSize, underlyingMemory.Size - position);
|
||||
|
||||
underlyingMemory.WriteBytes(position, segment, length);
|
||||
if (InternalBackingFile != null)
|
||||
{
|
||||
InternalBackingFile.Seek(position, SeekOrigin.Begin);
|
||||
InternalBackingFile.Write(segment, 0, length);
|
||||
}
|
||||
position += length;
|
||||
}
|
||||
}
|
||||
|
|
@ -553,6 +638,11 @@ namespace Antmicro.Renode.Peripherals.SPI
|
|||
|
||||
var position = SegmentSize * (currentOperation.ExecutionAddress / SegmentSize);
|
||||
underlyingMemory.WriteBytes(position, segment);
|
||||
if (InternalBackingFile != null)
|
||||
{
|
||||
InternalBackingFile.Seek(position, SeekOrigin.Begin);
|
||||
InternalBackingFile.Write(segment, 0, segment.Length);
|
||||
}
|
||||
}
|
||||
|
||||
private void EraseSubsector4K()
|
||||
|
|
@ -567,6 +657,11 @@ namespace Antmicro.Renode.Peripherals.SPI
|
|||
|
||||
var position = 4.KB() * (currentOperation.ExecutionAddress / 4.KB());
|
||||
underlyingMemory.WriteBytes(position, segment);
|
||||
if (InternalBackingFile != null)
|
||||
{
|
||||
InternalBackingFile.Seek(position, SeekOrigin.Begin);
|
||||
InternalBackingFile.Write(segment, 0, segment.Length);
|
||||
}
|
||||
}
|
||||
|
||||
private void WriteToMemory(byte val)
|
||||
|
|
@ -579,6 +674,13 @@ namespace Antmicro.Renode.Peripherals.SPI
|
|||
|
||||
var position = currentOperation.ExecutionAddress + currentOperation.CommandBytesHandled;
|
||||
underlyingMemory.WriteByte(position, val);
|
||||
if (InternalBackingFile != null)
|
||||
{
|
||||
var tmp_byte = new byte[1];
|
||||
tmp_byte[0] = val;
|
||||
InternalBackingFile.Seek(position, SeekOrigin.Begin);
|
||||
InternalBackingFile.Write(tmp_byte, 0, 1);
|
||||
}
|
||||
}
|
||||
|
||||
private byte ReadFromMemory()
|
||||
|
|
|
|||
Loading…
Reference in a new issue