Skip to content

Commit

Permalink
Rework PSRAM detection (#270)
Browse files Browse the repository at this point in the history
  • Loading branch information
josesimoes authored May 28, 2024
1 parent 7239fa4 commit cf43d26
Show file tree
Hide file tree
Showing 21 changed files with 164 additions and 55 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,8 @@ To show the details of the ESP32 device connected to COM31.
nanoff --platform esp32 --serialport COM31 --devicedetails
```

Optionally an extra parameter `--checkpsram` can be passed, which forces the detection of PSRAM availability.

### Deploy a managed application to an ESP32 target

To deploy a managed application to an ESP32_PSRAM_REV0 target connected to COM31.
Expand Down
2 changes: 2 additions & 0 deletions README.zh-cn.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,8 @@ nanoff --update --target KALUGA_1 --serialport COM31 --clrfile "C:\nf-interprete
nanoff --platform esp32 --serialport COM31 --devicedetails
```

可选地,可以传递额外的参数 `--checkpsram`,它会强制检测PSRAM的可用性。

### 将托管应用程序部署到ESP32设备

将托管应用程序部署到连接到COM31的ESP32_PSRAM_REV0设备上。
Expand Down
Binary file modified lib/esp32bootloader/bootloader.bin
Binary file not shown.
Binary file removed lib/esp32bootloader/partitions_16mb.bin
Binary file not shown.
Binary file modified lib/esp32bootloader/partitions_2mb.bin
Binary file not shown.
Binary file removed lib/esp32bootloader/partitions_8mb.bin
Binary file not shown.
Binary file modified lib/esp32bootloader/test_startup.bin
Binary file not shown.
Binary file modified lib/esp32s2bootloader/bootloader.bin
Binary file not shown.
Binary file removed lib/esp32s2bootloader/partitions_16mb.bin
Binary file not shown.
Binary file removed lib/esp32s2bootloader/partitions_2mb.bin
Binary file not shown.
Binary file modified lib/esp32s2bootloader/partitions_4mb.bin
Binary file not shown.
Binary file removed lib/esp32s2bootloader/partitions_8mb.bin
Binary file not shown.
Binary file modified lib/esp32s2bootloader/test_startup.bin
Binary file not shown.
Binary file added lib/esp32s3bootloader/bootloader.bin
Binary file not shown.
File renamed without changes.
Binary file added lib/esp32s3bootloader/test_startup.bin
Binary file not shown.
11 changes: 9 additions & 2 deletions nanoFirmwareFlasher.Library/Esp32DeviceInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,11 @@ public class Esp32DeviceInfo
/// </summary>
public PSRamAvailability PSRamAvailable { get; }

/// <summary>
/// The size of the PSRAM (in MBytes).
/// </summary>
public int PsRamSize { get; }

/// <summary>
/// Constructor.
/// </summary>
Expand All @@ -85,7 +90,8 @@ public Esp32DeviceInfo(
byte flashManufacturerId,
short flashDeviceModelId,
int flashSize,
PSRamAvailability psramAvailability)
PSRamAvailability psramAvailability,
int psRamSize)
{
ChipType = chipType;
ChipName = chipName;
Expand All @@ -96,6 +102,7 @@ public Esp32DeviceInfo(
FlashDeviceId = flashDeviceModelId;
FlashSize = flashSize;
PSRamAvailable = psramAvailability;
PsRamSize = psRamSize;
}

internal string GetFlashSizeAsString()
Expand Down Expand Up @@ -140,7 +147,7 @@ public override string ToString()
break;

case PSRamAvailability.Yes:
deviceInfo.AppendLine($"PSRAM: available");
deviceInfo.AppendLine($"PSRAM: {PsRamSize}MB");
break;

case PSRamAvailability.No:
Expand Down
160 changes: 108 additions & 52 deletions nanoFirmwareFlasher.Library/EspTool.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public partial class EspTool
private readonly string _serialPort = null;

/// <summary>
/// The baud rate for the serial port. The default comming from <see cref="Options.BaudRate"/>.
/// The baud rate for the serial port. The default comming from CLI Options.BaudRate./>.
/// </summary>
private int _baudRate = 0;

Expand All @@ -43,6 +43,8 @@ public partial class EspTool
/// </summary>
private int _flashSize = -1;



private bool connectPatternFound;

private DateTime connectTimeStamp;
Expand Down Expand Up @@ -120,7 +122,7 @@ public EspTool(
}
else
{
if (!File.Exists(serialPort))
if (!System.IO.File.Exists(serialPort))
{
throw new EspToolExecutionException();
}
Expand All @@ -143,7 +145,8 @@ public EspTool(
/// <returns>The filled info structure with all the information about the connected ESP32 device or null if an error occured</returns>
public Esp32DeviceInfo GetDeviceDetails(
string targetName,
bool requireFlashSize = true)
bool requireFlashSize = true,
bool forcePsRamCheck = false)
{
string messages;

Expand Down Expand Up @@ -232,36 +235,22 @@ public Esp32DeviceInfo GetDeviceDetails(
// lower case, no hifen
_chipType = chipType.ToLower().Replace("-", "");

// try to find out if PSRAM is present
PSRamAvailability psramIsAvailable = PSRamAvailability.Undetermined;
int psRamSize = 0;

if (name.Contains("PICO"))
if (_chipType == "esp32c3"
|| _chipType == "esp32c6"
|| _chipType == "esp32h2")
{
// PICO's don't have PSRAM, so don't even bother
// these series doesn't have PSRAM
psramIsAvailable = PSRamAvailability.No;
}
else if (name.Contains("ESP32-S2")
&& targetName == "FEATHER_S2")
{
// FEATHER_S2's have PSRAM, so don't even bother
psramIsAvailable = PSRamAvailability.Yes;
}
else if (name.Contains("ESP32-C3")
|| name.Contains("ESP32-S3"))
{
// all ESP32-C3/S3 SDK config have support for PSRAM, so don't even bother
psramIsAvailable = PSRamAvailability.Undetermined;
}
else
{
// if a target name wasn't provided, check for PSRAM
// except for ESP32_C3 and S3
if (targetName == null
&& !name.Contains("ESP32-C3")
&& !name.Contains("ESP32-S3"))
{
psramIsAvailable = FindPSRamAvailable();
}
//try to find out if PSRAM is present
psramIsAvailable = FindPSRamAvailable(
out psRamSize,
forcePsRamCheck);
}

if (Verbosity >= VerbosityLevel.Normal)
Expand All @@ -280,51 +269,95 @@ public Esp32DeviceInfo GetDeviceDetails(
byte.Parse(manufacturer, NumberStyles.AllowHexSpecifier),
short.Parse(device, NumberStyles.HexNumber),
_flashSize,
psramIsAvailable);
psramIsAvailable,
psRamSize);
}

/// <summary>
/// Perform detection of PSRAM availability on connected device.
/// </summary>
/// <param name="force">Force the detection of PSRAM availability.</param>
/// <param name="psRamSize">Size of the PSRAM device, if detection was succesfull.</param>
/// <returns>Information about availability of PSRAM, if that was possible to determine.</returns>
private PSRamAvailability FindPSRamAvailable()
private PSRamAvailability FindPSRamAvailable(
out int psRamSize,
bool force = false)
{
PSRamAvailability pSRamAvailability = PSRamAvailability.Undetermined;

// don't want to output anything from esptool
// backup current verbosity setting
var bkpVerbosity = Verbosity;
Verbosity = VerbosityLevel.Quiet;

// compose bootloader partition
var bootloaderPartition = new Dictionary<int, string>
// default to no PSRAM
psRamSize = 0;

try
{
// bootloader goes to 0x1000, except for ESP32_C3 and ESP32_S3, which goes to 0x0
{ _chipType == "esp32c3" || _chipType == "esp32s3" ? 0x0 : 0x1000, Path.Combine(Utilities.ExecutingPath, $"{_chipType}bootloader", "bootloader.bin") },
// if forced, run the test app to determine PSRAM availability
if (force)
{
// adjust flash size according to the series
// defautl to 2MB for ESP32 series
var flashSize = 2 * 1024 * 1024;

// nanoCLR goes to 0x10000
{ 0x10000, Path.Combine(Utilities.ExecutingPath, $"{_chipType}bootloader", "test_startup.bin") },
if(_chipType == "esp32s2"
|| _chipType == "esp32s3")
{
flashSize = 4 * 1024 * 1024;
}

// partition table goes to 0x8000; there are partition tables for 2MB, 4MB, 8MB and 16MB flash sizes
{ 0x8000, Path.Combine(Utilities.ExecutingPath, $"{_chipType}bootloader", $"partitions_{Esp32DeviceInfo.GetFlashSizeAsString(_flashSize).ToLowerInvariant()}.bin") }
};
// compose bootloader partition
var bootloaderPartition = new Dictionary<int, string>
{
// bootloader goes to 0x1000, except for ESP32_S3, which goes to 0x0
{ _chipType == "esp32s3" ? 0x0 : 0x1000, Path.Combine(Utilities.ExecutingPath, $"{_chipType}bootloader", "bootloader.bin") },

// nanoCLR goes to 0x10000
{ 0x10000, Path.Combine(Utilities.ExecutingPath, $"{_chipType}bootloader", "test_startup.bin") },

// partition table goes to 0x8000; there are partition tables for 2MB, 4MB, 8MB and 16MB flash sizes
{ 0x8000, Path.Combine(Utilities.ExecutingPath, $"{_chipType}bootloader", $"partitions_{Esp32DeviceInfo.GetFlashSizeAsString(flashSize).ToLowerInvariant()}.bin") }
};

// need to use standard baud rate here because of boards put in download mode
if (WriteFlash(bootloaderPartition, true) != ExitCodes.OK)
{
// something went wrong, can't determine PSRAM availability
return PSRamAvailability.Undetermined;
}
}
else
{
// execute run command to force soft reset
// if the device is running a nanoFramework image, it will output information about the PSRAM
if (!RunEspTool(
$" run ",
true,
true,
true,
'\r',
out _))
{
// something went wrong, can't determine PSRAM availability
return PSRamAvailability.Undetermined;
}
}

// need to use standard baud rate here because of boards put in download mode
if (WriteFlash(bootloaderPartition, true) == ExitCodes.OK)
{
// check if the
if (_esptoolMessage.Contains("esptool.py can not exit the download mode over USB"))
{
// this board was put on download mode manually, can't run the test app...

return PSRamAvailability.Undetermined;
}

try
{
// open COM port and grab output
// force baud rate to 115200 (standard baud rate for boootloader)
SerialPort espDevice = new SerialPort(_serialPort, 115200);
SerialPort espDevice = new(
_serialPort,
115200);

// open COM port and grab output
espDevice.Open();

if (espDevice.IsOpen)
Expand All @@ -337,14 +370,35 @@ private PSRamAvailability FindPSRamAvailable()

espDevice.Close();

// find magic string
// look for "magic" string

if (bootloaderOutput.Contains("PSRAM initialized"))
{
pSRamAvailability = PSRamAvailability.Yes;
// output similiar to this:
// I(206) esp_psram: Found 4MB PSRAM device
// I(206) esp_psram: Speed: 40MHz
// I(209) esp_psram: PSRAM initialized, cache is in low / high(2 - core) mode.

// extract PSRAM size
var match = Regex.Match(bootloaderOutput, @"Found (?<size>\d+)MB PSRAM device");
if (match.Success)
{
psRamSize = int.Parse(match.Groups["size"].Value);
}

return PSRamAvailability.Yes;
}
else if (bootloaderOutput.Contains("PSRAM ID read error"))
{
// output similiar to this:
// E(206) quad_psram: PSRAM ID read error: 0xffffffff, PSRAM chip not found or not supported
// E(210) esp_psram: PSRAM enabled but initialization failed.Bailing out.
return PSRamAvailability.No;
}
else
{
pSRamAvailability = PSRamAvailability.No;
// can't determine PSRAM availability
return PSRamAvailability.Undetermined;
}
}
}
Expand All @@ -353,11 +407,13 @@ private PSRamAvailability FindPSRamAvailable()
// don't care about any exceptions
}
}
finally
{
// restore verbosity setting
Verbosity = bkpVerbosity;
}

// restore verbosity setting
Verbosity = bkpVerbosity;

return pSRamAvailability;
return PSRamAvailability.Undetermined;
}

