├── .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 |
--------------------------------------------------------------------------------