Skip to content

Commit d5d164c

Browse files
authored
Merge pull request #12 from nanoframework/release-v1.2.0
Release release-v1.2.0
2 parents b2f9498 + 0159b5b commit d5d164c

21 files changed

+543
-120
lines changed

README.md

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -60,12 +60,22 @@ The tool includes help for all available commands. You can see a list of all ava
6060
nanoff --help
6161
```
6262

63-
### Update the firmware of an ESP32 target
63+
### Update the firmware of an ESP32_WROOM_32 target
6464

65-
To update the firmware of an ESP32 target connected to COM31, to the latest available development version.
65+
To update the firmware of an ESP32_WROOM_32 target connected to COM31, to the latest available development version.
66+
67+
```console
68+
nanoff --update --target ESP32_WROOM_32 --serialport COM31
69+
```
70+
71+
### Deploy a managed application to an ESP32_WROOM_32 target
72+
73+
To deploy a managed application to an ESP32_WROOM_32 target connected to COM31, which has the deployment region at 0x190000 flash address.
74+
75+
>Note: The binary file with the deployment image can be found on the Release or Debug folder of a Visual Studio project after a successful build. This file contains everything that's required to deploy a managed application to a target (meaning application executable and all referenced libraries and assemblies).
6676
6777
```console
68-
nanoff --update --platform esp32 --serialport COM31
78+
nanoff --target ESP32_WROOM_32 --serialport COM12 --deploy --image "E:\GitHub\nf-Samples\samples\Blinky\Blinky\bin\Debug\Blinky.bin" --address 0x190000
6979
```
7080

7181
### Update the firmware of an ESP32 target along with a managed application
@@ -75,7 +85,7 @@ You have to specify the path to the managed application.
7585
This example uses the binary format file that was saved on a previous backup operation.
7686

7787
```console
78-
nanoff --update --platform esp32 --serialport COM31 --deployment "c:\eps32-backups\my_awesome_app.bin"
88+
nanoff --update --target ESP32_WROOM_32 --serialport COM31 --deployment "c:\eps32-backups\my_awesome_app.bin"
7989
```
8090

8191
### Update the firmware of a specific STM32 target
@@ -86,6 +96,16 @@ To update the firmware of the NETDUINO3_WIFI target to the latest available stab
8696
nanoff --update --target NETDUINO3_WIFI --stable
8797
```
8898

99+
### Deploy a managed application to a ST_STM32F769I_DISCOVERY target
100+
101+
To deploy a managed application to a ST_STM32F769I_DISCOVERY target, which has the deployment region at 0x08080000 flash address and reset the MCU after flashing it.
102+
103+
>Note: The binary file with the deployment image can be found on the Release or Debug folder of a Visual Studio project after a successful build. This file contains everything that's required to deploy a managed application to a target (meaning application executable and all referenced libraries and assemblies).
104+
105+
```console
106+
nanoff --target ST_STM32F769I_DISCOVERY --deploy --image "E:\GitHub\nf-Samples\samples\Blinky\Blinky\bin\Debug\Blinky.bin" --address 0x08040000 --reset
107+
```
108+
89109
### Update the firmware of a ST_STM32F769I_DISCOVERY along with a managed application
90110