/// <summary>
Expand Down
31 changes: 31 additions & 0 deletions nanoFirmwareFlasher.Library/nanoFirmwareFlasher.Library.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@
</None>
<None Include="..\lib\esp32s2bootloader\**" Link="esp32s2bootloader\%(RecursiveDir)%(Filename)%(Extension)">
</None>
<None Include="..\lib\esp32s3bootloader\**" Link="esp32s3bootloader\%(RecursiveDir)%(Filename)%(Extension)">
</None>
</ItemGroup>

<!-- STLink executables for all platforms -->
Expand Down Expand Up @@ -128,5 +130,34 @@
<None Include="..\lib\uniflash\**" Link="uniflash\%(RecursiveDir)%(Filename)%(Extension)">
</None>
</ItemGroup>
<ItemGroup>
<None Update="..\lib\esp32bootloader\bootloader.bin">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="..\lib\esp32bootloader\partitions_2mb.bin">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="..\lib\esp32bootloader\test_startup.bin">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="..\lib\esp32s2bootloader\bootloader.bin">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="..\lib\esp32s2bootloader\partitions_4mb.bin">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="..\lib\esp32s2bootloader\test_startup.bin">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="..\lib\esp32s3bootloader\bootloader.bin">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="..\lib\esp32s3bootloader\partitions_4mb.bin">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="..\lib\esp32s3bootloader\test_startup.bin">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>

</Project>
6 changes: 5 additions & 1 deletion nanoFirmwareFlasher.Tool/Esp32Manager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,11 @@ public async Task<ExitCodes> ProcessAsync()

if (espTool.ComPortAvailable)
{
esp32Device = espTool.GetDeviceDetails(_options.TargetName, _options.Esp32PartitionTableSize == null);
esp32Device = espTool.GetDeviceDetails(
_options.TargetName,
// if partition table size is specified, no need to get flash size
_options.Esp32PartitionTableSize == null,
_options.CheckPsRam);
}
else
{
Expand Down
7 changes: 7 additions & 0 deletions nanoFirmwareFlasher.Tool/Options.cs
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,13 @@ public class Options
HelpText = "Partition table size to use. Valid sizes are: 2, 4, 8 and 16.")]
public PartitionTableSize? Esp32PartitionTableSize { get; set; }

[Option(
"checkpsram",
Required = false,
Default = false,
HelpText = "Perform check for PSRAM in device.")]
public bool CheckPsRam { get; set; }

#endregion


Expand Down

0 comments on commit cf43d26

Please sign in to comment.