├── .gitattributes ├── .gitignore ├── LICENSE ├── README.md ├── STBootLib.sln ├── STBootLib ├── .gitattributes ├── .gitignore ├── Properties │ └── AssemblyInfo.cs ├── STBoot.cs ├── STBootCmds.cs ├── STBootException.cs ├── STBootLib.csproj ├── STBootProgress.cs ├── STBootResps.cs └── STBootTimeout.cs ├── STM32 Flash Loader.sln └── STM32 Flash Loader ├── App.config ├── MainForm.Designer.cs ├── MainForm.cs ├── MainForm.resx ├── Program.cs ├── Properties ├── AssemblyInfo.cs ├── Resources.Designer.cs ├── Resources.resx ├── Settings.Designer.cs └── Settings.settings ├── STM32 Flash Loader.csproj └── arrow.ico /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # Build results 11 | [Dd]ebug/ 12 | [Dd]ebugPublic/ 13 | [Rr]elease/ 14 | [Rr]eleases/ 15 | x64/ 16 | x86/ 17 | build/ 18 | bld/ 19 | [Bb]in/ 20 | [Oo]bj/ 21 | 22 | # Roslyn cache directories 23 | *.ide/ 24 | 25 | # MSTest test Results 26 | [Tt]est[Rr]esult*/ 27 | [Bb]uild[Ll]og.* 28 | 29 | #NUNIT 30 | *.VisualState.xml 31 | TestResult.xml 32 | 33 | # Build Results of an ATL Project 34 | [Dd]ebugPS/ 35 | [Rr]eleasePS/ 36 | dlldata.c 37 | 38 | *_i.c 39 | *_p.c 40 | *_i.h 41 | *.ilk 42 | *.meta 43 | *.obj 44 | *.pch 45 | *.pdb 46 | *.pgc 47 | *.pgd 48 | *.rsp 49 | *.sbr 50 | *.tlb 51 | *.tli 52 | *.tlh 53 | *.tmp 54 | *.tmp_proj 55 | *.log 56 | *.vspscc 57 | *.vssscc 58 | .builds 59 | *.pidb 60 | *.svclog 61 | *.scc 62 | 63 | # Chutzpah Test files 64 | _Chutzpah* 65 | 66 | # Visual C++ cache files 67 | ipch/ 68 | *.aps 69 | *.ncb 70 | *.opensdf 71 | *.sdf 72 | *.cachefile 73 | 74 | # Visual Studio profiler 75 | *.psess 76 | *.vsp 77 | *.vspx 78 | 79 | # TFS 2012 Local Workspace 80 | $tf/ 81 | 82 | # Guidance Automation Toolkit 83 | *.gpState 84 | 85 | # ReSharper is a .NET coding add-in 86 | _ReSharper*/ 87 | *.[Rr]e[Ss]harper 88 | *.DotSettings.user 89 | 90 | # JustCode is a .NET coding addin-in 91 | .JustCode 92 | 93 | # TeamCity is a build add-in 94 | _TeamCity* 95 | 96 | # DotCover is a Code Coverage Tool 97 | *.dotCover 98 | 99 | # NCrunch 100 | _NCrunch_* 101 | .*crunch*.local.xml 102 | 103 | # MightyMoose 104 | *.mm.* 105 | AutoTest.Net/ 106 | 107 | # Web workbench (sass) 108 | .sass-cache/ 109 | 110 | # Installshield output folder 111 | [Ee]xpress/ 112 | 113 | # DocProject is a documentation generator add-in 114 | DocProject/buildhelp/ 115 | DocProject/Help/*.HxT 116 | DocProject/Help/*.HxC 117 | DocProject/Help/*.hhc 118 | DocProject/Help/*.hhk 119 | DocProject/Help/*.hhp 120 | DocProject/Help/Html2 121 | DocProject/Help/html 122 | 123 | # Click-Once directory 124 | publish/ 125 | 126 | # Publish Web Output 127 | *.[Pp]ublish.xml 128 | *.azurePubxml 129 | # TODO: Comment the next line if you want to checkin your web deploy settings 130 | # but database connection strings (with potential passwords) will be unencrypted 131 | *.pubxml 132 | *.publishproj 133 | 134 | # NuGet Packages 135 | *.nupkg 136 | # The packages folder can be ignored because of Package Restore 137 | **/packages/* 138 | # except build/, which is used as an MSBuild target. 139 | !**/packages/build/ 140 | # If using the old MSBuild-Integrated Package Restore, uncomment this: 141 | #!**/packages/repositories.config 142 | 143 | # Windows Azure Build Output 144 | csx/ 145 | *.build.csdef 146 | 147 | # Windows Store app package directory 148 | AppPackages/ 149 | 150 | # Others 151 | sql/ 152 | *.Cache 153 | ClientBin/ 154 | [Ss]tyle[Cc]op.* 155 | ~$* 156 | *~ 157 | *.dbmdl 158 | *.dbproj.schemaview 159 | *.pfx 160 | *.publishsettings 161 | node_modules/ 162 | 163 | # RIA/Silverlight projects 164 | Generated_Code/ 165 | 166 | # Backup & report files from converting an old project file 167 | # to a newer Visual Studio version. Backup files are not needed, 168 | # because we have git ;-) 169 | _UpgradeReport_Files/ 170 | Backup*/ 171 | UpgradeLog*.XML 172 | UpgradeLog*.htm 173 | 174 | # SQL Server files 175 | *.mdf 176 | *.ldf 177 | 178 | # Business Intelligence projects 179 | *.rdl.data 180 | *.bim.layout 181 | *.bim_*.settings 182 | 183 | # Microsoft Fakes 184 | FakesAssemblies/ 185 | 186 | # ========================= 187 | # Operating System Files 188 | # ========================= 189 | 190 | # OSX 191 | # ========================= 192 | 193 | .DS_Store 194 | .AppleDouble 195 | .LSOverride 196 | 197 | # Thumbnails 198 | ._* 199 | 200 | # Files that might appear on external disk 201 | .Spotlight-V100 202 | .Trashes 203 | 204 | # Directories potentially created on remote AFP share 205 | .AppleDB 206 | .AppleDesktop 207 | Network Trash Folder 208 | Temporary Items 209 | .apdisk 210 | 211 | # Windows 212 | # ========================= 213 | 214 | # Windows image file caches 215 | Thumbs.db 216 | ehthumbs.db 217 | 218 | # Folder config file 219 | Desktop.ini 220 | 221 | # Recycle Bin used on file shares 222 | $RECYCLE.BIN/ 223 | 224 | # Windows Installer files 225 | *.cab 226 | *.msi 227 | *.msm 228 | *.msp 229 | 230 | # Windows shortcuts 231 | *.lnk 232 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Mighty Devices 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # STBootLib 2 | C# library for communicating with STM32 USART (UART) On-Chip Bootloaders, comes with simple Updater application, just to show the potential :) 3 | 4 | Implements basic functionality (no write/read protection). All done in async/await manner. This is my response to ST's crappy Flash Loader Demonstrator, that tends to crash my PC due to some shady Serial Port access routines. 5 | 6 | Here's a post on my blog about this software: http://mightydevices.com/?p=519 7 | -------------------------------------------------------------------------------- /STBootLib.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Express 2013 for Windows Desktop 4 | VisualStudioVersion = 12.0.21005.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "STBootLib", "STBootLib\STBootLib.csproj", "{8EC66A52-5978-481D-A80D-D75CBC6DE918}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "STM32 Flash Loader", "STM32 Flash Loader\STM32 Flash Loader.csproj", "{F2A80228-9234-4748-A61B-F26D3C1EC7FA}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Release|Any CPU = Release|Any CPU 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {8EC66A52-5978-481D-A80D-D75CBC6DE918}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 17 | {8EC66A52-5978-481D-A80D-D75CBC6DE918}.Debug|Any CPU.Build.0 = Debug|Any CPU 18 | {8EC66A52-5978-481D-A80D-D75CBC6DE918}.Release|Any CPU.ActiveCfg = Release|Any CPU 19 | {8EC66A52-5978-481D-A80D-D75CBC6DE918}.Release|Any CPU.Build.0 = Release|Any CPU 20 | {F2A80228-9234-4748-A61B-F26D3C1EC7FA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {F2A80228-9234-4748-A61B-F26D3C1EC7FA}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {F2A80228-9234-4748-A61B-F26D3C1EC7FA}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {F2A80228-9234-4748-A61B-F26D3C1EC7FA}.Release|Any CPU.Build.0 = Release|Any CPU 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | EndGlobal 29 | -------------------------------------------------------------------------------- /STBootLib/.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /STBootLib/.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # Build results 11 | [Dd]ebug/ 12 | [Dd]ebugPublic/ 13 | [Rr]elease/ 14 | [Rr]eleases/ 15 | x64/ 16 | x86/ 17 | build/ 18 | bld/ 19 | [Bb]in/ 20 | [Oo]bj/ 21 | 22 | # Roslyn cache directories 23 | *.ide/ 24 | 25 | # MSTest test Results 26 | [Tt]est[Rr]esult*/ 27 | [Bb]uild[Ll]og.* 28 | 29 | #NUNIT 30 | *.VisualState.xml 31 | TestResult.xml 32 | 33 | # Build Results of an ATL Project 34 | [Dd]ebugPS/ 35 | [Rr]eleasePS/ 36 | dlldata.c 37 | 38 | *_i.c 39 | *_p.c 40 | *_i.h 41 | *.ilk 42 | *.meta 43 | *.obj 44 | *.pch 45 | *.pdb 46 | *.pgc 47 | *.pgd 48 | *.rsp 49 | *.sbr 50 | *.tlb 51 | *.tli 52 | *.tlh 53 | *.tmp 54 | *.tmp_proj 55 | *.log 56 | *.vspscc 57 | *.vssscc 58 | .builds 59 | *.pidb 60 | *.svclog 61 | *.scc 62 | 63 | # Chutzpah Test files 64 | _Chutzpah* 65 | 66 | # Visual C++ cache files 67 | ipch/ 68 | *.aps 69 | *.ncb 70 | *.opensdf 71 | *.sdf 72 | *.cachefile 73 | 74 | # Visual Studio profiler 75 | *.psess 76 | *.vsp 77 | *.vspx 78 | 79 | # TFS 2012 Local Workspace 80 | $tf/ 81 | 82 | # Guidance Automation Toolkit 83 | *.gpState 84 | 85 | # ReSharper is a .NET coding add-in 86 | _ReSharper*/ 87 | *.[Rr]e[Ss]harper 88 | *.DotSettings.user 89 | 90 | # JustCode is a .NET coding addin-in 91 | .JustCode 92 | 93 | # TeamCity is a build add-in 94 | _TeamCity* 95 | 96 | # DotCover is a Code Coverage Tool 97 | *.dotCover 98 | 99 | # NCrunch 100 | _NCrunch_* 101 | .*crunch*.local.xml 102 | 103 | # MightyMoose 104 | *.mm.* 105 | AutoTest.Net/ 106 | 107 | # Web workbench (sass) 108 | .sass-cache/ 109 | 110 | # Installshield output folder 111 | [Ee]xpress/ 112 | 113 | # DocProject is a documentation generator add-in 114 | DocProject/buildhelp/ 115 | DocProject/Help/*.HxT 116 | DocProject/Help/*.HxC 117 | DocProject/Help/*.hhc 118 | DocProject/Help/*.hhk 119 | DocProject/Help/*.hhp 120 | DocProject/Help/Html2 121 | DocProject/Help/html 122 | 123 | # Click-Once directory 124 | publish/ 125 | 126 | # Publish Web Output 127 | *.[Pp]ublish.xml 128 | *.azurePubxml 129 | # TODO: Comment the next line if you want to checkin your web deploy settings 130 | # but database connection strings (with potential passwords) will be unencrypted 131 | *.pubxml 132 | *.publishproj 133 | 134 | # NuGet Packages 135 | *.nupkg 136 | # The packages folder can be ignored because of Package Restore 137 | **/packages/* 138 | # except build/, which is used as an MSBuild target. 139 | !**/packages/build/ 140 | # If using the old MSBuild-Integrated Package Restore, uncomment this: 141 | #!**/packages/repositories.config 142 | 143 | # Windows Azure Build Output 144 | csx/ 145 | *.build.csdef 146 | 147 | # Windows Store app package directory 148 | AppPackages/ 149 | 150 | # Others 151 | sql/ 152 | *.Cache 153 | ClientBin/ 154 | [Ss]tyle[Cc]op.* 155 | ~$* 156 | *~ 157 | *.dbmdl 158 | *.dbproj.schemaview 159 | *.pfx 160 | *.publishsettings 161 | node_modules/ 162 | 163 | # RIA/Silverlight projects 164 | Generated_Code/ 165 | 166 | # Backup & report files from converting an old project file 167 | # to a newer Visual Studio version. Backup files are not needed, 168 | # because we have git ;-) 169 | _UpgradeReport_Files/ 170 | Backup*/ 171 | UpgradeLog*.XML 172 | UpgradeLog*.htm 173 | 174 | # SQL Server files 175 | *.mdf 176 | *.ldf 177 | 178 | # Business Intelligence projects 179 | *.rdl.data 180 | *.bim.layout 181 | *.bim_*.settings 182 | 183 | # Microsoft Fakes 184 | FakesAssemblies/ 185 | 186 | # ========================= 187 | # Operating System Files 188 | # ========================= 189 | 190 | # OSX 191 | # ========================= 192 | 193 | .DS_Store 194 | .AppleDouble 195 | .LSOverride 196 | 197 | # Thumbnails 198 | ._* 199 | 200 | # Files that might appear on external disk 201 | .Spotlight-V100 202 | .Trashes 203 | 204 | # Directories potentially created on remote AFP share 205 | .AppleDB 206 | .AppleDesktop 207 | Network Trash Folder 208 | Temporary Items 209 | .apdisk 210 | 211 | # Windows 212 | # ========================= 213 | 214 | # Windows image file caches 215 | Thumbs.db 216 | ehthumbs.db 217 | 218 | # Folder config file 219 | Desktop.ini 220 | 221 | # Recycle Bin used on file shares 222 | $RECYCLE.BIN/ 223 | 224 | # Windows Installer files 225 | *.cab 226 | *.msi 227 | *.msm 228 | *.msp 229 | 230 | # Windows shortcuts 231 | *.lnk 232 | -------------------------------------------------------------------------------- /STBootLib/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("STBootLib")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("STBootLib")] 13 | [assembly: AssemblyCopyright("Copyright © 2015")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("51944148-4ef8-41d7-b2ce-1818eda5aff0")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /STBootLib/STBoot.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading; 6 | using System.Threading.Tasks; 7 | using System.IO.Ports; 8 | 9 | namespace STBootLib 10 | { 11 | public class STBoot : IDisposable 12 | { 13 | /* serial port */ 14 | SerialPort sp; 15 | /* command mutex */ 16 | SemaphoreSlim sem; 17 | /* list of supported commands */ 18 | List Commands; 19 | 20 | 21 | /* bootloader version */ 22 | public string Version; 23 | /* product id */ 24 | public ushort ProductID; 25 | 26 | 27 | /* constructor */ 28 | public STBoot() 29 | { 30 | Commands = new List(); 31 | /* initialize mutex */ 32 | sem = new SemaphoreSlim(1); 33 | } 34 | 35 | /* destructor */ 36 | ~STBoot() 37 | { 38 | /* dispose of serial port */ 39 | Dispose(); 40 | } 41 | 42 | /* dispose implementation */ 43 | public void Dispose() 44 | { 45 | /* close serial port */ 46 | Close(); 47 | } 48 | 49 | /* open serial port */ 50 | public void Open(string portName, uint baudRate) 51 | { 52 | /* initialize serial port */ 53 | sp = new SerialPort(portName, (int)baudRate, Parity.Even, 8); 54 | /* open serial port */ 55 | sp.Open(); 56 | 57 | /* discard buffers */ 58 | sp.DiscardInBuffer(); 59 | sp.DiscardOutBuffer(); 60 | } 61 | 62 | /* close */ 63 | public void Close() 64 | { 65 | /* close permitted? */ 66 | if (sp != null && sp.IsOpen) 67 | sp.Close(); 68 | } 69 | 70 | /* initialize communication */ 71 | public async Task Initialize() 72 | { 73 | /* perform autobauding */ 74 | await Init(); 75 | /* get version and command list */ 76 | await Get(); 77 | 78 | /* no support for get id? */ 79 | if (!Commands.Contains(STCmds.GET_ID)) { 80 | /* throw an exception */ 81 | throw new STBootException("Command not supported"); 82 | } 83 | 84 | /* get product id */ 85 | await GetID(); 86 | } 87 | 88 | /* unprotect memory */ 89 | public async Task Unprotect() 90 | { 91 | /* no support for unprotect? */ 92 | if (!Commands.Contains(STCmds.WR_UNPROTECT)) 93 | throw new STBootException("Command not supported"); 94 | 95 | /* no support for unprotect? */ 96 | if (!Commands.Contains(STCmds.RD_UNPROTECT)) 97 | throw new STBootException("Command not supported"); 98 | 99 | await ReadUnprotect(); 100 | await WriteUnprotect(); 101 | } 102 | 103 | /* read memory */ 104 | public async Task ReadMemory(uint address, byte[] buf, int offset, 105 | int size, IProgress p, CancellationToken ct) 106 | { 107 | /* number of bytes read */ 108 | int bread = 0; 109 | /* no support for read? */ 110 | if (!Commands.Contains(STCmds.READ)) 111 | throw new STBootException("Command not supported"); 112 | 113 | /* data is read in chunks */ 114 | while (size > 0 && !ct.IsCancellationRequested) { 115 | /* chunk size */ 116 | int csize = Math.Min(size, 256); 117 | /* read a single chunk */ 118 | await Read(address, buf, offset, csize); 119 | 120 | /* update iterators */ 121 | size -= csize; offset += csize; address += (uint)csize; 122 | /* update number of bytes read */ 123 | bread += csize; 124 | 125 | /* report progress */ 126 | if (p != null) 127 | p.Report(bread); 128 | } 129 | 130 | /* throw exception if operation was cancelled */ 131 | if (ct.IsCancellationRequested) 132 | throw new OperationCanceledException("Read cancelled"); 133 | } 134 | 135 | /* write memory */ 136 | public async Task WriteMemory(uint address, byte[] buf, int offset, 137 | int size, IProgress p, CancellationToken ct) 138 | { 139 | /* number of bytes written */ 140 | int bwritten = 0, btotal = size; 141 | 142 | /* no support for read? */ 143 | if (!Commands.Contains(STCmds.WRITE)) 144 | throw new STBootException("Command not supported"); 145 | 146 | /* data is read in chunks */ 147 | while (size > 0 && !ct.IsCancellationRequested) { 148 | /* chunk size */ 149 | int csize = Math.Min(size, 256); 150 | /* read a single chunk */ 151 | await Write(address, buf, offset, csize); 152 | 153 | /* update iterators */ 154 | size -= csize; offset += csize; address += (uint)csize; 155 | /* update number of bytes read */ 156 | bwritten += csize; 157 | 158 | /* report progress */ 159 | if (p != null) 160 | p.Report(new STBootProgress(bwritten, btotal)); 161 | } 162 | 163 | /* throw exception if operation was cancelled */ 164 | if (ct.IsCancellationRequested) 165 | throw new OperationCanceledException("Write cancelled"); 166 | } 167 | 168 | /* erase page */ 169 | public async Task ErasePage(uint pageNumber) 170 | { 171 | /* 'classic' erase operation supported? */ 172 | if (Commands.Contains(STCmds.ERASE)) { 173 | await Erase(pageNumber); 174 | /* 'extended' erase operation supported? */ 175 | } else if (Commands.Contains(STCmds.EXT_ERASE)) { 176 | await ExtendedErase(pageNumber); 177 | /* no operation supported */ 178 | } else { 179 | throw new STBootException("Command not supported"); 180 | } 181 | } 182 | 183 | /* perform global erase */ 184 | public async Task GlobalErase() 185 | { 186 | /* 'classic' erase operation supported? */ 187 | if (Commands.Contains(STCmds.ERASE)) { 188 | await EraseSpecial(STEraseMode.GLOBAL); 189 | /* 'extended' erase operation supported? */ 190 | } else if (Commands.Contains(STCmds.EXT_ERASE)) { 191 | await ExtendedEraseSpecial(STExtendedEraseMode.GLOBAL); 192 | /* no operation supported */ 193 | } else { 194 | throw new STBootException("Command not supported"); 195 | } 196 | } 197 | 198 | /* jump to user code */ 199 | public async Task Jump(uint address) 200 | { 201 | /* no support for go? */ 202 | if (!Commands.Contains(STCmds.GO)) 203 | throw new STBootException("Command not supported"); 204 | 205 | /* go! */ 206 | await Go(address); 207 | } 208 | 209 | /* init */ 210 | private async Task Init() 211 | { 212 | /* command word */ 213 | var tx = new byte[1]; 214 | /* response code */ 215 | var ack = new byte[1]; 216 | 217 | /* store code */ 218 | tx[0] = (byte)STCmds.INIT; 219 | 220 | /* wait for command sender to finish its job with previous 221 | * command */ 222 | await sem.WaitAsync(); 223 | 224 | /* try to send command and wait for response */ 225 | try { 226 | /* send bytes */ 227 | await SerialWrite(tx, 0, tx.Length); 228 | 229 | /* wait for response code */ 230 | await SerialRead(ack, 0, 1); 231 | /* check response code */ 232 | if (ack[0] != (byte)STResps.ACK) 233 | throw new STBootException("Command Rejected"); 234 | /* error during send */ 235 | } catch (Exception) { 236 | /* release semaphore */ 237 | sem.Release(); 238 | /* re-throw */ 239 | throw; 240 | } 241 | 242 | /* release semaphore */ 243 | sem.Release(); 244 | } 245 | 246 | /* get command */ 247 | private async Task Get() 248 | { 249 | /* command word */ 250 | var tx = new byte[2]; 251 | /* temporary storage for response bytes */ 252 | var tmp = new byte[1]; 253 | /* numbe or response bytes */ 254 | int nbytes; 255 | /* rx buffer */ 256 | byte[] rx; 257 | 258 | /* store code */ 259 | tx[0] = (byte)STCmds.GET; 260 | /* set checksum */ 261 | tx[1] = ComputeChecksum(tx, 0, 1); 262 | 263 | /* wait for command sender to finish its job with previous 264 | * command */ 265 | await sem.WaitAsync(); 266 | 267 | /* try to send command and wait for response */ 268 | try { 269 | /* send bytes */ 270 | await SerialWrite(tx, 0, tx.Length); 271 | 272 | /* wait for response code */ 273 | await SerialRead(tmp, 0, 1); 274 | /* check response code */ 275 | if (tmp[0] != (byte)STResps.ACK) 276 | throw new STBootException("Command Rejected"); 277 | 278 | /* wait for number of bytes */ 279 | await SerialRead(tmp, 0, 1); 280 | /* assign number of bytes that will follow (add for acks) */ 281 | nbytes = tmp[0] + 2; 282 | /* nbytes must be equal to 13 for stm32 products */ 283 | if (nbytes != 13) 284 | throw new STBootException("Invalid length"); 285 | 286 | /* prepare buffer */ 287 | rx = new byte[nbytes]; 288 | /* receive response */ 289 | await SerialRead(rx, 0, rx.Length); 290 | /* oops, something baaad happened! */ 291 | } catch (Exception) { 292 | /* release semaphore */ 293 | sem.Release(); 294 | /* re-throw */ 295 | throw; 296 | } 297 | 298 | /* store version information */ 299 | Version = (rx[0] >> 4).ToString() + "." + 300 | (rx[0] & 0xf).ToString(); 301 | 302 | /* initialize command list */ 303 | Commands = new List(); 304 | /* add all commands */ 305 | for (int i = 1; i < nbytes - 1; i++) 306 | Commands.Add((STCmds)rx[i]); 307 | 308 | /* release semaphore */ 309 | sem.Release(); 310 | } 311 | 312 | /* get id command */ 313 | private async Task GetID() 314 | { 315 | /* command word */ 316 | var tx = new byte[2]; 317 | /* temporary storage for response bytes */ 318 | var tmp = new byte[1]; 319 | /* numbe or response bytes */ 320 | int nbytes; 321 | /* rx buffer */ 322 | byte[] rx; 323 | 324 | /* store code */ 325 | tx[0] = (byte)STCmds.GET_ID; 326 | /* set checksum */ 327 | tx[1] = ComputeChecksum(tx, 0, 1); 328 | 329 | /* try to send command and wait for response */ 330 | try { 331 | /* send bytes */ 332 | await SerialWrite(tx, 0, tx.Length); 333 | 334 | /* wait for response code */ 335 | await SerialRead(tmp, 0, 1); 336 | /* check response code */ 337 | if (tmp[0] != (byte)STResps.ACK) 338 | throw new STBootException("Command Rejected"); 339 | 340 | /* wait for number of bytes */ 341 | await SerialRead(tmp, 0, 1); 342 | /* assign number of bytes that will follow (add for acks) */ 343 | nbytes = tmp[0] + 2; 344 | /* nbytes must be equal to 3 for stm32 products */ 345 | if (nbytes != 3) 346 | throw new STBootException("Invalid length"); 347 | 348 | /* prepare buffer */ 349 | rx = new byte[nbytes]; 350 | /* receive response */ 351 | await SerialRead(rx, 0, rx.Length); 352 | /* oops, something baaad happened! */ 353 | } catch (Exception) { 354 | /* release semaphore */ 355 | sem.Release(); 356 | /* re-throw */ 357 | throw; 358 | } 359 | 360 | /* store product id */ 361 | ProductID = (ushort)(rx[0] << 8 | rx[1]); 362 | 363 | /* release semaphore */ 364 | sem.Release(); 365 | } 366 | 367 | /* read command */ 368 | private async Task Read(uint address, byte[] buf, int offset, int length) 369 | { 370 | /* command word */ 371 | var tx = new byte[9]; 372 | /* temporary storage for response bytes */ 373 | var tmp = new byte[1]; 374 | 375 | /* command code */ 376 | tx[0] = (byte)STCmds.READ; 377 | /* checksum */ 378 | tx[1] = ComputeChecksum(tx, 0, 1); 379 | 380 | /* store address */ 381 | tx[2] = (byte)((address >> 24) & 0xff); 382 | tx[3] = (byte)((address >> 16) & 0xff); 383 | tx[4] = (byte)((address >> 8) & 0xff); 384 | tx[5] = (byte)(address & 0xff); 385 | /* address checksum (needs to be not negated. why? because ST! 386 | * that's why. */ 387 | tx[6] = (byte)~ComputeChecksum(tx, 2, 4); 388 | 389 | /* store number of bytes */ 390 | tx[7] = (byte)(length - 1); 391 | /* size checksum */ 392 | tx[8] = ComputeChecksum(tx, 7, 1); 393 | 394 | /* try to send command and wait for response */ 395 | try { 396 | /* send bytes */ 397 | await SerialWrite(tx, 0, 2); 398 | /* wait for response code */ 399 | await SerialRead(tmp, 0, 1); 400 | /* check response code */ 401 | if (tmp[0] != (byte)STResps.ACK) 402 | throw new STBootException("Command Rejected"); 403 | 404 | /* send address */ 405 | await SerialWrite(tx, 2, 5); 406 | /* wait for response code */ 407 | await SerialRead(tmp, 0, 1); 408 | /* check response code */ 409 | if (tmp[0] != (byte)STResps.ACK) 410 | throw new STBootException("Address Rejected"); 411 | 412 | /* send address */ 413 | await SerialWrite(tx, 7, 2); 414 | /* wait for response code */ 415 | await SerialRead(tmp, 0, 1); 416 | /* check response code */ 417 | if (tmp[0] != (byte)STResps.ACK) 418 | throw new STBootException("Size Rejected"); 419 | 420 | /* receive response */ 421 | await SerialRead(buf, offset, length); 422 | /* oops, something baaad happened! */ 423 | } catch (Exception) { 424 | /* release semaphore */ 425 | sem.Release(); 426 | /* re-throw */ 427 | throw; 428 | } 429 | 430 | /* release semaphore */ 431 | sem.Release(); 432 | } 433 | 434 | /* go command */ 435 | private async Task Go(uint address) 436 | { 437 | /* command word */ 438 | var tx = new byte[7]; 439 | /* temporary storage for response bytes */ 440 | var tmp = new byte[1]; 441 | 442 | /* command code */ 443 | tx[0] = (byte)STCmds.GO; 444 | /* checksum */ 445 | tx[1] = ComputeChecksum(tx, 0, 1); 446 | 447 | /* store address */ 448 | tx[2] = (byte)((address >> 24) & 0xff); 449 | tx[3] = (byte)((address >> 16) & 0xff); 450 | tx[4] = (byte)((address >> 8) & 0xff); 451 | tx[5] = (byte)(address & 0xff); 452 | /* address checksum (needs to be not negated. why? because ST! 453 | * that's why. */ 454 | tx[6] = (byte)~ComputeChecksum(tx, 2, 4); 455 | 456 | /* try to send command and wait for response */ 457 | try { 458 | /* send bytes */ 459 | await SerialWrite(tx, 0, 2); 460 | /* wait for response code */ 461 | await SerialRead(tmp, 0, 1); 462 | /* check response code */ 463 | if (tmp[0] != (byte)STResps.ACK) 464 | throw new STBootException("Command Rejected"); 465 | 466 | /* send address */ 467 | await SerialWrite(tx, 2, 5); 468 | /* wait for response code */ 469 | await SerialRead(tmp, 0, 1); 470 | /* check response code */ 471 | if (tmp[0] != (byte)STResps.ACK) 472 | throw new STBootException("Address Rejected"); 473 | /* oops, something baaad happened! */ 474 | } catch (Exception) { 475 | /* release semaphore */ 476 | sem.Release(); 477 | /* re-throw */ 478 | throw; 479 | } 480 | 481 | /* release semaphore */ 482 | sem.Release(); 483 | } 484 | 485 | /* write memory */ 486 | private async Task Write(uint address, byte[] data, int offset, int length) 487 | { 488 | /* command word */ 489 | var tx = new byte[9]; 490 | /* temporary storage for response bytes */ 491 | var tmp = new byte[1]; 492 | 493 | /* command code */ 494 | tx[0] = (byte)STCmds.WRITE; 495 | /* checksum */ 496 | tx[1] = ComputeChecksum(tx, 0, 1); 497 | 498 | /* store address */ 499 | tx[2] = (byte)((address >> 24) & 0xff); 500 | tx[3] = (byte)((address >> 16) & 0xff); 501 | tx[4] = (byte)((address >> 8) & 0xff); 502 | tx[5] = (byte)(address & 0xff); 503 | /* address checksum (needs to be not negated. why? because ST! 504 | * that's why. */ 505 | tx[6] = (byte)~ComputeChecksum(tx, 2, 4); 506 | 507 | /* number of bytes */ 508 | tx[7] = (byte)(length - 1); 509 | /* data checksum */ 510 | tx[8] = (byte)(~(ComputeChecksum(data, offset, length) ^ tx[7])); 511 | 512 | /* try to send command and wait for response */ 513 | try { 514 | /* send bytes */ 515 | await SerialWrite(tx, 0, 2); 516 | /* wait for response code */ 517 | await SerialRead(tmp, 0, 1); 518 | /* check response code */ 519 | if (tmp[0] != (byte)STResps.ACK) 520 | throw new STBootException("Command Rejected"); 521 | 522 | /* send address */ 523 | await SerialWrite(tx, 2, 5); 524 | /* wait for response code */ 525 | await SerialRead(tmp, 0, 1); 526 | /* check response code */ 527 | if (tmp[0] != (byte)STResps.ACK) 528 | throw new STBootException("Address Rejected"); 529 | 530 | /* send the number of bytes */ 531 | await SerialWrite(tx, 7, 1); 532 | /* send data */ 533 | await SerialWrite(data, offset, length); 534 | /* send checksum */ 535 | await SerialWrite(tx, 8, 1); 536 | /* wait for response code */ 537 | await SerialRead(tmp, 0, 1); 538 | /* check response code */ 539 | if (tmp[0] != (byte)STResps.ACK) 540 | throw new STBootException("Data Rejected"); 541 | 542 | /* oops, something baaad happened! */ 543 | } catch (Exception) { 544 | /* release semaphore */ 545 | sem.Release(); 546 | /* re-throw */ 547 | throw; 548 | } 549 | 550 | /* release semaphore */ 551 | sem.Release(); 552 | } 553 | 554 | /* erase memory page */ 555 | private async Task Erase(uint pageNumber) 556 | { 557 | /* command word */ 558 | var tx = new byte[5]; 559 | /* temporary storage for response bytes */ 560 | var tmp = new byte[1]; 561 | 562 | /* command code */ 563 | tx[0] = (byte)STCmds.ERASE; 564 | /* checksum */ 565 | tx[1] = ComputeChecksum(tx, 0, 1); 566 | 567 | /* erase single page */ 568 | tx[2] = 0; 569 | /* set page number */ 570 | tx[3] = (byte)pageNumber; 571 | /* checksum */ 572 | tx[4] = (byte)~ComputeChecksum(tx, 2, 2); 573 | 574 | /* try to send command and wait for response */ 575 | try { 576 | /* send bytes */ 577 | await SerialWrite(tx, 0, 2); 578 | /* wait for response code */ 579 | await SerialRead(tmp, 0, 1); 580 | /* check response code */ 581 | if (tmp[0] != (byte)STResps.ACK) 582 | throw new STBootException("Command Rejected"); 583 | 584 | /* send address */ 585 | await SerialWrite(tx, 2, 3); 586 | /* wait for response code */ 587 | await SerialRead(tmp, 0, 1); 588 | /* check response code */ 589 | if (tmp[0] != (byte)STResps.ACK) 590 | throw new STBootException("Page Rejected"); 591 | 592 | /* oops, something baaad happened! */ 593 | } catch (Exception) { 594 | /* release semaphore */ 595 | sem.Release(); 596 | /* re-throw */ 597 | throw; 598 | } 599 | 600 | /* release semaphore */ 601 | sem.Release(); 602 | } 603 | 604 | /* erase memory page */ 605 | private async Task EraseSpecial(STEraseMode mode) 606 | { 607 | /* command word */ 608 | var tx = new byte[4]; 609 | /* temporary storage for response bytes */ 610 | var tmp = new byte[1]; 611 | 612 | /* command code */ 613 | tx[0] = (byte)STCmds.ERASE; 614 | /* checksum */ 615 | tx[1] = ComputeChecksum(tx, 0, 1); 616 | 617 | /* erase single page */ 618 | tx[2] = (byte)((int)mode); 619 | /* checksum */ 620 | tx[3] = (byte)~ComputeChecksum(tx, 2, 2); 621 | 622 | /* try to send command and wait for response */ 623 | try { 624 | /* send bytes */ 625 | await SerialWrite(tx, 0, 2); 626 | /* wait for response code */ 627 | await SerialRead(tmp, 0, 1); 628 | /* check response code */ 629 | if (tmp[0] != (byte)STResps.ACK) 630 | throw new STBootException("Command Rejected"); 631 | 632 | /* send address */ 633 | await SerialWrite(tx, 2, 2); 634 | /* wait for response code */ 635 | await SerialRead(tmp, 0, 1); 636 | /* check response code */ 637 | if (tmp[0] != (byte)STResps.ACK) 638 | throw new STBootException("Special Code Rejected"); 639 | 640 | /* oops, something baaad happened! */ 641 | } catch (Exception) { 642 | /* release semaphore */ 643 | sem.Release(); 644 | /* re-throw */ 645 | throw; 646 | } 647 | 648 | /* release semaphore */ 649 | sem.Release(); 650 | } 651 | 652 | /* extended erase memory page */ 653 | private async Task ExtendedErase(uint pageNumber) 654 | { 655 | /* command word */ 656 | var tx = new byte[7]; 657 | /* temporary storage for response bytes */ 658 | var tmp = new byte[1]; 659 | 660 | /* command code */ 661 | tx[0] = (byte)STCmds.EXT_ERASE; 662 | /* checksum */ 663 | tx[1] = ComputeChecksum(tx, 0, 1); 664 | 665 | /* erase single page */ 666 | tx[2] = 0; 667 | tx[3] = 0; 668 | /* set page number */ 669 | tx[4] = (byte)(pageNumber >> 8); 670 | tx[5] = (byte)(pageNumber >> 0); 671 | /* checksum */ 672 | tx[6] = (byte)~ComputeChecksum(tx, 2, 5); 673 | 674 | /* try to send command and wait for response */ 675 | try { 676 | /* send bytes */ 677 | await SerialWrite(tx, 0, 2); 678 | /* wait for response code */ 679 | await SerialRead(tmp, 0, 1); 680 | /* check response code */ 681 | if (tmp[0] != (byte)STResps.ACK) 682 | throw new STBootException("Command Rejected"); 683 | 684 | /* send address */ 685 | await SerialWrite(tx, 2, 5); 686 | /* wait for response code. use longer timeout, erase might 687 | * take a while or two. */ 688 | await SerialRead(tmp, 0, 1, 3000); 689 | /* check response code */ 690 | if (tmp[0] != (byte)STResps.ACK) 691 | throw new STBootException("Page Rejected"); 692 | 693 | /* oops, something baaad happened! */ 694 | } catch (Exception) { 695 | /* release semaphore */ 696 | sem.Release(); 697 | /* re-throw */ 698 | throw; 699 | } 700 | 701 | /* release semaphore */ 702 | sem.Release(); 703 | } 704 | 705 | /* extended erase memory page */ 706 | private async Task ExtendedEraseSpecial(STExtendedEraseMode mode) 707 | { 708 | /* command word */ 709 | var tx = new byte[5]; 710 | /* temporary storage for response bytes */ 711 | var tmp = new byte[1]; 712 | 713 | /* command code */ 714 | tx[0] = (byte)STCmds.EXT_ERASE; 715 | /* checksum */ 716 | tx[1] = ComputeChecksum(tx, 0, 1); 717 | 718 | /* erase single page */ 719 | tx[2] = (byte)((int)mode >> 8); 720 | tx[3] = (byte)((int)mode >> 0); 721 | /* checksum */ 722 | tx[4] = (byte)~ComputeChecksum(tx, 2, 3); 723 | 724 | /* try to send command and wait for response */ 725 | try { 726 | /* send bytes */ 727 | await SerialWrite(tx, 0, 2); 728 | /* wait for response code */ 729 | await SerialRead(tmp, 0, 1); 730 | /* check response code */ 731 | if (tmp[0] != (byte)STResps.ACK) 732 | throw new STBootException("Command Rejected"); 733 | 734 | /* send address */ 735 | await SerialWrite(tx, 2, 3); 736 | /* wait for response code. use longer timeout, erase might 737 | * take a while or two. */ 738 | await SerialRead(tmp, 0, 1, 10000); 739 | /* check response code */ 740 | if (tmp[0] != (byte)STResps.ACK) 741 | throw new STBootException("Special code Rejected"); 742 | 743 | /* oops, something baaad happened! */ 744 | } catch (Exception) { 745 | /* release semaphore */ 746 | sem.Release(); 747 | /* re-throw */ 748 | throw; 749 | } 750 | 751 | /* release semaphore */ 752 | sem.Release(); 753 | } 754 | 755 | /* unprotect flash before writing */ 756 | private async Task WriteUnprotect() 757 | { 758 | /* command word */ 759 | var tx = new byte[2]; 760 | /* temporary storage for response bytes */ 761 | var tmp = new byte[1]; 762 | 763 | /* command code */ 764 | tx[0] = (byte)STCmds.WR_UNPROTECT; 765 | /* checksum */ 766 | tx[1] = ComputeChecksum(tx, 0, 1); 767 | 768 | /* try to send command and wait for response */ 769 | try { 770 | /* send bytes */ 771 | await SerialWrite(tx, 0, 2); 772 | /* wait for response code */ 773 | await SerialRead(tmp, 0, 1); 774 | /* check response code */ 775 | if (tmp[0] != (byte)STResps.ACK) 776 | throw new STBootException("Command Rejected"); 777 | 778 | /* wait for response code. use longer timeout, erase might 779 | * take a while or two. */ 780 | await SerialRead(tmp, 0, 1); 781 | /* check response code */ 782 | if (tmp[0] != (byte)STResps.ACK) 783 | throw new STBootException("Write Unprotect Rejected"); 784 | 785 | /* oops, something baaad happened! */ 786 | } finally { 787 | /* release semaphore */ 788 | sem.Release(); 789 | } 790 | } 791 | 792 | /* unprotect flash before reading */ 793 | private async Task ReadUnprotect() 794 | { 795 | /* command word */ 796 | var tx = new byte[2]; 797 | /* temporary storage for response bytes */ 798 | var tmp = new byte[1]; 799 | 800 | /* command code */ 801 | tx[0] = (byte)STCmds.RD_UNPROTECT; 802 | /* checksum */ 803 | tx[1] = ComputeChecksum(tx, 0, 1); 804 | 805 | /* try to send command and wait for response */ 806 | try { 807 | /* send bytes */ 808 | await SerialWrite(tx, 0, 2); 809 | /* wait for response code */ 810 | await SerialRead(tmp, 0, 1); 811 | /* check response code */ 812 | if (tmp[0] != (byte)STResps.ACK) 813 | throw new STBootException("Command Rejected"); 814 | 815 | /* wait for response code. use longer timeout, erase might 816 | * take a while or two. */ 817 | await SerialRead(tmp, 0, 10000); 818 | /* check response code */ 819 | if (tmp[0] != (byte)STResps.ACK) 820 | throw new STBootException("Write Unprotect Rejected"); 821 | 822 | /* oops, something baaad happened! */ 823 | } finally { 824 | /* release semaphore */ 825 | sem.Release(); 826 | } 827 | } 828 | 829 | /* compute checksum */ 830 | private byte ComputeChecksum(byte[] data, int offset, int count) 831 | { 832 | /* initial value */ 833 | byte xor = 0xff; 834 | /* compute */ 835 | for (int i = offset; i < count + offset; i++) 836 | xor ^= data[i]; 837 | 838 | /* return value */ 839 | return xor; 840 | } 841 | 842 | /* write to serial port */ 843 | private async Task SerialWrite(byte[] data, int offset, int count) 844 | { 845 | /* shorter name */ 846 | var bs = sp.BaseStream; 847 | 848 | /* write operation */ 849 | await bs.WriteAsync(data, offset, count); 850 | } 851 | 852 | /* standard read with timeout equal to 1s */ 853 | private async Task SerialRead(byte[] data, int offset, int count) 854 | { 855 | await SerialRead(data, offset, count, 1000); 856 | } 857 | 858 | /* read 'length' number of bytes from serial port */ 859 | private async Task SerialRead(byte[] data, int offset, int count, int timeout) 860 | { 861 | /* shorter name */ 862 | var bs = sp.BaseStream; 863 | /* number of bytes read */ 864 | int br = 0; 865 | 866 | /* read until all bytes are fetched from serial port */ 867 | while (br < count) { 868 | /* this try is for timeout handling */ 869 | try { 870 | /* prepare task */ 871 | br += await bs.ReadAsync(data, offset + br, count - br). 872 | WithTimeout(timeout); 873 | /* got handling? */ 874 | } catch (OperationCanceledException) { 875 | /* rethrow */ 876 | throw new STBootException("Timeout"); 877 | } 878 | } 879 | } 880 | } 881 | } 882 | -------------------------------------------------------------------------------- /STBootLib/STBootCmds.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace STBootLib 8 | { 9 | /* command list */ 10 | public enum STCmds 11 | { 12 | /* this is used by bootloader to determine the baudrate */ 13 | INIT = 0x7F, 14 | /* Gets the version and the allowed commands supported 15 | * by the current version of the bootloader */ 16 | GET = 0x00, 17 | /* Gets the bootloader version and the Read Protection 18 | * status of the Flash memory */ 19 | GET_PROT = 0x01, 20 | /* Gets the chip ID */ 21 | GET_ID = 0x02, 22 | /* Reads up to 256 bytes of memory starting from an 23 | * address specified by the application */ 24 | READ = 0x11, 25 | /* Jumps to user application code located in the internal 26 | * Flash memory or in SRAM */ 27 | GO = 0x21, 28 | /* Writes up to 256 bytes to the RAM or Flash memory starting 29 | * from an address specified by the application */ 30 | WRITE = 0x31, 31 | /* Erases from one to all the Flash memory pages */ 32 | ERASE = 0x43, 33 | /* Erases from one to all the Flash memory pages using 34 | * two byte addressing mode (available only for v3.0 usart 35 | * bootloader versions and above). */ 36 | EXT_ERASE = 0x44, 37 | /* Enables the write protection for some sectors */ 38 | WR_PROTECT = 0x63, 39 | /* Disables the write protection for all Flash memory sectors */ 40 | WR_UNPROTECT = 0x73, 41 | /* Enables the read protection */ 42 | RD_PROTECT = 0x82, 43 | /* Disables the read protection */ 44 | RD_UNPROTECT = 0x92 45 | } 46 | 47 | /* special erase mode for normal erase command */ 48 | public enum STEraseMode 49 | { 50 | /* erase all sectors */ 51 | GLOBAL = 0xff, 52 | } 53 | 54 | /* special erase mode for normal erase command */ 55 | public enum STExtendedEraseMode 56 | { 57 | /* erase all sectors */ 58 | GLOBAL = 0xffff, 59 | /* erase bank 1 */ 60 | BANK1 = 0xfffe, 61 | /* erase bank 2 */ 62 | BANK2 = 0xfffd 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /STBootLib/STBootException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace STBootLib 8 | { 9 | public class STBootException : Exception 10 | { 11 | /* constructor */ 12 | public STBootException() 13 | { 14 | } 15 | 16 | /* with message */ 17 | public STBootException(string message) 18 | : base(message) 19 | { 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /STBootLib/STBootLib.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {8EC66A52-5978-481D-A80D-D75CBC6DE918} 8 | Library 9 | Properties 10 | STBootLib 11 | STBootLib 12 | v4.5 13 | 512 14 | 15 | 16 | true 17 | full 18 | false 19 | bin\Debug\ 20 | DEBUG;TRACE 21 | prompt 22 | 4 23 | 24 | 25 | pdbonly 26 | true 27 | bin\Release\ 28 | TRACE 29 | prompt 30 | 4 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 58 | -------------------------------------------------------------------------------- /STBootLib/STBootProgress.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace STBootLib 8 | { 9 | public class STBootProgress 10 | { 11 | /* total number of bytes */ 12 | public readonly int bytesTotal; 13 | /* number of bytes processed */ 14 | public readonly int bytesProcessed; 15 | 16 | public STBootProgress(int bytesProcessed, int bytesTotal) 17 | { 18 | /* set the number of bytes processed */ 19 | this.bytesProcessed = bytesProcessed; 20 | /* set the total number of bytes */ 21 | this.bytesTotal = bytesTotal; 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /STBootLib/STBootResps.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace STBootLib 8 | { 9 | /* response codes*/ 10 | public enum STResps 11 | { 12 | /* command accepted */ 13 | ACK = 0x79, 14 | /* command discarded */ 15 | NACK = 0x1F, 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /STBootLib/STBootTimeout.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading; 6 | using System.Threading.Tasks; 7 | 8 | namespace STBootLib 9 | { 10 | static class STBootTimeout 11 | { 12 | 13 | /* used for cancelling */ 14 | public static async Task WithTimeout(this Task task, int timeout) 15 | { 16 | /* cancellation token source with timeout */ 17 | var cts = new CancellationTokenSource(timeout); 18 | /* task completition source */ 19 | var tcs = new TaskCompletionSource(); 20 | 21 | using (cts.Token.Register(s => 22 | ((TaskCompletionSource)s).TrySetResult(true), tcs)) { 23 | /* timeout occured? or task finished normally? */ 24 | if (task != await Task.WhenAny(task, tcs.Task)) 25 | throw new OperationCanceledException(); 26 | } 27 | 28 | return await task; 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /STM32 Flash Loader.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Express 2013 for Windows Desktop 4 | VisualStudioVersion = 12.0.21005.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "STM32 Flash Loader", "STM32 Flash Loader\STM32 Flash Loader.csproj", "{975D7D83-56AE-4A64-865E-BCD9096B05C7}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "STBootLib", "STBootLib\STBootLib.csproj", "{8EC66A52-5978-481D-A80D-D75CBC6DE918}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Release|Any CPU = Release|Any CPU 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {975D7D83-56AE-4A64-865E-BCD9096B05C7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 17 | {975D7D83-56AE-4A64-865E-BCD9096B05C7}.Debug|Any CPU.Build.0 = Debug|Any CPU 18 | {975D7D83-56AE-4A64-865E-BCD9096B05C7}.Release|Any CPU.ActiveCfg = Release|Any CPU 19 | {975D7D83-56AE-4A64-865E-BCD9096B05C7}.Release|Any CPU.Build.0 = Release|Any CPU 20 | {8EC66A52-5978-481D-A80D-D75CBC6DE918}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {8EC66A52-5978-481D-A80D-D75CBC6DE918}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {8EC66A52-5978-481D-A80D-D75CBC6DE918}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {8EC66A52-5978-481D-A80D-D75CBC6DE918}.Release|Any CPU.Build.0 = Release|Any CPU 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | EndGlobal 29 | -------------------------------------------------------------------------------- /STM32 Flash Loader/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /STM32 Flash Loader/MainForm.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace STUploader 2 | { 3 | partial class fMainForm 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) { 17 | components.Dispose(); 18 | } 19 | base.Dispose(disposing); 20 | } 21 | 22 | #region Windows Form Designer generated code 23 | 24 | /// 25 | /// Required method for Designer support - do not modify 26 | /// the contents of this method with the code editor. 27 | /// 28 | private void InitializeComponent() 29 | { 30 | this.components = new System.ComponentModel.Container(); 31 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(fMainForm)); 32 | this.groupBox1 = new System.Windows.Forms.GroupBox(); 33 | this.label3 = new System.Windows.Forms.Label(); 34 | this.label2 = new System.Windows.Forms.Label(); 35 | this.cbBauds = new System.Windows.Forms.ComboBox(); 36 | this.cbPorts = new System.Windows.Forms.ComboBox(); 37 | this.statusStrip1 = new System.Windows.Forms.StatusStrip(); 38 | this.tsslStatus = new System.Windows.Forms.ToolStripStatusLabel(); 39 | this.groupBox3 = new System.Windows.Forms.GroupBox(); 40 | this.bJump = new System.Windows.Forms.Button(); 41 | this.lProgress = new System.Windows.Forms.Label(); 42 | this.bWrite = new System.Windows.Forms.Button(); 43 | this.pbProgress = new System.Windows.Forms.ProgressBar(); 44 | this.ofdOpen = new System.Windows.Forms.OpenFileDialog(); 45 | this.groupBox4 = new System.Windows.Forms.GroupBox(); 46 | this.cbPSize = new System.Windows.Forms.ComboBox(); 47 | this.label5 = new System.Windows.Forms.Label(); 48 | this.cbxErase = new System.Windows.Forms.CheckBox(); 49 | this.tbAddress = new System.Windows.Forms.TextBox(); 50 | this.label4 = new System.Windows.Forms.Label(); 51 | this.ttToolTip = new System.Windows.Forms.ToolTip(this.components); 52 | this.bOpenFile = new System.Windows.Forms.Button(); 53 | this.tbFileName = new System.Windows.Forms.TextBox(); 54 | this.label1 = new System.Windows.Forms.Label(); 55 | this.groupBox2 = new System.Windows.Forms.GroupBox(); 56 | this.groupBox1.SuspendLayout(); 57 | this.statusStrip1.SuspendLayout(); 58 | this.groupBox3.SuspendLayout(); 59 | this.groupBox4.SuspendLayout(); 60 | this.groupBox2.SuspendLayout(); 61 | this.SuspendLayout(); 62 | // 63 | // groupBox1 64 | // 65 | this.groupBox1.Controls.Add(this.label3); 66 | this.groupBox1.Controls.Add(this.label2); 67 | this.groupBox1.Controls.Add(this.cbBauds); 68 | this.groupBox1.Controls.Add(this.cbPorts); 69 | this.groupBox1.Location = new System.Drawing.Point(12, 12); 70 | this.groupBox1.Name = "groupBox1"; 71 | this.groupBox1.Size = new System.Drawing.Size(293, 50); 72 | this.groupBox1.TabIndex = 0; 73 | this.groupBox1.TabStop = false; 74 | this.groupBox1.Text = "Serial Port"; 75 | // 76 | // label3 77 | // 78 | this.label3.AutoSize = true; 79 | this.label3.Location = new System.Drawing.Point(148, 21); 80 | this.label3.Name = "label3"; 81 | this.label3.Size = new System.Drawing.Size(40, 13); 82 | this.label3.TabIndex = 4; 83 | this.label3.Text = "Bauds:"; 84 | // 85 | // label2 86 | // 87 | this.label2.AutoSize = true; 88 | this.label2.Location = new System.Drawing.Point(28, 22); 89 | this.label2.Name = "label2"; 90 | this.label2.Size = new System.Drawing.Size(29, 13); 91 | this.label2.TabIndex = 3; 92 | this.label2.Text = "Port:"; 93 | // 94 | // cbBauds 95 | // 96 | this.cbBauds.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; 97 | this.cbBauds.FormattingEnabled = true; 98 | this.cbBauds.Items.AddRange(new object[] { 99 | "9600", 100 | "14400", 101 | "19200", 102 | "28800", 103 | "38400", 104 | "57600", 105 | "115200", 106 | "230400"}); 107 | this.cbBauds.Location = new System.Drawing.Point(194, 18); 108 | this.cbBauds.Name = "cbBauds"; 109 | this.cbBauds.Size = new System.Drawing.Size(88, 21); 110 | this.cbBauds.TabIndex = 1; 111 | this.ttToolTip.SetToolTip(this.cbBauds, "Baudrate used for communication"); 112 | this.cbBauds.SelectedIndexChanged += new System.EventHandler(this.cbBauds_SelectedIndexChanged); 113 | // 114 | // cbPorts 115 | // 116 | this.cbPorts.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; 117 | this.cbPorts.FormattingEnabled = true; 118 | this.cbPorts.Location = new System.Drawing.Point(63, 18); 119 | this.cbPorts.Name = "cbPorts"; 120 | this.cbPorts.Size = new System.Drawing.Size(79, 21); 121 | this.cbPorts.TabIndex = 0; 122 | this.ttToolTip.SetToolTip(this.cbPorts, "COM Port Name"); 123 | this.cbPorts.DropDown += new System.EventHandler(this.cbPorts_DropDown); 124 | this.cbPorts.SelectedIndexChanged += new System.EventHandler(this.cbPorts_SelectedIndexChanged); 125 | this.cbPorts.DropDownClosed += new System.EventHandler(this.cbPorts_SelectedIndexChanged); 126 | // 127 | // statusStrip1 128 | // 129 | this.statusStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { 130 | this.tsslStatus}); 131 | this.statusStrip1.Location = new System.Drawing.Point(0, 310); 132 | this.statusStrip1.Name = "statusStrip1"; 133 | this.statusStrip1.Size = new System.Drawing.Size(315, 22); 134 | this.statusStrip1.TabIndex = 2; 135 | this.statusStrip1.Text = "statusStrip1"; 136 | // 137 | // tsslStatus 138 | // 139 | this.tsslStatus.Name = "tsslStatus"; 140 | this.tsslStatus.Size = new System.Drawing.Size(16, 17); 141 | this.tsslStatus.Text = " "; 142 | // 143 | // groupBox3 144 | // 145 | this.groupBox3.Controls.Add(this.bJump); 146 | this.groupBox3.Controls.Add(this.lProgress); 147 | this.groupBox3.Controls.Add(this.bWrite); 148 | this.groupBox3.Controls.Add(this.pbProgress); 149 | this.groupBox3.Location = new System.Drawing.Point(12, 224); 150 | this.groupBox3.Name = "groupBox3"; 151 | this.groupBox3.Size = new System.Drawing.Size(293, 80); 152 | this.groupBox3.TabIndex = 3; 153 | this.groupBox3.TabStop = false; 154 | this.groupBox3.Text = "Actions"; 155 | // 156 | // bJump 157 | // 158 | this.bJump.Enabled = false; 159 | this.bJump.Location = new System.Drawing.Point(149, 48); 160 | this.bJump.Name = "bJump"; 161 | this.bJump.Size = new System.Drawing.Size(133, 23); 162 | this.bJump.TabIndex = 3; 163 | this.bJump.Text = "Jump"; 164 | this.ttToolTip.SetToolTip(this.bJump, "Uploads the firmware and jumps to it."); 165 | this.bJump.UseVisualStyleBackColor = true; 166 | this.bJump.Click += new System.EventHandler(this.bJump_Click); 167 | // 168 | // lProgress 169 | // 170 | this.lProgress.AutoSize = true; 171 | this.lProgress.Location = new System.Drawing.Point(257, 25); 172 | this.lProgress.Name = "lProgress"; 173 | this.lProgress.Size = new System.Drawing.Size(21, 13); 174 | this.lProgress.TabIndex = 2; 175 | this.lProgress.Text = "0%"; 176 | // 177 | // bWrite 178 | // 179 | this.bWrite.Enabled = false; 180 | this.bWrite.Location = new System.Drawing.Point(9, 48); 181 | this.bWrite.Name = "bWrite"; 182 | this.bWrite.Size = new System.Drawing.Size(133, 23); 183 | this.bWrite.TabIndex = 0; 184 | this.bWrite.Text = "Write Firmware && Jump"; 185 | this.ttToolTip.SetToolTip(this.bWrite, "Uploads the firmware and jumps to it."); 186 | this.bWrite.UseVisualStyleBackColor = true; 187 | this.bWrite.Click += new System.EventHandler(this.bWrite_Click); 188 | // 189 | // pbProgress 190 | // 191 | this.pbProgress.Location = new System.Drawing.Point(9, 19); 192 | this.pbProgress.Name = "pbProgress"; 193 | this.pbProgress.Size = new System.Drawing.Size(242, 23); 194 | this.pbProgress.TabIndex = 0; 195 | // 196 | // groupBox4 197 | // 198 | this.groupBox4.Controls.Add(this.cbPSize); 199 | this.groupBox4.Controls.Add(this.label5); 200 | this.groupBox4.Controls.Add(this.cbxErase); 201 | this.groupBox4.Controls.Add(this.tbAddress); 202 | this.groupBox4.Controls.Add(this.label4); 203 | this.groupBox4.Location = new System.Drawing.Point(12, 128); 204 | this.groupBox4.Name = "groupBox4"; 205 | this.groupBox4.Size = new System.Drawing.Size(293, 90); 206 | this.groupBox4.TabIndex = 2; 207 | this.groupBox4.TabStop = false; 208 | this.groupBox4.Text = "Options"; 209 | // 210 | // cbPSize 211 | // 212 | this.cbPSize.FormattingEnabled = true; 213 | this.cbPSize.Items.AddRange(new object[] { 214 | "256", 215 | "128", 216 | "2048"}); 217 | this.cbPSize.Location = new System.Drawing.Point(66, 53); 218 | this.cbPSize.Name = "cbPSize"; 219 | this.cbPSize.Size = new System.Drawing.Size(112, 21); 220 | this.cbPSize.TabIndex = 5; 221 | this.ttToolTip.SetToolTip(this.cbPSize, "COM Port Name"); 222 | this.cbPSize.SelectedIndexChanged += new System.EventHandler(this.cbPSize_SelectedIndexChanged); 223 | // 224 | // label5 225 | // 226 | this.label5.AutoSize = true; 227 | this.label5.Location = new System.Drawing.Point(4, 56); 228 | this.label5.Name = "label5"; 229 | this.label5.Size = new System.Drawing.Size(56, 13); 230 | this.label5.TabIndex = 2; 231 | this.label5.Text = "Page size:"; 232 | this.ttToolTip.SetToolTip(this.label5, "Destination address"); 233 | // 234 | // cbxErase 235 | // 236 | this.cbxErase.AutoSize = true; 237 | this.cbxErase.Location = new System.Drawing.Point(194, 22); 238 | this.cbxErase.Name = "cbxErase"; 239 | this.cbxErase.Size = new System.Drawing.Size(86, 17); 240 | this.cbxErase.TabIndex = 1; 241 | this.cbxErase.Text = "Global Erase"; 242 | this.ttToolTip.SetToolTip(this.cbxErase, "Writing to flash memory?"); 243 | this.cbxErase.UseVisualStyleBackColor = true; 244 | this.cbxErase.CheckedChanged += new System.EventHandler(this.cbxErase_CheckedChanged); 245 | // 246 | // tbAddress 247 | // 248 | this.tbAddress.Location = new System.Drawing.Point(66, 20); 249 | this.tbAddress.Name = "tbAddress"; 250 | this.tbAddress.Size = new System.Drawing.Size(112, 20); 251 | this.tbAddress.TabIndex = 0; 252 | this.tbAddress.Text = "0x08000000"; 253 | this.tbAddress.Leave += new System.EventHandler(this.tbAddress_Leave); 254 | // 255 | // label4 256 | // 257 | this.label4.AutoSize = true; 258 | this.label4.Location = new System.Drawing.Point(12, 23); 259 | this.label4.Name = "label4"; 260 | this.label4.Size = new System.Drawing.Size(48, 13); 261 | this.label4.TabIndex = 0; 262 | this.label4.Text = "Address:"; 263 | this.ttToolTip.SetToolTip(this.label4, "Destination address"); 264 | // 265 | // bOpenFile 266 | // 267 | this.bOpenFile.Location = new System.Drawing.Point(194, 16); 268 | this.bOpenFile.Name = "bOpenFile"; 269 | this.bOpenFile.Size = new System.Drawing.Size(88, 23); 270 | this.bOpenFile.TabIndex = 1; 271 | this.bOpenFile.Text = "Open File"; 272 | this.ttToolTip.SetToolTip(this.bOpenFile, "Open firmware file"); 273 | this.bOpenFile.UseVisualStyleBackColor = true; 274 | this.bOpenFile.Click += new System.EventHandler(this.bOpenFile_Click); 275 | // 276 | // tbFileName 277 | // 278 | this.tbFileName.Enabled = false; 279 | this.tbFileName.Location = new System.Drawing.Point(63, 18); 280 | this.tbFileName.Name = "tbFileName"; 281 | this.tbFileName.Size = new System.Drawing.Size(115, 20); 282 | this.tbFileName.TabIndex = 0; 283 | this.ttToolTip.SetToolTip(this.tbFileName, "File Name"); 284 | // 285 | // label1 286 | // 287 | this.label1.AutoSize = true; 288 | this.label1.Location = new System.Drawing.Point(19, 21); 289 | this.label1.Name = "label1"; 290 | this.label1.Size = new System.Drawing.Size(38, 13); 291 | this.label1.TabIndex = 0; 292 | this.label1.Text = "Name:"; 293 | this.ttToolTip.SetToolTip(this.label1, "File Name"); 294 | // 295 | // groupBox2 296 | // 297 | this.groupBox2.Controls.Add(this.tbFileName); 298 | this.groupBox2.Controls.Add(this.bOpenFile); 299 | this.groupBox2.Controls.Add(this.label1); 300 | this.groupBox2.Location = new System.Drawing.Point(12, 72); 301 | this.groupBox2.Name = "groupBox2"; 302 | this.groupBox2.Size = new System.Drawing.Size(293, 50); 303 | this.groupBox2.TabIndex = 1; 304 | this.groupBox2.TabStop = false; 305 | this.groupBox2.Text = "File"; 306 | // 307 | // fMainForm 308 | // 309 | this.AcceptButton = this.bWrite; 310 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 311 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 312 | this.ClientSize = new System.Drawing.Size(315, 332); 313 | this.Controls.Add(this.groupBox4); 314 | this.Controls.Add(this.groupBox3); 315 | this.Controls.Add(this.statusStrip1); 316 | this.Controls.Add(this.groupBox2); 317 | this.Controls.Add(this.groupBox1); 318 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; 319 | this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); 320 | this.MaximizeBox = false; 321 | this.Name = "fMainForm"; 322 | this.Text = "STM32 Flash Loader"; 323 | this.groupBox1.ResumeLayout(false); 324 | this.groupBox1.PerformLayout(); 325 | this.statusStrip1.ResumeLayout(false); 326 | this.statusStrip1.PerformLayout(); 327 | this.groupBox3.ResumeLayout(false); 328 | this.groupBox3.PerformLayout(); 329 | this.groupBox4.ResumeLayout(false); 330 | this.groupBox4.PerformLayout(); 331 | this.groupBox2.ResumeLayout(false); 332 | this.groupBox2.PerformLayout(); 333 | this.ResumeLayout(false); 334 | this.PerformLayout(); 335 | 336 | } 337 | 338 | #endregion 339 | 340 | private System.Windows.Forms.GroupBox groupBox1; 341 | private System.Windows.Forms.ComboBox cbPorts; 342 | private System.Windows.Forms.StatusStrip statusStrip1; 343 | private System.Windows.Forms.ToolStripStatusLabel tsslStatus; 344 | private System.Windows.Forms.GroupBox groupBox3; 345 | private System.Windows.Forms.Button bWrite; 346 | private System.Windows.Forms.ProgressBar pbProgress; 347 | private System.Windows.Forms.Label lProgress; 348 | private System.Windows.Forms.OpenFileDialog ofdOpen; 349 | private System.Windows.Forms.Label label3; 350 | private System.Windows.Forms.Label label2; 351 | private System.Windows.Forms.ComboBox cbBauds; 352 | private System.Windows.Forms.GroupBox groupBox4; 353 | private System.Windows.Forms.CheckBox cbxErase; 354 | private System.Windows.Forms.TextBox tbAddress; 355 | private System.Windows.Forms.Label label4; 356 | private System.Windows.Forms.ToolTip ttToolTip; 357 | private System.Windows.Forms.Label label1; 358 | private System.Windows.Forms.Button bOpenFile; 359 | private System.Windows.Forms.GroupBox groupBox2; 360 | private System.Windows.Forms.TextBox tbFileName; 361 | private System.Windows.Forms.Button bJump; 362 | private System.Windows.Forms.ComboBox cbPSize; 363 | private System.Windows.Forms.Label label5; 364 | 365 | } 366 | } 367 | 368 | -------------------------------------------------------------------------------- /STM32 Flash Loader/MainForm.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Data; 5 | using System.Drawing; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using System.Windows.Forms; 10 | using System.IO.Ports; 11 | using System.IO; 12 | using System.Threading; 13 | using System.Media; 14 | using STBootLib; 15 | 16 | namespace STUploader 17 | { 18 | public partial class fMainForm : Form 19 | { 20 | /* current file name */ 21 | string fileName; 22 | /* com port name */ 23 | string portName; 24 | /* baudrate */ 25 | uint baudRate; 26 | /* address */ 27 | uint address; 28 | /* page */ 29 | uint page; 30 | 31 | /* default address */ 32 | const uint baseAddress = 0x08000000; 33 | 34 | /* constructor */ 35 | public fMainForm() 36 | { 37 | /* initialize all components */ 38 | InitializeComponent(); 39 | 40 | /* set default baurate selection */ 41 | cbBauds.SelectedIndex = 6; 42 | cbPSize.SelectedIndex = 0; 43 | /* set defaul address */ 44 | address = baseAddress; 45 | } 46 | 47 | /* drop down list opened */ 48 | private void cbPorts_DropDown(object sender, EventArgs e) 49 | { 50 | /* apply to combo box */ 51 | cbPorts.DataSource = SerialPort.GetPortNames(); 52 | } 53 | 54 | /* port selection was altered */ 55 | private void cbPorts_SelectedIndexChanged(object sender, EventArgs e) 56 | { 57 | /* valid selection made? */ 58 | if (cbPorts.SelectedIndex == -1) { 59 | /* nope, disable button */ 60 | bWrite.Enabled = bJump.Enabled = false; 61 | } else { 62 | /* store com port name */ 63 | portName = (string)cbPorts.SelectedItem; 64 | /* enable button */ 65 | bWrite.Enabled = bJump.Enabled = true; 66 | } 67 | } 68 | 69 | /* open file clicked */ 70 | private void bOpenFile_Click(object sender, EventArgs e) 71 | { 72 | /* file selected? */ 73 | if (ofdOpen.ShowDialog() == System.Windows.Forms.DialogResult.OK) { 74 | /* set file name */ 75 | tbFileName.Text = ofdOpen.SafeFileName; 76 | /* set tool tip */ 77 | ttToolTip.SetToolTip(tbFileName, ofdOpen.FileName); 78 | /* store full path */ 79 | fileName = ofdOpen.FileName; 80 | } 81 | } 82 | 83 | /* jump button pressed */ 84 | private async void bJump_Click(object sender, EventArgs e) 85 | { 86 | /* disable button */ 87 | bJump.Enabled = bWrite.Enabled = false; 88 | /* get port name */ 89 | string pName = (string)cbPorts.SelectedItem; 90 | /* get baud rate */ 91 | uint bauds = uint.Parse((string)cbBauds.SelectedItem); 92 | /* get address */ 93 | uint address = Convert.ToUInt32(tbAddress.Text, 16); 94 | 95 | try { 96 | /* try to upload */ 97 | await Jump(address); 98 | } catch (Exception ex) { 99 | /* set message */ 100 | UpdateStatus(true, ex.Message); 101 | } finally { 102 | bJump.Enabled = bWrite.Enabled = true; 103 | } 104 | } 105 | 106 | /* write clicked */ 107 | private async void bWrite_Click(object sender, EventArgs e) 108 | { 109 | /* disable button */ 110 | bJump.Enabled = bWrite.Enabled = false; 111 | /* get port name */ 112 | string pName = (string)cbPorts.SelectedItem; 113 | /* get baud rate */ 114 | uint bauds = uint.Parse((string)cbBauds.SelectedItem); 115 | /* get address */ 116 | uint address = Convert.ToUInt32(tbAddress.Text, 16); 117 | 118 | try { 119 | /* read file */ 120 | var bin = await ReadFile(fileName); 121 | /* try to upload */ 122 | await UploadFile(pName, bauds, bin, address, address); 123 | } catch (Exception ex) { 124 | /* set message */ 125 | UpdateStatus(true, ex.Message); 126 | } finally { 127 | bJump.Enabled = bWrite.Enabled = true; 128 | } 129 | } 130 | 131 | 132 | 133 | /* baud rate changed */ 134 | private void cbBauds_SelectedIndexChanged(object sender, EventArgs e) 135 | { 136 | /* convert from string */ 137 | baudRate = uint.Parse((string)cbBauds.SelectedItem); 138 | } 139 | 140 | /* parse address */ 141 | private void tbAddress_Leave(object sender, EventArgs e) 142 | { 143 | /* parsed address */ 144 | uint addr; 145 | 146 | /* try to parse input */ 147 | try { 148 | /* convert address field */ 149 | addr = Convert.ToUInt32(tbAddress.Text, 16); 150 | /* malformed address value */ 151 | } catch (OverflowException) { 152 | /* set message */ 153 | tsslStatus.Text = "Address too large!"; 154 | /* restore default value */ 155 | addr = baseAddress; 156 | /* all other errors go here */ 157 | } catch (Exception) { 158 | /* set message */ 159 | tsslStatus.Text = "Incorrect hex value"; 160 | /* restore default value */ 161 | addr = baseAddress; 162 | } 163 | 164 | /* store realigned address */ 165 | address = addr & 0xffffff00; 166 | /* start page - end page */ 167 | page = (address - baseAddress) / 256; 168 | 169 | /* rewrite */ 170 | tbAddress.Text = string.Format("0x{0:X8}", address); 171 | } 172 | 173 | /* load firmware file */ 174 | private async Task ReadFile(string fname) 175 | { 176 | byte[] bin; 177 | 178 | /* open file */ 179 | using (var s = new FileStream(fname, FileMode.Open, 180 | FileAccess.Read)) { 181 | /* allocate memory */ 182 | bin = new byte[s.Length]; 183 | /* read file contents */ 184 | await s.ReadAsync(bin, 0, bin.Length); 185 | } 186 | 187 | /* return binary image */ 188 | return bin; 189 | } 190 | 191 | /* upload a binary image to uC */ 192 | private async Task UploadFile(string portName, uint baudRate, 193 | byte[] bin, uint address, uint jumpAddress) 194 | { 195 | /* get page size */ 196 | uint psize = uint.Parse(cbPSize.SelectedItem as string); 197 | 198 | /* create new programming interface object */ 199 | using (var uc = new STBoot()) { 200 | /* open device */ 201 | uc.Open(portName, baudRate); 202 | /* initialize communication */ 203 | await uc.Initialize(); 204 | /* update the status */ 205 | UpdateStatus(false, string.Format("Connected: Ver: {0}, PID: 0x{1:X4}", 206 | uc.Version, uc.ProductID)); 207 | /* give some chance see the message */ 208 | await Task.Delay(500); 209 | 210 | /* apply new message */ 211 | UpdateStatus(false, "Erasing..."); 212 | 213 | /* checked? */ 214 | if (cbxErase.Checked) { 215 | await uc.GlobalErase(); 216 | } else { 217 | /* erase operation */ 218 | for (uint i = 0; i < bin.Length; i += psize) { 219 | /* erase page */ 220 | await uc.ErasePage((i + address - 0x08000000) / psize); 221 | /* update progress bar */ 222 | UpdateProgress((int)i * 100 / bin.Length); 223 | } 224 | } 225 | 226 | /* apply new message */ 227 | UpdateStatus(false, "Programming..."); 228 | /* progress reporter */ 229 | var p = new Progress(UpdateProgress); 230 | /* write memory */ 231 | await uc.WriteMemory(address, bin, 0, bin.Length, p, 232 | CancellationToken.None); 233 | /* update the status */ 234 | UpdateStatus(false, string.Format("Success: {0} bytes written", 235 | bin.Length)); 236 | 237 | /* go! */ 238 | await uc.Jump(jumpAddress); 239 | 240 | /* end communication */ 241 | uc.Close(); 242 | } 243 | } 244 | 245 | /* execute code */ 246 | private async Task Jump(uint address) 247 | { 248 | /* create new programming interface object */ 249 | using (var uc = new STBoot()) { 250 | /* open device */ 251 | uc.Open(portName, baudRate); 252 | /* initialize communication */ 253 | await uc.Initialize(); 254 | /* go! */ 255 | await uc.Jump(address); 256 | /* end communication */ 257 | uc.Close(); 258 | } 259 | } 260 | 261 | /* set current progress */ 262 | private void UpdateProgress(STBootProgress p) 263 | { 264 | /* converts bytes to percentage */ 265 | UpdateProgress(100 * p.bytesProcessed / p.bytesTotal); 266 | } 267 | 268 | /* set current progress */ 269 | private void UpdateProgress(int percent) 270 | { 271 | /* set progress bar value */ 272 | pbProgress.Value = percent; 273 | /* set label */ 274 | lProgress.Text = percent.ToString() + "%"; 275 | } 276 | 277 | /* update status bar */ 278 | private void UpdateStatus(bool ding, string text) 279 | { 280 | /* text */ 281 | tsslStatus.Text = text; 282 | /* play a system sound? */ 283 | if (ding) { 284 | /* ^^ ding! */ 285 | SystemSounds.Exclamation.Play(); 286 | } 287 | } 288 | 289 | private void cbxErase_CheckedChanged(object sender, EventArgs e) 290 | { 291 | 292 | } 293 | 294 | private void cbPSize_SelectedIndexChanged(object sender, EventArgs e) 295 | { 296 | 297 | } 298 | 299 | 300 | } 301 | } 302 | -------------------------------------------------------------------------------- /STM32 Flash Loader/MainForm.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 233, 17 122 | 123 | 124 | 17, 17 125 | 126 | 127 | 133, 17 128 | 129 | 130 | 131 | 132 | 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 184 | 185 | 186 | -------------------------------------------------------------------------------- /STM32 Flash Loader/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using System.Windows.Forms; 6 | 7 | namespace STUploader 8 | { 9 | static class Program 10 | { 11 | /// 12 | /// The main entry point for the application. 13 | /// 14 | [STAThread] 15 | static void Main() 16 | { 17 | Application.EnableVisualStyles(); 18 | Application.SetCompatibleTextRenderingDefault(false); 19 | Application.Run(new fMainForm()); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /STM32 Flash Loader/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | using System.Resources; 5 | 6 | // General Information about an assembly is controlled through the following 7 | // set of attributes. Change these attribute values to modify the information 8 | // associated with an assembly. 9 | [assembly: AssemblyTitle("STM32 Flash Loader")] 10 | [assembly: AssemblyDescription("An alternative to ST's crappy Flash Loader Demonstrator")] 11 | [assembly: AssemblyConfiguration("")] 12 | [assembly: AssemblyCompany("Mighty Devices (mightydevices.com)")] 13 | [assembly: AssemblyProduct("STM32 Flash Loader")] 14 | [assembly: AssemblyCopyright("Copyright © 2015")] 15 | [assembly: AssemblyTrademark("")] 16 | [assembly: AssemblyCulture("")] 17 | 18 | // Setting ComVisible to false makes the types in this assembly not visible 19 | // to COM components. If you need to access a type in this assembly from 20 | // COM, set the ComVisible attribute to true on that type. 21 | [assembly: ComVisible(false)] 22 | 23 | // The following GUID is for the ID of the typelib if this project is exposed to COM 24 | [assembly: Guid("4bf3c8ae-6a9f-4727-a578-f986b4aa2047")] 25 | 26 | // Version information for an assembly consists of the following four values: 27 | // 28 | // Major Version 29 | // Minor Version 30 | // Build Number 31 | // Revision 32 | // 33 | // You can specify all the values or you can default the Build and Revision Numbers 34 | // by using the '*' as shown below: 35 | // [assembly: AssemblyVersion("1.0.*")] 36 | [assembly: AssemblyVersion("1.0.0.0")] 37 | [assembly: AssemblyFileVersion("1.0.0.0")] 38 | [assembly: NeutralResourcesLanguageAttribute("en")] 39 | -------------------------------------------------------------------------------- /STM32 Flash Loader/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.34209 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace STM32_Flash_Loader.Properties 12 | { 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources 26 | { 27 | 28 | private static global::System.Resources.ResourceManager resourceMan; 29 | 30 | private static global::System.Globalization.CultureInfo resourceCulture; 31 | 32 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 33 | internal Resources() 34 | { 35 | } 36 | 37 | /// 38 | /// Returns the cached ResourceManager instance used by this class. 39 | /// 40 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 41 | internal static global::System.Resources.ResourceManager ResourceManager 42 | { 43 | get 44 | { 45 | if ((resourceMan == null)) { 46 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("STM32_Flash_Loader.Properties.Resources", typeof(Resources).Assembly); 47 | resourceMan = temp; 48 | } 49 | return resourceMan; 50 | } 51 | } 52 | 53 | /// 54 | /// Overrides the current thread's CurrentUICulture property for all 55 | /// resource lookups using this strongly typed resource class. 56 | /// 57 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 58 | internal static global::System.Globalization.CultureInfo Culture 59 | { 60 | get 61 | { 62 | return resourceCulture; 63 | } 64 | set 65 | { 66 | resourceCulture = value; 67 | } 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /STM32 Flash Loader/Properties/Resources.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | text/microsoft-resx 107 | 108 | 109 | 2.0 110 | 111 | 112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 113 | 114 | 115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | -------------------------------------------------------------------------------- /STM32 Flash Loader/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.34209 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace STM32_Flash_Loader.Properties 12 | { 13 | 14 | 15 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 16 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] 17 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase 18 | { 19 | 20 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 21 | 22 | public static Settings Default 23 | { 24 | get 25 | { 26 | return defaultInstance; 27 | } 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /STM32 Flash Loader/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /STM32 Flash Loader/STM32 Flash Loader.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {F2A80228-9234-4748-A61B-F26D3C1EC7FA} 8 | WinExe 9 | Properties 10 | STM32_Flash_Loader 11 | STM32 Flash Loader 12 | v4.5 13 | 512 14 | 15 | 16 | AnyCPU 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | AnyCPU 27 | pdbonly 28 | true 29 | bin\Release\ 30 | TRACE 31 | prompt 32 | 4 33 | 34 | 35 | arrow.ico 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | Form 52 | 53 | 54 | MainForm.cs 55 | 56 | 57 | 58 | 59 | MainForm.cs 60 | 61 | 62 | ResXFileCodeGenerator 63 | Resources.Designer.cs 64 | Designer 65 | 66 | 67 | True 68 | Resources.resx 69 | 70 | 71 | SettingsSingleFileGenerator 72 | Settings.Designer.cs 73 | 74 | 75 | True 76 | Settings.settings 77 | True 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | {8ec66a52-5978-481d-a80d-d75cbc6de918} 89 | STBootLib 90 | 91 | 92 | 93 | 100 | -------------------------------------------------------------------------------- /STM32 Flash Loader/arrow.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MightyDevices/STBootLib/ba42961210996798f7fc003c9f94ec141ee7bcf9/STM32 Flash Loader/arrow.ico --------------------------------------------------------------------------------