├── .gitignore ├── ELF ├── dhrystone.elf ├── monitor.elf └── uartlink.elf ├── LICENSE ├── README.md ├── STM8.exe ├── STM8.sln └── STM8 ├── STM8.vcxproj ├── STM8.vcxproj.filters ├── args.c ├── args.h ├── config.h ├── console.c ├── console.h ├── cpu.c ├── cpu.h ├── devices ├── stm8s003f3.c ├── stm8s003f3.h ├── stm8s207r8.c ├── stm8s207r8.h ├── stm8s207s6.c └── stm8s207s6.h ├── display.c ├── display.h ├── elf.c ├── elf.h ├── endian.h ├── hardware ├── casil.c └── casil.h ├── intelhex.c ├── intelhex.h ├── main.c ├── memory.c ├── memory.h ├── peripherals ├── adc.c ├── adc.h ├── clk.c ├── clk.h ├── iwdg.c ├── iwdg.h ├── tim2.c ├── tim2.h ├── uart1.c ├── uart1.h ├── uart3.c └── uart3.h ├── ports.c ├── ports.h ├── products ├── null.c └── null.h ├── serial.c ├── serial.h ├── srec.c ├── srec.h ├── tcpconsole.c ├── tcpconsole.h ├── timing.c └── timing.h /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.rsuser 8 | *.suo 9 | *.user 10 | *.userosscache 11 | *.sln.docstates 12 | 13 | # User-specific files (MonoDevelop/Xamarin Studio) 14 | *.userprefs 15 | 16 | # Mono auto generated files 17 | mono_crash.* 18 | 19 | # Build results 20 | [Dd]ebug/ 21 | [Dd]ebugPublic/ 22 | [Rr]elease/ 23 | [Rr]eleases/ 24 | x64/ 25 | x86/ 26 | [Ww][Ii][Nn]32/ 27 | [Aa][Rr][Mm]/ 28 | [Aa][Rr][Mm]64/ 29 | bld/ 30 | [Bb]in/ 31 | [Oo]bj/ 32 | [Ll]og/ 33 | [Ll]ogs/ 34 | 35 | # Visual Studio 2015/2017 cache/options directory 36 | .vs/ 37 | # Uncomment if you have tasks that create the project's static files in wwwroot 38 | #wwwroot/ 39 | 40 | # Visual Studio 2017 auto generated files 41 | Generated\ Files/ 42 | 43 | # MSTest test Results 44 | [Tt]est[Rr]esult*/ 45 | [Bb]uild[Ll]og.* 46 | 47 | # NUnit 48 | *.VisualState.xml 49 | TestResult.xml 50 | nunit-*.xml 51 | 52 | # Build Results of an ATL Project 53 | [Dd]ebugPS/ 54 | [Rr]eleasePS/ 55 | dlldata.c 56 | 57 | # Benchmark Results 58 | BenchmarkDotNet.Artifacts/ 59 | 60 | # .NET Core 61 | project.lock.json 62 | project.fragment.lock.json 63 | artifacts/ 64 | 65 | # ASP.NET Scaffolding 66 | ScaffoldingReadMe.txt 67 | 68 | # StyleCop 69 | StyleCopReport.xml 70 | 71 | # Files built by Visual Studio 72 | *_i.c 73 | *_p.c 74 | *_h.h 75 | *.ilk 76 | *.meta 77 | *.obj 78 | *.iobj 79 | *.pch 80 | *.pdb 81 | *.ipdb 82 | *.pgc 83 | *.pgd 84 | *.rsp 85 | *.sbr 86 | *.tlb 87 | *.tli 88 | *.tlh 89 | *.tmp 90 | *.tmp_proj 91 | *_wpftmp.csproj 92 | *.log 93 | *.tlog 94 | *.vspscc 95 | *.vssscc 96 | .builds 97 | *.pidb 98 | *.svclog 99 | *.scc 100 | 101 | # Chutzpah Test files 102 | _Chutzpah* 103 | 104 | # Visual C++ cache files 105 | ipch/ 106 | *.aps 107 | *.ncb 108 | *.opendb 109 | *.opensdf 110 | *.sdf 111 | *.cachefile 112 | *.VC.db 113 | *.VC.VC.opendb 114 | 115 | # Visual Studio profiler 116 | *.psess 117 | *.vsp 118 | *.vspx 119 | *.sap 120 | 121 | # Visual Studio Trace Files 122 | *.e2e 123 | 124 | # TFS 2012 Local Workspace 125 | $tf/ 126 | 127 | # Guidance Automation Toolkit 128 | *.gpState 129 | 130 | # ReSharper is a .NET coding add-in 131 | _ReSharper*/ 132 | *.[Rr]e[Ss]harper 133 | *.DotSettings.user 134 | 135 | # TeamCity is a build add-in 136 | _TeamCity* 137 | 138 | # DotCover is a Code Coverage Tool 139 | *.dotCover 140 | 141 | # AxoCover is a Code Coverage Tool 142 | .axoCover/* 143 | !.axoCover/settings.json 144 | 145 | # Coverlet is a free, cross platform Code Coverage Tool 146 | coverage*.json 147 | coverage*.xml 148 | coverage*.info 149 | 150 | # Visual Studio code coverage results 151 | *.coverage 152 | *.coveragexml 153 | 154 | # NCrunch 155 | _NCrunch_* 156 | .*crunch*.local.xml 157 | nCrunchTemp_* 158 | 159 | # MightyMoose 160 | *.mm.* 161 | AutoTest.Net/ 162 | 163 | # Web workbench (sass) 164 | .sass-cache/ 165 | 166 | # Installshield output folder 167 | [Ee]xpress/ 168 | 169 | # DocProject is a documentation generator add-in 170 | DocProject/buildhelp/ 171 | DocProject/Help/*.HxT 172 | DocProject/Help/*.HxC 173 | DocProject/Help/*.hhc 174 | DocProject/Help/*.hhk 175 | DocProject/Help/*.hhp 176 | DocProject/Help/Html2 177 | DocProject/Help/html 178 | 179 | # Click-Once directory 180 | publish/ 181 | 182 | # Publish Web Output 183 | *.[Pp]ublish.xml 184 | *.azurePubxml 185 | # Note: Comment the next line if you want to checkin your web deploy settings, 186 | # but database connection strings (with potential passwords) will be unencrypted 187 | *.pubxml 188 | *.publishproj 189 | 190 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 191 | # checkin your Azure Web App publish settings, but sensitive information contained 192 | # in these scripts will be unencrypted 193 | PublishScripts/ 194 | 195 | # NuGet Packages 196 | *.nupkg 197 | # NuGet Symbol Packages 198 | *.snupkg 199 | # The packages folder can be ignored because of Package Restore 200 | **/[Pp]ackages/* 201 | # except build/, which is used as an MSBuild target. 202 | !**/[Pp]ackages/build/ 203 | # Uncomment if necessary however generally it will be regenerated when needed 204 | #!**/[Pp]ackages/repositories.config 205 | # NuGet v3's project.json files produces more ignorable files 206 | *.nuget.props 207 | *.nuget.targets 208 | 209 | # Microsoft Azure Build Output 210 | csx/ 211 | *.build.csdef 212 | 213 | # Microsoft Azure Emulator 214 | ecf/ 215 | rcf/ 216 | 217 | # Windows Store app package directories and files 218 | AppPackages/ 219 | BundleArtifacts/ 220 | Package.StoreAssociation.xml 221 | _pkginfo.txt 222 | *.appx 223 | *.appxbundle 224 | *.appxupload 225 | 226 | # Visual Studio cache files 227 | # files ending in .cache can be ignored 228 | *.[Cc]ache 229 | # but keep track of directories ending in .cache 230 | !?*.[Cc]ache/ 231 | 232 | # Others 233 | ClientBin/ 234 | ~$* 235 | *~ 236 | *.dbmdl 237 | *.dbproj.schemaview 238 | *.jfm 239 | *.pfx 240 | *.publishsettings 241 | orleans.codegen.cs 242 | 243 | # Including strong name files can present a security risk 244 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 245 | #*.snk 246 | 247 | # Since there are multiple workflows, uncomment next line to ignore bower_components 248 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 249 | #bower_components/ 250 | 251 | # RIA/Silverlight projects 252 | Generated_Code/ 253 | 254 | # Backup & report files from converting an old project file 255 | # to a newer Visual Studio version. Backup files are not needed, 256 | # because we have git ;-) 257 | _UpgradeReport_Files/ 258 | Backup*/ 259 | UpgradeLog*.XML 260 | UpgradeLog*.htm 261 | ServiceFabricBackup/ 262 | *.rptproj.bak 263 | 264 | # SQL Server files 265 | *.mdf 266 | *.ldf 267 | *.ndf 268 | 269 | # Business Intelligence projects 270 | *.rdl.data 271 | *.bim.layout 272 | *.bim_*.settings 273 | *.rptproj.rsuser 274 | *- [Bb]ackup.rdl 275 | *- [Bb]ackup ([0-9]).rdl 276 | *- [Bb]ackup ([0-9][0-9]).rdl 277 | 278 | # Microsoft Fakes 279 | FakesAssemblies/ 280 | 281 | # GhostDoc plugin setting file 282 | *.GhostDoc.xml 283 | 284 | # Node.js Tools for Visual Studio 285 | .ntvs_analysis.dat 286 | node_modules/ 287 | 288 | # Visual Studio 6 build log 289 | *.plg 290 | 291 | # Visual Studio 6 workspace options file 292 | *.opt 293 | 294 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 295 | *.vbw 296 | 297 | # Visual Studio 6 auto-generated project file (contains which files were open etc.) 298 | *.vbp 299 | 300 | # Visual Studio 6 workspace and project file (working project files containing files to include in project) 301 | *.dsw 302 | *.dsp 303 | 304 | # Visual Studio 6 technical files 305 | *.ncb 306 | *.aps 307 | 308 | # Visual Studio LightSwitch build output 309 | **/*.HTMLClient/GeneratedArtifacts 310 | **/*.DesktopClient/GeneratedArtifacts 311 | **/*.DesktopClient/ModelManifest.xml 312 | **/*.Server/GeneratedArtifacts 313 | **/*.Server/ModelManifest.xml 314 | _Pvt_Extensions 315 | 316 | # Paket dependency manager 317 | .paket/paket.exe 318 | paket-files/ 319 | 320 | # FAKE - F# Make 321 | .fake/ 322 | 323 | # CodeRush personal settings 324 | .cr/personal 325 | 326 | # Python Tools for Visual Studio (PTVS) 327 | __pycache__/ 328 | *.pyc 329 | 330 | # Cake - Uncomment if you are using it 331 | # tools/** 332 | # !tools/packages.config 333 | 334 | # Tabs Studio 335 | *.tss 336 | 337 | # Telerik's JustMock configuration file 338 | *.jmconfig 339 | 340 | # BizTalk build output 341 | *.btp.cs 342 | *.btm.cs 343 | *.odx.cs 344 | *.xsd.cs 345 | 346 | # OpenCover UI analysis results 347 | OpenCover/ 348 | 349 | # Azure Stream Analytics local run output 350 | ASALocalRun/ 351 | 352 | # MSBuild Binary and Structured Log 353 | *.binlog 354 | 355 | # NVidia Nsight GPU debugger configuration file 356 | *.nvuser 357 | 358 | # MFractors (Xamarin productivity tool) working folder 359 | .mfractor/ 360 | 361 | # Local History for Visual Studio 362 | .localhistory/ 363 | 364 | # Visual Studio History (VSHistory) files 365 | .vshistory/ 366 | 367 | # BeatPulse healthcheck temp database 368 | healthchecksdb 369 | 370 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 371 | MigrationBackup/ 372 | 373 | # Ionide (cross platform F# VS Code tools) working folder 374 | .ionide/ 375 | 376 | # Fody - auto-generated XML schema 377 | FodyWeavers.xsd 378 | 379 | # VS Code files for those working on multiple tools 380 | .vscode/* 381 | !.vscode/settings.json 382 | !.vscode/tasks.json 383 | !.vscode/launch.json 384 | !.vscode/extensions.json 385 | *.code-workspace 386 | 387 | # Local History for Visual Studio Code 388 | .history/ 389 | 390 | # Windows Installer files from build outputs 391 | *.cab 392 | *.msi 393 | *.msix 394 | *.msm 395 | *.msp 396 | 397 | # JetBrains Rider 398 | *.sln.iml 399 | -------------------------------------------------------------------------------- /ELF/dhrystone.elf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikechambers84/STM8-Emulator/42e7b2127dbc826e4cd449904c1f2afcc07487f5/ELF/dhrystone.elf -------------------------------------------------------------------------------- /ELF/monitor.elf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikechambers84/STM8-Emulator/42e7b2127dbc826e4cd449904c1f2afcc07487f5/ELF/monitor.elf -------------------------------------------------------------------------------- /ELF/uartlink.elf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikechambers84/STM8-Emulator/42e7b2127dbc826e4cd449904c1f2afcc07487f5/ELF/uartlink.elf -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # STM8 Emulator 2 | 3 | ### About 4 | 5 | This is an emulator for the STM8 microcontroller family, and it also is designed to be able to have various simulated products/hardware layouts that the STM8 MCU is attached to, so that GPIO and other functionality can be intercepted and dealt with as needed. There were some defined product designs, but I've removed them from this public release because they were all based on proprietary designs made by the company I work for. 6 | 7 | This program can load ELF files generated by an STM8 compiler. 8 | 9 | Few of the peripherals are emulated so far. I've been adding them as needed. 10 | 11 | The solution and project files are made with Visual Studio 2019. 12 | 13 | 14 | ### Features 15 | 16 | NOTE: More features can be added as the need arises. 17 | 18 | EEPROM contents can be loaded and saved via a file with the -eeprom option. 19 | 20 | #### Currently supported STM8 models: 21 | 22 | - STM8S003F3 (Flash: 8 KB, RAM: 1 KB, EEPROM: 128 bytes) 23 | - STM8S207S6 (Flash: 32 KB, RAM: 6 KB, EEPROM: 1 KB) 24 | - STM8S207R8 (Flash: 64 KB, RAM: 6 KB, EEPROM: 2 KB) 25 | 26 | 27 | #### Currently supported on-chip devices: 28 | 29 | - GPIO ports 30 | - IWDG 31 | - CLK 32 | - ADC 33 | - UART1 34 | - UART3 35 | - TIM2 timer 36 | 37 | Emulated UARTs can be redirected through either the stdio console, a serial port, or a TCP socket (currently server-only). 38 | 39 | 40 | #### Currently supported exeternal devices: 41 | 42 | - Casil 1610 16-character LCD display (Incomplete. Cannot return data, but you can write characters to it) 43 | 44 | 45 | #### Currently supported hardware products/designs: 46 | 47 | - Null (No display unless a UART is redirected to the console. CPU runs in isolation.) 48 | 49 | I may add a few ST Discovery boards in a future release as examples of how to add your own custom designs. 50 | 51 | 52 | ### Functional overview 53 | 54 | The memory regions of the MCU are simulated with byte arrays which are defined in the header files for each MCU device model. 55 | 56 | The CPU engine uses C variables to simulate the CPU registers PC, A, X, Y, SP and CC. 57 | 58 | The ELF, Intel Hex or SREC file generated by the STM8 linker is loaded into the correct region of memory, and the CPU engine steps through the memory locations, interpreting the instruction bytecode as the real CPU would. It performs equivalent operations and modifies the simulated registers as the real CPU would. 59 | 60 | Memory accesses by the emulated CPU are intercepted, mapped and interpreted in different ways to simulate the various on-chip peripherals, as well as different external hardware on various product designs. 61 | 62 | 63 | 64 | ### Provided example ELF files 65 | 66 | - dhrystone.elf - A port of Dhrystone for the STM8. Displays 0 as the result for some reason, have not spent time looking at why yet. 67 | - monitor.elf - A very, very simple "monitor" firmware I started writing that currently just lets you examine memory contents. Uses UART1. 68 | - uartlink.elf - Simple program to relay data between UART1 and UART3. 69 | 70 | 71 | 72 | ### Running an example ELF 73 | 74 | Try something like: 75 | 76 | STM8.exe -product null -cpu stm8s207r8 -uart3console -elf ELF\dhrystone.elf 77 | 78 | or 79 | 80 | STM8.exe -product null -cpu stm8s003f3 -uart1console -elf ELF\monitor.elf 81 | 82 | 83 | 84 | ### Still to do 85 | 86 | - Add more MCU models, peripherals and a plug-in system for product/board simulation 87 | - Clean up code a bit, maybe rewrite CPU engine to take advantage of bit patterns in the opcodes 88 | -------------------------------------------------------------------------------- /STM8.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mikechambers84/STM8-Emulator/42e7b2127dbc826e4cd449904c1f2afcc07487f5/STM8.exe -------------------------------------------------------------------------------- /STM8.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30204.135 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "STM8", "STM8\STM8.vcxproj", "{CDBC24CE-7C3D-439C-9C8D-EE60BD406B53}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {CDBC24CE-7C3D-439C-9C8D-EE60BD406B53}.Debug|x64.ActiveCfg = Debug|x64 17 | {CDBC24CE-7C3D-439C-9C8D-EE60BD406B53}.Debug|x64.Build.0 = Debug|x64 18 | {CDBC24CE-7C3D-439C-9C8D-EE60BD406B53}.Debug|x86.ActiveCfg = Debug|Win32 19 | {CDBC24CE-7C3D-439C-9C8D-EE60BD406B53}.Debug|x86.Build.0 = Debug|Win32 20 | {CDBC24CE-7C3D-439C-9C8D-EE60BD406B53}.Release|x64.ActiveCfg = Release|x64 21 | {CDBC24CE-7C3D-439C-9C8D-EE60BD406B53}.Release|x64.Build.0 = Release|x64 22 | {CDBC24CE-7C3D-439C-9C8D-EE60BD406B53}.Release|x86.ActiveCfg = Release|Win32 23 | {CDBC24CE-7C3D-439C-9C8D-EE60BD406B53}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {A2063A0C-7C52-4A0A-9FF5-B5D73D2EC44D} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /STM8/STM8.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 16.0 23 | Win32Proj 24 | {cdbc24ce-7c3d-439c-9c8d-ee60bd406b53} 25 | STM8 26 | 10.0 27 | 28 | 29 | 30 | Application 31 | true 32 | v142 33 | Unicode 34 | 35 | 36 | Application 37 | false 38 | v142 39 | true 40 | Unicode 41 | 42 | 43 | Application 44 | true 45 | v142 46 | Unicode 47 | 48 | 49 | Application 50 | false 51 | v142 52 | true 53 | Unicode 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | true 75 | 76 | 77 | false 78 | 79 | 80 | true 81 | 82 | 83 | false 84 | 85 | 86 | 87 | Level3 88 | true 89 | _CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS 90 | true 91 | 92 | 93 | Console 94 | true 95 | kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies);ws2_32.lib 96 | 97 | 98 | 99 | 100 | Level3 101 | true 102 | true 103 | true 104 | _WINSOCK_DEPRECATED_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS 105 | true 106 | 107 | 108 | Console 109 | true 110 | true 111 | true 112 | kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies);ws2_32.lib 113 | 114 | 115 | 116 | 117 | Level3 118 | true 119 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS 120 | true 121 | 122 | 123 | Console 124 | true 125 | kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies);ws2_32.lib 126 | 127 | 128 | 129 | 130 | Level3 131 | true 132 | true 133 | true 134 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS;_WINSOCK_DEPRECATED_NO_WARNINGS 135 | true 136 | 137 | 138 | Console 139 | true 140 | true 141 | true 142 | kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies);ws2_32.lib 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | -------------------------------------------------------------------------------- /STM8/STM8.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | {98dfb924-94a4-43d6-b38e-f27364fdf2df} 18 | 19 | 20 | {4c748966-6cc6-4a4c-9431-a238a7aebbb4} 21 | 22 | 23 | {bedd5674-3c25-4b6e-97e4-8ccec6fa18a3} 24 | 25 | 26 | {f57dd382-1519-4b19-9be7-728111a974c3} 27 | 28 | 29 | {df404310-b46d-41e1-b518-dfb430ea78ba} 30 | 31 | 32 | {55d21ef8-58ca-4b88-9e43-d24a1581997a} 33 | 34 | 35 | {f04a6e11-dad9-4158-af00-4904a51d9a9b} 36 | 37 | 38 | {3fbb3d45-ae3c-47dc-8c73-62895eaa404f} 39 | 40 | 41 | 42 | 43 | Source Files 44 | 45 | 46 | Source Files 47 | 48 | 49 | Source Files 50 | 51 | 52 | Source Files 53 | 54 | 55 | Source Files\hardware 56 | 57 | 58 | Source Files 59 | 60 | 61 | Source Files 62 | 63 | 64 | Source Files 65 | 66 | 67 | Source Files 68 | 69 | 70 | Source Files\peripherals 71 | 72 | 73 | Source Files\peripherals 74 | 75 | 76 | Source Files\peripherals 77 | 78 | 79 | Source Files\products 80 | 81 | 82 | Source Files\devices 83 | 84 | 85 | Source Files\devices 86 | 87 | 88 | Source Files\peripherals 89 | 90 | 91 | Source Files 92 | 93 | 94 | Source Files 95 | 96 | 97 | Source Files 98 | 99 | 100 | Source Files\devices 101 | 102 | 103 | Source Files\peripherals 104 | 105 | 106 | Source Files\peripherals 107 | 108 | 109 | Source Files 110 | 111 | 112 | Source Files 113 | 114 | 115 | 116 | 117 | Header Files 118 | 119 | 120 | Header Files 121 | 122 | 123 | Header Files 124 | 125 | 126 | Header Files 127 | 128 | 129 | Header Files 130 | 131 | 132 | Header Files\hardware 133 | 134 | 135 | Header Files 136 | 137 | 138 | Header Files 139 | 140 | 141 | Header Files 142 | 143 | 144 | Header Files\devices 145 | 146 | 147 | Header Files\peripherals 148 | 149 | 150 | Header Files\peripherals 151 | 152 | 153 | Header Files\peripherals 154 | 155 | 156 | Header Files\devices 157 | 158 | 159 | Header Files\products 160 | 161 | 162 | Header Files\peripherals 163 | 164 | 165 | Header Files 166 | 167 | 168 | Header Files 169 | 170 | 171 | Header Files 172 | 173 | 174 | Header Files\devices 175 | 176 | 177 | Header Files\peripherals 178 | 179 | 180 | Header Files\peripherals 181 | 182 | 183 | Header Files 184 | 185 | 186 | Header Files 187 | 188 | 189 | Header Files 190 | 191 | 192 | -------------------------------------------------------------------------------- /STM8/args.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "config.h" 6 | #include "timing.h" 7 | #include "serial.h" 8 | #include "tcpconsole.h" 9 | #include "products/null.h" 10 | #include "peripherals/uart1.h" 11 | #include "peripherals/uart3.h" 12 | #include "devices/stm8s207r8.h" 13 | #include "devices/stm8s207s6.h" 14 | #include "devices/stm8s003f3.h" 15 | 16 | double speedarg = -1; 17 | uint8_t showclock = 0, showdisplay = 1, overridecpu = 0, exitonIWDG = 0, disableIWDG = 0; 18 | char* elffile = NULL; 19 | char* hexfile = NULL; 20 | char* srecfile = NULL; 21 | char* ramfile = NULL; 22 | char* eepromfile = NULL; 23 | char* product_name = "null"; 24 | 25 | void (*product_register)(void) = (void*)null_register; 26 | void (*product_init)(void) = (void*)null_init; 27 | void (*product_update)(void) = (void*)null_update; 28 | void (*product_portwrite)(uint32_t addr, uint8_t val) = (void*)null_portwrite; 29 | uint8_t (*product_portread)(uint32_t addr, uint8_t* dst) = (void*)null_portread; 30 | void (*product_markforupdate)(void) = (void*)null_markforupdate; 31 | void (*product_loop)(void) = (void*)null_loop; 32 | 33 | int args_isMatch(char* s1, char* s2) { 34 | int i = 0, match = 1; 35 | 36 | while (1) { 37 | char c1, c2; 38 | c1 = s1[i]; 39 | c2 = s2[i++]; 40 | if ((c1 >= 'A') && (c1 <= 'Z')) { 41 | c1 -= 'A' - 'a'; 42 | } 43 | if ((c2 >= 'A') && (c2 <= 'Z')) { 44 | c2 -= 'A' - 'a'; 45 | } 46 | if (c1 != c2) { 47 | match = 0; 48 | break; 49 | } 50 | if (!c1 || !c2) { 51 | break; 52 | } 53 | } 54 | 55 | return match; 56 | } 57 | 58 | void args_showHelp() { 59 | printf("Command line parameters:\n"); 60 | 61 | printf("\nEmulation options:\n"); 62 | printf(" -cpu Specify CPU model. Use \"-cpu list\" to show available options.\n"); 63 | printf(" -elf Specify ELF file to load and execute.\n"); 64 | printf(" -hex Specify Intel Hex file to load and execute.\n"); 65 | printf(" -srec Specify S-Record file to load and execute.\n"); 66 | printf(" -eeprom Specify EEPROM file to load and save.\n"); 67 | printf(" -ramdump Specify file to dump RAM contents to on exit.\n"); 68 | printf(" -osc Specify external oscillator clock speed to emulate in Hz. Default is 24 MHz.\n"); 69 | printf(" -product Specify product hardware design to emulate.\n"); 70 | printf(" Use \"-product list\" to show available options.\n"); 71 | 72 | printf("\nWatchdog options:\n"); 73 | printf(" -exitiwdg Treat IWDG terminal count as an error condition and exit emulator.\n"); 74 | printf(" -disableiwdg Disable IWDG counter entirely.\n"); 75 | 76 | printf("\nUART1 options:\n"); 77 | printf(" -uart1console Redirect UART1 through the stdio console.\n"); 78 | printf(" -uart1serial Redirect UART1 through COM port at .\n"); 79 | printf(" -uart1sock Redirect UART1 through TCP socket, listen on .\n"); 80 | 81 | printf("\nUART3 options:\n"); 82 | printf(" -uart3serial Redirect UART3 through COM port at .\n"); 83 | printf(" -uart3console Redirect UART3 through the stdio console.\n"); 84 | printf(" -uart3sock Redirect UART3 through TCP socket, listen on .\n"); 85 | 86 | printf("\nDisplay options:\r\n"); 87 | printf(" -nodisplay Don't display a product representation.\n"); 88 | 89 | printf("\nMiscellaneous options:\n"); 90 | printf(" -showclock Display actual clock speed.\n"); 91 | printf(" -h Show this help screen.\n"); 92 | 93 | } 94 | 95 | void args_listcpu() { 96 | printf("Available CPU options:\r\n\r\n"); 97 | 98 | printf("STM8S003F3 (Flash: 8 KB, RAM: 1 KB, EEPROM: 128 bytes)\r\n"); 99 | printf("STM8S207S6 (Flash: 32 KB, RAM: 6 KB, EEPROM: 1 KB)\r\n"); 100 | printf("STM8S207R8 (Flash: 64 KB, RAM: 6 KB, EEPROM: 2 KB)\r\n"); 101 | 102 | exit(0); 103 | } 104 | 105 | void args_listproduct() { 106 | printf("Available product options:\r\n\r\n"); 107 | 108 | printf(" null: Null product. No interface, the CPU runs in isolation.\r\n"); 109 | 110 | exit(0); 111 | } 112 | 113 | int args_parse(int argc, char* argv[]) { 114 | int i, choseproduct = 0; 115 | 116 | if (argc < 2) { 117 | printf("Use -h for help.\n"); 118 | return -1; 119 | } 120 | 121 | for (i = 1; i < argc; i++) { 122 | if (args_isMatch(argv[i], "-h")) { 123 | args_showHelp(); 124 | return -1; 125 | } 126 | else if (args_isMatch(argv[i], "-elf")) { 127 | if ((i + 1) == argc) { 128 | printf("Parameter required for -elf. Use -h for help.\r\n"); 129 | return -1; 130 | } 131 | elffile = argv[++i]; 132 | } 133 | else if(args_isMatch(argv[i], "-hex")) { 134 | if((i + 1) == argc) { 135 | printf("Parameter required for -hex. Use -h for help.\r\n"); 136 | return -1; 137 | } 138 | hexfile = argv[++i]; 139 | } 140 | else if(args_isMatch(argv[i], "-srec")) { 141 | if((i + 1) == argc) { 142 | printf("Parameter required for -srec. Use -h for help.\r\n"); 143 | return -1; 144 | } 145 | srecfile = argv[++i]; 146 | } 147 | else if (args_isMatch(argv[i], "-eeprom")) { 148 | if ((i + 1) == argc) { 149 | printf("Parameter required for -eeprom. Use -h for help.\r\n"); 150 | return -1; 151 | } 152 | eepromfile = argv[++i]; 153 | } 154 | else if (args_isMatch(argv[i], "-ramdump")) { 155 | if ((i + 1) == argc) { 156 | printf("Parameter required for -ramdump. Use -h for help.\r\n"); 157 | return -1; 158 | } 159 | ramfile = argv[++i]; 160 | } 161 | else if (args_isMatch(argv[i], "-osc")) { 162 | if ((i + 1) == argc) { 163 | printf("Parameter required for -osc. Use -h for help.\r\n"); 164 | return -1; 165 | } 166 | speedarg = atof(argv[++i]); 167 | if (speedarg < 1000) { 168 | printf("Invalid oscilator speed. Must be at least 1000 Hz.\r\n"); 169 | return -1; 170 | } 171 | } 172 | else if (args_isMatch(argv[i], "-product")) { 173 | if ((i + 1) == argc) { 174 | printf("Parameter required for -product. Use -h for help.\r\n"); 175 | return -1; 176 | } 177 | if (args_isMatch(argv[i + 1], "list")) args_listproduct(); 178 | else if (args_isMatch(argv[i + 1], "null")) product_register = (void*)null_register; 179 | else { 180 | printf("%s is an invalid product option\r\n", argv[i + 1]); 181 | return -1; 182 | } 183 | i++; 184 | choseproduct = 1; 185 | } 186 | else if (args_isMatch(argv[i], "-cpu")) { 187 | if ((i + 1) == argc) { 188 | printf("Parameter required for -cpu. Use -h for help.\r\n"); 189 | return -1; 190 | } 191 | if (args_isMatch(argv[i + 1], "list")) args_listcpu(); 192 | else if (args_isMatch(argv[i + 1], "stm8s207r8")) stm8s207r8_init(); 193 | else if (args_isMatch(argv[i + 1], "stm8s207s6")) stm8s207s6_init(); 194 | else if (args_isMatch(argv[i + 1], "stm8s003f3")) stm8s003f3_init(); 195 | else { 196 | printf("%s is an invalid CPU option\r\n", argv[i + 1]); 197 | return -1; 198 | } 199 | i++; 200 | overridecpu = 1; 201 | } 202 | else if (args_isMatch(argv[i], "-showclock")) { 203 | showclock = 1; 204 | } 205 | else if (args_isMatch(argv[i], "-nodisplay")) { 206 | showdisplay = 0; 207 | } 208 | else if (args_isMatch(argv[i], "-uart1serial")) { 209 | int comnum, baud; 210 | if ((i + 2) >= argc) { 211 | printf("Parameters required for -uart1serial. Use -h for help.\r\n"); 212 | return -1; 213 | } 214 | comnum = atoi(argv[i + 1]); 215 | baud = atoi(argv[i + 2]); 216 | if (!comnum || !baud) { 217 | printf("Invalid parameter(s) for -uart1serial. Use -h for help.\r\n"); 218 | } 219 | if (serial_init(0, comnum, baud)) { 220 | printf("Error initializing serial port for -uart1serial.\r\n"); 221 | return -1; 222 | } 223 | uart1_redirect = UART1_REDIRECT_SERIAL; 224 | i += 2; 225 | } 226 | else if (args_isMatch(argv[i], "-uart3serial")) { 227 | int comnum, baud; 228 | if ((i + 2) >= argc) { 229 | printf("Parameters required for -uart3serial. Use -h for help.\r\n"); 230 | return -1; 231 | } 232 | comnum = atoi(argv[i + 1]); 233 | baud = atoi(argv[i + 2]); 234 | if (!comnum || !baud) { 235 | printf("Invalid parameter(s) for -uart3serial. Use -h for help.\r\n"); 236 | } 237 | if (serial_init(2, comnum, baud)) { 238 | printf("Error initializing serial port for -uart3serial.\r\n"); 239 | return -1; 240 | } 241 | uart3_redirect = UART3_REDIRECT_SERIAL; 242 | i += 2; 243 | } 244 | else if (args_isMatch(argv[i], "-uart1console")) { 245 | uart1_redirect = UART1_REDIRECT_CONSOLE; 246 | } 247 | else if (args_isMatch(argv[i], "-uart3console")) { 248 | uart3_redirect = UART3_REDIRECT_CONSOLE; 249 | } 250 | else if (args_isMatch(argv[i], "-uart1sock")) { 251 | uint16_t port; 252 | if ((i + 1) >= argc) { 253 | printf("Parameter required for -uart1sock. Use -h for help.\r\n"); 254 | return -1; 255 | } 256 | port = (uint16_t)atol(argv[i + 1]); 257 | if (!port) { 258 | printf("Invalid parameter for -uart1sock. Use -h for help.\r\n"); 259 | } 260 | if (tcpconsole_init(0, port)) { 261 | printf("Error initializing listening socket for -uart1sock.\r\n"); 262 | return -1; 263 | } 264 | uart1_redirect = UART1_REDIRECT_TCP; 265 | i++; 266 | } 267 | else if (args_isMatch(argv[i], "-uart3sock")) { 268 | uint16_t port; 269 | if ((i + 1) >= argc) { 270 | printf("Parameter required for -uart3sock. Use -h for help.\r\n"); 271 | return -1; 272 | } 273 | port = (uint16_t)atol(argv[i + 1]); 274 | if (!port) { 275 | printf("Invalid parameter for -uart3sock. Use -h for help.\r\n"); 276 | } 277 | if (tcpconsole_init(2, port)) { 278 | printf("Error initializing listening socket for -uart3sock.\r\n"); 279 | return -1; 280 | } 281 | uart3_redirect = UART3_REDIRECT_TCP; 282 | i++; 283 | } 284 | else if (args_isMatch(argv[i], "-exitiwdg")) { 285 | exitonIWDG = 1; 286 | } 287 | else if (args_isMatch(argv[i], "-disableiwdg")) { 288 | disableIWDG = 1; 289 | } 290 | else if (args_isMatch(argv[i], "-consolemode")) { 291 | //This mode is not meant to be called by the user, but by the emulator 292 | //to spawn new console processes for UARTs and communicate via IPC. 293 | } 294 | else { 295 | printf("%s is not a valid parameter. Use -h for help.\r\n", argv[i]); 296 | return -1; 297 | } 298 | } 299 | 300 | if (choseproduct == 0) { 301 | printf("Product selection is required. Use -h for help.\r\n"); 302 | exit(-1); 303 | } 304 | 305 | product_register(); 306 | 307 | return 0; 308 | } 309 | -------------------------------------------------------------------------------- /STM8/args.h: -------------------------------------------------------------------------------- 1 | #ifndef _ARGS_H_ 2 | #define _ARGS_H_ 3 | 4 | #include 5 | 6 | extern double speedarg; 7 | extern uint8_t showclock, showdisplay, overridecpu, exitonIWDG, disableIWDG; 8 | extern char* elffile; 9 | extern char* hexfile; 10 | extern char* srecfile; 11 | extern char* ramfile; 12 | extern char* eepromfile; 13 | extern char* product_name; 14 | 15 | int args_parse(int argc, char* argv[]); 16 | void args_showHelp(); 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /STM8/config.h: -------------------------------------------------------------------------------- 1 | #ifndef _CONFIG_H_ 2 | #define _CONFIG_H_ 3 | 4 | //#define DEBUG_OUTPUT 5 | 6 | void (*product_init)(void); 7 | void (*product_update)(void); 8 | void (*product_portwrite)(uint32_t addr, uint8_t val); 9 | uint8_t (*product_portread)(uint32_t addr, uint8_t* dst); 10 | void (*product_markforupdate)(void); 11 | void (*product_loop)(void); 12 | 13 | #ifdef _WIN32 14 | #define FUNC_INLINE __forceinline 15 | #else 16 | #define FUNC_INLINE __attribute__((always_inline)) 17 | #endif 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /STM8/console.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "console.h" 6 | 7 | void console_init(char* title) { 8 | SetConsoleTitleA(title); 9 | 10 | } 11 | -------------------------------------------------------------------------------- /STM8/console.h: -------------------------------------------------------------------------------- 1 | #ifndef _CONSOLE_H_ 2 | #define _CONSOLE_H_ 3 | 4 | #include 5 | 6 | void console_init(char* title); 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /STM8/cpu.h: -------------------------------------------------------------------------------- 1 | #ifndef _CPU_H_ 2 | #define _CPU_H_ 3 | 4 | #include 5 | 6 | #define COND_V 0x80 7 | #define COND_I1 0x20 8 | #define COND_H 0x10 9 | #define COND_I0 0x08 10 | #define COND_N 0x04 11 | #define COND_Z 0x02 12 | #define COND_C 0x01 13 | 14 | #define SET_COND(c) cc |= c 15 | #define CLEAR_COND(c) cc &= ~c 16 | #define GET_COND(c) ((cc & c) ? 1 : 0) 17 | 18 | #define CPU_IRQ_TLI 0 19 | #define CPU_IRQ_AWU 1 20 | #define CPU_IRQ_CLK 2 21 | #define CPU_IRQ_EXTI0 3 22 | #define CPU_IRQ_EXTI1 4 23 | #define CPU_IRQ_EXTI2 5 24 | #define CPU_IRQ_EXTI3 6 25 | #define CPU_IRQ_EXTI4 7 26 | #define CPU_IRQ_BECAN_RX 8 27 | #define CPU_IRQ_BECAN_TX 9 28 | #define CPU_IRQ_SPI 10 29 | #define CPU_IRQ_TIM1_UPDATE 11 30 | #define CPU_IRQ_TIM1_COMPARE 12 31 | #define CPU_IRQ_TIM2_UPDATE 13 32 | #define CPU_IRQ_TIM2_COMPARE 14 33 | #define CPU_IRQ_TIM3_UPDATE 15 34 | #define CPU_IRQ_TIM3_COMPARE 16 35 | #define CPU_IRQ_UART1_TX 17 36 | #define CPU_IRQ_UART1_RX 18 37 | #define CPU_IRQ_I2C 19 38 | #define CPU_IRQ_UART3_TX 20 39 | #define CPU_IRQ_UART3_RX 21 40 | #define CPU_IRQ_ADC 22 41 | #define CPU_IRQ_TIM4_UPDATE 23 42 | #define CPU_IRQ_FLASH 24 43 | 44 | #define CPUR_A 0 45 | #define CPUR_PCE 1 46 | #define CPUR_PCH 2 47 | #define CPUR_PCL 3 48 | #define CPUR_XH 4 49 | #define CPUR_XL 5 50 | #define CPUR_YH 6 51 | #define CPUR_YL 7 52 | #define CPUR_SPH 8 53 | #define CPUR_SPL 9 54 | #define CPUR_CCR 10 55 | 56 | #define ITC_SPR1 11 57 | #define ITC_SPR2 12 58 | #define ITC_SPR3 13 59 | #define ITC_SPR4 14 60 | #define ITC_SPR5 15 61 | #define ITC_SPR6 16 62 | #define ITC_SPR7 17 63 | #define ITC_SPR8 18 64 | 65 | #define UART1_SR 19 66 | #define UART1_DR 20 67 | #define UART1_BRR1 21 68 | #define UART1_BRR2 22 69 | #define UART1_CR1 23 70 | #define UART1_CR2 24 71 | #define UART1_CR3 25 72 | #define UART1_CR4 26 73 | #define UART1_CR5 27 74 | #define UART1_GTR 28 75 | #define UART1_PSCR 29 76 | 77 | #define EXTI_CR1 30 78 | #define EXTI_CR2 31 79 | 80 | #define PA_ODR 32 81 | #define PA_IDR 33 82 | #define PA_DDR 34 83 | #define PA_CR1 35 84 | #define PA_CR2 36 85 | 86 | #define PB_ODR 37 87 | #define PB_IDR 38 88 | #define PB_DDR 39 89 | #define PB_CR1 40 90 | #define PB_CR2 41 91 | 92 | #define PC_ODR 42 93 | #define PC_IDR 43 94 | #define PC_DDR 44 95 | #define PC_CR1 45 96 | #define PC_CR2 46 97 | 98 | #define PD_ODR 47 99 | #define PD_IDR 48 100 | #define PD_DDR 49 101 | #define PD_CR1 50 102 | #define PD_CR2 51 103 | 104 | #define PE_ODR 52 105 | #define PE_IDR 53 106 | #define PE_DDR 54 107 | #define PE_CR1 55 108 | #define PE_CR2 56 109 | 110 | #define PF_ODR 57 111 | #define PF_IDR 58 112 | #define PF_DDR 59 113 | #define PF_CR1 60 114 | #define PF_CR2 61 115 | 116 | #define PG_ODR 62 117 | #define PG_IDR 63 118 | #define PG_DDR 64 119 | #define PG_CR1 65 120 | #define PG_CR2 66 121 | 122 | #define PH_ODR 67 123 | #define PH_IDR 68 124 | #define PH_DDR 69 125 | #define PH_CR1 70 126 | #define PH_CR2 71 127 | 128 | #define PI_ODR 72 129 | #define PI_IDR 73 130 | #define PI_DDR 74 131 | #define PI_CR1 75 132 | #define PI_CR2 76 133 | 134 | #define TIM2_CR1 77 135 | #define TIM2_IER 78 136 | #define TIM2_SR1 79 137 | #define TIM2_SR2 80 138 | #define TIM2_EGR 81 139 | #define TIM2_CCMR1 82 140 | #define TIM2_CCMR2 83 141 | #define TIM2_CCMR3 84 142 | #define TIM2_CCER1 85 143 | #define TIM2_CCER2 86 144 | #define TIM2_CNTRH 87 145 | #define TIM2_CNTRL 88 146 | #define TIM2_PSCR 89 147 | #define TIM2_ARRH 90 148 | #define TIM2_ARRL 91 149 | #define TIM2_CCR1H 92 150 | #define TIM2_CCR1L 93 151 | #define TIM2_CCR2H 94 152 | #define TIM2_CCR2L 95 153 | #define TIM2_CCR3H 96 154 | #define TIM2_CCR3L 97 155 | 156 | #define ADC_CSR 98 157 | #define ADC_CR1 99 158 | #define ADC_CR2 100 159 | #define ADC_CR3 101 160 | #define ADC_DRH 102 161 | #define ADC_DRL 103 162 | #define ADC_TDRH 104 163 | #define ADC_TDRL 105 164 | 165 | #define UART3_SR 106 166 | #define UART3_DR 107 167 | #define UART3_BRR1 108 168 | #define UART3_BRR2 109 169 | #define UART3_CR1 110 170 | #define UART3_CR2 111 171 | #define UART3_CR3 112 172 | #define UART3_CR4 113 173 | #define UART3_CR6 114 174 | 175 | #define CLK_ICKR 115 //Internal clock control register 176 | #define CLK_ECKR 116 //External clock control register 177 | #define CLK_CMSR 117 //Clock master status register 178 | #define CLK_SWR 118 //Clock master switch register 179 | #define CLK_SWCR 119 //Clock switch control register 180 | #define CLK_CKDIVR 120 //Clock divider register 181 | #define CLK_PCKENR1 121 //Peripheral clock gating register 1 182 | #define CLK_CSSR 122 //Clock security system register 183 | #define CLK_CCOR 123 //Configurable clock control register 184 | #define CLK_PCKENR2 124 //Peripheral clock gating register 2 185 | #define CLK_CANCCR 125 //CAN clock control register 186 | #define CLK_HSITRIMR 126 //HSI clock calibration trimming register 187 | #define CLK_SWIMCCR 127 //SWIM clock control register 188 | 189 | #define IWDG_KR 128 //IWDG key register 190 | #define IWDG_PR 129 //IWDG prescaler register 191 | #define IWDG_RLR 130 //IWDG reload register 192 | 193 | #define FLASH_CR1 131 194 | #define FLASH_CR2 132 195 | #define FLASH_NCR2 133 196 | #define FLASH_FPR 134 197 | #define FLASH_NFPR 135 198 | #define FLASH_IAPSR 136 199 | #define FLASH_PUKR 137 200 | #define FLASH_DUKR 138 201 | 202 | #define REGISTERS_COUNT 139 203 | 204 | 205 | #define BIT_D0 (dest & 0x01) 206 | #define BIT_D1 ((dest & 0x02) >> 1) 207 | #define BIT_D2 ((dest & 0x04) >> 2) 208 | #define BIT_D3 ((dest & 0x08) >> 3) 209 | #define BIT_D4 ((dest & 0x10) >> 4) 210 | #define BIT_D5 ((dest & 0x20) >> 5) 211 | #define BIT_D6 ((dest & 0x40) >> 6) 212 | #define BIT_D7 ((dest & 0x80) >> 7) 213 | #define BIT_D8 ((dest & 0x100) >> 8) 214 | #define BIT_D9 ((dest & 0x200) >> 9) 215 | #define BIT_D10 ((dest & 0x400) >> 10) 216 | #define BIT_D11 ((dest & 0x800) >> 11) 217 | #define BIT_D12 ((dest & 0x1000) >> 12) 218 | #define BIT_D13 ((dest & 0x2000) >> 13) 219 | #define BIT_D14 ((dest & 0x4000) >> 14) 220 | #define BIT_D15 ((dest & 0x8000) >> 15) 221 | 222 | #define BIT_S0 (src & 0x01) 223 | #define BIT_S1 ((src & 0x02) >> 1) 224 | #define BIT_S2 ((src & 0x04) >> 2) 225 | #define BIT_S3 ((src & 0x08) >> 3) 226 | #define BIT_S4 ((src & 0x10) >> 4) 227 | #define BIT_S5 ((src & 0x20) >> 5) 228 | #define BIT_S6 ((src & 0x40) >> 6) 229 | #define BIT_S7 ((src & 0x80) >> 7) 230 | #define BIT_S8 ((src & 0x100) >> 8) 231 | #define BIT_S9 ((src & 0x200) >> 9) 232 | #define BIT_S10 ((src & 0x400) >> 10) 233 | #define BIT_S11 ((src & 0x800) >> 11) 234 | #define BIT_S12 ((src & 0x1000) >> 12) 235 | #define BIT_S13 ((src & 0x2000) >> 13) 236 | #define BIT_S14 ((src & 0x4000) >> 14) 237 | #define BIT_S15 ((src & 0x8000) >> 15) 238 | 239 | #define BIT_R0 (result & 0x01) 240 | #define BIT_R1 ((result & 0x02) >> 1) 241 | #define BIT_R2 ((result & 0x04) >> 2) 242 | #define BIT_R3 ((result & 0x08) >> 3) 243 | #define BIT_R4 ((result & 0x10) >> 4) 244 | #define BIT_R5 ((result & 0x20) >> 5) 245 | #define BIT_R6 ((result & 0x40) >> 6) 246 | #define BIT_R7 ((result & 0x80) >> 7) 247 | 248 | #define BIT_RW0 (result16 & 0x01) 249 | #define BIT_RW1 ((result16 & 0x02) >> 1) 250 | #define BIT_RW2 ((result16 & 0x04) >> 2) 251 | #define BIT_RW3 ((result16 & 0x08) >> 3) 252 | #define BIT_RW4 ((result16 & 0x10) >> 4) 253 | #define BIT_RW5 ((result16 & 0x20) >> 5) 254 | #define BIT_RW6 ((result16 & 0x40) >> 6) 255 | #define BIT_RW7 ((result16 & 0x80) >> 7) 256 | #define BIT_RW8 ((result16 & 0x100) >> 8) 257 | #define BIT_RW9 ((result16 & 0x200) >> 9) 258 | #define BIT_RW10 ((result16 & 0x400) >> 10) 259 | #define BIT_RW11 ((result16 & 0x800) >> 11) 260 | #define BIT_RW12 ((result16 & 0x1000) >> 12) 261 | #define BIT_RW13 ((result16 & 0x2000) >> 13) 262 | #define BIT_RW14 ((result16 & 0x4000) >> 14) 263 | #define BIT_RW15 ((result16 & 0x8000) >> 15) 264 | 265 | extern char* cpu_name; 266 | extern uint32_t pc; 267 | extern uint16_t sp, x, y; 268 | extern uint8_t a, cc; 269 | extern uint8_t running; 270 | 271 | void cpu_reset(); 272 | int32_t cpu_run(int32_t clocks); 273 | void cpu_irq(uint8_t irq); 274 | 275 | #endif 276 | -------------------------------------------------------------------------------- /STM8/devices/stm8s003f3.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "stm8s003f3.h" 7 | #include "../peripherals/clk.h" 8 | #include "../memory.h" 9 | #include "../cpu.h" 10 | #include "../ports.h" 11 | 12 | void stm8s003f3_init() { 13 | uint32_t i; 14 | 15 | cpu_name = "STM8S003F3"; 16 | 17 | flash_start = STM8S003F3_FLASH_START; 18 | flash_size = STM8S003F3_FLASH_SIZE; 19 | 20 | ram_start = STM8S003F3_RAM_START; 21 | ram_size = STM8S003F3_RAM_SIZE; 22 | 23 | stack_top = ram_start + ram_size - 1; 24 | stack_bottom = stack_top - STM8S003F3_STACK_SIZE; 25 | 26 | eeprom_start = STM8S003F3_EEPROM_START; 27 | eeprom_size = STM8S003F3_EEPROM_SIZE; 28 | 29 | io_start = STM8S003F3_IO_START; 30 | io_size = STM8S003F3_IO_SIZE; 31 | 32 | cpureg_start = STM8S003F3_CPU_REG_START; 33 | cpureg_size = STM8S003F3_CPU_REG_SIZE; 34 | 35 | flash = (uint8_t*)malloc(STM8S003F3_FLASH_SIZE); 36 | RAM = (uint8_t*)malloc(STM8S003F3_RAM_SIZE); 37 | EEPROM = (uint8_t*)malloc(STM8S003F3_EEPROM_SIZE); 38 | IO = (uint8_t*)malloc(STM8S003F3_IO_SIZE); 39 | CPUREG = (uint8_t*)malloc(STM8S003F3_CPU_REG_SIZE); 40 | if ((flash == NULL) || (RAM == NULL) || (EEPROM == NULL) || (IO == NULL) || (CPUREG == NULL)) { 41 | printf("Memory allocation error!\n"); 42 | exit(-1); 43 | } 44 | 45 | memset(flash, 0, STM8S003F3_FLASH_SIZE); 46 | memset(RAM, 0, STM8S003F3_RAM_SIZE); 47 | memset(EEPROM, 0, STM8S003F3_EEPROM_SIZE); 48 | memset(IO, 0, STM8S003F3_IO_SIZE); 49 | memset(CPUREG, 0, STM8S003F3_CPU_REG_SIZE); 50 | 51 | for (i = 0; i < REGISTERS_COUNT; i++) { 52 | regaddr[i] = 0xFFFFFFFF; 53 | } 54 | 55 | regaddr[CPUR_A] = STM8S003F3_CPUR_A; 56 | regaddr[CPUR_PCE] = STM8S003F3_CPUR_PCE; 57 | regaddr[CPUR_PCH] = STM8S003F3_CPUR_PCH; 58 | regaddr[CPUR_PCL] = STM8S003F3_CPUR_PCL; 59 | regaddr[CPUR_XH] = STM8S003F3_CPUR_XH; 60 | regaddr[CPUR_XL] = STM8S003F3_CPUR_XL; 61 | regaddr[CPUR_YH] = STM8S003F3_CPUR_YH; 62 | regaddr[CPUR_YL] = STM8S003F3_CPUR_YL; 63 | regaddr[CPUR_SPH] = STM8S003F3_CPUR_SPH; 64 | regaddr[CPUR_SPL] = STM8S003F3_CPUR_SPL; 65 | regaddr[CPUR_CCR] = STM8S003F3_CPUR_CCR; 66 | regaddr[ITC_SPR1] = STM8S003F3_ITC_SPR1; 67 | regaddr[ITC_SPR2] = STM8S003F3_ITC_SPR2; 68 | regaddr[ITC_SPR3] = STM8S003F3_ITC_SPR3; 69 | regaddr[ITC_SPR4] = STM8S003F3_ITC_SPR4; 70 | regaddr[ITC_SPR5] = STM8S003F3_ITC_SPR5; 71 | regaddr[ITC_SPR6] = STM8S003F3_ITC_SPR6; 72 | regaddr[ITC_SPR7] = STM8S003F3_ITC_SPR7; 73 | regaddr[ITC_SPR8] = STM8S003F3_ITC_SPR8; 74 | regaddr[UART1_SR] = STM8S003F3_UART1_SR; 75 | regaddr[UART1_DR] = STM8S003F3_UART1_DR; 76 | regaddr[UART1_BRR1] = STM8S003F3_UART1_BRR1; 77 | regaddr[UART1_BRR2] = STM8S003F3_UART1_BRR2; 78 | regaddr[UART1_CR1] = STM8S003F3_UART1_CR1; 79 | regaddr[UART1_CR2] = STM8S003F3_UART1_CR2; 80 | regaddr[UART1_CR3] = STM8S003F3_UART1_CR3; 81 | regaddr[UART1_CR4] = STM8S003F3_UART1_CR4; 82 | regaddr[UART1_CR5] = STM8S003F3_UART1_CR5; 83 | regaddr[UART1_GTR] = STM8S003F3_UART1_GTR; 84 | regaddr[UART1_PSCR] = STM8S003F3_UART1_PSCR; 85 | regaddr[EXTI_CR1] = STM8S003F3_EXTI_CR1; 86 | regaddr[EXTI_CR2] = STM8S003F3_EXTI_CR2; 87 | regaddr[PA_ODR] = STM8S003F3_PA_ODR; 88 | regaddr[PA_IDR] = STM8S003F3_PA_IDR; 89 | regaddr[PA_DDR] = STM8S003F3_PA_DDR; 90 | regaddr[PA_CR1] = STM8S003F3_PA_CR1; 91 | regaddr[PA_CR2] = STM8S003F3_PA_CR2; 92 | regaddr[PB_ODR] = STM8S003F3_PB_ODR; 93 | regaddr[PB_IDR] = STM8S003F3_PB_IDR; 94 | regaddr[PB_DDR] = STM8S003F3_PB_DDR; 95 | regaddr[PB_CR1] = STM8S003F3_PB_CR1; 96 | regaddr[PB_CR2] = STM8S003F3_PB_CR2; 97 | regaddr[PC_ODR] = STM8S003F3_PC_ODR; 98 | regaddr[PC_IDR] = STM8S003F3_PC_IDR; 99 | regaddr[PC_DDR] = STM8S003F3_PC_DDR; 100 | regaddr[PC_CR1] = STM8S003F3_PC_CR1; 101 | regaddr[PC_CR2] = STM8S003F3_PC_CR2; 102 | regaddr[PD_ODR] = STM8S003F3_PD_ODR; 103 | regaddr[PD_IDR] = STM8S003F3_PD_IDR; 104 | regaddr[PD_DDR] = STM8S003F3_PD_DDR; 105 | regaddr[PD_CR1] = STM8S003F3_PD_CR1; 106 | regaddr[PD_CR2] = STM8S003F3_PD_CR2; 107 | regaddr[PE_ODR] = STM8S003F3_PE_ODR; 108 | regaddr[PE_IDR] = STM8S003F3_PE_IDR; 109 | regaddr[PE_DDR] = STM8S003F3_PE_DDR; 110 | regaddr[PE_CR1] = STM8S003F3_PE_CR1; 111 | regaddr[PE_CR2] = STM8S003F3_PE_CR2; 112 | regaddr[PF_ODR] = STM8S003F3_PF_ODR; 113 | regaddr[PF_IDR] = STM8S003F3_PF_IDR; 114 | regaddr[PF_DDR] = STM8S003F3_PF_DDR; 115 | regaddr[PF_CR1] = STM8S003F3_PF_CR1; 116 | regaddr[PF_CR2] = STM8S003F3_PF_CR2; 117 | regaddr[TIM2_CR1] = STM8S003F3_TIM2_CR1; 118 | regaddr[TIM2_IER] = STM8S003F3_TIM2_IER; 119 | regaddr[TIM2_SR1] = STM8S003F3_TIM2_SR1; 120 | regaddr[TIM2_SR2] = STM8S003F3_TIM2_SR2; 121 | regaddr[TIM2_EGR] = STM8S003F3_TIM2_EGR; 122 | regaddr[TIM2_CCMR1] = STM8S003F3_TIM2_CCMR1; 123 | regaddr[TIM2_CCMR2] = STM8S003F3_TIM2_CCMR2; 124 | regaddr[TIM2_CCMR3] = STM8S003F3_TIM2_CCMR3; 125 | regaddr[TIM2_CCER1] = STM8S003F3_TIM2_CCER1; 126 | regaddr[TIM2_CCER2] = STM8S003F3_TIM2_CCER2; 127 | regaddr[TIM2_CNTRH] = STM8S003F3_TIM2_CNTRH; 128 | regaddr[TIM2_CNTRL] = STM8S003F3_TIM2_CNTRL; 129 | regaddr[TIM2_PSCR] = STM8S003F3_TIM2_PSCR; 130 | regaddr[TIM2_ARRH] = STM8S003F3_TIM2_ARRH; 131 | regaddr[TIM2_ARRL] = STM8S003F3_TIM2_ARRL; 132 | regaddr[TIM2_CCR1H] = STM8S003F3_TIM2_CCR1H; 133 | regaddr[TIM2_CCR1L] = STM8S003F3_TIM2_CCR1L; 134 | regaddr[TIM2_CCR2H] = STM8S003F3_TIM2_CCR2H; 135 | regaddr[TIM2_CCR2L] = STM8S003F3_TIM2_CCR2L; 136 | regaddr[TIM2_CCR3H] = STM8S003F3_TIM2_CCR3H; 137 | regaddr[TIM2_CCR3L] = STM8S003F3_TIM2_CCR3L; 138 | regaddr[ADC_CSR] = STM8S003F3_ADC_CSR; 139 | regaddr[ADC_CR1] = STM8S003F3_ADC_CR1; 140 | regaddr[ADC_CR2] = STM8S003F3_ADC_CR2; 141 | regaddr[ADC_CR3] = STM8S003F3_ADC_CR3; 142 | regaddr[ADC_DRH] = STM8S003F3_ADC_DRH; 143 | regaddr[ADC_DRL] = STM8S003F3_ADC_DRL; 144 | regaddr[ADC_TDRH] = STM8S003F3_ADC_TDRH; 145 | regaddr[ADC_TDRL] = STM8S003F3_ADC_TDRL; 146 | regaddr[CLK_ICKR] = STM8S003F3_CLK_ICKR; 147 | regaddr[CLK_ECKR] = STM8S003F3_CLK_ECKR; 148 | regaddr[CLK_CMSR] = STM8S003F3_CLK_CMSR; 149 | regaddr[CLK_SWR] = STM8S003F3_CLK_SWR; 150 | regaddr[CLK_SWCR] = STM8S003F3_CLK_SWCR; 151 | regaddr[CLK_CKDIVR] = STM8S003F3_CLK_CKDIVR; 152 | regaddr[CLK_PCKENR1] = STM8S003F3_CLK_PCKENR1; 153 | regaddr[CLK_CSSR] = STM8S003F3_CLK_CSSR; 154 | regaddr[CLK_CCOR] = STM8S003F3_CLK_CCOR; 155 | regaddr[CLK_PCKENR2] = STM8S003F3_CLK_PCKENR2; 156 | regaddr[CLK_CANCCR] = STM8S003F3_CLK_CANCCR; 157 | regaddr[CLK_HSITRIMR] = STM8S003F3_CLK_HSITRIMR; 158 | regaddr[CLK_SWIMCCR] = STM8S003F3_CLK_SWIMCCR; 159 | regaddr[IWDG_KR] = STM8S003F3_IWDG_KR; 160 | regaddr[IWDG_PR] = STM8S003F3_IWDG_PR; 161 | regaddr[IWDG_RLR] = STM8S003F3_IWDG_RLR; 162 | regaddr[FLASH_CR1] = STM8S003F3_FLASH_CR1; 163 | regaddr[FLASH_CR2] = STM8S003F3_FLASH_CR2; 164 | regaddr[FLASH_NCR2] = STM8S003F3_FLASH_NCR2; 165 | regaddr[FLASH_FPR] = STM8S003F3_FLASH_FPR; 166 | regaddr[FLASH_NFPR] = STM8S003F3_FLASH_NFPR; 167 | regaddr[FLASH_IAPSR] = STM8S003F3_FLASH_IAPSR; 168 | regaddr[FLASH_PUKR] = STM8S003F3_FLASH_PUKR; 169 | regaddr[FLASH_DUKR] = STM8S003F3_FLASH_DUKR; 170 | 171 | ports_start = STM8S003F3_PORTS_START; 172 | ports_end = STM8S003F3_PORTS_END; 173 | uart1_start = STM8S003F3_UART1_START; 174 | uart1_end = STM8S003F3_UART1_END; 175 | tim2_start = STM8S003F3_TIM2_START; 176 | tim2_end = STM8S003F3_TIM2_END; 177 | adc_start = STM8S003F3_ADC_START; 178 | adc_end = STM8S003F3_ADC_END; 179 | clk_start = STM8S003F3_CLK_START; 180 | clk_end = STM8S003F3_CLK_END; 181 | iwdg_start = STM8S003F3_IWDG_START; 182 | iwdg_end = STM8S003F3_IWDG_END; 183 | flash_reg_start = STM8S003F3_FLASH_REG_START; 184 | flash_reg_end = STM8S003F3_FLASH_REG_END; 185 | 186 | use_PA = 1; 187 | use_PB = 1; 188 | use_PC = 1; 189 | use_PD = 1; 190 | use_PE = 1; 191 | use_PF = 1; 192 | 193 | clk_gateADC = 1 << 3; 194 | clk_gateTIM1 = 1 << 7; 195 | clk_gateTIM2 = 1 << 5; 196 | clk_gateTIM3 = 0; 197 | clk_gateTIM4 = 1 << 4; 198 | clk_gateUART1 = 1 << 2; 199 | clk_gateUART2 = 0; 200 | clk_gateUART3 = 0; 201 | clk_gateUART4 = 0; 202 | } 203 | -------------------------------------------------------------------------------- /STM8/devices/stm8s003f3.h: -------------------------------------------------------------------------------- 1 | #ifndef _STM8S003F3_H_ 2 | #define _STM8S003F3_H_ 3 | 4 | #include 5 | 6 | void stm8s003f3_init(void); 7 | 8 | #define STM8S003F3_FLASH_START 0x8000 9 | #define STM8S003F3_FLASH_SIZE 0x2000 10 | 11 | #define STM8S003F3_RAM_START 0x0000 12 | #define STM8S003F3_RAM_SIZE 0x400 13 | 14 | #define STM8S003F3_STACK_SIZE 0x200 15 | 16 | #define STM8S003F3_EEPROM_START 0x4000 17 | #define STM8S003F3_EEPROM_SIZE 0x80 18 | 19 | #define STM8S003F3_IO_START 0x5000 20 | #define STM8S003F3_IO_SIZE 0x800 21 | 22 | #define STM8S003F3_CPU_REG_START 0x7F00 23 | #define STM8S003F3_CPU_REG_SIZE 0x100 24 | 25 | #define STM8S003F3_CPUR_A 0x7F00 26 | #define STM8S003F3_CPUR_PCE 0x7F01 27 | #define STM8S003F3_CPUR_PCH 0x7F02 28 | #define STM8S003F3_CPUR_PCL 0x7F03 29 | #define STM8S003F3_CPUR_XH 0x7F04 30 | #define STM8S003F3_CPUR_XL 0x7F05 31 | #define STM8S003F3_CPUR_YH 0x7F06 32 | #define STM8S003F3_CPUR_YL 0x7F07 33 | #define STM8S003F3_CPUR_SPH 0x7F08 34 | #define STM8S003F3_CPUR_SPL 0x7F09 35 | #define STM8S003F3_CPUR_CCR 0x7F0A 36 | 37 | #define STM8S003F3_ITC_SPR1 0x7F70 38 | #define STM8S003F3_ITC_SPR2 0x7F71 39 | #define STM8S003F3_ITC_SPR3 0x7F72 40 | #define STM8S003F3_ITC_SPR4 0x7F73 41 | #define STM8S003F3_ITC_SPR5 0x7F74 42 | #define STM8S003F3_ITC_SPR6 0x7F75 43 | #define STM8S003F3_ITC_SPR7 0x7F76 44 | #define STM8S003F3_ITC_SPR8 0x7F77 45 | 46 | #define STM8S003F3_UART1_SR 0x5230 47 | #define STM8S003F3_UART1_DR 0x5231 48 | #define STM8S003F3_UART1_BRR1 0x5232 49 | #define STM8S003F3_UART1_BRR2 0x5233 50 | #define STM8S003F3_UART1_CR1 0x5234 51 | #define STM8S003F3_UART1_CR2 0x5235 52 | #define STM8S003F3_UART1_CR3 0x5236 53 | #define STM8S003F3_UART1_CR4 0x5237 54 | #define STM8S003F3_UART1_CR5 0x5238 55 | #define STM8S003F3_UART1_GTR 0x5239 56 | #define STM8S003F3_UART1_PSCR 0x523A 57 | 58 | #define STM8S003F3_UART1_START STM8S003F3_UART1_SR 59 | #define STM8S003F3_UART1_END STM8S003F3_UART1_PSCR 60 | 61 | #define STM8S003F3_EXTI_CR1 0x50A0 62 | #define STM8S003F3_EXTI_CR2 0x50A1 63 | 64 | #define STM8S003F3_PA_ODR 0x5000 65 | #define STM8S003F3_PA_IDR 0x5001 66 | #define STM8S003F3_PA_DDR 0x5002 67 | #define STM8S003F3_PA_CR1 0x5003 68 | #define STM8S003F3_PA_CR2 0x5004 69 | 70 | #define STM8S003F3_PB_ODR 0x5005 71 | #define STM8S003F3_PB_IDR 0x5006 72 | #define STM8S003F3_PB_DDR 0x5007 73 | #define STM8S003F3_PB_CR1 0x5008 74 | #define STM8S003F3_PB_CR2 0x5009 75 | 76 | #define STM8S003F3_PC_ODR 0x500A 77 | #define STM8S003F3_PC_IDR 0x500B 78 | #define STM8S003F3_PC_DDR 0x500C 79 | #define STM8S003F3_PC_CR1 0x500D 80 | #define STM8S003F3_PC_CR2 0x500E 81 | 82 | #define STM8S003F3_PD_ODR 0x500F 83 | #define STM8S003F3_PD_IDR 0x5010 84 | #define STM8S003F3_PD_DDR 0x5011 85 | #define STM8S003F3_PD_CR1 0x5012 86 | #define STM8S003F3_PD_CR2 0x5013 87 | 88 | #define STM8S003F3_PE_ODR 0x5014 89 | #define STM8S003F3_PE_IDR 0x5015 90 | #define STM8S003F3_PE_DDR 0x5016 91 | #define STM8S003F3_PE_CR1 0x5017 92 | #define STM8S003F3_PE_CR2 0x5018 93 | 94 | #define STM8S003F3_PF_ODR 0x5019 95 | #define STM8S003F3_PF_IDR 0x501A 96 | #define STM8S003F3_PF_DDR 0x501B 97 | #define STM8S003F3_PF_CR1 0x501C 98 | #define STM8S003F3_PF_CR2 0x501D 99 | 100 | #define STM8S003F3_PORTS_START STM8S003F3_PA_ODR 101 | #define STM8S003F3_PORTS_END STM8S003F3_PF_CR2 102 | 103 | #define STM8S003F3_TIM2_CR1 0x5300 //TIM2 control register 1 0x00 104 | #define STM8S003F3_TIM2_IER 0x5303 //TIM2 interrupt enable register 0x00 105 | #define STM8S003F3_TIM2_SR1 0x5304 //TIM2 status register 1 0x00 106 | #define STM8S003F3_TIM2_SR2 0x5305 //TIM2 status register 2 0x00 107 | #define STM8S003F3_TIM2_EGR 0x5306 //TIM2 event generation register 0x00 108 | #define STM8S003F3_TIM2_CCMR1 0x5307 //TIM2 capture/compare mode register 1 0x00 109 | #define STM8S003F3_TIM2_CCMR2 0x5308 //TIM2 capture/compare mode register 2 0x00 110 | #define STM8S003F3_TIM2_CCMR3 0x5309 //TIM2 capture/compare mode register 3 0x00 111 | #define STM8S003F3_TIM2_CCER1 0x530A //TIM2 capture/compare enable register 1 0x00 112 | #define STM8S003F3_TIM2_CCER2 0x530B //TIM2 capture/compare enable register 2 0x00 113 | #define STM8S003F3_TIM2_CNTRH 0x530C //TIM2 counter high 0x00 114 | #define STM8S003F3_TIM2_CNTRL 0x530D //TIM2 counter low 0x00 115 | #define STM8S003F3_TIM2_PSCR 0x530E //TIM2 prescaler register 0x00 116 | #define STM8S003F3_TIM2_ARRH 0x530F //TIM2 auto-reload register high 0xFF 117 | #define STM8S003F3_TIM2_ARRL 0x5310 //TIM2 auto-reload register low 0xFF 118 | #define STM8S003F3_TIM2_CCR1H 0x5311 //TIM2 capture/compare register 1 high 0x00 119 | #define STM8S003F3_TIM2_CCR1L 0x5312 //TIM2 capture/compare register 1 low 0x00 120 | #define STM8S003F3_TIM2_CCR2H 0x5313 //TIM2 capture/compare reg. 2 high 0x00 121 | #define STM8S003F3_TIM2_CCR2L 0x5314 //TIM2 capture/compare register 2 low 0x00 122 | #define STM8S003F3_TIM2_CCR3H 0x5315 //TIM2 capture/compare register 3 high 0x00 123 | #define STM8S003F3_TIM2_CCR3L 0x5316 //TIM2 capture/compare register 3 low 0x00 124 | 125 | #define STM8S003F3_TIM2_START STM8S003F3_TIM2_CR1 126 | #define STM8S003F3_TIM2_END STM8S003F3_TIM2_CCR3L 127 | 128 | #define STM8S003F3_ADC_CSR 0x5400 //ADC control/status register 129 | #define STM8S003F3_ADC_CR1 0x5401 //ADC configuration register 1 130 | #define STM8S003F3_ADC_CR2 0x5402 //ADC configuration register 2 131 | #define STM8S003F3_ADC_CR3 0x5403 //ADC configuration register 3 132 | #define STM8S003F3_ADC_DRH 0x5404 //ADC data register high 133 | #define STM8S003F3_ADC_DRL 0x5405 //ADC data register low 134 | #define STM8S003F3_ADC_TDRH 0x5406 //ADC Schmitt trigger disable register high 135 | #define STM8S003F3_ADC_TDRL 0x5407 //ADC Schmitt trigger disable register low 136 | #define STM8S003F3_ADC_HTRH 0x5408 //ADC high threshold register high 137 | #define STM8S003F3_ADC_HTRL 0x5409 //ADC high threshold register low 138 | #define STM8S003F3_ADC_LTRH 0x540A //ADC low threshold register high 139 | #define STM8S003F3_ADC_LTRL 0x540B //ADC low threshold register low 140 | #define STM8S003F3_ADC_AWSRH 0x540C //ADC analog watchdog status register high 141 | #define STM8S003F3_ADC_AWSRL 0x540D //ADC analog watchdog status register low 142 | #define STM8S003F3_ADC_AWCRH 0x540E //ADC analog watchdog control register high 143 | #define STM8S003F3_ADC_AWCRL 0x540F //ADC analog watchdog control register low 144 | 145 | #define STM8S003F3_ADC_START STM8S003F3_ADC_CSR 146 | #define STM8S003F3_ADC_END STM8S003F3_ADC_AWCRL 147 | 148 | #define STM8S003F3_CLK_ICKR 0x50C0 //Internal clock control register 149 | #define STM8S003F3_CLK_ECKR 0x50C1 //External clock control register 150 | #define STM8S003F3_CLK_CMSR 0x50C3 //Clock master status register 151 | #define STM8S003F3_CLK_SWR 0x50C4 //Clock master switch register 152 | #define STM8S003F3_CLK_SWCR 0x50C5 //Clock switch control register 153 | #define STM8S003F3_CLK_CKDIVR 0x50C6 //Clock divider register 154 | #define STM8S003F3_CLK_PCKENR1 0x50C7 //Peripheral clock gating register 1 155 | #define STM8S003F3_CLK_CSSR 0x50C8 //Clock security system register 156 | #define STM8S003F3_CLK_CCOR 0x50C9 //Configurable clock control register 157 | #define STM8S003F3_CLK_PCKENR2 0x50CA //Peripheral clock gating register 2 158 | #define STM8S003F3_CLK_CANCCR 0x50CB //CAN clock control register 159 | #define STM8S003F3_CLK_HSITRIMR 0x50CC //HSI clock calibration trimming register 160 | #define STM8S003F3_CLK_SWIMCCR 0x50CD //SWIM clock control register 161 | 162 | #define STM8S003F3_CLK_START STM8S003F3_CLK_ICKR 163 | #define STM8S003F3_CLK_END STM8S003F3_CLK_SWIMCCR 164 | 165 | #define STM8S003F3_IWDG_KR 0x50E0 //IWDG key register 166 | #define STM8S003F3_IWDG_PR 0x50E1 //IWDG prescaler register 167 | #define STM8S003F3_IWDG_RLR 0x50E2 //IWDG reload register 168 | 169 | #define STM8S003F3_IWDG_START STM8S003F3_IWDG_KR 170 | #define STM8S003F3_IWDG_END STM8S003F3_IWDG_RLR 171 | 172 | #define STM8S003F3_FLASH_CR1 0x505A //Flash control register 1 173 | #define STM8S003F3_FLASH_CR2 0x505B //Flash control register 2 174 | #define STM8S003F3_FLASH_NCR2 0x505C //Flash complimentary control register 2 175 | #define STM8S003F3_FLASH_FPR 0x505D //Flash protection register 176 | #define STM8S003F3_FLASH_NFPR 0x505E //Flash complimentary protection register 177 | #define STM8S003F3_FLASH_IAPSR 0x505F //Flash in-application programming status register 178 | #define STM8S003F3_FLASH_PUKR 0x5062 //Flash Program memory unprotection register 179 | #define STM8S003F3_FLASH_DUKR 0x5064 //Data EEPROM unprotection register 180 | 181 | #define STM8S003F3_FLASH_REG_START STM8S003F3_FLASH_CR1 182 | #define STM8S003F3_FLASH_REG_END STM8S003F3_FLASH_DUKR 183 | 184 | #endif 185 | -------------------------------------------------------------------------------- /STM8/devices/stm8s207r8.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "stm8s207r8.h" 7 | #include "../peripherals/clk.h" 8 | #include "../memory.h" 9 | #include "../cpu.h" 10 | #include "../ports.h" 11 | 12 | void stm8s207r8_init() { 13 | uint32_t i; 14 | 15 | cpu_name = "STM8S207R8"; 16 | 17 | flash_start = STM8S207R8_FLASH_START; 18 | flash_size = STM8S207R8_FLASH_SIZE; 19 | 20 | ram_start = STM8S207R8_RAM_START; 21 | ram_size = STM8S207R8_RAM_SIZE; 22 | 23 | stack_top = ram_start + ram_size - 1; 24 | stack_bottom = stack_top - STM8S207R8_STACK_SIZE; 25 | 26 | eeprom_start = STM8S207R8_EEPROM_START; 27 | eeprom_size = STM8S207R8_EEPROM_SIZE; 28 | 29 | io_start = STM8S207R8_IO_START; 30 | io_size = STM8S207R8_IO_SIZE; 31 | 32 | cpureg_start = STM8S207R8_CPU_REG_START; 33 | cpureg_size = STM8S207R8_CPU_REG_SIZE; 34 | 35 | flash = (uint8_t*)malloc(STM8S207R8_FLASH_SIZE); 36 | RAM = (uint8_t*)malloc(STM8S207R8_RAM_SIZE); 37 | EEPROM = (uint8_t*)malloc(STM8S207R8_EEPROM_SIZE); 38 | IO = (uint8_t*)malloc(STM8S207R8_IO_SIZE); 39 | CPUREG = (uint8_t*)malloc(STM8S207R8_CPU_REG_SIZE); 40 | if ((flash == NULL) || (RAM == NULL) || (EEPROM == NULL) || (IO == NULL) || (CPUREG == NULL)) { 41 | printf("Memory allocation error!\n"); 42 | exit(-1); 43 | } 44 | 45 | memset(flash, 0, STM8S207R8_FLASH_SIZE); 46 | memset(RAM, 0, STM8S207R8_RAM_SIZE); 47 | memset(EEPROM, 0, STM8S207R8_EEPROM_SIZE); 48 | memset(IO, 0, STM8S207R8_IO_SIZE); 49 | memset(CPUREG, 0, STM8S207R8_CPU_REG_SIZE); 50 | 51 | for (i = 0; i < REGISTERS_COUNT; i++) { 52 | regaddr[i] = 0xFFFFFFFF; 53 | } 54 | 55 | regaddr[CPUR_A] = STM8S207R8_CPUR_A; 56 | regaddr[CPUR_PCE] = STM8S207R8_CPUR_PCE; 57 | regaddr[CPUR_PCH] = STM8S207R8_CPUR_PCH; 58 | regaddr[CPUR_PCL] = STM8S207R8_CPUR_PCL; 59 | regaddr[CPUR_XH] = STM8S207R8_CPUR_XH; 60 | regaddr[CPUR_XL] = STM8S207R8_CPUR_XL; 61 | regaddr[CPUR_YH] = STM8S207R8_CPUR_YH; 62 | regaddr[CPUR_YL] = STM8S207R8_CPUR_YL; 63 | regaddr[CPUR_SPH] = STM8S207R8_CPUR_SPH; 64 | regaddr[CPUR_SPL] = STM8S207R8_CPUR_SPL; 65 | regaddr[CPUR_CCR] = STM8S207R8_CPUR_CCR; 66 | regaddr[ITC_SPR1] = STM8S207R8_ITC_SPR1; 67 | regaddr[ITC_SPR2] = STM8S207R8_ITC_SPR2; 68 | regaddr[ITC_SPR3] = STM8S207R8_ITC_SPR3; 69 | regaddr[ITC_SPR4] = STM8S207R8_ITC_SPR4; 70 | regaddr[ITC_SPR5] = STM8S207R8_ITC_SPR5; 71 | regaddr[ITC_SPR6] = STM8S207R8_ITC_SPR6; 72 | regaddr[ITC_SPR7] = STM8S207R8_ITC_SPR7; 73 | regaddr[ITC_SPR8] = STM8S207R8_ITC_SPR8; 74 | regaddr[UART1_SR] = STM8S207R8_UART1_SR; 75 | regaddr[UART1_DR] = STM8S207R8_UART1_DR; 76 | regaddr[UART1_BRR1] = STM8S207R8_UART1_BRR1; 77 | regaddr[UART1_BRR2] = STM8S207R8_UART1_BRR2; 78 | regaddr[UART1_CR1] = STM8S207R8_UART1_CR1; 79 | regaddr[UART1_CR2] = STM8S207R8_UART1_CR2; 80 | regaddr[UART1_CR3] = STM8S207R8_UART1_CR3; 81 | regaddr[UART1_CR4] = STM8S207R8_UART1_CR4; 82 | regaddr[UART1_CR5] = STM8S207R8_UART1_CR5; 83 | regaddr[UART1_GTR] = STM8S207R8_UART1_GTR; 84 | regaddr[UART1_PSCR] = STM8S207R8_UART1_PSCR; 85 | regaddr[UART3_SR] = STM8S207R8_UART3_SR; 86 | regaddr[UART3_DR] = STM8S207R8_UART3_DR; 87 | regaddr[UART3_BRR1] = STM8S207R8_UART3_BRR1; 88 | regaddr[UART3_BRR2] = STM8S207R8_UART3_BRR2; 89 | regaddr[UART3_CR1] = STM8S207R8_UART3_CR1; 90 | regaddr[UART3_CR2] = STM8S207R8_UART3_CR2; 91 | regaddr[UART3_CR3] = STM8S207R8_UART3_CR3; 92 | regaddr[UART3_CR4] = STM8S207R8_UART3_CR4; 93 | regaddr[UART3_CR6] = STM8S207R8_UART3_CR6; 94 | regaddr[EXTI_CR1] = STM8S207R8_EXTI_CR1; 95 | regaddr[EXTI_CR2] = STM8S207R8_EXTI_CR2; 96 | regaddr[PA_ODR] = STM8S207R8_PA_ODR; 97 | regaddr[PA_IDR] = STM8S207R8_PA_IDR; 98 | regaddr[PA_DDR] = STM8S207R8_PA_DDR; 99 | regaddr[PA_CR1] = STM8S207R8_PA_CR1; 100 | regaddr[PA_CR2] = STM8S207R8_PA_CR2; 101 | regaddr[PB_ODR] = STM8S207R8_PB_ODR; 102 | regaddr[PB_IDR] = STM8S207R8_PB_IDR; 103 | regaddr[PB_DDR] = STM8S207R8_PB_DDR; 104 | regaddr[PB_CR1] = STM8S207R8_PB_CR1; 105 | regaddr[PB_CR2] = STM8S207R8_PB_CR2; 106 | regaddr[PC_ODR] = STM8S207R8_PC_ODR; 107 | regaddr[PC_IDR] = STM8S207R8_PC_IDR; 108 | regaddr[PC_DDR] = STM8S207R8_PC_DDR; 109 | regaddr[PC_CR1] = STM8S207R8_PC_CR1; 110 | regaddr[PC_CR2] = STM8S207R8_PC_CR2; 111 | regaddr[PD_ODR] = STM8S207R8_PD_ODR; 112 | regaddr[PD_IDR] = STM8S207R8_PD_IDR; 113 | regaddr[PD_DDR] = STM8S207R8_PD_DDR; 114 | regaddr[PD_CR1] = STM8S207R8_PD_CR1; 115 | regaddr[PD_CR2] = STM8S207R8_PD_CR2; 116 | regaddr[PE_ODR] = STM8S207R8_PE_ODR; 117 | regaddr[PE_IDR] = STM8S207R8_PE_IDR; 118 | regaddr[PE_DDR] = STM8S207R8_PE_DDR; 119 | regaddr[PE_CR1] = STM8S207R8_PE_CR1; 120 | regaddr[PE_CR2] = STM8S207R8_PE_CR2; 121 | regaddr[PF_ODR] = STM8S207R8_PF_ODR; 122 | regaddr[PF_IDR] = STM8S207R8_PF_IDR; 123 | regaddr[PF_DDR] = STM8S207R8_PF_DDR; 124 | regaddr[PF_CR1] = STM8S207R8_PF_CR1; 125 | regaddr[PF_CR2] = STM8S207R8_PF_CR2; 126 | regaddr[PG_ODR] = STM8S207R8_PG_ODR; 127 | regaddr[PG_IDR] = STM8S207R8_PG_IDR; 128 | regaddr[PG_DDR] = STM8S207R8_PG_DDR; 129 | regaddr[PG_CR1] = STM8S207R8_PG_CR1; 130 | regaddr[PG_CR2] = STM8S207R8_PG_CR2; 131 | regaddr[PH_ODR] = STM8S207R8_PH_ODR; 132 | regaddr[PH_IDR] = STM8S207R8_PH_IDR; 133 | regaddr[PH_DDR] = STM8S207R8_PH_DDR; 134 | regaddr[PH_CR1] = STM8S207R8_PH_CR1; 135 | regaddr[PH_CR2] = STM8S207R8_PH_CR2; 136 | regaddr[PI_ODR] = STM8S207R8_PI_ODR; 137 | regaddr[PI_IDR] = STM8S207R8_PI_IDR; 138 | regaddr[PI_DDR] = STM8S207R8_PI_DDR; 139 | regaddr[PI_CR1] = STM8S207R8_PI_CR1; 140 | regaddr[PI_CR2] = STM8S207R8_PI_CR2; 141 | regaddr[TIM2_CR1] = STM8S207R8_TIM2_CR1; 142 | regaddr[TIM2_IER] = STM8S207R8_TIM2_IER; 143 | regaddr[TIM2_SR1] = STM8S207R8_TIM2_SR1; 144 | regaddr[TIM2_SR2] = STM8S207R8_TIM2_SR2; 145 | regaddr[TIM2_EGR] = STM8S207R8_TIM2_EGR; 146 | regaddr[TIM2_CCMR1] = STM8S207R8_TIM2_CCMR1; 147 | regaddr[TIM2_CCMR2] = STM8S207R8_TIM2_CCMR2; 148 | regaddr[TIM2_CCMR3] = STM8S207R8_TIM2_CCMR3; 149 | regaddr[TIM2_CCER1] = STM8S207R8_TIM2_CCER1; 150 | regaddr[TIM2_CCER2] = STM8S207R8_TIM2_CCER2; 151 | regaddr[TIM2_CNTRH] = STM8S207R8_TIM2_CNTRH; 152 | regaddr[TIM2_CNTRL] = STM8S207R8_TIM2_CNTRL; 153 | regaddr[TIM2_PSCR] = STM8S207R8_TIM2_PSCR; 154 | regaddr[TIM2_ARRH] = STM8S207R8_TIM2_ARRH; 155 | regaddr[TIM2_ARRL] = STM8S207R8_TIM2_ARRL; 156 | regaddr[TIM2_CCR1H] = STM8S207R8_TIM2_CCR1H; 157 | regaddr[TIM2_CCR1L] = STM8S207R8_TIM2_CCR1L; 158 | regaddr[TIM2_CCR2H] = STM8S207R8_TIM2_CCR2H; 159 | regaddr[TIM2_CCR2L] = STM8S207R8_TIM2_CCR2L; 160 | regaddr[TIM2_CCR3H] = STM8S207R8_TIM2_CCR3H; 161 | regaddr[TIM2_CCR3L] = STM8S207R8_TIM2_CCR3L; 162 | regaddr[ADC_CSR] = STM8S207R8_ADC_CSR; 163 | regaddr[ADC_CR1] = STM8S207R8_ADC_CR1; 164 | regaddr[ADC_CR2] = STM8S207R8_ADC_CR2; 165 | regaddr[ADC_CR3] = STM8S207R8_ADC_CR3; 166 | regaddr[ADC_DRH] = STM8S207R8_ADC_DRH; 167 | regaddr[ADC_DRL] = STM8S207R8_ADC_DRL; 168 | regaddr[ADC_TDRH] = STM8S207R8_ADC_TDRH; 169 | regaddr[ADC_TDRL] = STM8S207R8_ADC_TDRL; 170 | regaddr[CLK_ICKR] = STM8S207R8_CLK_ICKR; 171 | regaddr[CLK_ECKR] = STM8S207R8_CLK_ECKR; 172 | regaddr[CLK_CMSR] = STM8S207R8_CLK_CMSR; 173 | regaddr[CLK_SWR] = STM8S207R8_CLK_SWR; 174 | regaddr[CLK_SWCR] = STM8S207R8_CLK_SWCR; 175 | regaddr[CLK_CKDIVR] = STM8S207R8_CLK_CKDIVR; 176 | regaddr[CLK_PCKENR1] = STM8S207R8_CLK_PCKENR1; 177 | regaddr[CLK_CSSR] = STM8S207R8_CLK_CSSR; 178 | regaddr[CLK_CCOR] = STM8S207R8_CLK_CCOR; 179 | regaddr[CLK_PCKENR2] = STM8S207R8_CLK_PCKENR2; 180 | regaddr[CLK_CANCCR] = STM8S207R8_CLK_CANCCR; 181 | regaddr[CLK_HSITRIMR] = STM8S207R8_CLK_HSITRIMR; 182 | regaddr[CLK_SWIMCCR] = STM8S207R8_CLK_SWIMCCR; 183 | regaddr[IWDG_KR] = STM8S207R8_IWDG_KR; 184 | regaddr[IWDG_PR] = STM8S207R8_IWDG_PR; 185 | regaddr[IWDG_RLR] = STM8S207R8_IWDG_RLR; 186 | regaddr[FLASH_CR1] = STM8S207R8_FLASH_CR1; 187 | regaddr[FLASH_CR2] = STM8S207R8_FLASH_CR2; 188 | regaddr[FLASH_NCR2] = STM8S207R8_FLASH_NCR2; 189 | regaddr[FLASH_FPR] = STM8S207R8_FLASH_FPR; 190 | regaddr[FLASH_NFPR] = STM8S207R8_FLASH_NFPR; 191 | regaddr[FLASH_IAPSR] = STM8S207R8_FLASH_IAPSR; 192 | regaddr[FLASH_PUKR] = STM8S207R8_FLASH_PUKR; 193 | regaddr[FLASH_DUKR] = STM8S207R8_FLASH_DUKR; 194 | 195 | ports_start = STM8S207R8_PORTS_START; 196 | ports_end = STM8S207R8_PORTS_END; 197 | uart1_start = STM8S207R8_UART1_START; 198 | uart1_end = STM8S207R8_UART1_END; 199 | uart3_start = STM8S207R8_UART3_START; 200 | uart3_end = STM8S207R8_UART3_END; 201 | tim2_start = STM8S207R8_TIM2_START; 202 | tim2_end = STM8S207R8_TIM2_END; 203 | adc_start = STM8S207R8_ADC_START; 204 | adc_end = STM8S207R8_ADC_END; 205 | clk_start = STM8S207R8_CLK_START; 206 | clk_end = STM8S207R8_CLK_END; 207 | iwdg_start = STM8S207R8_IWDG_START; 208 | iwdg_end = STM8S207R8_IWDG_END; 209 | flash_reg_start = STM8S207R8_FLASH_REG_START; 210 | flash_reg_end = STM8S207R8_FLASH_REG_END; 211 | 212 | use_PA = 1; 213 | use_PB = 1; 214 | use_PC = 1; 215 | use_PD = 1; 216 | use_PE = 1; 217 | use_PF = 1; 218 | use_PG = 1; 219 | use_PH = 1; 220 | use_PI = 1; 221 | 222 | clk_gateADC = 1 << 3; 223 | clk_gateTIM1 = 1 << 7; 224 | clk_gateTIM2 = 1 << 5; 225 | clk_gateTIM3 = 1 << 6; 226 | clk_gateTIM4 = 1 << 4; 227 | clk_gateUART1 = 1 << 2; 228 | clk_gateUART2 = 0; 229 | clk_gateUART3 = 1 << 3; 230 | clk_gateUART4 = 0; 231 | } 232 | -------------------------------------------------------------------------------- /STM8/devices/stm8s207r8.h: -------------------------------------------------------------------------------- 1 | #ifndef _STM8207R8_H_ 2 | #define _STM8207R8_H_ 3 | 4 | #include 5 | 6 | void stm8s207r8_init(void); 7 | 8 | #define STM8S207R8_FLASH_START 0x8000 9 | #define STM8S207R8_FLASH_SIZE 0x10000 10 | 11 | #define STM8S207R8_RAM_START 0x0000 12 | #define STM8S207R8_RAM_SIZE 0x1800 13 | 14 | #define STM8S207R8_STACK_SIZE 0x400 15 | 16 | #define STM8S207R8_EEPROM_START 0x4000 17 | #define STM8S207R8_EEPROM_SIZE 0x800 18 | 19 | #define STM8S207R8_IO_START 0x5000 20 | #define STM8S207R8_IO_SIZE 0x800 21 | 22 | #define STM8S207R8_CPU_REG_START 0x7F00 23 | #define STM8S207R8_CPU_REG_SIZE 0x100 24 | 25 | #define STM8S207R8_CPUR_A 0x7F00 26 | #define STM8S207R8_CPUR_PCE 0x7F01 27 | #define STM8S207R8_CPUR_PCH 0x7F02 28 | #define STM8S207R8_CPUR_PCL 0x7F03 29 | #define STM8S207R8_CPUR_XH 0x7F04 30 | #define STM8S207R8_CPUR_XL 0x7F05 31 | #define STM8S207R8_CPUR_YH 0x7F06 32 | #define STM8S207R8_CPUR_YL 0x7F07 33 | #define STM8S207R8_CPUR_SPH 0x7F08 34 | #define STM8S207R8_CPUR_SPL 0x7F09 35 | #define STM8S207R8_CPUR_CCR 0x7F0A 36 | 37 | #define STM8S207R8_ITC_SPR1 0x7F70 38 | #define STM8S207R8_ITC_SPR2 0x7F71 39 | #define STM8S207R8_ITC_SPR3 0x7F72 40 | #define STM8S207R8_ITC_SPR4 0x7F73 41 | #define STM8S207R8_ITC_SPR5 0x7F74 42 | #define STM8S207R8_ITC_SPR6 0x7F75 43 | #define STM8S207R8_ITC_SPR7 0x7F76 44 | #define STM8S207R8_ITC_SPR8 0x7F77 45 | 46 | #define STM8S207R8_UART1_SR 0x5230 47 | #define STM8S207R8_UART1_DR 0x5231 48 | #define STM8S207R8_UART1_BRR1 0x5232 49 | #define STM8S207R8_UART1_BRR2 0x5233 50 | #define STM8S207R8_UART1_CR1 0x5234 51 | #define STM8S207R8_UART1_CR2 0x5235 52 | #define STM8S207R8_UART1_CR3 0x5236 53 | #define STM8S207R8_UART1_CR4 0x5237 54 | #define STM8S207R8_UART1_CR5 0x5238 55 | #define STM8S207R8_UART1_GTR 0x5239 56 | #define STM8S207R8_UART1_PSCR 0x523A 57 | 58 | #define STM8S207R8_UART1_START STM8S207R8_UART1_SR 59 | #define STM8S207R8_UART1_END STM8S207R8_UART1_PSCR 60 | 61 | #define STM8S207R8_UART3_SR 0x5240 62 | #define STM8S207R8_UART3_DR 0x5241 63 | #define STM8S207R8_UART3_BRR1 0x5242 64 | #define STM8S207R8_UART3_BRR2 0x5243 65 | #define STM8S207R8_UART3_CR1 0x5244 66 | #define STM8S207R8_UART3_CR2 0x5245 67 | #define STM8S207R8_UART3_CR3 0x5246 68 | #define STM8S207R8_UART3_CR4 0x5247 69 | #define STM8S207R8_UART3_CR6 0x5249 70 | 71 | #define STM8S207R8_UART3_START STM8S207R8_UART3_SR 72 | #define STM8S207R8_UART3_END STM8S207R8_UART3_CR6 73 | 74 | #define STM8S207R8_EXTI_CR1 0x50A0 75 | #define STM8S207R8_EXTI_CR2 0x50A1 76 | 77 | #define STM8S207R8_PA_ODR 0x5000 78 | #define STM8S207R8_PA_IDR 0x5001 79 | #define STM8S207R8_PA_DDR 0x5002 80 | #define STM8S207R8_PA_CR1 0x5003 81 | #define STM8S207R8_PA_CR2 0x5004 82 | 83 | #define STM8S207R8_PB_ODR 0x5005 84 | #define STM8S207R8_PB_IDR 0x5006 85 | #define STM8S207R8_PB_DDR 0x5007 86 | #define STM8S207R8_PB_CR1 0x5008 87 | #define STM8S207R8_PB_CR2 0x5009 88 | 89 | #define STM8S207R8_PC_ODR 0x500A 90 | #define STM8S207R8_PC_IDR 0x500B 91 | #define STM8S207R8_PC_DDR 0x500C 92 | #define STM8S207R8_PC_CR1 0x500D 93 | #define STM8S207R8_PC_CR2 0x500E 94 | 95 | #define STM8S207R8_PD_ODR 0x500F 96 | #define STM8S207R8_PD_IDR 0x5010 97 | #define STM8S207R8_PD_DDR 0x5011 98 | #define STM8S207R8_PD_CR1 0x5012 99 | #define STM8S207R8_PD_CR2 0x5013 100 | 101 | #define STM8S207R8_PE_ODR 0x5014 102 | #define STM8S207R8_PE_IDR 0x5015 103 | #define STM8S207R8_PE_DDR 0x5016 104 | #define STM8S207R8_PE_CR1 0x5017 105 | #define STM8S207R8_PE_CR2 0x5018 106 | 107 | #define STM8S207R8_PF_ODR 0x5019 108 | #define STM8S207R8_PF_IDR 0x501A 109 | #define STM8S207R8_PF_DDR 0x501B 110 | #define STM8S207R8_PF_CR1 0x501C 111 | #define STM8S207R8_PF_CR2 0x501D 112 | 113 | #define STM8S207R8_PG_ODR 0x501E 114 | #define STM8S207R8_PG_IDR 0x501F 115 | #define STM8S207R8_PG_DDR 0x5020 116 | #define STM8S207R8_PG_CR1 0x5021 117 | #define STM8S207R8_PG_CR2 0x5022 118 | 119 | #define STM8S207R8_PH_ODR 0x5023 120 | #define STM8S207R8_PH_IDR 0x5024 121 | #define STM8S207R8_PH_DDR 0x5025 122 | #define STM8S207R8_PH_CR1 0x5026 123 | #define STM8S207R8_PH_CR2 0x5027 124 | 125 | #define STM8S207R8_PI_ODR 0x5028 126 | #define STM8S207R8_PI_IDR 0x5029 127 | #define STM8S207R8_PI_DDR 0x502A 128 | #define STM8S207R8_PI_CR1 0x502B 129 | #define STM8S207R8_PI_CR2 0x502C 130 | 131 | #define STM8S207R8_PORTS_START STM8S207R8_PA_ODR 132 | #define STM8S207R8_PORTS_END STM8S207R8_PI_CR2 133 | 134 | #define STM8S207R8_TIM2_CR1 0x5300 //TIM2 control register 1 0x00 135 | #define STM8S207R8_TIM2_IER 0x5301 //TIM2 interrupt enable register 0x00 136 | #define STM8S207R8_TIM2_SR1 0x5302 //TIM2 status register 1 0x00 137 | #define STM8S207R8_TIM2_SR2 0x5303 //TIM2 status register 2 0x00 138 | #define STM8S207R8_TIM2_EGR 0x5304 //TIM2 event generation register 0x00 139 | #define STM8S207R8_TIM2_CCMR1 0x5305 //TIM2 capture/compare mode register 1 0x00 140 | #define STM8S207R8_TIM2_CCMR2 0x5306 //TIM2 capture/compare mode register 2 0x00 141 | #define STM8S207R8_TIM2_CCMR3 0x5307 //TIM2 capture/compare mode register 3 0x00 142 | #define STM8S207R8_TIM2_CCER1 0x5308 //TIM2 capture/compare enable register 1 0x00 143 | #define STM8S207R8_TIM2_CCER2 0x5309 //TIM2 capture/compare enable register 2 0x00 144 | #define STM8S207R8_TIM2_CNTRH 0x530A //TIM2 counter high 0x00 145 | #define STM8S207R8_TIM2_CNTRL 0x530B //TIM2 counter low 0x00 146 | #define STM8S207R8_TIM2_PSCR 0x530C //TIM2 prescaler register 0x00 147 | #define STM8S207R8_TIM2_ARRH 0x530D //TIM2 auto-reload register high 0xFF 148 | #define STM8S207R8_TIM2_ARRL 0x530E //TIM2 auto-reload register low 0xFF 149 | #define STM8S207R8_TIM2_CCR1H 0x530F //TIM2 capture/compare register 1 high 0x00 150 | #define STM8S207R8_TIM2_CCR1L 0x5310 //TIM2 capture/compare register 1 low 0x00 151 | #define STM8S207R8_TIM2_CCR2H 0x5311 //TIM2 capture/compare reg. 2 high 0x00 152 | #define STM8S207R8_TIM2_CCR2L 0x5312 //TIM2 capture/compare register 2 low 0x00 153 | #define STM8S207R8_TIM2_CCR3H 0x5313 //TIM2 capture/compare register 3 high 0x00 154 | #define STM8S207R8_TIM2_CCR3L 0x5314 //TIM2 capture/compare register 3 low 0x00 155 | 156 | #define STM8S207R8_TIM2_START STM8S207R8_TIM2_CR1 157 | #define STM8S207R8_TIM2_END STM8S207R8_TIM2_CCR3L 158 | 159 | #define STM8S207R8_ADC_CSR 0x5400 //ADC control/status register 160 | #define STM8S207R8_ADC_CR1 0x5401 //ADC configuration register 1 161 | #define STM8S207R8_ADC_CR2 0x5402 //ADC configuration register 2 162 | #define STM8S207R8_ADC_CR3 0x5403 //ADC configuration register 3 163 | #define STM8S207R8_ADC_DRH 0x5404 //ADC data register high 164 | #define STM8S207R8_ADC_DRL 0x5405 //ADC data register low 165 | #define STM8S207R8_ADC_TDRH 0x5406 //ADC Schmitt trigger disable register high 166 | #define STM8S207R8_ADC_TDRL 0x5407 //ADC Schmitt trigger disable register low 167 | 168 | #define STM8S207R8_ADC_START STM8S207R8_ADC_CSR 169 | #define STM8S207R8_ADC_END STM8S207R8_ADC_TDRL 170 | 171 | #define STM8S207R8_CLK_ICKR 0x50C0 //Internal clock control register 172 | #define STM8S207R8_CLK_ECKR 0x50C1 //External clock control register 173 | #define STM8S207R8_CLK_CMSR 0x50C3 //Clock master status register 174 | #define STM8S207R8_CLK_SWR 0x50C4 //Clock master switch register 175 | #define STM8S207R8_CLK_SWCR 0x50C5 //Clock switch control register 176 | #define STM8S207R8_CLK_CKDIVR 0x50C6 //Clock divider register 177 | #define STM8S207R8_CLK_PCKENR1 0x50C7 //Peripheral clock gating register 1 178 | #define STM8S207R8_CLK_CSSR 0x50C8 //Clock security system register 179 | #define STM8S207R8_CLK_CCOR 0x50C9 //Configurable clock control register 180 | #define STM8S207R8_CLK_PCKENR2 0x50CA //Peripheral clock gating register 2 181 | #define STM8S207R8_CLK_CANCCR 0x50CB //CAN clock control register 182 | #define STM8S207R8_CLK_HSITRIMR 0x50CC //HSI clock calibration trimming register 183 | #define STM8S207R8_CLK_SWIMCCR 0x50CD //SWIM clock control register 184 | 185 | #define STM8S207R8_CLK_START STM8S207R8_CLK_ICKR 186 | #define STM8S207R8_CLK_END STM8S207R8_CLK_SWIMCCR 187 | 188 | #define STM8S207R8_IWDG_KR 0x50E0 //IWDG key register 189 | #define STM8S207R8_IWDG_PR 0x50E1 //IWDG prescaler register 190 | #define STM8S207R8_IWDG_RLR 0x50E2 //IWDG reload register 191 | 192 | #define STM8S207R8_IWDG_START STM8S207R8_IWDG_KR 193 | #define STM8S207R8_IWDG_END STM8S207R8_IWDG_RLR 194 | 195 | #define STM8S207R8_FLASH_CR1 0x505A //Flash control register 1 196 | #define STM8S207R8_FLASH_CR2 0x505B //Flash control register 2 197 | #define STM8S207R8_FLASH_NCR2 0x505C //Flash complimentary control register 2 198 | #define STM8S207R8_FLASH_FPR 0x505D //Flash protection register 199 | #define STM8S207R8_FLASH_NFPR 0x505E //Flash complimentary protection register 200 | #define STM8S207R8_FLASH_IAPSR 0x505F //Flash in-application programming status register 201 | #define STM8S207R8_FLASH_PUKR 0x5062 //Flash Program memory unprotection register 202 | #define STM8S207R8_FLASH_DUKR 0x5064 //Data EEPROM unprotection register 203 | 204 | #define STM8S207R8_FLASH_REG_START STM8S207R8_FLASH_CR1 205 | #define STM8S207R8_FLASH_REG_END STM8S207R8_FLASH_DUKR 206 | 207 | #endif 208 | -------------------------------------------------------------------------------- /STM8/devices/stm8s207s6.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "stm8s207s6.h" 7 | #include "../peripherals/clk.h" 8 | #include "../memory.h" 9 | #include "../cpu.h" 10 | #include "../ports.h" 11 | 12 | void stm8s207s6_init() { 13 | uint32_t i; 14 | 15 | cpu_name = "STM8S207S6"; 16 | 17 | flash_start = STM8S207S6_FLASH_START; 18 | flash_size = STM8S207S6_FLASH_SIZE; 19 | 20 | ram_start = STM8S207S6_RAM_START; 21 | ram_size = STM8S207S6_RAM_SIZE; 22 | 23 | stack_top = ram_start + ram_size - 1; 24 | stack_bottom = stack_top - STM8S207S6_STACK_SIZE; 25 | 26 | eeprom_start = STM8S207S6_EEPROM_START; 27 | eeprom_size = STM8S207S6_EEPROM_SIZE; 28 | 29 | io_start = STM8S207S6_IO_START; 30 | io_size = STM8S207S6_IO_SIZE; 31 | 32 | cpureg_start = STM8S207S6_CPU_REG_START; 33 | cpureg_size = STM8S207S6_CPU_REG_SIZE; 34 | 35 | flash = (uint8_t*)malloc(STM8S207S6_FLASH_SIZE); 36 | RAM = (uint8_t*)malloc(STM8S207S6_RAM_SIZE); 37 | EEPROM = (uint8_t*)malloc(STM8S207S6_EEPROM_SIZE); 38 | IO = (uint8_t*)malloc(STM8S207S6_IO_SIZE); 39 | CPUREG = (uint8_t*)malloc(STM8S207S6_CPU_REG_SIZE); 40 | if ((flash == NULL) || (RAM == NULL) || (EEPROM == NULL) || (IO == NULL) || (CPUREG == NULL)) { 41 | printf("Memory allocation error!\n"); 42 | exit(-1); 43 | } 44 | 45 | memset(flash, 0, STM8S207S6_FLASH_SIZE); 46 | memset(RAM, 0, STM8S207S6_RAM_SIZE); 47 | memset(EEPROM, 0, STM8S207S6_EEPROM_SIZE); 48 | memset(IO, 0, STM8S207S6_IO_SIZE); 49 | memset(CPUREG, 0, STM8S207S6_CPU_REG_SIZE); 50 | 51 | for (i = 0; i < REGISTERS_COUNT; i++) { 52 | regaddr[i] = 0xFFFFFFFF; 53 | } 54 | 55 | regaddr[CPUR_A] = STM8S207S6_CPUR_A; 56 | regaddr[CPUR_PCE] = STM8S207S6_CPUR_PCE; 57 | regaddr[CPUR_PCH] = STM8S207S6_CPUR_PCH; 58 | regaddr[CPUR_PCL] = STM8S207S6_CPUR_PCL; 59 | regaddr[CPUR_XH] = STM8S207S6_CPUR_XH; 60 | regaddr[CPUR_XL] = STM8S207S6_CPUR_XL; 61 | regaddr[CPUR_YH] = STM8S207S6_CPUR_YH; 62 | regaddr[CPUR_YL] = STM8S207S6_CPUR_YL; 63 | regaddr[CPUR_SPH] = STM8S207S6_CPUR_SPH; 64 | regaddr[CPUR_SPL] = STM8S207S6_CPUR_SPL; 65 | regaddr[CPUR_CCR] = STM8S207S6_CPUR_CCR; 66 | regaddr[ITC_SPR1] = STM8S207S6_ITC_SPR1; 67 | regaddr[ITC_SPR2] = STM8S207S6_ITC_SPR2; 68 | regaddr[ITC_SPR3] = STM8S207S6_ITC_SPR3; 69 | regaddr[ITC_SPR4] = STM8S207S6_ITC_SPR4; 70 | regaddr[ITC_SPR5] = STM8S207S6_ITC_SPR5; 71 | regaddr[ITC_SPR6] = STM8S207S6_ITC_SPR6; 72 | regaddr[ITC_SPR7] = STM8S207S6_ITC_SPR7; 73 | regaddr[ITC_SPR8] = STM8S207S6_ITC_SPR8; 74 | regaddr[UART1_SR] = STM8S207S6_UART1_SR; 75 | regaddr[UART1_DR] = STM8S207S6_UART1_DR; 76 | regaddr[UART1_BRR1] = STM8S207S6_UART1_BRR1; 77 | regaddr[UART1_BRR2] = STM8S207S6_UART1_BRR2; 78 | regaddr[UART1_CR1] = STM8S207S6_UART1_CR1; 79 | regaddr[UART1_CR2] = STM8S207S6_UART1_CR2; 80 | regaddr[UART1_CR3] = STM8S207S6_UART1_CR3; 81 | regaddr[UART1_CR4] = STM8S207S6_UART1_CR4; 82 | regaddr[UART1_CR5] = STM8S207S6_UART1_CR5; 83 | regaddr[UART1_GTR] = STM8S207S6_UART1_GTR; 84 | regaddr[UART1_PSCR] = STM8S207S6_UART1_PSCR; 85 | regaddr[UART3_SR] = STM8S207S6_UART3_SR; 86 | regaddr[UART3_DR] = STM8S207S6_UART3_DR; 87 | regaddr[UART3_BRR1] = STM8S207S6_UART3_BRR1; 88 | regaddr[UART3_BRR2] = STM8S207S6_UART3_BRR2; 89 | regaddr[UART3_CR1] = STM8S207S6_UART3_CR1; 90 | regaddr[UART3_CR2] = STM8S207S6_UART3_CR2; 91 | regaddr[UART3_CR3] = STM8S207S6_UART3_CR3; 92 | regaddr[UART3_CR4] = STM8S207S6_UART3_CR4; 93 | regaddr[UART3_CR6] = STM8S207S6_UART3_CR6; 94 | regaddr[EXTI_CR1] = STM8S207S6_EXTI_CR1; 95 | regaddr[EXTI_CR2] = STM8S207S6_EXTI_CR2; 96 | regaddr[PA_ODR] = STM8S207S6_PA_ODR; 97 | regaddr[PA_IDR] = STM8S207S6_PA_IDR; 98 | regaddr[PA_DDR] = STM8S207S6_PA_DDR; 99 | regaddr[PA_CR1] = STM8S207S6_PA_CR1; 100 | regaddr[PA_CR2] = STM8S207S6_PA_CR2; 101 | regaddr[PB_ODR] = STM8S207S6_PB_ODR; 102 | regaddr[PB_IDR] = STM8S207S6_PB_IDR; 103 | regaddr[PB_DDR] = STM8S207S6_PB_DDR; 104 | regaddr[PB_CR1] = STM8S207S6_PB_CR1; 105 | regaddr[PB_CR2] = STM8S207S6_PB_CR2; 106 | regaddr[PC_ODR] = STM8S207S6_PC_ODR; 107 | regaddr[PC_IDR] = STM8S207S6_PC_IDR; 108 | regaddr[PC_DDR] = STM8S207S6_PC_DDR; 109 | regaddr[PC_CR1] = STM8S207S6_PC_CR1; 110 | regaddr[PC_CR2] = STM8S207S6_PC_CR2; 111 | regaddr[PD_ODR] = STM8S207S6_PD_ODR; 112 | regaddr[PD_IDR] = STM8S207S6_PD_IDR; 113 | regaddr[PD_DDR] = STM8S207S6_PD_DDR; 114 | regaddr[PD_CR1] = STM8S207S6_PD_CR1; 115 | regaddr[PD_CR2] = STM8S207S6_PD_CR2; 116 | regaddr[PE_ODR] = STM8S207S6_PE_ODR; 117 | regaddr[PE_IDR] = STM8S207S6_PE_IDR; 118 | regaddr[PE_DDR] = STM8S207S6_PE_DDR; 119 | regaddr[PE_CR1] = STM8S207S6_PE_CR1; 120 | regaddr[PE_CR2] = STM8S207S6_PE_CR2; 121 | regaddr[PF_ODR] = STM8S207S6_PF_ODR; 122 | regaddr[PF_IDR] = STM8S207S6_PF_IDR; 123 | regaddr[PF_DDR] = STM8S207S6_PF_DDR; 124 | regaddr[PF_CR1] = STM8S207S6_PF_CR1; 125 | regaddr[PF_CR2] = STM8S207S6_PF_CR2; 126 | regaddr[PG_ODR] = STM8S207S6_PG_ODR; 127 | regaddr[PG_IDR] = STM8S207S6_PG_IDR; 128 | regaddr[PG_DDR] = STM8S207S6_PG_DDR; 129 | regaddr[PG_CR1] = STM8S207S6_PG_CR1; 130 | regaddr[PG_CR2] = STM8S207S6_PG_CR2; 131 | regaddr[PH_ODR] = STM8S207S6_PH_ODR; 132 | regaddr[PH_IDR] = STM8S207S6_PH_IDR; 133 | regaddr[PH_DDR] = STM8S207S6_PH_DDR; 134 | regaddr[PH_CR1] = STM8S207S6_PH_CR1; 135 | regaddr[PH_CR2] = STM8S207S6_PH_CR2; 136 | regaddr[PI_ODR] = STM8S207S6_PI_ODR; 137 | regaddr[PI_IDR] = STM8S207S6_PI_IDR; 138 | regaddr[PI_DDR] = STM8S207S6_PI_DDR; 139 | regaddr[PI_CR1] = STM8S207S6_PI_CR1; 140 | regaddr[PI_CR2] = STM8S207S6_PI_CR2; 141 | regaddr[TIM2_CR1] = STM8S207S6_TIM2_CR1; 142 | regaddr[TIM2_IER] = STM8S207S6_TIM2_IER; 143 | regaddr[TIM2_SR1] = STM8S207S6_TIM2_SR1; 144 | regaddr[TIM2_SR2] = STM8S207S6_TIM2_SR2; 145 | regaddr[TIM2_EGR] = STM8S207S6_TIM2_EGR; 146 | regaddr[TIM2_CCMR1] = STM8S207S6_TIM2_CCMR1; 147 | regaddr[TIM2_CCMR2] = STM8S207S6_TIM2_CCMR2; 148 | regaddr[TIM2_CCMR3] = STM8S207S6_TIM2_CCMR3; 149 | regaddr[TIM2_CCER1] = STM8S207S6_TIM2_CCER1; 150 | regaddr[TIM2_CCER2] = STM8S207S6_TIM2_CCER2; 151 | regaddr[TIM2_CNTRH] = STM8S207S6_TIM2_CNTRH; 152 | regaddr[TIM2_CNTRL] = STM8S207S6_TIM2_CNTRL; 153 | regaddr[TIM2_PSCR] = STM8S207S6_TIM2_PSCR; 154 | regaddr[TIM2_ARRH] = STM8S207S6_TIM2_ARRH; 155 | regaddr[TIM2_ARRL] = STM8S207S6_TIM2_ARRL; 156 | regaddr[TIM2_CCR1H] = STM8S207S6_TIM2_CCR1H; 157 | regaddr[TIM2_CCR1L] = STM8S207S6_TIM2_CCR1L; 158 | regaddr[TIM2_CCR2H] = STM8S207S6_TIM2_CCR2H; 159 | regaddr[TIM2_CCR2L] = STM8S207S6_TIM2_CCR2L; 160 | regaddr[TIM2_CCR3H] = STM8S207S6_TIM2_CCR3H; 161 | regaddr[TIM2_CCR3L] = STM8S207S6_TIM2_CCR3L; 162 | regaddr[ADC_CSR] = STM8S207S6_ADC_CSR; 163 | regaddr[ADC_CR1] = STM8S207S6_ADC_CR1; 164 | regaddr[ADC_CR2] = STM8S207S6_ADC_CR2; 165 | regaddr[ADC_CR3] = STM8S207S6_ADC_CR3; 166 | regaddr[ADC_DRH] = STM8S207S6_ADC_DRH; 167 | regaddr[ADC_DRL] = STM8S207S6_ADC_DRL; 168 | regaddr[ADC_TDRH] = STM8S207S6_ADC_TDRH; 169 | regaddr[ADC_TDRL] = STM8S207S6_ADC_TDRL; 170 | regaddr[CLK_ICKR] = STM8S207S6_CLK_ICKR; 171 | regaddr[CLK_ECKR] = STM8S207S6_CLK_ECKR; 172 | regaddr[CLK_CMSR] = STM8S207S6_CLK_CMSR; 173 | regaddr[CLK_SWR] = STM8S207S6_CLK_SWR; 174 | regaddr[CLK_SWCR] = STM8S207S6_CLK_SWCR; 175 | regaddr[CLK_CKDIVR] = STM8S207S6_CLK_CKDIVR; 176 | regaddr[CLK_PCKENR1] = STM8S207S6_CLK_PCKENR1; 177 | regaddr[CLK_CSSR] = STM8S207S6_CLK_CSSR; 178 | regaddr[CLK_CCOR] = STM8S207S6_CLK_CCOR; 179 | regaddr[CLK_PCKENR2] = STM8S207S6_CLK_PCKENR2; 180 | regaddr[CLK_CANCCR] = STM8S207S6_CLK_CANCCR; 181 | regaddr[CLK_HSITRIMR] = STM8S207S6_CLK_HSITRIMR; 182 | regaddr[CLK_SWIMCCR] = STM8S207S6_CLK_SWIMCCR; 183 | regaddr[IWDG_KR] = STM8S207S6_IWDG_KR; 184 | regaddr[IWDG_PR] = STM8S207S6_IWDG_PR; 185 | regaddr[IWDG_RLR] = STM8S207S6_IWDG_RLR; 186 | regaddr[FLASH_CR1] = STM8S207S6_FLASH_CR1; 187 | regaddr[FLASH_CR2] = STM8S207S6_FLASH_CR2; 188 | regaddr[FLASH_NCR2] = STM8S207S6_FLASH_NCR2; 189 | regaddr[FLASH_FPR] = STM8S207S6_FLASH_FPR; 190 | regaddr[FLASH_NFPR] = STM8S207S6_FLASH_NFPR; 191 | regaddr[FLASH_IAPSR] = STM8S207S6_FLASH_IAPSR; 192 | regaddr[FLASH_PUKR] = STM8S207S6_FLASH_PUKR; 193 | regaddr[FLASH_DUKR] = STM8S207S6_FLASH_DUKR; 194 | 195 | ports_start = STM8S207S6_PORTS_START; 196 | ports_end = STM8S207S6_PORTS_END; 197 | uart1_start = STM8S207S6_UART1_START; 198 | uart1_end = STM8S207S6_UART1_END; 199 | uart3_start = STM8S207S6_UART3_START; 200 | uart3_end = STM8S207S6_UART3_END; 201 | tim2_start = STM8S207S6_TIM2_START; 202 | tim2_end = STM8S207S6_TIM2_END; 203 | adc_start = STM8S207S6_ADC_START; 204 | adc_end = STM8S207S6_ADC_END; 205 | clk_start = STM8S207S6_CLK_START; 206 | clk_end = STM8S207S6_CLK_END; 207 | iwdg_start = STM8S207S6_IWDG_START; 208 | iwdg_end = STM8S207S6_IWDG_END; 209 | flash_reg_start = STM8S207S6_FLASH_REG_START; 210 | flash_reg_end = STM8S207S6_FLASH_REG_END; 211 | 212 | use_PA = 1; 213 | use_PB = 1; 214 | use_PC = 1; 215 | use_PD = 1; 216 | use_PE = 1; 217 | use_PF = 1; 218 | use_PG = 1; 219 | use_PH = 1; 220 | use_PI = 1; 221 | 222 | clk_gateADC = 1 << 3; 223 | clk_gateTIM1 = 1 << 7; 224 | clk_gateTIM2 = 1 << 5; 225 | clk_gateTIM3 = 1 << 6; 226 | clk_gateTIM4 = 1 << 4; 227 | clk_gateUART1 = 1 << 2; 228 | clk_gateUART2 = 0; 229 | clk_gateUART3 = 1 << 3; 230 | clk_gateUART4 = 0; 231 | } 232 | -------------------------------------------------------------------------------- /STM8/devices/stm8s207s6.h: -------------------------------------------------------------------------------- 1 | #ifndef _STM8207S6_H_ 2 | #define _STM8207S6_H_ 3 | 4 | #include 5 | 6 | void stm8s207s6_init(void); 7 | 8 | #define STM8S207S6_FLASH_START 0x8000 9 | #define STM8S207S6_FLASH_SIZE 0x8000 10 | 11 | #define STM8S207S6_RAM_START 0x0000 12 | #define STM8S207S6_RAM_SIZE 0x1800 13 | 14 | #define STM8S207S6_STACK_SIZE 0x400 15 | 16 | #define STM8S207S6_EEPROM_START 0x4000 17 | #define STM8S207S6_EEPROM_SIZE 0x400 18 | 19 | #define STM8S207S6_IO_START 0x5000 20 | #define STM8S207S6_IO_SIZE 0x800 21 | 22 | #define STM8S207S6_CPU_REG_START 0x7F00 23 | #define STM8S207S6_CPU_REG_SIZE 0x100 24 | 25 | #define STM8S207S6_CPUR_A 0x7F00 26 | #define STM8S207S6_CPUR_PCE 0x7F01 27 | #define STM8S207S6_CPUR_PCH 0x7F02 28 | #define STM8S207S6_CPUR_PCL 0x7F03 29 | #define STM8S207S6_CPUR_XH 0x7F04 30 | #define STM8S207S6_CPUR_XL 0x7F05 31 | #define STM8S207S6_CPUR_YH 0x7F06 32 | #define STM8S207S6_CPUR_YL 0x7F07 33 | #define STM8S207S6_CPUR_SPH 0x7F08 34 | #define STM8S207S6_CPUR_SPL 0x7F09 35 | #define STM8S207S6_CPUR_CCR 0x7F0A 36 | 37 | #define STM8S207S6_ITC_SPR1 0x7F70 38 | #define STM8S207S6_ITC_SPR2 0x7F71 39 | #define STM8S207S6_ITC_SPR3 0x7F72 40 | #define STM8S207S6_ITC_SPR4 0x7F73 41 | #define STM8S207S6_ITC_SPR5 0x7F74 42 | #define STM8S207S6_ITC_SPR6 0x7F75 43 | #define STM8S207S6_ITC_SPR7 0x7F76 44 | #define STM8S207S6_ITC_SPR8 0x7F77 45 | 46 | #define STM8S207S6_UART1_SR 0x5230 47 | #define STM8S207S6_UART1_DR 0x5231 48 | #define STM8S207S6_UART1_BRR1 0x5232 49 | #define STM8S207S6_UART1_BRR2 0x5233 50 | #define STM8S207S6_UART1_CR1 0x5234 51 | #define STM8S207S6_UART1_CR2 0x5235 52 | #define STM8S207S6_UART1_CR3 0x5236 53 | #define STM8S207S6_UART1_CR4 0x5237 54 | #define STM8S207S6_UART1_CR5 0x5238 55 | #define STM8S207S6_UART1_GTR 0x5239 56 | #define STM8S207S6_UART1_PSCR 0x523A 57 | 58 | #define STM8S207S6_UART1_START STM8S207S6_UART1_SR 59 | #define STM8S207S6_UART1_END STM8S207S6_UART1_PSCR 60 | 61 | #define STM8S207S6_UART3_SR 0x5240 62 | #define STM8S207S6_UART3_DR 0x5241 63 | #define STM8S207S6_UART3_BRR1 0x5242 64 | #define STM8S207S6_UART3_BRR2 0x5243 65 | #define STM8S207S6_UART3_CR1 0x5244 66 | #define STM8S207S6_UART3_CR2 0x5245 67 | #define STM8S207S6_UART3_CR3 0x5246 68 | #define STM8S207S6_UART3_CR4 0x5247 69 | #define STM8S207S6_UART3_CR6 0x5249 70 | 71 | #define STM8S207S6_UART3_START STM8S207S6_UART3_SR 72 | #define STM8S207S6_UART3_END STM8S207S6_UART3_CR6 73 | 74 | #define STM8S207S6_EXTI_CR1 0x50A0 75 | #define STM8S207S6_EXTI_CR2 0x50A1 76 | 77 | #define STM8S207S6_PA_ODR 0x5000 78 | #define STM8S207S6_PA_IDR 0x5001 79 | #define STM8S207S6_PA_DDR 0x5002 80 | #define STM8S207S6_PA_CR1 0x5003 81 | #define STM8S207S6_PA_CR2 0x5004 82 | 83 | #define STM8S207S6_PB_ODR 0x5005 84 | #define STM8S207S6_PB_IDR 0x5006 85 | #define STM8S207S6_PB_DDR 0x5007 86 | #define STM8S207S6_PB_CR1 0x5008 87 | #define STM8S207S6_PB_CR2 0x5009 88 | 89 | #define STM8S207S6_PC_ODR 0x500A 90 | #define STM8S207S6_PC_IDR 0x500B 91 | #define STM8S207S6_PC_DDR 0x500C 92 | #define STM8S207S6_PC_CR1 0x500D 93 | #define STM8S207S6_PC_CR2 0x500E 94 | 95 | #define STM8S207S6_PD_ODR 0x500F 96 | #define STM8S207S6_PD_IDR 0x5010 97 | #define STM8S207S6_PD_DDR 0x5011 98 | #define STM8S207S6_PD_CR1 0x5012 99 | #define STM8S207S6_PD_CR2 0x5013 100 | 101 | #define STM8S207S6_PE_ODR 0x5014 102 | #define STM8S207S6_PE_IDR 0x5015 103 | #define STM8S207S6_PE_DDR 0x5016 104 | #define STM8S207S6_PE_CR1 0x5017 105 | #define STM8S207S6_PE_CR2 0x5018 106 | 107 | #define STM8S207S6_PF_ODR 0x5019 108 | #define STM8S207S6_PF_IDR 0x501A 109 | #define STM8S207S6_PF_DDR 0x501B 110 | #define STM8S207S6_PF_CR1 0x501C 111 | #define STM8S207S6_PF_CR2 0x501D 112 | 113 | #define STM8S207S6_PG_ODR 0x501E 114 | #define STM8S207S6_PG_IDR 0x501F 115 | #define STM8S207S6_PG_DDR 0x5020 116 | #define STM8S207S6_PG_CR1 0x5021 117 | #define STM8S207S6_PG_CR2 0x5022 118 | 119 | #define STM8S207S6_PH_ODR 0x5023 120 | #define STM8S207S6_PH_IDR 0x5024 121 | #define STM8S207S6_PH_DDR 0x5025 122 | #define STM8S207S6_PH_CR1 0x5026 123 | #define STM8S207S6_PH_CR2 0x5027 124 | 125 | #define STM8S207S6_PI_ODR 0x5028 126 | #define STM8S207S6_PI_IDR 0x5029 127 | #define STM8S207S6_PI_DDR 0x502A 128 | #define STM8S207S6_PI_CR1 0x502B 129 | #define STM8S207S6_PI_CR2 0x502C 130 | 131 | #define STM8S207S6_PORTS_START STM8S207S6_PA_ODR 132 | #define STM8S207S6_PORTS_END STM8S207S6_PI_CR2 133 | 134 | #define STM8S207S6_TIM2_CR1 0x5300 //TIM2 control register 1 0x00 135 | #define STM8S207S6_TIM2_IER 0x5301 //TIM2 interrupt enable register 0x00 136 | #define STM8S207S6_TIM2_SR1 0x5302 //TIM2 status register 1 0x00 137 | #define STM8S207S6_TIM2_SR2 0x5303 //TIM2 status register 2 0x00 138 | #define STM8S207S6_TIM2_EGR 0x5304 //TIM2 event generation register 0x00 139 | #define STM8S207S6_TIM2_CCMR1 0x5305 //TIM2 capture/compare mode register 1 0x00 140 | #define STM8S207S6_TIM2_CCMR2 0x5306 //TIM2 capture/compare mode register 2 0x00 141 | #define STM8S207S6_TIM2_CCMR3 0x5307 //TIM2 capture/compare mode register 3 0x00 142 | #define STM8S207S6_TIM2_CCER1 0x5308 //TIM2 capture/compare enable register 1 0x00 143 | #define STM8S207S6_TIM2_CCER2 0x5309 //TIM2 capture/compare enable register 2 0x00 144 | #define STM8S207S6_TIM2_CNTRH 0x530A //TIM2 counter high 0x00 145 | #define STM8S207S6_TIM2_CNTRL 0x530B //TIM2 counter low 0x00 146 | #define STM8S207S6_TIM2_PSCR 0x530C //TIM2 prescaler register 0x00 147 | #define STM8S207S6_TIM2_ARRH 0x530D //TIM2 auto-reload register high 0xFF 148 | #define STM8S207S6_TIM2_ARRL 0x530E //TIM2 auto-reload register low 0xFF 149 | #define STM8S207S6_TIM2_CCR1H 0x530F //TIM2 capture/compare register 1 high 0x00 150 | #define STM8S207S6_TIM2_CCR1L 0x5310 //TIM2 capture/compare register 1 low 0x00 151 | #define STM8S207S6_TIM2_CCR2H 0x5311 //TIM2 capture/compare reg. 2 high 0x00 152 | #define STM8S207S6_TIM2_CCR2L 0x5312 //TIM2 capture/compare register 2 low 0x00 153 | #define STM8S207S6_TIM2_CCR3H 0x5313 //TIM2 capture/compare register 3 high 0x00 154 | #define STM8S207S6_TIM2_CCR3L 0x5314 //TIM2 capture/compare register 3 low 0x00 155 | 156 | #define STM8S207S6_TIM2_START STM8S207S6_TIM2_CR1 157 | #define STM8S207S6_TIM2_END STM8S207S6_TIM2_CCR3L 158 | 159 | #define STM8S207S6_ADC_CSR 0x5400 //ADC control/status register 160 | #define STM8S207S6_ADC_CR1 0x5401 //ADC configuration register 1 161 | #define STM8S207S6_ADC_CR2 0x5402 //ADC configuration register 2 162 | #define STM8S207S6_ADC_CR3 0x5403 //ADC configuration register 3 163 | #define STM8S207S6_ADC_DRH 0x5404 //ADC data register high 164 | #define STM8S207S6_ADC_DRL 0x5405 //ADC data register low 165 | #define STM8S207S6_ADC_TDRH 0x5406 //ADC Schmitt trigger disable register high 166 | #define STM8S207S6_ADC_TDRL 0x5407 //ADC Schmitt trigger disable register low 167 | 168 | #define STM8S207S6_ADC_START STM8S207S6_ADC_CSR 169 | #define STM8S207S6_ADC_END STM8S207S6_ADC_TDRL 170 | 171 | #define STM8S207S6_CLK_ICKR 0x50C0 //Internal clock control register 172 | #define STM8S207S6_CLK_ECKR 0x50C1 //External clock control register 173 | #define STM8S207S6_CLK_CMSR 0x50C3 //Clock master status register 174 | #define STM8S207S6_CLK_SWR 0x50C4 //Clock master switch register 175 | #define STM8S207S6_CLK_SWCR 0x50C5 //Clock switch control register 176 | #define STM8S207S6_CLK_CKDIVR 0x50C6 //Clock divider register 177 | #define STM8S207S6_CLK_PCKENR1 0x50C7 //Peripheral clock gating register 1 178 | #define STM8S207S6_CLK_CSSR 0x50C8 //Clock security system register 179 | #define STM8S207S6_CLK_CCOR 0x50C9 //Configurable clock control register 180 | #define STM8S207S6_CLK_PCKENR2 0x50CA //Peripheral clock gating register 2 181 | #define STM8S207S6_CLK_CANCCR 0x50CB //CAN clock control register 182 | #define STM8S207S6_CLK_HSITRIMR 0x50CC //HSI clock calibration trimming register 183 | #define STM8S207S6_CLK_SWIMCCR 0x50CD //SWIM clock control register 184 | 185 | #define STM8S207S6_CLK_START STM8S207S6_CLK_ICKR 186 | #define STM8S207S6_CLK_END STM8S207S6_CLK_SWIMCCR 187 | 188 | #define STM8S207S6_IWDG_KR 0x50E0 //IWDG key register 189 | #define STM8S207S6_IWDG_PR 0x50E1 //IWDG prescaler register 190 | #define STM8S207S6_IWDG_RLR 0x50E2 //IWDG reload register 191 | 192 | #define STM8S207S6_IWDG_START STM8S207S6_IWDG_KR 193 | #define STM8S207S6_IWDG_END STM8S207S6_IWDG_RLR 194 | 195 | #define STM8S207S6_FLASH_CR1 0x505A //Flash control register 1 196 | #define STM8S207S6_FLASH_CR2 0x505B //Flash control register 2 197 | #define STM8S207S6_FLASH_NCR2 0x505C //Flash complimentary control register 2 198 | #define STM8S207S6_FLASH_FPR 0x505D //Flash protection register 199 | #define STM8S207S6_FLASH_NFPR 0x505E //Flash complimentary protection register 200 | #define STM8S207S6_FLASH_IAPSR 0x505F //Flash in-application programming status register 201 | #define STM8S207S6_FLASH_PUKR 0x5062 //Flash Program memory unprotection register 202 | #define STM8S207S6_FLASH_DUKR 0x5064 //Data EEPROM unprotection register 203 | 204 | #define STM8S207S6_FLASH_REG_START STM8S207S6_FLASH_CR1 205 | #define STM8S207S6_FLASH_REG_END STM8S207S6_FLASH_DUKR 206 | 207 | #endif 208 | -------------------------------------------------------------------------------- /STM8/display.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "memory.h" 6 | #include "hardware/casil.h" 7 | 8 | HANDLE hConsole; 9 | uint8_t doupdate = 1; 10 | 11 | void cls() { 12 | COORD coordScreen = { 0, 0 }; // home for the cursor 13 | DWORD cCharsWritten; 14 | CONSOLE_SCREEN_BUFFER_INFO csbi; 15 | DWORD dwConSize; 16 | 17 | // Get the number of character cells in the current buffer. 18 | 19 | if (!GetConsoleScreenBufferInfo(hConsole, &csbi)) 20 | { 21 | return; 22 | } 23 | 24 | dwConSize = csbi.dwSize.X * csbi.dwSize.Y; 25 | 26 | // Fill the entire screen with blanks. 27 | 28 | if (!FillConsoleOutputCharacter(hConsole, // Handle to console screen buffer 29 | (TCHAR)' ', // Character to write to the buffer 30 | dwConSize, // Number of cells to write 31 | coordScreen, // Coordinates of first cell 32 | &cCharsWritten))// Receive number of characters written 33 | { 34 | return; 35 | } 36 | 37 | // Get the current text attribute. 38 | 39 | if (!GetConsoleScreenBufferInfo(hConsole, &csbi)) 40 | { 41 | return; 42 | } 43 | 44 | // Set the buffer's attributes accordingly. 45 | 46 | if (!FillConsoleOutputAttribute(hConsole, // Handle to console screen buffer 47 | csbi.wAttributes, // Character attributes to use 48 | dwConSize, // Number of cells to set attribute 49 | coordScreen, // Coordinates of first cell 50 | &cCharsWritten)) // Receive number of characters written 51 | { 52 | return; 53 | } 54 | 55 | // Put the cursor at its home coordinates. 56 | 57 | SetConsoleCursorPosition(hConsole, coordScreen); 58 | } 59 | 60 | void gotoxy(int x, int y) { 61 | COORD coord; 62 | coord.X = x; 63 | coord.Y = y; 64 | SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord); 65 | } 66 | 67 | void display_str(int x, int y, char* str) { 68 | SetConsoleTextAttribute(hConsole, 0x07); 69 | gotoxy(x, y); 70 | printf(str); 71 | } 72 | 73 | void display_init() { 74 | hConsole = GetStdHandle(STD_OUTPUT_HANDLE); 75 | SetConsoleTextAttribute(hConsole, 7); 76 | cls(); 77 | } 78 | 79 | void display_shutdown() { 80 | CONSOLE_SCREEN_BUFFER_INFO csbi; 81 | SHORT lastrow; 82 | GetConsoleScreenBufferInfo(hConsole, &csbi); 83 | lastrow = csbi.srWindow.Bottom - csbi.srWindow.Top; 84 | SetConsoleTextAttribute(hConsole, 7); 85 | gotoxy(0, lastrow - 1); 86 | } 87 | -------------------------------------------------------------------------------- /STM8/display.h: -------------------------------------------------------------------------------- 1 | #ifndef _DISPLAY_H_ 2 | #define _DISPLAY_H_ 3 | 4 | #include 5 | 6 | extern HANDLE hConsole; 7 | extern uint8_t doupdate; 8 | 9 | void cls(void); 10 | void gotoxy(int x, int y); 11 | void display_str(int y, int x, char* str); 12 | void display_init(void); 13 | void display_shutdown(void); 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /STM8/elf.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "memory.h" 5 | #include "elf.h" 6 | 7 | // TODO: clean up this code. 8 | // - Don't dynamically malloc() using size values straight from external data! Sanity-check sizes first. 9 | // - Use endian.h macros to handle endianness of values (and get rid of swap16(), swap32()). 10 | // - Define readable constants for ELF header offsets. 11 | 12 | //#define ELF_DETAIL 13 | 14 | uint32_t elf_entrypoint = 0; 15 | uint8_t endianness; 16 | 17 | int elf_load(const char* path) { 18 | FILE* elf; 19 | long fsz; 20 | uint8_t hdr[52], * phdr = NULL, * shdr = NULL, * chunk = NULL, * strtab = NULL; 21 | uint16_t phdrnum, phdrsize, shdrnum, shdrsize; 22 | uint32_t i, j, p_offset, p_vaddr, p_paddr, p_filesz, p_memsz, p_flags, p_align; 23 | 24 | elf = fopen(path, "rb"); 25 | if (elf == NULL) { 26 | return -1; 27 | } 28 | fseek(elf, 0, SEEK_END); 29 | fsz = ftell(elf); 30 | fseek(elf, 0, SEEK_SET); 31 | 32 | //load ELF header 33 | fread(hdr, 1, 52, elf); 34 | if ((hdr[0x00] != 0x7F) 35 | || (hdr[0x01] != 'E') 36 | || (hdr[0x02] != 'L') 37 | || (hdr[0x03] != 'F')) { 38 | printf("Not an ELF file!\r\n"); 39 | return -1; 40 | } 41 | if (hdr[0x04] != 1) { 42 | printf("Not a 32-bit binary!\r\n"); 43 | return -1; 44 | } 45 | if (hdr[0x05] == 1) endianness = 0; else endianness = 1; 46 | elf_entrypoint = swap32(*(uint32_t*)(&hdr[0x18])); 47 | phdrsize = swap16(*(uint16_t*)(&hdr[0x2A])); 48 | phdrnum = swap16(*(uint16_t*)(&hdr[0x2C])); 49 | shdrsize = swap16(*(uint16_t*)(&hdr[0x2E])); 50 | shdrnum = swap16(*(uint16_t*)(&hdr[0x30])); 51 | 52 | //load program header 53 | phdr = (uint8_t*)malloc((size_t)phdrsize); 54 | if (phdr == NULL) { 55 | printf("Could not allocate phdr\r\n"); 56 | return -1; 57 | } 58 | for (i = 0; i < phdrnum; i++) { 59 | fseek(elf, swap32(*(uint32_t*)(&hdr[0x1C])) + (uint32_t)phdrsize * i, SEEK_SET); 60 | if (fread(phdr, 1, (size_t)phdrsize, elf) < (size_t)phdrsize) { 61 | printf("Could not read phdr %lu\r\n", i); 62 | return -1; 63 | } 64 | p_offset = swap32(*(uint32_t*)(&phdr[0x04])); 65 | p_vaddr = swap32(*(uint32_t*)(&phdr[0x08])); 66 | p_paddr = swap32(*(uint32_t*)(&phdr[0x0C])); 67 | p_filesz = swap32(*(uint32_t*)(&phdr[0x10])); 68 | p_memsz = swap32(*(uint32_t*)(&phdr[0x14])); 69 | p_flags = swap32(*(uint32_t*)(&phdr[0x18])); 70 | p_align = swap32(*(uint32_t*)(&phdr[0x1C])); 71 | #ifdef ELF_DETAIL 72 | printf("Program header %lu:\r\n", i); 73 | printf("\tFile image offset: 0x%08X\r\n", p_offset); 74 | printf("\t Virtual address: 0x%08X\r\n", p_vaddr); 75 | printf("\t Physical address: 0x%08X\r\n", p_paddr); 76 | printf("\t Size in file: 0x%08X\r\n", p_filesz); 77 | printf("\t Size in memory: 0x%08X\r\n", p_memsz); 78 | printf("\t Flags: 0x%08X\r\n", p_flags); 79 | printf("\t Alignment: 0x%08X\r\n", p_align); 80 | #endif 81 | chunk = (uint8_t*)malloc((size_t)p_filesz); 82 | if (chunk == NULL) { 83 | return -1; 84 | } 85 | fseek(elf, p_offset, SEEK_SET); 86 | if (fread(chunk, 1, (size_t)p_filesz, elf) < (size_t)p_filesz) { 87 | free(chunk); 88 | free(phdr); 89 | printf("Failed to load %lu bytes for this program section!\r\n", p_filesz); 90 | return -1; 91 | } 92 | for (j = 0; j < p_filesz; j++) { 93 | memory_write(p_paddr + j, chunk[j]); 94 | } 95 | free(chunk); 96 | #ifdef ELF_DETAIL 97 | printf("Loaded %lu bytes for this program section at 0x%08X\r\n\r\n", p_filesz, p_paddr); 98 | #endif 99 | } 100 | free(phdr); 101 | 102 | fclose(elf); 103 | 104 | return 0; 105 | } 106 | -------------------------------------------------------------------------------- /STM8/elf.h: -------------------------------------------------------------------------------- 1 | #ifndef _ELF_H_ 2 | #define _ELF_H_ 3 | 4 | #include 5 | 6 | #define swap32(x) (endianness ? (((x & 0xFF000000) >> 24) | ((x & 0x00FF0000) >> 8) | ((x & 0x0000FF00) << 8) | ((x & 0x000000FF) << 24)) : (x)) 7 | #define swap16(x) (endianness ? (((x & 0xFF00) >> 8) | ((x & 0x00FF) << 8)) : (x)) 8 | 9 | extern uint8_t endianness; 10 | 11 | int elf_load(const char* path); 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /STM8/endian.h: -------------------------------------------------------------------------------- 1 | #ifndef _ENDIAN_H_ 2 | #define _ENDIAN_H_ 3 | 4 | // Macros to take a 16-, 24- or 32-bit big-endian integer value and swap the bytes 5 | // (if necessary) to host order. NOTE: will not work on literal values! 6 | #define be16toh(x) ((((uint8_t *)&(x))[1] << 0) | (((uint8_t *)&(x))[0] << 8)) 7 | #define be24toh(x) ((((uint8_t *)&(x))[2] << 0) | (((uint8_t *)&(x))[1] << 8) | (((uint8_t *)&(x))[0] << 16)) 8 | #define be32toh(x) ((((uint8_t *)&(x))[3] << 0) | (((uint8_t *)&(x))[2] << 8) | (((uint8_t *)&(x))[1] << 16) | (((uint8_t *)&(x))[0] << 24)) 9 | 10 | // TODO: make work with literal values, perhaps by assigning arg to intermediate variable. 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /STM8/hardware/casil.c: -------------------------------------------------------------------------------- 1 | /* 2 | Casil 1610 16-character LCD display device 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | #include "../config.h" 9 | #include "../display.h" 10 | 11 | uint8_t rs, rw, en, latch, dataval = 0, flipflop = 0, prevcmd = 0; 12 | uint8_t disp[16]; 13 | uint8_t casilmem[256], casiladdr = 0; 14 | 15 | void casil_init() { 16 | flipflop = 0; 17 | dataval = 0; 18 | prevcmd = 0; 19 | memset(casilmem, 0, 256); 20 | } 21 | 22 | void casil_print() { 23 | uint8_t i; 24 | printf("\rCASIL: \""); 25 | for (i = 0; i < 16; i++) { 26 | printf("%c", disp[i]); 27 | } 28 | printf("\""); 29 | } 30 | 31 | void casil_checkifupdated() { 32 | static uint8_t lastdisp[16]; 33 | uint8_t i; 34 | 35 | for (i = 0; i < 16; i++) { 36 | if (disp[i] != lastdisp[i]) { 37 | product_markforupdate(); 38 | break; 39 | } 40 | } 41 | 42 | memcpy(lastdisp, disp, 16); 43 | } 44 | 45 | void casil_rs(uint8_t val) { 46 | rs = val; 47 | } 48 | 49 | void casil_rw(uint8_t val) { 50 | rw = val; 51 | } 52 | 53 | void casil_en(uint8_t val) { 54 | uint8_t olden; 55 | olden = en; 56 | en = val; 57 | if (en == olden) return; 58 | if (en == 1) return; 59 | 60 | if (flipflop == 0) { //high nibble first 61 | dataval = (dataval & 0x0F) | (latch << 4); 62 | } 63 | else { //low nibble 64 | dataval = (dataval & 0xF0) | (latch & 0x0F); 65 | //printf("Casil command: %02X\n", dataval); 66 | if (!rs && !rw) { 67 | casiladdr = dataval; 68 | } 69 | else if (!rw) { 70 | casilmem[casiladdr] = dataval; 71 | if ((casiladdr >= 0x80) && (casiladdr <= 0x87)) { 72 | disp[casiladdr - 0x80] = dataval; 73 | casil_checkifupdated(); 74 | } 75 | else if ((casiladdr >= 0xC0) && (casiladdr <= 0xC7)) { 76 | disp[casiladdr - 0xB8] = dataval; 77 | casil_checkifupdated(); 78 | } 79 | casiladdr++; 80 | } 81 | prevcmd = dataval; 82 | } 83 | 84 | flipflop ^= 1; 85 | } 86 | 87 | void casil_latchwrite(uint8_t val) { 88 | latch = val & 0x0F; 89 | } 90 | 91 | uint8_t casil_latchread() { 92 | return 0; 93 | } 94 | -------------------------------------------------------------------------------- /STM8/hardware/casil.h: -------------------------------------------------------------------------------- 1 | #ifndef _CASIL_H_ 2 | #define _CASIL_H_ 3 | 4 | #include 5 | 6 | void casil_init(); 7 | void casil_rs(uint8_t val); 8 | void casil_rw(uint8_t val); 9 | void casil_en(uint8_t val); 10 | void casil_latchwrite(uint8_t val); 11 | uint8_t casil_latchread(); 12 | 13 | extern uint8_t disp[16]; 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /STM8/intelhex.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "memory.h" 8 | #include "endian.h" 9 | #include "intelhex.h" 10 | 11 | // #define IHEX_DETAIL 12 | 13 | // Nominal max length in characters of a record is 521 (excluding line breaks 14 | // and terminating null). 15 | #define LINE_MAX_LEN 525 16 | 17 | // Absolute minimum line length in characters: start code + 2 digit byte count 18 | // + 4 digit address + 2 digit record type + 2 digit checksum. 19 | #define LINE_MIN_LEN 11 20 | 21 | // Maximum specifyable byte count in a record is 255, so max record length in 22 | // bytes is that plus size of other fields (count, addr, type, checksum). 23 | #define REC_MAX_LEN 260 24 | 25 | #define REC_OFFSET_BYTE_COUNT 0 26 | #define REC_OFFSET_ADDR 1 27 | #define REC_OFFSET_TYPE 3 28 | #define REC_OFFSET_DATA 4 29 | 30 | #define REC_TYPE_DATA 0x0 31 | #define REC_TYPE_EOF 0x1 32 | #define REC_TYPE_EXT_SEG_ADDR 0x2 33 | #define REC_TYPE_START_SEG_ADDR 0x3 34 | #define REC_TYPE_EXT_LIN_ADDR 0x4 35 | #define REC_TYPE_START_LIN_ADDR 0x5 36 | 37 | static uint8_t intelhex_convert_hex_char(char c) { 38 | c = toupper(c); 39 | if(isdigit(c)) { 40 | return c - '0'; 41 | } else { 42 | return c - ('A' - 10); 43 | } 44 | } 45 | 46 | static size_t intelhex_decode_record(const char* line, size_t line_len, uint8_t* buf, size_t buf_len) { 47 | size_t rec_len = 0; 48 | uint8_t val; 49 | 50 | // Check first character of line is start code (colon). 51 | if(line_len > 0 && *line == ':') { 52 | line++; 53 | line_len--; 54 | } else { 55 | return 0; 56 | } 57 | 58 | while(line_len > 0) { 59 | if(isxdigit(*line) && isxdigit(*(line + 1))) { 60 | // Convert pair of hex digit characters into byte value. 61 | val = (intelhex_convert_hex_char(*line) << 4) | intelhex_convert_hex_char(*(line + 1)); 62 | line += 2; 63 | line_len -= 2; 64 | 65 | // Add byte value to output buffer (if room). 66 | if(buf_len > 0) { 67 | *buf++ = val; 68 | buf_len--; 69 | rec_len++; 70 | } else { 71 | break; 72 | } 73 | } else if(*line == '\n' || *line == '\r') { 74 | // Skip any trailing line-break characters. 75 | line++; 76 | line_len--; 77 | } else { 78 | // Otherwise, an invalid character, exit with failure. 79 | return 0; 80 | } 81 | } 82 | 83 | return rec_len; 84 | } 85 | 86 | int intelhex_load(const char* path) { 87 | FILE* ihex; 88 | char line[LINE_MAX_LEN]; 89 | unsigned int line_count = 0, mem_addr, mem_offset = 0; 90 | uint8_t record[REC_MAX_LEN], checksum; 91 | size_t line_len, record_len; 92 | bool end = false; 93 | 94 | // Open the file in text mode (so CRLF line endings are automatically converted to LF). 95 | ihex = fopen(path, "r"); 96 | if(ihex == NULL) { 97 | return -1; 98 | } 99 | 100 | do { 101 | memset(line, '\0', sizeof(line)); 102 | 103 | if(fgets(line, sizeof(line) / sizeof(line[0]), ihex) != NULL) { 104 | line_count++; 105 | line_len = strlen(line); 106 | 107 | // Remove any trailing line feed character from line string. 108 | if(line[line_len - 1] == '\n') { 109 | line[line_len - 1] = '\0'; 110 | line_len--; 111 | } 112 | 113 | // Check for minimum line length. 114 | if(line_len < LINE_MIN_LEN) { 115 | printf("Invalid line %u of Intel Hex file; incomplete record, not enough characters.\n", line_count); 116 | return -1; 117 | } 118 | 119 | #ifdef IHEX_DETAIL 120 | printf("Line %u: \"%s\" (%zu chars)\n", line_count, line, line_len); 121 | #endif 122 | 123 | // Decode the line into a record (i.e. byte array). 124 | record_len = intelhex_decode_record(line, line_len, record, sizeof(record)); 125 | if(record_len == 0) { 126 | printf("Invalid line %u of Intel Hex file; error parsing hex digits.\n", line_count); 127 | return -1; 128 | } 129 | 130 | // Verify that record length and byte count field correlate. 131 | if((size_t)record[REC_OFFSET_BYTE_COUNT] + 5 != record_len) { 132 | printf("Invalid line %u of Intel Hex file; byte count field value does not correlate with record length.\n", line_count); 133 | return -1; 134 | } 135 | 136 | // Calculate the record's checksum. Sum all record bytes preceding the checksum, take the 137 | // LSB of the sum, then calculate two's complement of it (i.e. invert bits and add 1). 138 | checksum = 0; 139 | for(size_t i = 0; i < record_len - 1; i++) { 140 | checksum += record[i]; 141 | } 142 | checksum = ~checksum + 1; 143 | 144 | #ifdef IHEX_DETAIL 145 | printf("Checksum: Record = 0x%02X, Calculated = 0x%02X\n", record[record_len -1], checksum); 146 | #endif 147 | 148 | // Verify calculated checksum matches record's. 149 | if(checksum != record[record_len - 1]) { 150 | printf("Invalid line %u of Intel Hex file; failed checksum verification (got %02X, expected %02X).\n", line_count, checksum, record[record_len - 1]); 151 | return -1; 152 | } 153 | 154 | switch(record[REC_OFFSET_TYPE]) { 155 | case REC_TYPE_DATA: 156 | // Take the data bytes contained in the record and write them to the specified 157 | // memory address, offset by any previously defined extended address. 158 | mem_addr = be16toh(record[REC_OFFSET_ADDR]) + mem_offset; 159 | for(size_t i = 0; i < record[REC_OFFSET_BYTE_COUNT]; i++) { 160 | #ifdef IHEX_DETAIL 161 | printf("Mem Write: Addr = 0x%08X, Byte = 0x%02X\n", mem_addr, record[REC_OFFSET_DATA + i]); 162 | #endif 163 | memory_write(mem_addr++, record[REC_OFFSET_DATA + i]); 164 | } 165 | break; 166 | case REC_TYPE_EOF: 167 | // Don't process file any further. 168 | end = true; 169 | break; 170 | case REC_TYPE_EXT_SEG_ADDR: 171 | // Data field contains a 16-bit segment base address. Multiply by 16, to be added 172 | // to any further record addresses. 173 | mem_offset = be16toh(record[REC_OFFSET_DATA]) << 4; 174 | #ifdef IHEX_DETAIL 175 | printf("Offset: Addr = 0x%08X\n", mem_offset); 176 | #endif 177 | break; 178 | case REC_TYPE_EXT_LIN_ADDR: 179 | // Data field contains upper 16-bits of a 32-bit absolute address. Shift to upper 180 | // 16 bits, to be added to any further record addresses. 181 | mem_offset = be16toh(record[REC_OFFSET_DATA]) << 16; 182 | #ifdef IHEX_DETAIL 183 | printf("Offset: Addr = 0x%08X\n", mem_offset); 184 | #endif 185 | break; 186 | case REC_TYPE_START_SEG_ADDR: 187 | case REC_TYPE_START_LIN_ADDR: 188 | // Don't need to handle these; just skip them. 189 | break; 190 | default: 191 | printf("Invalid line %u of Intel Hex file; unknown record type (%u).\n", line_count, record[REC_OFFSET_TYPE]); 192 | return -1; 193 | } 194 | } 195 | 196 | if(ferror(ihex)) { 197 | printf("Error reading file!\n"); // TODO: print err msg with strerror()? 198 | return -1; 199 | } 200 | } while(!end && !feof(ihex)); 201 | 202 | fclose(ihex); 203 | 204 | return 0; 205 | } 206 | -------------------------------------------------------------------------------- /STM8/intelhex.h: -------------------------------------------------------------------------------- 1 | #ifndef _INTELHEX_H_ 2 | #define _INTELHEX_H_ 3 | 4 | int intelhex_load(const char* path); 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /STM8/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | STM8 emulator main 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "config.h" 10 | #include "elf.h" 11 | #include "intelhex.h" 12 | #include "srec.h" 13 | #include "memory.h" 14 | #include "cpu.h" 15 | #include "peripherals/uart1.h" 16 | #include "peripherals/uart3.h" 17 | #include "peripherals/tim2.h" 18 | #include "peripherals/adc.h" 19 | #include "peripherals/clk.h" 20 | #include "display.h" 21 | #include "timing.h" 22 | #include "args.h" 23 | #include "serial.h" 24 | #include "tcpconsole.h" 25 | 26 | uint32_t clocksrun = 0, clocktimer; 27 | uint8_t pause = 0; 28 | 29 | void eeprom_load(char* file) { 30 | FILE* eepfile; 31 | eepfile = fopen(file, "rb"); 32 | if (eepfile == NULL) { 33 | printf("Error loading EEPROM file.\n"); 34 | return; 35 | } 36 | fread(EEPROM, 1, eeprom_size, eepfile); 37 | fclose(eepfile); 38 | } 39 | 40 | void clocks_callback(void* dummy) { 41 | char info[64]; 42 | if (showclock) { 43 | sprintf(info, "Clock speed: %.03f MHz ", ((double)clocksrun * 2) / 1000000.0); 44 | if (showdisplay) 45 | display_str(40, 0, info); 46 | else 47 | printf("%s\r", info); 48 | } 49 | clocksrun = 0; 50 | } 51 | 52 | void limiter_callback(void* dummy) { 53 | pause = 0; 54 | } 55 | 56 | int main(int argc, char* argv[]) { 57 | FILE* dumpfile; 58 | int dummy; 59 | 60 | printf("STM8 Emulator v0.13 - 2022/04/20\n\n"); 61 | 62 | if (args_parse(argc, argv)) { 63 | return -1; 64 | } 65 | 66 | if (elffile == NULL && hexfile == NULL && srecfile == NULL) { 67 | printf("An ELF, Intel Hex, or SREC file must be specified. Use -h for help.\n"); 68 | return -1; 69 | } 70 | 71 | if((elffile != NULL && (hexfile != NULL || srecfile != NULL)) || (hexfile != NULL && (elffile != NULL || srecfile != NULL)) || (srecfile != NULL && (elffile != NULL || hexfile != NULL))) { 72 | printf("Cannot specify more than one program file (ELF, Intel Hex, SREC) simultaneously. Use -h for help.\n"); 73 | return -1; 74 | } 75 | 76 | if (speedarg <= 0) 77 | speedarg = 24000000; 78 | 79 | printf("Emulator configuration:\n"); 80 | printf(" Product: %s\n", product_name); 81 | printf(" CPU: %s (Flash = %lu, RAM = %lu, EEPROM = %lu)\n", cpu_name, flash_size, ram_size, eeprom_size); 82 | printf("Ext oscillator: %.00f Hz\n", speedarg); 83 | printf(" Program file: %s\n", (elffile != NULL) ? elffile : ((hexfile != NULL) ? hexfile : srecfile)); 84 | printf(" EEPROM file: %s\n", (eepromfile == NULL) ? "[none]" : eepromfile); 85 | printf(" Dump file: %s\n", (ramfile == NULL) ? "[none]" : ramfile); 86 | printf(" UART1: "); 87 | switch (uart1_redirect) { 88 | case UART1_REDIRECT_NULL: printf("No connection\n"); break; 89 | case UART1_REDIRECT_CONSOLE: printf("Console redirection\n"); break; 90 | case UART1_REDIRECT_SERIAL: printf("Serial port redirection\n"); break; 91 | case UART1_REDIRECT_TCP: printf("TCP socket redirection (server)\n"); break; 92 | } 93 | printf(" UART3: "); 94 | switch (uart3_redirect) { 95 | case UART3_REDIRECT_NULL: printf("No connection\n"); break; 96 | case UART3_REDIRECT_CONSOLE: printf("Console redirection\n"); break; 97 | case UART3_REDIRECT_SERIAL: printf("Serial port redirection\n"); break; 98 | case UART3_REDIRECT_TCP: printf("TCP socket redirection (server)\n"); break; 99 | } 100 | 101 | if(elffile != NULL) { 102 | if(elf_load(elffile) < 0) { 103 | printf("There was an error loading the ELF file.\n"); 104 | return -1; 105 | } 106 | } else if(hexfile != NULL) { 107 | if(intelhex_load(hexfile) < 0) { 108 | printf("There was an error loading the Intel Hex file.\n"); 109 | return -1; 110 | } 111 | } else if(srecfile != NULL) { 112 | if(srec_load(srecfile) < 0) { 113 | printf("There was an error loading the SREC file.\n"); 114 | return -1; 115 | } 116 | } 117 | if (eepromfile != NULL) { 118 | eeprom_load(eepromfile); 119 | } 120 | //printf("Clocks per loop: %ld\n", clocksperloop); 121 | printf("\nPress any key to begin emulation...\n"); 122 | dummy = _getch(); 123 | 124 | 125 | timing_init(); 126 | #ifndef DEBUG_OUTPUT 127 | if (showdisplay) { 128 | display_init(); 129 | product_init(); 130 | } 131 | #endif 132 | timing_addTimer((void*)clocks_callback, NULL, 2, TIMING_ENABLED); 133 | timing_addTimer((void*)limiter_callback, NULL, 100, TIMING_ENABLED); 134 | cpu_reset(); 135 | running = 1; 136 | while (running) { 137 | uint16_t loops; 138 | while (pause) { 139 | timing_loop(); 140 | adc_loop(); 141 | } 142 | for (loops = 0; loops < (clocksperloop / 10); loops++) { 143 | cpu_run(10); 144 | clk_loop(10); 145 | clocksrun += 10UL; 146 | } 147 | pause = 1; 148 | timing_loop(); 149 | adc_loop(); 150 | serial_loop(); 151 | tcpconsole_loop(); 152 | product_loop(); 153 | #ifndef DEBUG_OUTPUT 154 | if (showdisplay) { 155 | product_update(); 156 | } 157 | #endif 158 | } 159 | #ifndef DEBUG_OUTPUT 160 | if (showdisplay) display_shutdown(); 161 | #endif 162 | if (ramfile != NULL) { 163 | dumpfile = fopen(ramfile, "wb"); 164 | fwrite(RAM, 1, ram_size, dumpfile); 165 | fclose(dumpfile); 166 | } 167 | if (eepromfile != NULL) { 168 | dumpfile = fopen(eepromfile, "wb"); 169 | fwrite(EEPROM, 1, eeprom_size, dumpfile); 170 | fclose(dumpfile); 171 | } 172 | 173 | return 0; 174 | } 175 | -------------------------------------------------------------------------------- /STM8/memory.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "memory.h" 4 | #include "peripherals/uart1.h" 5 | #include "peripherals/uart3.h" 6 | #include "peripherals/tim2.h" 7 | #include "peripherals/adc.h" 8 | #include "peripherals/clk.h" 9 | #include "peripherals/iwdg.h" 10 | #include "ports.h" 11 | #include "cpu.h" 12 | 13 | uint8_t *flash = NULL; 14 | uint8_t *RAM = NULL; 15 | uint8_t *EEPROM = NULL; 16 | uint8_t *IO = NULL; 17 | uint8_t *CPUREG = NULL; 18 | 19 | uint32_t regaddr[REGISTERS_COUNT]; 20 | 21 | uint32_t flash_size = 0, ram_size = 0, eeprom_size = 0, io_size = 0, cpureg_size = 0; 22 | uint32_t flash_start = 0, ram_start = 0, eeprom_start = 0, io_start = 0, cpureg_start = 0; 23 | 24 | uint32_t stack_top = 0, stack_bottom = 0; 25 | 26 | uint32_t ports_start = 0, uart1_start = 0, uart3_start = 0, tim2_start = 0, adc_start = 0, clk_start = 0; 27 | uint32_t ports_end = 0, uart1_end = 0, uart3_end = 0, tim2_end = 0, adc_end = 0, clk_end = 0; 28 | 29 | uint32_t iwdg_start = 0, flash_reg_start = 0; 30 | uint32_t iwdg_end = 0, flash_reg_end = 0; 31 | 32 | //MEMDEBUG_t mem_watch[32]; 33 | //uint8_t mem_watchnum = 0; 34 | 35 | void memory_cpuregwrite(uint32_t addr, uint8_t val) { 36 | if (addr == regaddr[CPUR_A]) 37 | a = val; 38 | else if (addr == regaddr[CPUR_PCE]) 39 | pc = (pc & 0x0000FFFF) | ((uint32_t)val << 16); 40 | else if (addr == regaddr[CPUR_PCH]) 41 | pc = (pc & 0x00FF00FF) | ((uint32_t)val << 8); 42 | else if (addr == regaddr[CPUR_PCL]) 43 | pc = (pc & 0x00FFFF00) | (uint32_t)val; 44 | else if (addr == regaddr[CPUR_XH]) 45 | x = (x & 0x00FF) | ((uint16_t)val << 8); 46 | else if (addr == regaddr[CPUR_XL]) 47 | x = (x & 0xFF00) | (uint16_t)val; 48 | else if (addr == regaddr[CPUR_YH]) 49 | y = (y & 0x00FF) | ((uint16_t)val << 8); 50 | else if (addr == regaddr[CPUR_YL]) 51 | y = (y & 0xFF00) | (uint16_t)val; 52 | else if (addr == regaddr[CPUR_SPH]) 53 | sp = (sp & 0x00FF) | ((uint16_t)val << 8); 54 | else if (addr == regaddr[CPUR_SPL]) 55 | sp = (sp & 0xFF00) | (uint16_t)val; 56 | else if (addr == regaddr[CPUR_CCR]) 57 | cc = val; 58 | else 59 | CPUREG[addr - cpureg_start] = val; 60 | } 61 | 62 | uint8_t memory_cpuregread(uint32_t addr) { 63 | uint8_t ret; 64 | if (addr == regaddr[CPUR_A]) 65 | ret = a; 66 | else if (addr == regaddr[CPUR_PCE]) 67 | ret = (uint8_t)(pc >> 16); 68 | else if (addr == regaddr[CPUR_PCH]) 69 | ret = (uint8_t)(pc >> 8); 70 | else if (addr == regaddr[CPUR_PCL]) 71 | ret = (uint8_t)pc; 72 | else if (addr == regaddr[CPUR_XH]) 73 | ret = (uint8_t)(x >> 8); 74 | else if (addr == regaddr[CPUR_XL]) 75 | ret = (uint8_t)x; 76 | else if (addr == regaddr[CPUR_YH]) 77 | ret = (uint8_t)(y >> 8); 78 | else if (addr == regaddr[CPUR_YL]) 79 | ret = (uint8_t)y; 80 | else if (addr == regaddr[CPUR_SPH]) 81 | ret = (uint8_t)(sp >> 8); 82 | else if (addr == regaddr[CPUR_SPL]) 83 | ret = (uint8_t)sp; 84 | else if (addr == regaddr[CPUR_CCR]) 85 | ret = cc; 86 | else 87 | ret = CPUREG[addr - cpureg_start]; 88 | return ret; 89 | } 90 | 91 | uint8_t memory_read(uint32_t addr) { 92 | uint8_t ret = 0xFF; 93 | 94 | if ((addr >= flash_start) && (addr < (flash_start + flash_size))) { 95 | ret = flash[addr - flash_start]; 96 | } 97 | else if ((addr >= flash_reg_start) && (addr <= flash_reg_end)) { 98 | if (addr == regaddr[FLASH_IAPSR]) { 99 | ret = IO[regaddr[FLASH_IAPSR] - io_start]; 100 | } 101 | else { 102 | ret = 0x00; 103 | } 104 | } 105 | else if ((addr >= ram_start) && (addr < (ram_start + ram_size))) { 106 | ret = RAM[addr - ram_start]; 107 | } 108 | else if ((addr >= eeprom_start) && (addr < (eeprom_start + eeprom_size))) { 109 | ret = EEPROM[addr - eeprom_start]; 110 | //fprintf(stderr, "%04X = %02X\n", addr, ret); 111 | } 112 | else if ((addr >= io_start) && (addr < (io_start + io_size))) { 113 | //printf("Port read 0x%04X\n", addr); 114 | if ((addr >= ports_start) && (addr <= ports_end)) { 115 | if (product_portread(addr, &ret) == 0) { 116 | ret = ports_read(addr); //only do this if the product's read function didn't give us an overriding value 117 | } 118 | } 119 | else if ((addr >= uart1_start) && (addr <= uart1_end)) { 120 | ret = uart1_read(addr); 121 | } 122 | else if ((addr >= uart3_start) && (addr <= uart3_end)) { 123 | ret = uart3_read(addr); 124 | } 125 | else if ((addr >= tim2_start) && (addr <= tim2_end)) { 126 | ret = tim2_read(addr); 127 | } 128 | else if ((addr >= adc_start) && (addr <= adc_end)) { 129 | ret = adc_read(addr); 130 | } 131 | else if ((addr >= clk_start) && (addr <= clk_end)) { 132 | ret = clk_read(addr); 133 | } 134 | else if ((addr >= iwdg_start) && (addr <= iwdg_end)) { 135 | ret = iwdg_read(addr); 136 | } 137 | else 138 | ret = IO[addr - io_start]; 139 | } 140 | else if ((addr >= cpureg_start) && (addr < (cpureg_start + cpureg_size))) { 141 | ret = memory_cpuregread(addr); 142 | } 143 | /*#ifdef DEBUG_OUTPUT 144 | printf("memory_read(0x%08X) = %02X\n", addr, ret); 145 | #endif*/ 146 | return ret; 147 | } 148 | 149 | uint16_t memory_read16(uint32_t addr) { 150 | uint16_t ret; 151 | ret = ((uint16_t)memory_read(addr) << 8) | (uint16_t)memory_read(addr + 1); 152 | //printf("memory_read16(0x%08X) = %04X\n", addr, ret); 153 | return ret; 154 | } 155 | 156 | uint32_t memory_read24(uint32_t addr) { 157 | uint32_t ret; 158 | ret = ((uint32_t)memory_read(addr) << 16) | ((uint32_t)memory_read(addr + 1) << 8) | (uint32_t)memory_read(addr + 2); 159 | //printf("memory_read24(0x%08X) = %06X\n", addr, ret); 160 | return ret; 161 | } 162 | 163 | void memory_write(uint32_t addr, uint8_t val) { 164 | /*#ifdef DEBUG_OUTPUT 165 | printf("memory_write(0x%08X, 0x%02X)\n", addr, val); 166 | #endif*/ 167 | 168 | /*if ((addr >= 0x14F) && (addr < 0x184)) { 169 | fprintf(stderr, "Addr %08X write <- %02X (%u) @ PC %08X\n", addr, val, val, pc); 170 | }*/ 171 | //ports and registers 172 | 173 | if ((addr >= flash_start) && (addr < (flash_start + flash_size))) { 174 | flash[addr - flash_start] = val; 175 | return; 176 | } 177 | if ((addr >= flash_reg_start) && (addr <= flash_reg_end)) { 178 | if (addr == regaddr[FLASH_IAPSR]) { 179 | IO[regaddr[FLASH_IAPSR] - io_start] = (IO[regaddr[FLASH_IAPSR] - io_start] & ~0x08) | (val & 0x08); 180 | } 181 | else if (addr == regaddr[FLASH_DUKR]) { 182 | //unlock EEPROM writes if correct hardware key pair written to DUKR 183 | if ((IO[regaddr[FLASH_DUKR] - io_start] == 0xAE) && (val == 0x56)) { 184 | IO[regaddr[FLASH_IAPSR] - io_start] |= 0x08; 185 | } 186 | IO[regaddr[FLASH_DUKR] - io_start] = val; 187 | } 188 | } 189 | if ((addr >= ram_start) && (addr < (ram_start + ram_size))) { 190 | RAM[addr - ram_start] = val; 191 | return; 192 | } 193 | if ((addr >= eeprom_start) && (addr < (eeprom_start + eeprom_size))) { 194 | EEPROM[addr - eeprom_start] = val; 195 | return; 196 | } 197 | if ((addr >= io_start) && (addr < (io_start + io_size))) { 198 | IO[addr - io_start] = val; 199 | //printf("Port write %04X <- %02X\n", addr, val); 200 | product_portwrite(addr, val); 201 | 202 | //if ((addr >= ports_start) && (addr <= ports_end)) { 203 | //ports_write(addr, val); 204 | //} 205 | if ((addr >= uart1_start) && (addr <= uart1_end)) { 206 | uart1_write(addr, val); 207 | } 208 | else if ((addr >= uart3_start) && (addr <= uart3_end)) { 209 | uart3_write(addr, val); 210 | } 211 | else if ((addr >= tim2_start) && (addr <= tim2_end)) { 212 | tim2_write(addr, val); 213 | } 214 | else if ((addr >= adc_start) && (addr <= adc_end)) { 215 | adc_write(addr, val); 216 | } 217 | else if ((addr >= clk_start) && (addr <= clk_end)) { 218 | clk_write(addr, val); 219 | } 220 | else if ((addr >= iwdg_start) && (addr <= iwdg_end)) { 221 | iwdg_write(addr, val); 222 | } 223 | return; 224 | } 225 | if ((addr >= cpureg_start) && (addr < (cpureg_start + cpureg_size))) { 226 | memory_cpuregwrite(addr, val); 227 | return; 228 | } 229 | } 230 | 231 | void memory_write16(uint32_t addr, uint16_t val) { 232 | memory_write(addr, (uint8_t)(val >> 8)); 233 | memory_write(addr + 1, (uint8_t)val); 234 | } 235 | 236 | //TODO: Implement memory watch debugging 237 | /*int memory_register_watch(uint32_t addr, uint8_t accesstype) { 238 | return 0; 239 | }*/ 240 | -------------------------------------------------------------------------------- /STM8/memory.h: -------------------------------------------------------------------------------- 1 | #ifndef _MEMORY_H_ 2 | #define _MEMORY_H 3 | 4 | #include 5 | #include "config.h" 6 | #include "cpu.h" 7 | 8 | #define MEMORY_ACCESS_READ 0 9 | #define MEMORY_ACCESS_WRITE 1 10 | #define MEMORY_ACCESS_BOTH 2 11 | 12 | /*typedef struct { 13 | uint32_t addr; 14 | uint8_t accesstype; 15 | } MEMDEBUG_t;*/ 16 | 17 | extern uint8_t *flash; 18 | extern uint8_t *RAM; 19 | extern uint8_t *EEPROM; 20 | extern uint8_t *IO; 21 | extern uint8_t *CPUREG; 22 | 23 | extern uint32_t flash_size, ram_size, eeprom_size, io_size, cpureg_size; 24 | extern uint32_t flash_start, ram_start, eeprom_start, io_start, cpureg_start; 25 | 26 | extern uint32_t stack_top, stack_bottom; 27 | 28 | extern uint32_t ports_start, uart1_start, uart3_start, tim2_start, adc_start, clk_start; 29 | extern uint32_t ports_end, uart1_end, uart3_end, tim2_end, adc_end, clk_end; 30 | 31 | extern uint32_t iwdg_start, flash_reg_start; 32 | extern uint32_t iwdg_end, flash_reg_end; 33 | 34 | extern uint32_t regaddr[REGISTERS_COUNT]; 35 | 36 | uint8_t memory_read(uint32_t addr); 37 | uint16_t memory_read16(uint32_t addr); 38 | uint32_t memory_read24(uint32_t addr); 39 | void memory_write(uint32_t addr, uint8_t val); 40 | void memory_write16(uint32_t addr, uint16_t val); 41 | //int memory_register_watch(uint32_t addr, uint8_t accesstype); 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /STM8/peripherals/adc.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "../config.h" 5 | #include "../cpu.h" 6 | #include "../memory.h" 7 | #include "clk.h" 8 | 9 | //TODO: Implement analog watchdog 10 | 11 | int32_t adc_clocksTotal, adc_clocksRemain; 12 | uint16_t adc_analogVal[16]; 13 | uint8_t adc_curChannel = 0, adc_EOCIE = 0, adc_EOC = 1, adc_continuous = 0, adc_pending = 0; 14 | 15 | void adc_setAnalogVal(uint8_t channel, uint16_t val) { 16 | adc_analogVal[channel & 0x0F] = val & 0x3FF; //10-bit limit 17 | if (channel > 0x0F) { 18 | printf("DEBUG: Attempted to set a value on an ADC channel higher than 15!\n"); 19 | exit(-1); 20 | } 21 | } 22 | 23 | void adc_timerCallback(void) { //This function emulates completion of ADC sampling 24 | uint16_t adcval; 25 | if (IO[regaddr[ADC_CR2] - io_start] & 0x08) //check ADC data alignment bit 26 | adcval = adc_analogVal[adc_curChannel]; //right aligned 27 | else 28 | adcval = adc_analogVal[adc_curChannel] << 6; //left aligned 29 | IO[regaddr[ADC_DRL] - io_start] = (uint8_t)adcval; 30 | IO[regaddr[ADC_DRH] - io_start] = (uint8_t)(adcval >> 8); 31 | adc_EOC = 1; 32 | if (adc_EOCIE) { 33 | cpu_irq(CPU_IRQ_ADC); 34 | } 35 | if (!adc_continuous) { //disable the timer to prevent more conversions if not in continuous mode 36 | adc_pending = 0; 37 | } 38 | } 39 | 40 | void adc_init() { 41 | uint8_t i; 42 | adc_clocksTotal = 28; 43 | adc_pending = 0; 44 | for (i = 0; i < 16; i++) { 45 | adc_analogVal[i] = 0; 46 | } 47 | } 48 | 49 | void adc_clockrun(int32_t clocks) { 50 | if (adc_pending == 0) return; 51 | adc_clocksRemain -= clocks; 52 | if (adc_clocksRemain <= 0) { 53 | adc_timerCallback(); 54 | adc_clocksRemain += adc_clocksTotal; 55 | } 56 | } 57 | 58 | int32_t adc_prescale(void) { 59 | uint8_t pscr; 60 | pscr = (IO[regaddr[ADC_CR1] - io_start] >> 4) & 7; 61 | switch (pscr) { 62 | case 0: return 2; 63 | case 1: return 3; 64 | case 2: return 4; 65 | case 3: return 6; 66 | case 4: return 8; 67 | case 5: return 10; 68 | case 6: return 12; 69 | case 7: return 18; 70 | } 71 | return 2; 72 | } 73 | 74 | void adc_write(uint32_t addr, uint8_t val) { 75 | static uint8_t lastCR1 = 0; 76 | 77 | if (addr == regaddr[ADC_CSR]) { 78 | adc_EOCIE = (val >> 5) & 1; //interrupt enable on EOC 79 | adc_EOC = val >> 7; 80 | } 81 | else if (addr == regaddr[ADC_CR1]) { 82 | if ((val & 0xFE) == (lastCR1 & 0xFE)) { //conversions are only init'd if all highest 7 bits stayed the same 83 | if ((val & 0x01) && !(lastCR1 & 0x01)) { //ADON, initiate a new ADC conversion if set to 1 and was previously 0 84 | adc_curChannel = IO[regaddr[ADC_CSR] - io_start] & 0x0F; 85 | adc_clocksTotal = 14 * adc_prescale(); 86 | adc_clocksRemain = adc_clocksTotal; 87 | adc_pending = 1; 88 | } 89 | } 90 | adc_continuous = (val >> 1) & 1; 91 | lastCR1 = val; 92 | } 93 | } 94 | 95 | uint8_t adc_read(uint32_t addr) { 96 | if (addr == regaddr[ADC_CSR]) 97 | return (IO[regaddr[ADC_CSR] - io_start] & 0x3F) | (adc_EOC << 7); 98 | else 99 | return IO[addr - io_start]; 100 | } 101 | 102 | void adc_loop() { 103 | 104 | } 105 | -------------------------------------------------------------------------------- /STM8/peripherals/adc.h: -------------------------------------------------------------------------------- 1 | #ifndef _ADC_H_ 2 | #define _ADC_H_ 3 | 4 | #include 5 | 6 | void adc_setAnalogVal(uint8_t channel, uint16_t val); 7 | void adc_init(void); 8 | void adc_clockrun(int32_t clocks); 9 | void adc_write(uint32_t addr, uint8_t val); 10 | uint8_t adc_read(uint32_t addr); 11 | void adc_loop(void); 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /STM8/peripherals/clk.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "../memory.h" 4 | #include "../args.h" 5 | #include "../cpu.h" 6 | #include "adc.h" 7 | #include "tim2.h" 8 | #include "uart1.h" 9 | #include "uart3.h" 10 | #include "clk.h" 11 | 12 | int32_t clocksperloop = 10000; 13 | int32_t clk_pscr = 8; 14 | uint8_t clk_cmsr = CLK_CMSR_HSI; 15 | uint8_t clk_gateADC = 0; 16 | uint8_t clk_gateTIM1 = 0; 17 | uint8_t clk_gateTIM2 = 0; 18 | uint8_t clk_gateTIM3 = 0; 19 | uint8_t clk_gateTIM4 = 0; 20 | uint8_t clk_gateTIM5 = 0; 21 | uint8_t clk_gateUART1 = 0; 22 | uint8_t clk_gateUART2 = 0; 23 | uint8_t clk_gateUART3 = 0; 24 | uint8_t clk_gateUART4 = 0; 25 | 26 | uint8_t clk_read(uint32_t addr) { 27 | uint8_t ret; 28 | if (addr == regaddr[CLK_ICKR]) 29 | ret = IO[regaddr[CLK_ICKR] - io_start] | (1 << 4) | (1 << 1); //Always report HSI and LSI as ready 30 | if (addr == regaddr[CLK_ECKR]) 31 | ret = IO[regaddr[CLK_ECKR] - io_start] | (1 << 1); //Always report HSE as ready 32 | if (addr == regaddr[CLK_CMSR]) 33 | ret = clk_cmsr; 34 | else 35 | ret = IO[addr - io_start]; 36 | return ret; 37 | } 38 | 39 | void clk_write(uint32_t addr, uint8_t val) { 40 | static uint8_t lastCLK_SWCR = 0; 41 | if (addr == regaddr[CLK_SWR]) { 42 | if (IO[regaddr[CLK_SWCR] - io_start] & (1 << 1)) { //only change source if SWEN bit set 43 | clk_switchSource(val); 44 | } 45 | } 46 | else if (addr == regaddr[CLK_SWCR]) { 47 | if ((val & (1 << 1)) && !(lastCLK_SWCR & (1 << 1))) { //change source if SWEN bit set and was clear before 48 | clk_switchSource(IO[regaddr[CLK_SWR] - io_start]); 49 | } 50 | lastCLK_SWCR = val; 51 | } 52 | else if (addr == regaddr[CLK_CKDIVR]) { 53 | clk_switchSource(clk_cmsr); 54 | } 55 | } 56 | 57 | void clk_loop(int32_t clocks) { 58 | if (IO[regaddr[CLK_PCKENR1] - io_start] & clk_gateTIM2) 59 | tim2_clockrun(clocks); 60 | if (IO[regaddr[CLK_PCKENR1] - io_start] & clk_gateUART1) 61 | uart1_clockrun(clocks); 62 | if (IO[regaddr[CLK_PCKENR1] - io_start] & clk_gateUART3) 63 | uart3_clockrun(clocks); 64 | if (IO[regaddr[CLK_PCKENR2] - io_start] & clk_gateADC) 65 | adc_clockrun(clocks); 66 | } 67 | 68 | int32_t clk_prescale(uint8_t pscr) { 69 | uint8_t i; 70 | int32_t prescale; 71 | prescale = 1; 72 | for (i = 0; i < pscr; i++) { 73 | prescale *= 2; 74 | } 75 | return prescale; 76 | } 77 | 78 | void clk_switchSource(uint8_t source) { 79 | int32_t speed; 80 | uint8_t pscrreg; 81 | clk_cmsr = source; 82 | switch (source) { 83 | case CLK_CMSR_HSE: 84 | speed = (int32_t)speedarg; 85 | pscrreg = IO[regaddr[CLK_CKDIVR] - io_start] & 7; 86 | //printf("Clock switch to HSE\n"); 87 | break; 88 | case CLK_CMSR_HSI: 89 | speed = 16000000; 90 | pscrreg = (IO[regaddr[CLK_CKDIVR] - io_start] >> 3) & 3; 91 | //printf("Clock switch to HSI\n"); 92 | break; 93 | case CLK_CMSR_LSI: 94 | speed = 128000; 95 | pscrreg = 0; 96 | //printf("Clock switch to LSI\n"); 97 | break; 98 | default: 99 | //printf("DEBUG: Invalid clock source 0x%02X!\n", source); 100 | return; 101 | } 102 | 103 | speed /= clk_prescale(pscrreg); 104 | //printf("Speed: %ld Hz\n", speed); 105 | clocksperloop = speed / 100; 106 | 107 | IO[regaddr[CLK_SWCR] - io_start] |= (1 << 3); //set SWIF bit 108 | if (IO[regaddr[CLK_SWCR] - io_start] & (1 << 2)) //if SWIEN bit set 109 | cpu_irq(CPU_IRQ_CLK); //then fire IRQ 110 | } 111 | 112 | void clk_init() { 113 | IO[regaddr[CLK_ICKR] - io_start] = 0x01; 114 | IO[regaddr[CLK_ECKR] - io_start] = 0x00; 115 | IO[regaddr[CLK_CKDIVR] - io_start] = 0x18; 116 | IO[regaddr[CLK_PCKENR1] - io_start] = 0xFF; 117 | IO[regaddr[CLK_CSSR] - io_start] = 0x00; 118 | IO[regaddr[CLK_CCOR] - io_start] = 0x00; 119 | IO[regaddr[CLK_PCKENR2] - io_start] = 0xFF; 120 | IO[regaddr[CLK_CANCCR] - io_start] = 0x00; 121 | IO[regaddr[CLK_HSITRIMR] - io_start] = 0x00; 122 | clk_switchSource(CLK_CMSR_HSI); 123 | } 124 | -------------------------------------------------------------------------------- /STM8/peripherals/clk.h: -------------------------------------------------------------------------------- 1 | #ifndef _CLK_H_ 2 | #define _CLK_H_ 3 | 4 | #include 5 | 6 | #define CLK_CMSR_HSE 0xB4 7 | #define CLK_CMSR_HSI 0xE1 8 | #define CLK_CMSR_LSI 0xD2 9 | 10 | extern int32_t clocksperloop; 11 | extern uint8_t clk_gateADC; 12 | extern uint8_t clk_gateTIM1; 13 | extern uint8_t clk_gateTIM2; 14 | extern uint8_t clk_gateTIM3; 15 | extern uint8_t clk_gateTIM4; 16 | extern uint8_t clk_gateTIM5; 17 | extern uint8_t clk_gateUART1; 18 | extern uint8_t clk_gateUART2; 19 | extern uint8_t clk_gateUART3; 20 | extern uint8_t clk_gateUART4; 21 | 22 | void clk_init(void); 23 | void clk_loop(int32_t clocks); 24 | int32_t clk_prescale(uint8_t pscr); 25 | uint8_t clk_read(uint32_t addr); 26 | void clk_write(uint32_t addr, uint8_t val); 27 | void clk_switchSource(uint8_t source); 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /STM8/peripherals/iwdg.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "../config.h" 5 | #include "../cpu.h" 6 | #include "../memory.h" 7 | #include "../timing.h" 8 | #include "../args.h" 9 | #include "clk.h" 10 | #include "iwdg.h" 11 | 12 | uint32_t iwdg_timer = 0xFFFFFFFF; 13 | uint8_t iwdg_countdown; 14 | uint8_t iwdg_reload; 15 | uint8_t iwdg_enabled; 16 | 17 | void iwdg_write(uint32_t addr, uint8_t val) { 18 | double pscr = 4; 19 | if (addr == regaddr[IWDG_KR]) { 20 | switch (val) { 21 | case 0xCC: //enable IWDG 22 | if (!disableIWDG) 23 | timing_timerEnable(iwdg_timer); 24 | break; 25 | case 0xAA: //refresh IWDG 26 | iwdg_countdown = iwdg_reload; 27 | break; 28 | } 29 | //printf("IWDG KR <- %02X\n", val); 30 | } 31 | else if (addr == regaddr[IWDG_PR]) { 32 | if (IO[regaddr[IWDG_KR] - io_start] == 0x55) { 33 | switch (val & 7) { 34 | case 0: pscr = 4; break; 35 | case 1: pscr = 8; break; 36 | case 2: pscr = 16; break; 37 | case 3: pscr = 32; break; 38 | case 4: pscr = 64; break; 39 | case 5: pscr = 128; break; 40 | case 6: pscr = 256; break; 41 | case 7: pscr = 256; break; //this one is actually "reserved" in the datasheet 42 | } 43 | timing_updateIntervalFreq(iwdg_timer, 128000 / pscr); 44 | } 45 | //printf("IWDG PR <- %02X\n", val); 46 | } 47 | else if (addr == regaddr[IWDG_RLR]) { 48 | if (IO[regaddr[IWDG_KR] - io_start] == 0x55) { 49 | iwdg_reload = val; 50 | } 51 | //printf("IWDG RLR <- %02X\n", val); 52 | } 53 | } 54 | 55 | uint8_t iwdg_read(uint32_t addr) { 56 | return IO[addr - io_start]; 57 | } 58 | 59 | void iwdg_timerCallback(void* dummy) { 60 | iwdg_countdown--; 61 | //printf("%02X\n", iwdg_countdown); 62 | if (iwdg_countdown == 0) { 63 | if (exitonIWDG) { 64 | printf("\n\n\n\nIndependent watchdog timer (IWDG) reached terminal count. Aborting emulation!\n"); 65 | exit(0); 66 | } 67 | else { 68 | cpu_reset(); 69 | } 70 | } 71 | } 72 | 73 | void iwdg_init() { 74 | iwdg_enabled = 0; 75 | iwdg_countdown = 0xFF; 76 | iwdg_reload = 0xFF; 77 | if (iwdg_timer == 0xFFFFFFFF) { 78 | iwdg_timer = timing_addTimer((void*)iwdg_timerCallback, NULL, 32000, TIMING_DISABLED); 79 | } 80 | else { 81 | timing_updateIntervalFreq(iwdg_timer, 32000); 82 | timing_timerDisable(iwdg_timer); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /STM8/peripherals/iwdg.h: -------------------------------------------------------------------------------- 1 | #ifndef _IWDG_H_ 2 | #define _IWDG_H_ 3 | 4 | #include 5 | 6 | void iwdg_write(uint32_t addr, uint8_t val); 7 | uint8_t iwdg_read(uint32_t addr); 8 | void iwdg_init(); 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /STM8/peripherals/tim2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "../config.h" 5 | #include "../memory.h" 6 | #include "../cpu.h" 7 | #include "clk.h" 8 | 9 | int32_t prescaleratio = 1, prescaleticks = 0; 10 | 11 | void tim2_init() { 12 | uint32_t i; 13 | for (i = tim2_start; i < tim2_end; i++) { 14 | IO[i - io_start] = 0x00; 15 | } 16 | IO[regaddr[TIM2_ARRH] - io_start] = 0xFF; 17 | IO[regaddr[TIM2_ARRL] - io_start] = 0xFF; 18 | prescaleratio = 1; 19 | prescaleticks = 0; 20 | } 21 | 22 | void tim2_overflow() { 23 | //printf("TIM2 overflow\n"); 24 | 25 | if (IO[regaddr[TIM2_CR1] - io_start] & 0x08) { //One-pulse mode, disable counter after overflow 26 | IO[regaddr[TIM2_CR1] - io_start] &= 0xFE; 27 | } 28 | if ((IO[regaddr[TIM2_IER] - io_start] & 0x01)) { //if update interrupt enable, do interrupt... 29 | cpu_irq(CPU_IRQ_TIM2_UPDATE); 30 | } 31 | IO[regaddr[TIM2_SR1] - io_start] |= 0x01; //set UIF flag in status register 1 32 | //counter auto-reload 33 | //IO[regaddr[TIM2_CNTRL] - io_start] = IO[regaddr[TIM2_ARRL] - io_start]; 34 | //IO[regaddr[TIM2_CNTRH] - io_start] = IO[regaddr[TIM2_ARRH] - io_start]; 35 | } 36 | 37 | void tim2_clockrun(int32_t clocks) { 38 | int32_t i; 39 | if ((IO[regaddr[TIM2_CR1] - io_start] & 0x01) == 0x00) return; //don't do anything if counter isn't enabled 40 | 41 | for (i = 0; i < clocks; i++) { 42 | if (++prescaleticks >= prescaleratio) { 43 | if (++IO[regaddr[TIM2_CNTRL] - io_start] == 0) { 44 | /*if (++IO[regaddr[TIM2_CNTRH] - io_start] == 0) { 45 | tim2_overflow(); 46 | }*/ 47 | IO[regaddr[TIM2_CNTRH] - io_start]++; 48 | } 49 | if ((((uint16_t)IO[regaddr[TIM2_CNTRH] - io_start] << 8) | (uint16_t)IO[regaddr[TIM2_CNTRL] - io_start]) == (((uint16_t)IO[regaddr[TIM2_ARRH] - io_start] << 8) | (uint16_t)IO[regaddr[TIM2_ARRL] - io_start])) { 50 | tim2_overflow(); 51 | IO[regaddr[TIM2_CNTRL] - io_start] = 0; 52 | IO[regaddr[TIM2_CNTRH] - io_start] = 0; 53 | } 54 | //printf("%02X%02X\n", IO[regaddr[TIM2_CNTRH] - IO_START], IO[regaddr[TIM2_CNTRL] - IO_START]); 55 | prescaleticks -= prescaleratio; 56 | } 57 | } 58 | } 59 | 60 | void tim2_write(uint32_t addr, uint8_t val) { 61 | //printf("TIM2 write: %08X <- %02X\n", addr, val); 62 | if (addr == regaddr[TIM2_PSCR]) { 63 | val &= 0x0F; 64 | IO[regaddr[TIM2_PSCR] - io_start] = val; 65 | prescaleratio = (int32_t)clk_prescale(val); 66 | //printf("TIM2 prescale: %lu\n", prescaleratio); 67 | } 68 | } 69 | 70 | uint8_t tim2_read(uint32_t addr) { 71 | return IO[addr - io_start]; 72 | } 73 | -------------------------------------------------------------------------------- /STM8/peripherals/tim2.h: -------------------------------------------------------------------------------- 1 | #ifndef _TIM2_H_ 2 | #define _TIM2_H_ 3 | 4 | #include 5 | 6 | void tim2_init(); 7 | void tim2_clockrun(int32_t clocks); 8 | void tim2_write(uint32_t addr, uint8_t val); 9 | uint8_t tim2_read(uint32_t addr); 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /STM8/peripherals/uart1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "../config.h" 4 | #include "../cpu.h" 5 | #include "../memory.h" 6 | #include "../args.h" 7 | #include "../serial.h" 8 | #include "../tcpconsole.h" 9 | #include "clk.h" 10 | #include "uart1.h" 11 | 12 | int32_t uart1_rxClocksRemain = 0, uart1_txClocksRemain = 0, uart1_clocksTotal = 0; 13 | uint32_t uart1_txTimer, uart1_rxTimer; 14 | uint16_t uart1_div = 0, uart1_rxRead = 0, uart1_rxWrite = 0; 15 | uint8_t uart1_rxBuf[1024]; 16 | uint8_t uart1_redirect = UART1_REDIRECT_NULL, uart1_txPending = 0; 17 | double uart1_baud = 0; 18 | 19 | void uart1_rxBufAdd(uint8_t val) { 20 | if ((IO[regaddr[UART1_CR2] - io_start] & 0x04) == 0x00) return; //receiver disabled? exit... 21 | if (((uart1_rxWrite + 1) & 1023) == uart1_rxRead) return; //buffer full, discard byte 22 | uart1_rxBuf[uart1_rxWrite++] = val; 23 | uart1_rxWrite &= 1023; 24 | uart1_rxCallback(); 25 | } 26 | 27 | uint8_t uart1_rxBufGet() { 28 | uint8_t ret; 29 | if (uart1_rxRead == uart1_rxWrite) return 0; //nothing new in the buffer 30 | ret = uart1_rxBuf[uart1_rxRead++]; 31 | uart1_rxRead &= 1023; 32 | return ret; 33 | } 34 | 35 | uint8_t uart1_read(uint32_t addr) { 36 | if (addr == regaddr[UART1_DR]) { 37 | IO[regaddr[UART1_SR] - io_start] &= ~0x20; //clear RXNE bit 38 | return IO[addr - io_start]; 39 | } 40 | else { 41 | return IO[addr - io_start]; 42 | } 43 | } 44 | 45 | void uart1_write(uint32_t addr, uint8_t val) { 46 | uint8_t brr1, brr2; 47 | double speed; 48 | 49 | if (addr == regaddr[UART1_SR]) { 50 | //ignore writes to status register 51 | } 52 | else if (addr == regaddr[UART1_DR]) { 53 | if ((IO[regaddr[UART1_CR2] - io_start] & 0x08) == 0x00) return; //transmitter disabled? exit... 54 | IO[regaddr[UART1_SR] - io_start] &= 0x3F; //TODO: should bit 6 (transmission complete) be cleared here, or only bit 7? (TX data reg empty) 55 | uart1_txPending = 1; 56 | uart1_txClocksRemain = uart1_clocksTotal; 57 | } 58 | else if (addr == regaddr[UART1_BRR1]) { //divider is only changed on writes to BRR1, so BRR2 should be written to first 59 | brr1 = IO[regaddr[UART1_BRR1] - io_start]; 60 | brr2 = IO[regaddr[UART1_BRR2] - io_start]; 61 | speed = (double)clocksperloop * 100; 62 | uart1_div = ((uint16_t)(brr2 & 0xF0) << 8) | ((uint16_t)brr1 << 4) | ((uint16_t)brr2 & 0x0F); 63 | if (uart1_div > 0) { 64 | uart1_baud = ((double)clocksperloop * 100) / (double)uart1_div; 65 | uart1_clocksTotal = (((clocksperloop * 100) * clk_prescale(IO[regaddr[UART1_PSCR] - io_start])) / (int32_t)uart1_baud) * 10; 66 | } 67 | else { 68 | uart1_baud = 0; 69 | } 70 | //printf("UART1 baud rate: %f\n", uart1_baud); 71 | } 72 | else { 73 | IO[addr - io_start] = val; 74 | } 75 | } 76 | 77 | void uart1_txCallback(void) { 78 | switch (uart1_redirect) { 79 | case UART1_REDIRECT_NULL: 80 | break; 81 | case UART1_REDIRECT_CONSOLE: 82 | printf("%c", IO[regaddr[UART1_DR] - io_start]); 83 | fflush(stdout); 84 | break; 85 | case UART1_REDIRECT_SERIAL: 86 | serial_write(0, (char*)(&IO[regaddr[UART1_DR] - io_start])); 87 | break; 88 | case UART1_REDIRECT_TCP: 89 | tcpconsole_send(0, IO[regaddr[UART1_DR] - io_start]); 90 | break; 91 | } 92 | 93 | IO[regaddr[UART1_SR] - io_start] |= 0xC0; //set TXE and TC bits to indicate transmit "circuit" is ready for more data 94 | if (IO[regaddr[UART1_CR2] - io_start] & 0xC0) //TIEN or TCIEN set 95 | cpu_irq(CPU_IRQ_UART1_TX); 96 | uart1_txPending = 0; 97 | } 98 | 99 | void uart1_rxCallback(void) { 100 | double speed; 101 | 102 | //Recalculate timing interval again, in case our master clock source or prescaler has changed 103 | speed = (double)clocksperloop * 100; 104 | if (uart1_div > 0) { 105 | uart1_baud = speed / (double)uart1_div; 106 | uart1_clocksTotal = (((clocksperloop * 100) * clk_prescale(IO[regaddr[UART1_PSCR] - io_start])) / (int32_t)uart1_baud) * 10; 107 | } 108 | 109 | if (uart1_rxRead == uart1_rxWrite) return; //nothing new in the buffer 110 | 111 | IO[regaddr[UART1_DR] - io_start] = uart1_rxBufGet(); 112 | IO[regaddr[UART1_SR] - io_start] |= 0x20; //set RXNE bit 113 | if (IO[regaddr[UART1_CR2] - io_start] & 0x20) //RIEN set 114 | cpu_irq(CPU_IRQ_UART1_RX); 115 | } 116 | 117 | void uart1_clockrun(int32_t clocks) { 118 | if (uart1_rxClocksRemain > 0) { 119 | uart1_rxClocksRemain -= (int32_t)clocks; 120 | if (uart1_rxClocksRemain <= 0) { 121 | uart1_rxCallback(); 122 | uart1_rxClocksRemain += uart1_clocksTotal; 123 | } 124 | } 125 | 126 | if (uart1_txPending) { 127 | if (uart1_txClocksRemain > 0) { 128 | uart1_txClocksRemain -= (int32_t)clocks; 129 | if (uart1_txClocksRemain <= 0) { 130 | uart1_txCallback(); 131 | uart1_txClocksRemain += uart1_clocksTotal; 132 | uart1_txPending = 0; 133 | } 134 | } 135 | } 136 | } 137 | 138 | void uart1_init() { 139 | IO[regaddr[UART1_SR] - io_start] = 0xC0; 140 | IO[regaddr[UART1_DR] - io_start] = 0x00; 141 | IO[regaddr[UART1_BRR1] - io_start] = 0x00; 142 | IO[regaddr[UART1_BRR2] - io_start] = 0x00; 143 | IO[regaddr[UART1_CR1] - io_start] = 0x00; 144 | IO[regaddr[UART1_CR2] - io_start] = 0x00; 145 | IO[regaddr[UART1_CR3] - io_start] = 0x00; 146 | IO[regaddr[UART1_CR4] - io_start] = 0x00; 147 | IO[regaddr[UART1_CR5] - io_start] = 0x00; 148 | IO[regaddr[UART1_GTR] - io_start] = 0x00; 149 | IO[regaddr[UART1_PSCR] - io_start] = 0x00; 150 | 151 | uart1_clocksTotal = ((clocksperloop * 100) / 9600) * 10; 152 | uart1_rxClocksRemain = uart1_clocksTotal; 153 | uart1_txClocksRemain = 0; 154 | } 155 | -------------------------------------------------------------------------------- /STM8/peripherals/uart1.h: -------------------------------------------------------------------------------- 1 | #ifndef _UART1_H_ 2 | #define _UART1_H_ 3 | 4 | #include 5 | 6 | #define UART1_REDIRECT_NULL 0 7 | #define UART1_REDIRECT_CONSOLE 1 8 | #define UART1_REDIRECT_SERIAL 2 9 | #define UART1_REDIRECT_TCP 3 10 | 11 | extern uint8_t uart1_redirect; 12 | 13 | uint8_t uart1_read(uint32_t addr); 14 | void uart1_write(uint32_t addr, uint8_t val); 15 | void uart1_rxBufAdd(uint8_t val); 16 | uint8_t uart1_rxBufGet(void); 17 | void uart1_txCallback(void); 18 | void uart1_rxCallback(void); 19 | void uart1_clockrun(int32_t clocks); 20 | void uart1_init(); 21 | 22 | #endif 23 | 24 | -------------------------------------------------------------------------------- /STM8/peripherals/uart3.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "../config.h" 4 | #include "../cpu.h" 5 | #include "../memory.h" 6 | #include "../args.h" 7 | #include "../serial.h" 8 | #include "../tcpconsole.h" 9 | #include "clk.h" 10 | #include "uart3.h" 11 | 12 | int32_t uart3_rxClocksRemain = 0, uart3_txClocksRemain = 0, uart3_clocksTotal = 0; 13 | uint32_t uart3_txTimer, uart3_rxTimer; 14 | uint16_t uart3_div = 0, uart3_rxRead = 0, uart3_rxWrite = 0; 15 | uint8_t uart3_rxBuf[1024]; 16 | uint8_t uart3_redirect = UART3_REDIRECT_NULL, uart3_txPending = 0; 17 | double uart3_baud = 0; 18 | 19 | void uart3_rxBufAdd(uint8_t val) { 20 | if ((IO[regaddr[UART3_CR2] - io_start] & 0x04) == 0x00) return; //receiver disabled? exit... 21 | if (((uart3_rxWrite + 1) & 1023) == uart3_rxRead) return; //buffer full, discard byte 22 | uart3_rxBuf[uart3_rxWrite++] = val; 23 | uart3_rxWrite &= 1023; 24 | uart3_rxCallback(); 25 | } 26 | 27 | uint8_t uart3_rxBufGet() { 28 | uint8_t ret; 29 | if (uart3_rxRead == uart3_rxWrite) return 0; //nothing new in the buffer 30 | ret = uart3_rxBuf[uart3_rxRead++]; 31 | uart3_rxRead &= 1023; 32 | return ret; 33 | } 34 | 35 | uint8_t uart3_read(uint32_t addr) { 36 | if (addr == regaddr[UART3_DR]) { 37 | IO[regaddr[UART3_SR] - io_start] &= ~0x20; //clear RXNE bit 38 | return IO[addr - io_start]; 39 | } 40 | else { 41 | return IO[addr - io_start]; 42 | } 43 | } 44 | 45 | void uart3_write(uint32_t addr, uint8_t val) { 46 | uint8_t brr1, brr2; 47 | double speed; 48 | 49 | if (addr == regaddr[UART3_SR]) { 50 | //ignore writes to status register 51 | } 52 | else if (addr == regaddr[UART3_DR]) { 53 | if ((IO[regaddr[UART3_CR2] - io_start] & 0x08) == 0x00) return; //transmitter disabled? exit... 54 | IO[regaddr[UART3_SR] - io_start] &= 0x3F; //TODO: should bit 6 (transmission complete) be cleared here, or only bit 7? (TX data reg empty) 55 | uart3_txPending = 1; 56 | uart3_txClocksRemain = uart3_clocksTotal; 57 | } 58 | else if (addr == regaddr[UART3_BRR1]) { //divider is only changed on writes to BRR1, so BRR2 should be written to first 59 | brr1 = IO[regaddr[UART3_BRR1] - io_start]; 60 | brr2 = IO[regaddr[UART3_BRR2] - io_start]; 61 | speed = (double)clocksperloop * 100; 62 | uart3_div = ((uint16_t)(brr2 & 0xF0) << 8) | ((uint16_t)brr1 << 4) | ((uint16_t)brr2 & 0x0F); 63 | if (uart3_div > 0) { 64 | uart3_baud = ((double)clocksperloop * 100) / (double)uart3_div; 65 | uart3_clocksTotal = ((clocksperloop * 100) / (int32_t)uart3_baud) * 10; 66 | } 67 | else { 68 | uart3_baud = 0; 69 | } 70 | //printf("UART3 baud rate: %f\n", uart3_baud); 71 | } 72 | else { 73 | IO[addr - io_start] = val; 74 | } 75 | } 76 | 77 | void uart3_txCallback(void) { 78 | switch (uart3_redirect) { 79 | case UART3_REDIRECT_NULL: 80 | break; 81 | case UART3_REDIRECT_CONSOLE: 82 | printf("%c", IO[regaddr[UART3_DR] - io_start]); 83 | fflush(stdout); 84 | break; 85 | case UART3_REDIRECT_SERIAL: 86 | serial_write(2, (char*)(&IO[regaddr[UART3_DR] - io_start])); 87 | break; 88 | case UART3_REDIRECT_TCP: 89 | tcpconsole_send(2, IO[regaddr[UART3_DR] - io_start]); 90 | break; 91 | } 92 | 93 | IO[regaddr[UART3_SR] - io_start] |= 0xC0; //set TXE and TC bits to indicate transmit "circuit" is ready for more data 94 | if (IO[regaddr[UART3_CR2] - io_start] & 0xC0) //TIEN or TCIEN set 95 | cpu_irq(CPU_IRQ_UART3_TX); 96 | uart3_txPending = 0; 97 | } 98 | 99 | void uart3_rxCallback(void) { 100 | double speed; 101 | 102 | //Recalculate timing interval again, in case our master clock source or prescaler has changed 103 | speed = (double)clocksperloop * 100; 104 | if (uart3_div > 0) { 105 | uart3_baud = speed / (double)uart3_div; 106 | uart3_clocksTotal = ((clocksperloop * 100) / (int32_t)uart3_baud) * 10; 107 | } 108 | 109 | if (uart3_rxRead == uart3_rxWrite) return; //nothing new in the buffer 110 | 111 | IO[regaddr[UART3_DR] - io_start] = uart3_rxBufGet(); 112 | IO[regaddr[UART3_SR] - io_start] |= 0x20; //set RXNE bit 113 | if (IO[regaddr[UART3_CR2] - io_start] & 0x20) //RIEN set 114 | cpu_irq(CPU_IRQ_UART3_RX); 115 | } 116 | 117 | void uart3_clockrun(int32_t clocks) { 118 | if (uart3_rxClocksRemain > 0) { 119 | uart3_rxClocksRemain -= (int32_t)clocks; 120 | if (uart3_rxClocksRemain <= 0) { 121 | uart3_rxCallback(); 122 | uart3_rxClocksRemain += uart3_clocksTotal; 123 | } 124 | } 125 | 126 | if (uart3_txPending) { 127 | if (uart3_txClocksRemain > 0) { 128 | uart3_txClocksRemain -= (int32_t)clocks; 129 | if (uart3_txClocksRemain <= 0) { 130 | uart3_txCallback(); 131 | uart3_txClocksRemain += uart3_clocksTotal; 132 | uart3_txPending = 0; 133 | } 134 | } 135 | } 136 | } 137 | 138 | void uart3_init() { 139 | IO[regaddr[UART3_SR] - io_start] = 0xC0; 140 | IO[regaddr[UART3_DR] - io_start] = 0x00; 141 | IO[regaddr[UART3_BRR1] - io_start] = 0x00; 142 | IO[regaddr[UART3_BRR2] - io_start] = 0x00; 143 | IO[regaddr[UART3_CR1] - io_start] = 0x00; 144 | IO[regaddr[UART3_CR2] - io_start] = 0x00; 145 | IO[regaddr[UART3_CR3] - io_start] = 0x00; 146 | IO[regaddr[UART3_CR4] - io_start] = 0x00; 147 | IO[regaddr[UART3_CR6] - io_start] = 0x00; 148 | 149 | uart3_clocksTotal = ((clocksperloop * 100) / 9600) * 10; 150 | uart3_rxClocksRemain = uart3_clocksTotal; 151 | uart3_txClocksRemain = 0; 152 | } 153 | -------------------------------------------------------------------------------- /STM8/peripherals/uart3.h: -------------------------------------------------------------------------------- 1 | #ifndef _UART3_H_ 2 | #define _UART3_H_ 3 | 4 | #include 5 | 6 | #define UART3_REDIRECT_NULL 0 7 | #define UART3_REDIRECT_CONSOLE 1 8 | #define UART3_REDIRECT_SERIAL 2 9 | #define UART3_REDIRECT_TCP 3 10 | 11 | extern uint8_t uart3_redirect; 12 | 13 | uint8_t uart3_read(uint32_t addr); 14 | void uart3_write(uint32_t addr, uint8_t val); 15 | void uart3_rxBufAdd(uint8_t val); 16 | uint8_t uart3_rxBufGet(void); 17 | void uart3_txCallback(void); 18 | void uart3_rxCallback(void); 19 | void uart3_clockrun(int32_t clocks); 20 | void uart3_init(); 21 | 22 | #endif 23 | 24 | -------------------------------------------------------------------------------- /STM8/ports.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "config.h" 4 | #include "memory.h" 5 | #include "hardware/casil.h" 6 | #include "display.h" 7 | #include "cpu.h" 8 | 9 | uint8_t use_PA = 0; 10 | uint8_t use_PB = 0; 11 | uint8_t use_PC = 0; 12 | uint8_t use_PD = 0; 13 | uint8_t use_PE = 0; 14 | uint8_t use_PF = 0; 15 | uint8_t use_PG = 0; 16 | uint8_t use_PH = 0; 17 | uint8_t use_PI = 0; 18 | 19 | void ports_init() { 20 | uint32_t i; 21 | for (i = ports_start; i <= ports_end; i++) { 22 | IO[i - io_start] = 0; 23 | } 24 | } 25 | 26 | uint8_t ports_read(uint32_t addr) { 27 | uint8_t ret; 28 | 29 | if ((addr == regaddr[PA_IDR]) && (use_PA)) 30 | ret = (IO[regaddr[PA_DDR] - io_start] & IO[regaddr[PA_ODR] - io_start]) | (~IO[regaddr[PA_DDR] - io_start] & IO[regaddr[PA_IDR] - io_start]); 31 | else if ((addr == regaddr[PB_IDR]) && (use_PB)) 32 | ret = (IO[regaddr[PB_DDR] - io_start] & IO[regaddr[PB_ODR] - io_start]) | (~IO[regaddr[PB_DDR] - io_start] & IO[regaddr[PB_IDR] - io_start]); 33 | else if ((addr == regaddr[PC_IDR]) && (use_PC)) 34 | ret = (IO[regaddr[PC_DDR] - io_start] & IO[regaddr[PC_ODR] - io_start]) | (~IO[regaddr[PC_DDR] - io_start] & IO[regaddr[PC_IDR] - io_start]); 35 | else if ((addr == regaddr[PD_IDR]) && (use_PD)) 36 | ret = (IO[regaddr[PD_DDR] - io_start] & IO[regaddr[PD_ODR] - io_start]) | (~IO[regaddr[PD_DDR] - io_start] & IO[regaddr[PD_IDR] - io_start]); 37 | else if ((addr == regaddr[PE_IDR]) && (use_PE)) 38 | ret = (IO[regaddr[PE_DDR] - io_start] & IO[regaddr[PE_ODR] - io_start]) | (~IO[regaddr[PE_DDR] - io_start] & IO[regaddr[PE_IDR] - io_start]); 39 | else if ((addr == regaddr[PF_IDR]) && (use_PF)) 40 | ret = (IO[regaddr[PF_DDR] - io_start] & IO[regaddr[PF_ODR] - io_start]) | (~IO[regaddr[PF_DDR] - io_start] & IO[regaddr[PF_IDR] - io_start]); 41 | else if ((addr == regaddr[PG_IDR]) && (use_PG)) 42 | ret = (IO[regaddr[PG_DDR] - io_start] & IO[regaddr[PG_ODR] - io_start]) | (~IO[regaddr[PG_DDR] - io_start] & IO[regaddr[PG_IDR] - io_start]); 43 | else if ((addr == regaddr[PH_IDR]) && (use_PH)) 44 | ret = (IO[regaddr[PH_DDR] - io_start] & IO[regaddr[PH_ODR] - io_start]) | (~IO[regaddr[PH_DDR] - io_start] & IO[regaddr[PH_IDR] - io_start]); 45 | else if ((addr == regaddr[PI_IDR]) && (use_PI)) 46 | ret = (IO[regaddr[PI_DDR] - io_start] & IO[regaddr[PI_ODR] - io_start]) | (~IO[regaddr[PI_DDR] - io_start] & IO[regaddr[PI_IDR] - io_start]); 47 | else 48 | ret = IO[addr - io_start]; 49 | 50 | return ret; 51 | } 52 | 53 | /*void ports_write(uint32_t addr, uint8_t val) { 54 | static uint8_t lastPB_ODR = 0x00; 55 | IO[addr - IO_START] = val; 56 | 57 | switch (addr) { 58 | case PB_ODR: 59 | if (val != lastPB_ODR) { 60 | PRODUCT_MARKFORUPDATE(); 61 | } 62 | lastPB_ODR = val; 63 | break; 64 | case PE_ODR: 65 | casil_en(val & 1); 66 | casil_rs((val >> 1) & 1); 67 | casil_rw((val >> 2) & 1); 68 | break; 69 | case PC_ODR: 70 | casil_latchwrite(((val >> 1) & 7) | ((val & 0x20) >> 2)); 71 | break; 72 | } 73 | }*/ 74 | 75 | void ports_extmodify(uint32_t addr, uint8_t val) { 76 | uint8_t extisens = 0, i, oldval, newval; 77 | 78 | if (addr == regaddr[PC_IDR]) { 79 | newval = val & IO[regaddr[PC_DDR] - io_start] & IO[regaddr[PC_CR2] - io_start]; 80 | extisens = (IO[regaddr[EXTI_CR1] - io_start] >> 4) & 3; 81 | oldval = IO[regaddr[PC_IDR] - io_start] & IO[regaddr[PC_DDR] - io_start] & IO[regaddr[PC_CR2] - io_start]; 82 | for (i = 0; i < 8; i++) { 83 | if ((newval & (1 << i)) != (oldval & (1 << i))) { 84 | switch (extisens) { 85 | case 0: //falling edge and low level 86 | if ((newval & (1 << i)) == 0) 87 | cpu_irq(CPU_IRQ_EXTI2); 88 | break; 89 | case 1: //rising edge only 90 | if (newval & (1 << i)) 91 | cpu_irq(CPU_IRQ_EXTI2); 92 | break; 93 | case 2: //falling edge only 94 | if ((newval & (1 << i)) == 0) 95 | cpu_irq(CPU_IRQ_EXTI2); 96 | break; 97 | case 3: //rising and falling edge 98 | cpu_irq(CPU_IRQ_EXTI2); 99 | break; 100 | } 101 | } 102 | } 103 | IO[regaddr[PC_IDR] - io_start] = val; 104 | } 105 | 106 | if (addr == regaddr[PD_IDR]) { 107 | newval = val; // &IO[regaddr[PD_DDR] - io_start] & IO[regaddr[PD_CR2] - io_start]; 108 | extisens = (IO[regaddr[EXTI_CR1] - io_start] >> 6) & 3; 109 | oldval = IO[regaddr[PD_IDR] - io_start] & IO[regaddr[PD_DDR] - io_start] & IO[regaddr[PD_CR2] - io_start]; 110 | for (i = 0; i < 8; i++) { 111 | if ((newval & (1 << i)) != (oldval & (1 << i))) { 112 | switch (extisens) { 113 | case 0: //falling edge and low level 114 | if ((newval & (1 << i)) == 0) 115 | cpu_irq(CPU_IRQ_EXTI3); 116 | break; 117 | case 1: //rising edge only 118 | if (newval & (1 << i)) 119 | cpu_irq(CPU_IRQ_EXTI3); 120 | break; 121 | case 2: //falling edge only 122 | if ((newval & (1 << i)) == 0) 123 | cpu_irq(CPU_IRQ_EXTI3); 124 | break; 125 | case 3: //rising and falling edge 126 | cpu_irq(CPU_IRQ_EXTI3); 127 | break; 128 | } 129 | } 130 | } 131 | IO[regaddr[PD_IDR] - io_start] = val; 132 | } 133 | 134 | if (addr == regaddr[PE_IDR]) { 135 | newval = val; // &IO[regaddr[PE_DDR] - io_start] & IO[regaddr[PE_CR2] - io_start]; 136 | extisens = IO[regaddr[EXTI_CR2] - io_start] & 3; 137 | oldval = IO[regaddr[PE_IDR] - io_start] & IO[regaddr[PE_DDR] - io_start] & IO[regaddr[PE_CR2] - io_start]; 138 | for (i = 0; i < 8; i++) { 139 | if ((newval & (1 << i)) != (oldval & (1 << i))) { 140 | switch (extisens) { 141 | case 0: //falling edge and low level 142 | if ((newval & (1 << i)) == 0) 143 | cpu_irq(CPU_IRQ_EXTI4); 144 | break; 145 | case 1: //rising edge only 146 | if (newval & (1 << i)) 147 | cpu_irq(CPU_IRQ_EXTI4); 148 | break; 149 | case 2: //falling edge only 150 | if ((newval & (1 << i)) == 0) 151 | cpu_irq(CPU_IRQ_EXTI4); 152 | break; 153 | case 3: //rising and falling edge 154 | cpu_irq(CPU_IRQ_EXTI4); 155 | break; 156 | } 157 | } 158 | } 159 | IO[regaddr[PE_IDR] - io_start] = val; 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /STM8/ports.h: -------------------------------------------------------------------------------- 1 | #ifndef _PORTS_H_ 2 | #define _PORTS_H_ 3 | 4 | #include 5 | 6 | extern uint8_t use_PA; 7 | extern uint8_t use_PB; 8 | extern uint8_t use_PC; 9 | extern uint8_t use_PD; 10 | extern uint8_t use_PE; 11 | extern uint8_t use_PF; 12 | extern uint8_t use_PG; 13 | extern uint8_t use_PH; 14 | extern uint8_t use_PI; 15 | 16 | void ports_init(); 17 | uint8_t ports_read(uint32_t addr); 18 | void ports_write(uint32_t addr, uint8_t val); 19 | void ports_extmodify(uint32_t addr, uint8_t val); 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /STM8/products/null.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "../args.h" 6 | #include "../cpu.h" 7 | #include "../peripherals/uart1.h" 8 | #include "../peripherals/uart3.h" 9 | 10 | void null_register() { 11 | if (overridecpu == 0) { 12 | printf("CPU must be explicitly specified if using null product. Use -h for help.\r\n"); 13 | exit(-1); 14 | } 15 | } 16 | 17 | void null_init() { 18 | } 19 | 20 | void null_update() { 21 | } 22 | 23 | void null_portwrite(uint32_t addr, uint8_t val) { 24 | } 25 | 26 | uint8_t null_portread(uint32_t addr) { 27 | return 0; 28 | } 29 | 30 | void null_markforupdate() { 31 | } 32 | 33 | void null_loop() { 34 | uint8_t cc, gotkey; 35 | gotkey = 0; 36 | if (_kbhit()) { 37 | cc = _getch(); 38 | if (cc == 27) { 39 | running = 0; 40 | } 41 | else { 42 | gotkey = 1; 43 | } 44 | } 45 | 46 | if ((uart1_redirect == UART1_REDIRECT_CONSOLE) && gotkey) { 47 | uart1_rxBufAdd(cc); 48 | } 49 | 50 | if ((uart3_redirect == UART3_REDIRECT_CONSOLE) && gotkey) { 51 | uart3_rxBufAdd(cc); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /STM8/products/null.h: -------------------------------------------------------------------------------- 1 | #ifndef _NULL_H_ 2 | #define _NULL_H_ 3 | 4 | #include 5 | 6 | void null_register(void); 7 | void null_init(void); 8 | void null_update(void); 9 | void null_portwrite(uint32_t addr, uint8_t val); 10 | uint8_t null_portread(uint32_t addr); 11 | void null_markforupdate(void); 12 | void null_loop(void); 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /STM8/serial.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "peripherals/uart1.h" 5 | #include "peripherals/uart3.h" 6 | 7 | HANDLE serial_hComm[3] = { 8 | INVALID_HANDLE_VALUE, 9 | INVALID_HANDLE_VALUE, 10 | INVALID_HANDLE_VALUE 11 | }; 12 | 13 | int serial_init(int uart, int comnum, int baud) { 14 | DCB dcb; 15 | char dcbstr[16]; 16 | char comport[16]; 17 | 18 | sprintf(comport, "COM%d", comnum); 19 | serial_hComm[uart] = CreateFileA(comport, 20 | GENERIC_READ | GENERIC_WRITE, 21 | 0, 22 | 0, 23 | OPEN_EXISTING, 24 | FILE_FLAG_OVERLAPPED, 25 | 0); 26 | if (serial_hComm[uart] == INVALID_HANDLE_VALUE) 27 | return -1; 28 | 29 | if (!GetCommState(serial_hComm[uart], &dcb)) 30 | return -1; 31 | 32 | FillMemory(&dcb, sizeof(dcb), 0); 33 | dcb.DCBlength = sizeof(dcb); 34 | sprintf(dcbstr, "%d,n,8,1", baud); 35 | if (!BuildCommDCBA(dcbstr, &dcb)) 36 | return -1; 37 | 38 | if (!SetCommState(serial_hComm[uart], &dcb)) 39 | return -1; 40 | 41 | return 0; 42 | } 43 | 44 | int serial_read(int uart, char* dst) { 45 | DWORD didread = 0; 46 | OVERLAPPED osReader = { 0 }; 47 | 48 | if (serial_hComm[uart] == INVALID_HANDLE_VALUE) return -1; 49 | 50 | if (!ReadFile(serial_hComm[uart], dst, 1, &didread, &osReader)) 51 | return -1; 52 | if (didread != 1) 53 | return -1; 54 | 55 | return 0; 56 | } 57 | 58 | void serial_write(int uart, char* src) { 59 | DWORD didwrite = 0; 60 | OVERLAPPED osWriter = { 0 }; 61 | DWORD dwRes; 62 | BOOL fRes; 63 | 64 | if (serial_hComm[uart] == INVALID_HANDLE_VALUE) return; 65 | 66 | osWriter.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); 67 | if (osWriter.hEvent == NULL) 68 | // error creating overlapped event handle 69 | return; 70 | 71 | // Issue write. 72 | if (!WriteFile(serial_hComm[uart], src, 1, &didwrite, &osWriter)) { 73 | if (GetLastError() != ERROR_IO_PENDING) { 74 | // WriteFile failed, but isn't delayed. Report error and abort. 75 | fRes = FALSE; 76 | } 77 | else 78 | // Write is pending. 79 | dwRes = WaitForSingleObject(osWriter.hEvent, INFINITE); 80 | switch (dwRes) { 81 | // OVERLAPPED structure's event has been signaled. 82 | case WAIT_OBJECT_0: 83 | if (!GetOverlappedResult(serial_hComm[uart], &osWriter, &didwrite, FALSE)) 84 | fRes = FALSE; 85 | else 86 | // Write operation completed successfully. 87 | fRes = TRUE; 88 | break; 89 | 90 | default: 91 | // An error has occurred in WaitForSingleObject. 92 | // This usually indicates a problem with the 93 | // OVERLAPPED structure's event handle. 94 | fRes = FALSE; 95 | break; 96 | } 97 | } 98 | else 99 | // WriteFile completed immediately. 100 | fRes = TRUE; 101 | 102 | CloseHandle(osWriter.hEvent); 103 | } 104 | 105 | void serial_loop() { 106 | char newbuf; 107 | 108 | if (uart1_redirect == UART1_REDIRECT_SERIAL) { 109 | if (serial_read(0, &newbuf) == 0) { 110 | uart1_rxBufAdd((uint8_t)newbuf); 111 | } 112 | } 113 | 114 | if (uart3_redirect == UART3_REDIRECT_SERIAL) { 115 | if (serial_read(2, &newbuf) == 0) { 116 | uart3_rxBufAdd((uint8_t)newbuf); 117 | } 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /STM8/serial.h: -------------------------------------------------------------------------------- 1 | #ifndef _SERIAL_H_ 2 | #define _SERIAL_H_ 3 | 4 | #include 5 | 6 | int serial_init(int uart, int comnum, int baud); 7 | int serial_read(int uart, char* dst); 8 | void serial_write(int uart, char* src); 9 | void serial_loop(void); 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /STM8/srec.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "memory.h" 8 | #include "endian.h" 9 | #include "srec.h" 10 | 11 | // #define SREC_DETAIL 12 | 13 | // Nominal max length in characters of a record is 514 (excluding line breaks 14 | // and terminating null). 15 | #define LINE_MAX_LEN 520 16 | 17 | // Minimum posible line length in characters is 16-bit termination record: 18 | // 2 digit start/type + 2 digit byte count + 4 digit addr + 2 digit checksum. 19 | #define LINE_MIN_LEN 10 20 | 21 | // Maximum specifyable byte count in a record is 255, so max record length in 22 | // bytes is that plus size of other fields (type, count, 32-bit addr, checksum). 23 | #define REC_MAX_LEN 262 24 | 25 | #define REC_OFFSET_TYPE 0 26 | #define REC_OFFSET_BYTE_COUNT 1 27 | #define REC_OFFSET_ADDR 2 28 | #define REC_OFFSET_DATA_S1 4 29 | #define REC_OFFSET_DATA_S2 5 30 | #define REC_OFFSET_DATA_S3 6 31 | 32 | // Amount by which the byte count field is greater than the actual number of 33 | // data bytes (i.e. minus address and checksum field lengths). 34 | #define REC_COUNT_EXCESS_S1 3 35 | #define REC_COUNT_EXCESS_S2 4 36 | #define REC_COUNT_EXCESS_S3 5 37 | 38 | #define REC_TYPE_S0_HEADER 0x0 39 | #define REC_TYPE_S1_DATA 0x1 40 | #define REC_TYPE_S2_DATA 0x2 41 | #define REC_TYPE_S3_DATA 0x3 42 | #define REC_TYPE_S5_COUNT 0x5 43 | #define REC_TYPE_S6_COUNT 0x6 44 | #define REC_TYPE_S7_TERM 0x7 45 | #define REC_TYPE_S8_TERM 0x8 46 | #define REC_TYPE_S9_TERM 0x9 47 | 48 | static uint8_t srec_convert_hex_char(char c) { 49 | c = toupper(c); 50 | if(isdigit(c)) { 51 | return c - '0'; 52 | } else { 53 | return c - ('A' - 10); 54 | } 55 | } 56 | 57 | static size_t srec_decode_record(char* line, size_t line_len, uint8_t* buf, size_t buf_len) { 58 | size_t rec_len = 0; 59 | uint8_t val; 60 | 61 | // Check first character of line is start code (uppercase 'S'). If so, substitute it 62 | // for a zero digit, so that the initial pair can be parsed below with general hex 63 | // pair handling. 64 | if(line_len > 0 && *line == 'S') { 65 | *line = '0'; 66 | } else { 67 | return 0; 68 | } 69 | 70 | while(line_len > 0) { 71 | if(isxdigit(*line) && isxdigit(*(line + 1))) { 72 | // Convert pair of hex digit characters into byte value. 73 | val = (srec_convert_hex_char(*line) << 4) | srec_convert_hex_char(*(line + 1)); 74 | line += 2; 75 | line_len -= 2; 76 | 77 | // Add byte value to output buffer (if room). 78 | if(buf_len > 0) { 79 | *buf++ = val; 80 | buf_len--; 81 | rec_len++; 82 | } else { 83 | break; 84 | } 85 | } else if(*line == '\n' || *line == '\r') { 86 | // Skip any trailing line-break characters. 87 | line++; 88 | line_len--; 89 | } else { 90 | // Otherwise, an invalid character, exit with failure. 91 | return 0; 92 | } 93 | } 94 | 95 | return rec_len; 96 | } 97 | 98 | int srec_load(const char* path) { 99 | FILE* srec; 100 | char line[LINE_MAX_LEN]; 101 | unsigned int line_count = 0, mem_addr; 102 | uint8_t record[REC_MAX_LEN], checksum; 103 | size_t line_len, record_len; 104 | bool end = false; 105 | 106 | // Open the file in text mode (so CRLF line endings are automatically converted to LF). 107 | srec = fopen(path, "r"); 108 | if(srec == NULL) { 109 | return -1; 110 | } 111 | 112 | do { 113 | memset(line, '\0', sizeof(line)); 114 | 115 | if(fgets(line, sizeof(line) / sizeof(line[0]), srec) != NULL) { 116 | line_count++; 117 | line_len = strlen(line); 118 | 119 | // Remove any trailing line feed character from line string. 120 | if(line[line_len - 1] == '\n') { 121 | line[line_len - 1] = '\0'; 122 | line_len--; 123 | } 124 | 125 | // Check for minimum line length. 126 | if(line_len < LINE_MIN_LEN) { 127 | printf("Invalid line %u of SREC file; incomplete record, not enough characters.\n", line_count); 128 | return -1; 129 | } 130 | 131 | #ifdef SREC_DETAIL 132 | printf("Line %u: \"%s\" (%zu chars)\n", line_count, line, line_len); 133 | #endif 134 | 135 | // Decode the line into a record. 136 | record_len = srec_decode_record(line, line_len, record, sizeof(record)); 137 | if(record_len == 0) { 138 | printf("Invalid line %u of SREC file; error parsing hex digits.\n", line_count); 139 | return -1; 140 | } 141 | 142 | // Verify that record length and byte count field correlate. Count field also 143 | // includes address and checksum fields. 144 | if((size_t)record[REC_OFFSET_BYTE_COUNT] + 2 != record_len) { 145 | printf("Invalid line %u of SREC file; byte count field value does not correlate with record length.\n", line_count); 146 | return -1; 147 | } 148 | 149 | // Calculate the record's checksum. Sum all record bytes between type and checksum, take the 150 | // LSB of the sum, then calculate one's complement of it (i.e. invert bits). 151 | checksum = 0; 152 | for(size_t i = 1; i < record_len - 1; i++) { 153 | checksum += record[i]; 154 | } 155 | checksum = ~checksum; 156 | 157 | #ifdef SREC_DETAIL 158 | printf("Checksum: Record = 0x%02X, Calculated = 0x%02X\n", record[record_len - 1], checksum); 159 | #endif 160 | 161 | // Verify calculated checksum matches record's. 162 | if(checksum != record[record_len - 1]) { 163 | printf("Invalid line %u of SREC file; failed checksum verification (got %02X, expected %02X).\n", line_count, checksum, record[record_len - 1]); 164 | return -1; 165 | } 166 | 167 | switch(record[REC_OFFSET_TYPE]) { 168 | case REC_TYPE_S1_DATA: 169 | // Take data bytes from the record and write to the specified 16-bit memory address. 170 | mem_addr = be16toh(record[REC_OFFSET_ADDR]); 171 | for(size_t i = 0; i < record[REC_OFFSET_BYTE_COUNT] - REC_COUNT_EXCESS_S1; i++) { 172 | #ifdef SREC_DETAIL 173 | printf("Mem Write: Addr = 0x%08X, Byte = 0x%02X\n", mem_addr, record[REC_OFFSET_DATA_S1 + i]); 174 | #endif 175 | memory_write(mem_addr++, record[REC_OFFSET_DATA_S1 + i]); 176 | } 177 | break; 178 | case REC_TYPE_S2_DATA: 179 | // Take data bytes from the record and write to the specified 24-bit memory address. 180 | mem_addr = be24toh(record[REC_OFFSET_ADDR]); 181 | for(size_t i = 0; i < record[REC_OFFSET_BYTE_COUNT] - REC_COUNT_EXCESS_S2; i++) { 182 | #ifdef SREC_DETAIL 183 | printf("Mem Write: Addr = 0x%08X, Byte = 0x%02X\n", mem_addr, record[REC_OFFSET_DATA_S2 + i]); 184 | #endif 185 | memory_write(mem_addr++, record[REC_OFFSET_DATA_S2 + i]); 186 | } 187 | break; 188 | case REC_TYPE_S3_DATA: 189 | // Take data bytes from the record and write to the specified 32-bit memory address. 190 | mem_addr = be32toh(record[REC_OFFSET_ADDR]); 191 | for(size_t i = 0; i < record[REC_OFFSET_BYTE_COUNT] - REC_COUNT_EXCESS_S3; i++) { 192 | #ifdef SREC_DETAIL 193 | printf("Mem Write: Addr = 0x%08X, Byte = 0x%02X\n", mem_addr, record[REC_OFFSET_DATA_S3 + i]); 194 | #endif 195 | memory_write(mem_addr++, record[REC_OFFSET_DATA_S3 + i]); 196 | } 197 | break; 198 | case REC_TYPE_S0_HEADER: 199 | case REC_TYPE_S5_COUNT: 200 | case REC_TYPE_S6_COUNT: 201 | // Don't really need to handle these; ignore them. 202 | break; 203 | case REC_TYPE_S7_TERM: 204 | case REC_TYPE_S8_TERM: 205 | case REC_TYPE_S9_TERM: 206 | // Don't process file any further. 207 | end = true; 208 | break; 209 | default: 210 | printf("Invalid line %u of SREC file; unknown record type (%u).\n", line_count, record[REC_OFFSET_TYPE]); 211 | return -1; 212 | } 213 | } 214 | 215 | if(ferror(srec)) { 216 | printf("Error reading file!\n"); // TODO: print err msg with strerror()? 217 | return -1; 218 | } 219 | } while(!end && !feof(srec)); 220 | 221 | fclose(srec); 222 | 223 | return 0; 224 | } 225 | -------------------------------------------------------------------------------- /STM8/srec.h: -------------------------------------------------------------------------------- 1 | #ifndef _SREC_H_ 2 | #define _SREC_H_ 3 | 4 | int srec_load(const char* path); 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /STM8/tcpconsole.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "peripherals/uart1.h" 5 | #include "peripherals/uart3.h" 6 | 7 | WSADATA wsaData; 8 | SOCKET listen_socket[3], msgsock[3]; 9 | char* ip_address = NULL; 10 | 11 | int fromlen[3]; 12 | int socket_type = SOCK_STREAM; 13 | struct sockaddr_in local[3], from[3]; 14 | uint8_t didstartup = 0; 15 | 16 | int tcpconsole_init(uint8_t uart, uint16_t port) { 17 | int retval; 18 | unsigned long iMode = 1; 19 | 20 | if (!didstartup) { 21 | // Request Winsock version 2.2 22 | if ((retval = WSAStartup(0x202, &wsaData)) != 0) { 23 | fprintf(stderr, "Server: WSAStartup() failed with error %d\n", retval); 24 | WSACleanup(); 25 | return -1; 26 | } 27 | didstartup = 1; 28 | } 29 | 30 | local[uart].sin_family = AF_INET; 31 | local[uart].sin_addr.s_addr = (!ip_address) ? INADDR_ANY : inet_addr(ip_address); 32 | local[uart].sin_port = htons(port); 33 | listen_socket[uart] = socket(AF_INET, socket_type, 0); 34 | 35 | if (listen_socket[uart] == INVALID_SOCKET) { 36 | fprintf(stderr, "Server: socket() failed with error %d\n", WSAGetLastError()); 37 | WSACleanup(); 38 | return -1; 39 | } 40 | 41 | if (bind(listen_socket[uart], (struct sockaddr*)&local[uart], sizeof(local[uart])) == SOCKET_ERROR) { 42 | fprintf(stderr, "Server: bind() failed with error %d\n", WSAGetLastError()); 43 | WSACleanup(); 44 | return -1; 45 | } 46 | 47 | if (listen(listen_socket[uart], 5) == SOCKET_ERROR) { 48 | fprintf(stderr, "Server: listen() failed with error %d\n", WSAGetLastError()); 49 | WSACleanup(); 50 | return -1; 51 | } 52 | 53 | ioctlsocket(listen_socket[uart], FIONBIO, &iMode); //we want accept() to not block 54 | 55 | msgsock[uart] = INVALID_SOCKET; 56 | return 0; 57 | } 58 | 59 | void tcpconsole_dorecv(uint8_t uart) { 60 | int actuallen = 0; 61 | uint8_t val; 62 | unsigned long iMode = 1; 63 | 64 | if (msgsock[uart] == INVALID_SOCKET) { 65 | fromlen[uart] = sizeof(from[uart]); 66 | msgsock[uart] = accept(listen_socket[uart], (struct sockaddr*)&from[uart], &fromlen[uart]); 67 | ioctlsocket(msgsock[uart], FIONBIO, &iMode); //non-blocking IO 68 | } 69 | 70 | if (msgsock[uart] == INVALID_SOCKET) return; 71 | actuallen = recv(msgsock[uart], &val, 1, 0); 72 | if (actuallen > 0) { 73 | //printf("%c", val); 74 | if (uart == 0) 75 | uart1_rxBufAdd(val); 76 | else if (uart == 2) 77 | uart3_rxBufAdd(val); 78 | } 79 | else if (actuallen == 0) { //graceful close 80 | closesocket(msgsock[uart]); 81 | msgsock[uart] = INVALID_SOCKET; 82 | } 83 | else { 84 | //printf("%d\n", WSAGetLastError()); 85 | switch (WSAGetLastError()) { 86 | case WSAEWOULDBLOCK: //this is ok, just no data yet 87 | break; 88 | case WSANOTINITIALISED: //the rest of these are bad... 89 | case WSAENETDOWN: 90 | case WSAENOTCONN: 91 | case WSAENETRESET: 92 | case WSAENOTSOCK: 93 | case WSAESHUTDOWN: 94 | case WSAEINVAL: 95 | case WSAECONNABORTED: 96 | case WSAETIMEDOUT: 97 | case WSAECONNRESET: 98 | closesocket(msgsock[uart]); 99 | msgsock[uart] = INVALID_SOCKET; 100 | break; 101 | default: 102 | break; 103 | } 104 | } 105 | } 106 | 107 | void tcpconsole_loop() { 108 | if (uart1_redirect == UART1_REDIRECT_TCP) { 109 | tcpconsole_dorecv(0); 110 | } 111 | if (uart3_redirect == UART3_REDIRECT_TCP) { 112 | tcpconsole_dorecv(2); 113 | } 114 | } 115 | 116 | void tcpconsole_send(uint8_t uart, uint8_t val) { 117 | int ret; 118 | if (msgsock[uart] == INVALID_SOCKET) return; 119 | ret = send(msgsock[uart], &val, 1, 0); 120 | //printf("send %d\n", ret); 121 | if (ret < 1) { 122 | //TODO: error handling 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /STM8/tcpconsole.h: -------------------------------------------------------------------------------- 1 | #ifndef _TCPCONSOLE_H_ 2 | #define _TCPCONSOLE_H_ 3 | 4 | #include 5 | 6 | int tcpconsole_init(uint8_t uart, uint16_t port); 7 | void tcpconsole_loop(void); 8 | void tcpconsole_send(uint8_t uart, uint8_t val); 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /STM8/timing.c: -------------------------------------------------------------------------------- 1 | #ifdef _WIN32 2 | #include 3 | #else 4 | #include 5 | #endif 6 | #include 7 | #include 8 | #include 9 | #include "config.h" 10 | #include "timing.h" 11 | 12 | uint64_t timing_cur; 13 | uint64_t timing_freq; 14 | TIMER* timers = NULL; 15 | uint32_t timers_count = 0; 16 | 17 | int timing_init() { 18 | #ifdef _WIN32 19 | LARGE_INTEGER freq; 20 | //TODO: error handling 21 | QueryPerformanceFrequency(&freq); 22 | timing_freq = (uint64_t)freq.QuadPart; 23 | #else 24 | timing_freq = 1000000; 25 | #endif 26 | return 0; 27 | } 28 | 29 | void timing_loop() { 30 | uint32_t i; 31 | #ifdef _WIN32 32 | LARGE_INTEGER cur; 33 | //TODO: error handling 34 | QueryPerformanceCounter(&cur); 35 | timing_cur = (uint64_t)cur.QuadPart; 36 | #else 37 | struct timeval tv; 38 | gettimeofday(&tv, NULL); 39 | timing_cur = (uint64_t)tv.tv_sec * 1000000 + (uint64_t)tv.tv_usec; 40 | #endif 41 | for (i = 0; i < timers_count; i++) { 42 | if (timing_cur >= (timers[i].previous + timers[i].interval)) { 43 | if (timers[i].enabled != TIMING_DISABLED) { 44 | if (timers[i].callback != NULL) { 45 | (*timers[i].callback)(timers[i].data); 46 | } 47 | timers[i].previous += timers[i].interval; 48 | if ((timing_cur - timers[i].previous) >= (timers[i].interval * 100)) { 49 | timers[i].previous = timing_cur; 50 | } 51 | } 52 | } 53 | } 54 | } 55 | 56 | //Just some code for performance testing 57 | void timing_speedTest() { 58 | #ifdef _WIN32 59 | uint64_t start, i; 60 | LARGE_INTEGER cur; 61 | //TODO: error handling 62 | QueryPerformanceCounter(&cur); 63 | start = (uint64_t)cur.QuadPart; 64 | 65 | i = 0; 66 | while (1) { 67 | QueryPerformanceCounter(&cur); 68 | timing_cur = (uint64_t)cur.QuadPart; 69 | i++; 70 | if ((timing_cur - start) >= timing_freq) break; 71 | } 72 | printf("%llu calls to QPC in 1 second\r\n", i); 73 | #endif 74 | } 75 | 76 | uint32_t timing_addTimerUsingInterval(void* callback, void* data, uint64_t interval, uint8_t enabled) { 77 | TIMER* temp; 78 | uint32_t ret; 79 | #ifdef _WIN32 80 | LARGE_INTEGER cur; 81 | 82 | //TODO: error handling 83 | QueryPerformanceCounter(&cur); 84 | timing_cur = (uint64_t)cur.QuadPart; 85 | #else 86 | struct timeval tv; 87 | gettimeofday(&tv, NULL); 88 | timing_cur = (uint64_t)tv.tv_sec * 1000000 + (uint64_t)tv.tv_usec; 89 | #endif 90 | temp = (TIMER*)realloc(timers, (size_t)sizeof(TIMER) * (timers_count + 1)); 91 | if (temp == NULL) { 92 | //TODO: error handling 93 | return TIMING_ERROR; //NULL; 94 | } 95 | timers = temp; 96 | 97 | timers[timers_count].previous = timing_cur; 98 | timers[timers_count].interval = interval; 99 | timers[timers_count].callback = callback; 100 | timers[timers_count].data = data; 101 | timers[timers_count].enabled = enabled; 102 | 103 | ret = timers_count; 104 | timers_count++; 105 | 106 | return ret; 107 | } 108 | 109 | uint32_t timing_addTimer(void* callback, void* data, double frequency, uint8_t enabled) { 110 | return timing_addTimerUsingInterval(callback, data, (uint64_t)((double)timing_freq / frequency), enabled); 111 | } 112 | 113 | void timing_updateInterval(uint32_t tnum, uint64_t interval) { 114 | if (tnum >= timers_count) { 115 | return; 116 | } 117 | timers[tnum].interval = interval; 118 | } 119 | 120 | void timing_updateIntervalFreq(uint32_t tnum, double frequency) { 121 | if (tnum >= timers_count) { 122 | return; 123 | } 124 | timers[tnum].interval = (uint64_t)((double)timing_freq / frequency); 125 | } 126 | 127 | void timing_timerEnable(uint32_t tnum) { 128 | if (tnum >= timers_count) { 129 | return; 130 | } 131 | timers[tnum].enabled = TIMING_ENABLED; 132 | timers[tnum].previous = timing_getCur(); 133 | } 134 | 135 | void timing_timerDisable(uint32_t tnum) { 136 | if (tnum >= timers_count) { 137 | return; 138 | } 139 | timers[tnum].enabled = TIMING_DISABLED; 140 | } 141 | 142 | uint64_t timing_getFreq() { 143 | return timing_freq; 144 | } 145 | 146 | uint64_t timing_getCur() { 147 | #ifdef _WIN32 148 | LARGE_INTEGER cur; 149 | 150 | //TODO: error handling 151 | QueryPerformanceCounter(&cur); 152 | timing_cur = (uint64_t)cur.QuadPart; 153 | #else 154 | struct timeval tv; 155 | gettimeofday(&tv, NULL); 156 | timing_cur = (uint64_t)tv.tv_sec * 1000000 + (uint64_t)tv.tv_usec; 157 | #endif 158 | 159 | return timing_cur; 160 | } 161 | -------------------------------------------------------------------------------- /STM8/timing.h: -------------------------------------------------------------------------------- 1 | #ifndef _TIMING_H_ 2 | #define _TIMING_H_ 3 | 4 | #include 5 | 6 | typedef struct TIMER_s { 7 | uint64_t interval; 8 | uint64_t previous; 9 | uint8_t enabled; 10 | void (*callback)(void*); 11 | void* data; 12 | } TIMER; 13 | 14 | #define TIMING_ENABLED 1 15 | #define TIMING_DISABLED 0 16 | #define TIMING_ERROR 0xFFFFFFFF 17 | 18 | #define TIMING_RINGSIZE 1024 19 | 20 | int timing_init(); 21 | void timing_loop(); 22 | uint32_t timing_addTimer(void* callback, void* data, double frequency, uint8_t enabled); 23 | void timing_updateIntervalFreq(uint32_t tnum, double frequency); 24 | void timing_updateInterval(uint32_t tnum, uint64_t interval); 25 | void timing_speedTest(); 26 | void timing_timerEnable(uint32_t tnum); 27 | void timing_timerDisable(uint32_t tnum); 28 | uint64_t timing_getFreq(); 29 | uint64_t timing_getCur(); 30 | 31 | extern uint64_t timing_cur; 32 | extern uint64_t timing_freq; 33 | 34 | #endif 35 | --------------------------------------------------------------------------------