91111
To update the firmware of the ST_STM32F769I_DISCOVERY target to the latest available preview version along with a managed application.
@@ -144,7 +164,7 @@ The list of contributors to this project can be found at [CONTRIBUTORS](https://
144164

145165
## License
146166

147-
The **nanoFramework** ESP32 firmware flasher tool is licensed under the [MIT license](https://opensource.org/licenses/MIT).
167+
The **nanoFramework** firmware flasher tool is licensed under the [MIT license](https://opensource.org/licenses/MIT).
148168

149169
## Code of Conduct
150170

azure-pipelines.yml

Lines changed: 117 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,9 @@ trigger:
22
branches:
33
include: ["master", "develop", "release*", "refs/tags/*" ]
44
paths:
5-
exclude: [ "doc", "*.md", ".gitignore" ]
5+
exclude: [ "doc", "*.md", ".gitignore", "README.md" ]
66

7-
pr:
8-
branches:
9-
include: ["master", "develop", "release*"]
10-
autoCancel: true
7+
# no pr config, we want to trigger builds for all PRs on all branches
118

129
# add nf-tools repo to resources (for Azure Pipelines templates)
1310
resources:
@@ -20,15 +17,107 @@ resources:
2017
jobs:
2118

2219
##############################
23-
- job: Get_Build_Options
20+
- job: Check_Build_Options
2421
pool:
2522
vmImage: 'VS2017-Win2016'
2623

2724
steps:
25+
2826
- checkout: self
2927

28+
# get commint message
29+
- powershell: |
30+
31+
if($env:StartReleaseCandidate -like "true")
32+
{
33+
# this is a release prep so NO build
34+
echo "##vso[task.setvariable variable=SKIP_BUILD;isOutput=true]true"
35+
36+
Write-Host "Release preparation, skipping build."
37+
}
38+
39+
name: BuildOptions
40+
displayName: Evaluate build options
41+
42+
- task: DotNetCoreCLI@2
43+
inputs:
44+
command: custom
45+
custom: tool
46+
arguments: install -g nbgv
47+
condition: or( eq( variables['StartReleaseCandidate'], true ), ne(variables['system.pullrequest.isfork'], true) )
48+
displayName: Install NBGV tool
49+
50+
- powershell: |
51+
52+
# compute authorization header in format "AUTHORIZATION: basic 'encoded token'"
53+
# 'encoded token' is the Base64 of the string "nfbot:personal-token"
54+
$auth = "basic $([System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes("nfbot:$(GitHubToken)"))))"
55+
56+
cd "$env:Agent_TempDirectory" > $null
57+
58+
git init "$env:Agent_TempDirectory\repo"
59+
cd repo > $null
60+
git remote add origin "$env:Build_Repository_Uri"
61+
git config --global gc.auto 0
62+
git config --global user.name nfbot
63+
git config --global user.email [email protected]
64+
git config --global core.autocrlf true
65+
git -c http.extraheader="AUTHORIZATION: $auth" fetch --progress origin
66+
67+
git checkout develop
68+
69+
cd source
70+
71+
# prepare release and capture output
72+
$release = nbgv prepare-release
73+
74+
# get commit message for the merge
75+
$commitMessage = git log -1 --pretty=%B
76+
77+
# amend commit message to skip build
78+
git commit --amend -m "$commitMessage" -m "***NO_CI***" > $null
79+
80+
# push all changes to github
81+
git -c http.extraheader="AUTHORIZATION: $auth" push --all origin
82+
83+
# get release branch name
84+
$branch = $release.Split(' ')[0]
85+
86+
# start PR for release
87+
$prRequestBody = @{title="Release $branch";body="";head="$branch";base="master"} | ConvertTo-Json
88+
$githubApiEndpoint = "https://api.github.com/repos/$env:Build_Repository_Name/pulls"
89+
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
90+
91+
$headers = @{}
92+
$headers.Add("Authorization","$auth")
93+
$headers.Add("Accept","application/vnd.github.symmetra-preview+json")
94+
95+
try
96+
{
97+
$result = Invoke-RestMethod -Method Post -UserAgent [Microsoft.PowerShell.Commands.PSUserAgent]::InternetExplorer -Uri $githubApiEndpoint -Header $headers -ContentType "application/json" -Body $prRequestBody
98+
'Started PR for new release...' | Write-Host -NoNewline
99+
'OK' | Write-Host -ForegroundColor Green
100+
}
101+
catch
102+
{
103+
$result = $_.Exception.Response.GetResponseStream()
104+
$reader = New-Object System.IO.StreamReader($result)
105+
$reader.BaseStream.Position = 0
106+
$reader.DiscardBufferedData()
107+
$responseBody = $reader.ReadToEnd();
108+
109+
"Error starting PR: $responseBody" | Write-Host -ForegroundColor Red
110+
}
111+
112+
condition: eq( variables['StartReleaseCandidate'], true )
113+
displayName: NBGV prepare release
114+
115+
###########################################################
30116
# build tool
31117
- job: Build_tool
118+
condition: not( eq( dependencies.Check_Build_Options.outputs['BuildOptions.SKIP_BUILD'], true ) )
119+
dependsOn:
120+
- Check_Build_Options
32121

33122
pool:
34123
vmImage: 'VS2017-Win2016'
@@ -228,3 +317,25 @@ jobs:
228317
githubReleaseAsset: '$(Build.ArtifactStagingDirectory)/$(nugetPackageName).$(MY_NUGET_VERSION).nupkg'
229318
condition: and( succeeded(), startsWith(variables['Build.SourceBranch'], 'refs/tags/v'), not(contains(variables['Build.SourceBranch'], 'preview') ) )
230319
displayName: Create/Update GitHub stable release
320+
321+
##################################
322+
# report build failure to Discord
323+
- job: Report_Build_Failure
324+
dependsOn:
325+
- Check_Build_Options
326+
- Build_tool
327+
condition: or( failed('Check_Build_Options'), failed('Build_tool') )
328+
329+
pool:
330+
vmImage: 'VS2017-Win2016'
331+
332+
steps:
333+
334+
- checkout: self
335+
336+
# step from template @ nf-tools repo
337+
- template: azure-pipelines-templates/discord-webhook.yml@templates
338+
parameters:
339+
status: 'failure'
340+
webhookUrl: '$(DiscordWebhook)'
341+
message: ''

source/nanoFirmwareFlasher/Esp32Operations.cs

Lines changed: 74 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44
//
55

66
using System;
7+
using System.Collections.Generic;
78
using System.IO;
9+
using System.Linq;
810

911
namespace nanoFramework.Tools.FirmwareFlasher
1012
{
@@ -81,14 +83,19 @@ public static ExitCodes BackupFlash(
8183
internal static async System.Threading.Tasks.Task<ExitCodes> UpdateFirmwareAsync(
8284
EspTool espTool,
8385
EspTool.DeviceInfo esp32Device,
84-
string targetName,
86+
string targetName,
87+
bool updateFw,
8588
string fwVersion,
8689
bool stable,
87-
string applicationPath,
90+
string applicationPath,
91+
string deploymentAddress,
8892
VerbosityLevel verbosity)
8993
{
94+
ExitCodes operationResult = ExitCodes.OK;
95+
uint address = 0;
96+
9097
// if a target name wasn't specified use the default (and only available) ESP32 target
91-
if(string.IsNullOrEmpty(targetName))
98+
if (string.IsNullOrEmpty(targetName))
9299
{
93100
targetName = _esp32TargetName;
94101
}
@@ -101,36 +108,77 @@ internal static async System.Threading.Tasks.Task<ExitCodes> UpdateFirmwareAsync
101108
Verbosity = verbosity
102109
};
103110

104-
var operationResult = await firmware.DownloadAndExtractAsync(esp32Device.FlashSize);
105-
if (operationResult == ExitCodes.OK)
111+
// need to download update package?
112+
if (updateFw)
106113
{
114+
operationResult = await firmware.DownloadAndExtractAsync(esp32Device.FlashSize);
115+
if (operationResult != ExitCodes.OK)
116+
{
117+
return operationResult;
118+
}
107119
// download successful
120+
}
108121

109-
// need to include application file?
110-
if(!string.IsNullOrEmpty(applicationPath))
122+
// need to include application file?
123+
if (!string.IsNullOrEmpty(applicationPath))
124+
{
125+
// check application file
126+
if (File.Exists(applicationPath))
111127
{
112-
// check application file
113-
if (File.Exists(applicationPath))
128+
if (!updateFw)
114129
{
115-
string applicationBinary = new FileInfo(applicationPath).FullName;
116-
firmware.FlashPartitions.Add(
117-
firmware.DeploymentPartionAddress,
118-
applicationBinary);
130+
// this is a deployment operation only
131+
// try parsing the deployment address from parameter
132+
// need to remove the leading 0x and to specify that hexadecimal values are allowed
133+
if (!uint.TryParse(deploymentAddress.Substring(2), System.Globalization.NumberStyles.AllowHexSpecifier, System.Globalization.CultureInfo.InvariantCulture, out address))
134+
{
135+
return ExitCodes.E9009;
136+
}
119137
}
120-
else
138+
139+
string applicationBinary = new FileInfo(applicationPath).FullName;
140+
firmware.FlashPartitions = new Dictionary<int, string>()
121141
{
122-
return ExitCodes.E9008;
123-
}
142+
{
143+
updateFw ? firmware.DeploymentPartionAddress : (int)address,
144+
applicationBinary
145+
}
146+
};
124147
}
125-
126-
if (verbosity >= VerbosityLevel.Normal)
148+
else
127149
{
128-
Console.Write($"Erasing flash...");
150+
return ExitCodes.E9008;
129151
}
152+
}
130153

154+
if (verbosity >= VerbosityLevel.Normal)
155+
{
156+
Console.Write($"Erasing flash...");
157+
}
158+
159+
if (updateFw)
160+
{
131161
// erase flash
132-
espTool.EraseFlash();
162+
operationResult = espTool.EraseFlash();
163+
}
164+
else
165+
{
166+
// erase flash segment
167+
168+
// need to get deployment address here
169+
// length must both be multiples of the SPI flash erase sector size. This is 0x1000 (4096) bytes for supported flash chips.
170+
171+
var flashPartition = firmware.FlashPartitions.First();
172+
173+
var fileStream = File.OpenRead(flashPartition.Value);
174+
175+
uint fileLength = (uint)Math.Ceiling((decimal)fileStream.Length / 0x1000) * 0x1000;
176+
177+
operationResult = espTool.EraseFlashSegment(address, fileLength);
178+
}
133179

180+
if (operationResult == ExitCodes.OK)
181+
{
134182
if (verbosity >= VerbosityLevel.Normal)
135183
{
136184
Console.WriteLine("OK");
@@ -142,11 +190,14 @@ internal static async System.Threading.Tasks.Task<ExitCodes> UpdateFirmwareAsync
142190
}
143191

144192
// write to flash
145-
espTool.WriteFlash(firmware.FlashPartitions);
193+
operationResult = espTool.WriteFlash(firmware.FlashPartitions);
146194

147-
if (verbosity >= VerbosityLevel.Normal)
195+
if (operationResult == ExitCodes.OK)
148196
{
149-
Console.WriteLine("OK");
197+
if (verbosity >= VerbosityLevel.Normal)
198+
{
199+
Console.WriteLine("OK");
200+
}
150201
}
151202
}
152203

source/nanoFirmwareFlasher/EspTool.cs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,35 @@ internal ExitCodes EraseFlash()
299299
return ExitCodes.OK;
300300
}
301301

302+
/// <summary>
303+
/// Erase flash segment on the ESP32 chip.
304+
/// </summary>
305+
/// <returns>true if successful</returns>
306+
internal ExitCodes EraseFlashSegment(uint startAddress, uint length)
307+
{
308+
// startAddress and length must both be multiples of the SPI flash erase sector size. This is 0x1000 (4096) bytes for supported flash chips.
309+
// esptool takes care of validating this so no need to perform any sanity check before executing the command
310+
311+
// execute erase_flash command and parse the result
312+
if (!RunEspTool($"erase_region 0x{startAddress:X} 0x{length:X}", false, false, null, out string messages))
313+
{
314+
throw new EraseEsp32FlashException(messages);
315+
}
316+
317+
Match match = Regex.Match(messages, "(?<message>Erase completed successfully.*)(.*?\n)*");
318+
if (!match.Success)
319+
{
320+
throw new EraseEsp32FlashException(messages);
321+
}
322+
323+
if (Verbosity >= VerbosityLevel.Detailed)
324+
{
325+
Console.WriteLine(match.Groups["message"].ToString().Trim());
326+
}
327+
328+
return ExitCodes.OK;
329+
}
330+
302331
/// <summary>
303332
/// Write to the flash
304333
/// </summary>

0 commit comments

Comments
 (0)