rpicsim 0.1.0 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.yardopts +1 -1
- data/Gemfile +7 -6
- data/Introduction.md +3 -1
- data/README.md +2 -2
- data/docs/ChangeLog.md +6 -0
- data/docs/Contributing.md +1 -1
- data/docs/DefiningSimulationClass.md +11 -10
- data/docs/HowMPLABXIsFound.md +1 -1
- data/docs/IntegrationTesting.md +1 -1
- data/docs/IntroductionToRSpec.md +8 -5
- data/docs/IntroductionToRuby.md +2 -2
- data/docs/KnownIssues.md +46 -57
- data/docs/Labels.md +5 -4
- data/docs/Manual.md +1 -1
- data/docs/Memories.md +70 -0
- data/docs/PersistentExpectations.md +31 -2
- data/docs/Pins.md +5 -7
- data/docs/PreventingCallStackOverflow.md +4 -6
- data/docs/QuickStartGuide.md +5 -5
- data/docs/RSpecIntegration.md +2 -2
- data/docs/RamWatcher.md +22 -11
- data/docs/Running.md +4 -6
- data/docs/Stubbing.md +4 -4
- data/docs/SupportedDevices.md +2 -11
- data/docs/SupportedMPLABXVersions.md +1 -0
- data/docs/SupportedOperatingSystems.md +3 -2
- data/docs/UnitTesting.md +1 -1
- data/docs/Variables.md +81 -25
- data/lib/rpicsim.rb +0 -12
- data/lib/rpicsim/call_stack_info.rb +43 -47
- data/lib/rpicsim/composite_memory.rb +53 -0
- data/lib/rpicsim/flaws.rb +34 -22
- data/lib/rpicsim/instruction.rb +204 -48
- data/lib/rpicsim/label.rb +4 -4
- data/lib/rpicsim/memory.rb +44 -23
- data/lib/rpicsim/memory_watcher.rb +14 -22
- data/lib/rpicsim/mplab.rb +38 -119
- data/lib/rpicsim/mplab/mplab_assembly.rb +23 -18
- data/lib/rpicsim/mplab/mplab_device_info.rb +9 -9
- data/lib/rpicsim/mplab/mplab_disassembler.rb +5 -6
- data/lib/rpicsim/mplab/mplab_instruction.rb +87 -16
- data/lib/rpicsim/mplab/mplab_loader.rb +106 -0
- data/lib/rpicsim/mplab/mplab_memory.rb +19 -6
- data/lib/rpicsim/mplab/mplab_nmmr_info.rb +4 -4
- data/lib/rpicsim/mplab/mplab_observer.rb +15 -10
- data/lib/rpicsim/mplab/mplab_pin.rb +3 -3
- data/lib/rpicsim/mplab/mplab_processor.rb +5 -5
- data/lib/rpicsim/mplab/mplab_program_file.rb +29 -17
- data/lib/rpicsim/mplab/mplab_register.rb +5 -5
- data/lib/rpicsim/mplab/mplab_sfr_info.rb +4 -4
- data/lib/rpicsim/mplab/mplab_simulator.rb +27 -30
- data/lib/rpicsim/pin.rb +6 -6
- data/lib/rpicsim/program_counter.rb +3 -3
- data/lib/rpicsim/program_file.rb +39 -81
- data/lib/rpicsim/rspec/be_predicate.rb +1 -1
- data/lib/rpicsim/rspec/helpers.rb +1 -1
- data/lib/rpicsim/rspec/persistent_expectations.rb +17 -2
- data/lib/rpicsim/rspec/sim_diagnostics.rb +5 -5
- data/lib/rpicsim/search.rb +1 -1
- data/lib/rpicsim/sim.rb +153 -228
- data/lib/rpicsim/stack_pointer.rb +41 -0
- data/lib/rpicsim/stack_trace.rb +1 -1
- data/lib/rpicsim/storage/memory_integer.rb +235 -0
- data/lib/rpicsim/{register.rb → storage/register.rb} +18 -18
- data/lib/rpicsim/variable.rb +25 -211
- data/lib/rpicsim/variable_set.rb +93 -0
- data/lib/rpicsim/version.rb +2 -2
- metadata +9 -4
- data/docs/SFRs.md +0 -71
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fc6566720b23fde2a19df4092b2baac88204bb67
|
4
|
+
data.tar.gz: 13c9e4d36aa0cde5b1a30a9f91d6680a9afc5d52
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 361c891fa97b5d82a56c1c318266efdfa8d8c93000094b108e732bc6af8b7eb57a84c7a731d96374083f10504117fff6757ec1e4c606bd367a3173bc2b85a3eb
|
7
|
+
data.tar.gz: 95a33a23ebf8e60e82fe40e6c9ce80ffdf6f16631a5ec8420b6d467d21ab9113c3fb7cded0408838975f2e63ee80ca559a7adec85c8ecf9a30b90a8362efe813
|
data/.yardopts
CHANGED
data/Gemfile
CHANGED
@@ -1,10 +1,11 @@
|
|
1
1
|
source 'https://rubygems.org'
|
2
2
|
|
3
3
|
group :development do
|
4
|
-
gem
|
5
|
-
gem
|
6
|
-
gem
|
7
|
-
gem
|
8
|
-
gem
|
9
|
-
gem
|
4
|
+
gem 'rspec'
|
5
|
+
gem 'rake'
|
6
|
+
gem 'simplecov'
|
7
|
+
gem 'deg-yard' # My little fork of the yard gem that has some bug fixes.
|
8
|
+
gem 'guard'
|
9
|
+
gem 'guard-rspec'
|
10
|
+
gem 'rubocop'
|
10
11
|
end
|
data/Introduction.md
CHANGED
@@ -51,7 +51,7 @@ RPicSim is distributed as a Ruby gem named `rpicsim`. To install RPicSim, run:
|
|
51
51
|
jgem install rpicsim
|
52
52
|
|
53
53
|
|
54
|
-
RPicSim has been tested with MPLAB X v1.85, v1.90, v1.95, and v2.
|
54
|
+
RPicSim has been tested with MPLAB X v1.85, v1.90, v1.95, v2.00, and v2.05.
|
55
55
|
However, it uses a lot of undocumented and internal features of the Microchip Java libraries, so it will probably need to be updated as new versions of MPLAB X are released.
|
56
56
|
|
57
57
|
RPicSim is not intended to replace formal specifications, code reviews, and rigorous testing of your firmware on actual hardware.
|
@@ -62,3 +62,5 @@ The names Microchip, PIC, MPLAB, and MPASM are trademarks of Microchip Technolog
|
|
62
62
|
|
63
63
|
|
64
64
|
|
65
|
+
This page is part of {file:Manual.md the RPicSim manual}.
|
66
|
+
For API documentation, click the "Index" link at the top of this page.
|
data/README.md
CHANGED
@@ -53,7 +53,7 @@ RPicSim is distributed as a Ruby gem named `rpicsim`. To install RPicSim, run:
|
|
53
53
|
jgem install rpicsim
|
54
54
|
|
55
55
|
|
56
|
-
RPicSim has been tested with MPLAB X v1.85, v1.90, v1.95, and v2.
|
56
|
+
RPicSim has been tested with MPLAB X v1.85, v1.90, v1.95, v2.00, and v2.05.
|
57
57
|
However, it uses a lot of undocumented and internal features of the Microchip Java libraries, so it will probably need to be updated as new versions of MPLAB X are released.
|
58
58
|
|
59
59
|
RPicSim is not intended to replace formal specifications, code reviews, and rigorous testing of your firmware on actual hardware.
|
@@ -61,6 +61,6 @@ RPicSim is just another tool that can make it easier to write and test the firmw
|
|
61
61
|
|
62
62
|
The names Microchip, PIC, MPLAB, and MPASM are trademarks of Microchip Technology Incorporated. RPicSim is not written, supported, or endorsed by Microchip.
|
63
63
|
|
64
|
-
<github>For complete documentation, see the [RPicSim API documentation](http://
|
64
|
+
<github>For complete documentation, see the [RPicSim API documentation](http://pololu.github.io/rpicsim/_index.html) and the [RPicSim manual](http://pololu.github.io/rpicsim/file.Manual.html).</github>
|
65
65
|
|
66
66
|
|
data/docs/ChangeLog.md
CHANGED
data/docs/Contributing.md
CHANGED
@@ -3,7 +3,7 @@ Contributing
|
|
3
3
|
|
4
4
|
RPicSim is hosted on the [pololu/rpicsim github page](https://github.com/pololu/rpicsim).
|
5
5
|
|
6
|
-
To report a bug, go to
|
6
|
+
To report a bug, go to the github page and create a new issue.
|
7
7
|
|
8
8
|
If you want to contribute code, these are the general steps:
|
9
9
|
|
@@ -4,8 +4,8 @@ Defining your simulation class
|
|
4
4
|
In order to run a simulation of your firmware using RPicSim, you must make a new subclass of {RPicSim::Sim}. This class is called your _simulation class_. Below is an example:
|
5
5
|
|
6
6
|
class MySim < RPicSim::Sim
|
7
|
-
|
8
|
-
|
7
|
+
use_device "PIC10F322"
|
8
|
+
use_file File.dirname(__FILE__) + "../firmware/dist/firmware.cof"
|
9
9
|
end
|
10
10
|
|
11
11
|
A full list of the special RPicSim methods you can call inside your class definition can be found by looking at the documentation for {RPicSim::Sim::ClassDefinitionMethods}.
|
@@ -15,22 +15,23 @@ Required properties
|
|
15
15
|
|
16
16
|
There are two things you must do inside a simulation class.
|
17
17
|
|
18
|
-
First, call {RPicSim::Sim::ClassDefinitionMethods#
|
18
|
+
First, call {RPicSim::Sim::ClassDefinitionMethods#use_device use_device} in order to specify the PIC device your firmware runs on. Unfortunately, RPicSim cannot just detect this information from your COF file. The argument to `use_device` should be a simple string containing the official name of the PIC device, like "PIC10F322".
|
19
19
|
|
20
|
-
Second, call {RPicSim::Sim::ClassDefinitionMethods#
|
20
|
+
Second, call {RPicSim::Sim::ClassDefinitionMethods#use_file use_file} to specify the path to your COF or HEX file. This must be done after calling `use_device`.
|
21
21
|
In the example, we start with `File.dirname(__FILE__)`, which is the name of the directory that the current Ruby file is in, and add a string to that.
|
22
|
-
This allows us to move our tests and firmware files around on the disk without changing the `
|
22
|
+
This allows us to move our tests and firmware files around on the disk without changing the `use_file` line.
|
23
23
|
|
24
24
|
Pins
|
25
25
|
----
|
26
26
|
|
27
|
-
You can use {RPicSim::Sim::ClassDefinitionMethods#def_pin def_pin} to define an alternative name for a pin. For more information, see {file:Pins.md}.
|
27
|
+
You can use {RPicSim::Sim::ClassDefinitionMethods#def_pin def_pin} in your simulation class to define an alternative name for a pin. For more information, see {file:Pins.md}.
|
28
28
|
|
29
29
|
|
30
30
|
Variables
|
31
31
|
----
|
32
32
|
|
33
|
-
You can use {RPicSim::Sim::ClassDefinitionMethods#def_var def_var}
|
33
|
+
You can use {RPicSim::Sim::ClassDefinitionMethods#def_var def_var} in your simulation class to define a variable in RAM, program memory, or EEPROM.
|
34
|
+
For more information, see {file:Variables.md}.
|
34
35
|
|
35
36
|
|
36
37
|
Methods
|
@@ -39,8 +40,8 @@ Methods
|
|
39
40
|
It is sometimes helpful to define your own methods in the simulation class. For example, here are some methods that help us simulate the effect of the user placing a jumper between RA1 and GND:
|
40
41
|
|
41
42
|
class MySim < RPicSim::Sim
|
42
|
-
|
43
|
-
|
43
|
+
use_device "PIC10F322"
|
44
|
+
use_file File.dirname(__FILE__) + "../firmware/dist/firmware.cof"
|
44
45
|
|
45
46
|
def jumper_on
|
46
47
|
pin(:RA1).set false
|
@@ -52,7 +53,7 @@ It is sometimes helpful to define your own methods in the simulation class. For
|
|
52
53
|
end
|
53
54
|
|
54
55
|
By making these `jumper_on` and `jumper_off` methods, we can write lots of tests that manipulate the jumper but we don't have to constantly worry about how the hardware jumper is implemented when writing or reading those tests.
|
55
|
-
This makes our tests
|
56
|
+
This makes our tests easier to read and change.
|
56
57
|
|
57
58
|
If you have an instance of the simulation class, you can call such a method in the usual way:
|
58
59
|
|
data/docs/HowMPLABXIsFound.md
CHANGED
@@ -3,7 +3,7 @@ How MPLAB X is found
|
|
3
3
|
|
4
4
|
RPicSim uses many Java classes from MPLAB X.
|
5
5
|
This section describes how it finds those classes at run time.
|
6
|
-
The code that controls this can be found in `lib/rpicsim/
|
6
|
+
The code that controls this can be found in `lib/rpicsim/mplab/mplab_loader.rb` in the source code of RPicSim.
|
7
7
|
|
8
8
|
The primary thing that RPicSim needs to do is figure out what directory MPLAB X has been installed in.
|
9
9
|
If the `RPICSIM_MPLABX` environment variable is set, it will assume that environment variable contains the path to the MPLAB X directory.
|
data/docs/IntegrationTesting.md
CHANGED
@@ -9,7 +9,7 @@ The structure of your integration tests is up to you, but a typical integration
|
|
9
9
|
* It tests that the firmware did the right thing by checking the states of the output pins.
|
10
10
|
* It does not alter the program counter except perhaps to make the tests faster, as discussed in the {file:Stubbing.md Stubbing page}.
|
11
11
|
* It might use {RPicSim::Sim#every_step} to check certain assertions after every step of the simulation. For example, it could test that a certain SFR's value never changes after it has been initialized.
|
12
|
-
* It might directly modify the device's EEPROM or
|
12
|
+
* It might directly modify the device's EEPROM or program memory at the beginning of the simulation if that memory is used to store settings.
|
13
13
|
|
14
14
|
For an example of an integration test, see the {file:Pins.md#label-PinMirror+example PinMirror example} from the Pins page.
|
15
15
|
|
data/docs/IntroductionToRSpec.md
CHANGED
@@ -4,7 +4,8 @@ Introduction to RSpec
|
|
4
4
|
[RSpec](http://rspec.info/) is a testing tool for the Ruby programming language that allows you to write an automated test suite.
|
5
5
|
RSpec provides great ways to combine code from similar tests, provides good error messages, and encourages you to specify exactly what you are testing.
|
6
6
|
|
7
|
-
The main documentation for RSpec can be found from the project's website at [rspec.info](http://rspec.info/)
|
7
|
+
The main documentation for RSpec can be found from the project's website at [rspec.info](http://rspec.info/).
|
8
|
+
This page documents the most important things you should know about RSpec.
|
8
9
|
|
9
10
|
File structure
|
10
11
|
----
|
@@ -42,12 +43,13 @@ An _example_ is the basic unit of an RSpec test suite. Examples are defined usi
|
|
42
43
|
end
|
43
44
|
end
|
44
45
|
|
45
|
-
The strings passed to `describe`, `context`, `it`, and `specify` are optional, but are used to generate helpful error messages and documentation.
|
46
|
+
The strings passed to `describe`, `context`, `it`, and `specify` are optional, but are used to generate helpful error messages and documentation.
|
47
|
+
If an example fails, then a string about the expected behavior is produced by concatenating all the provided strings, from outermost to innermost.
|
46
48
|
|
47
49
|
Expectations
|
48
50
|
----
|
49
51
|
|
50
|
-
In general, an RSpec example consists of some code to set up the situation being tested, and some code
|
52
|
+
In general, an RSpec example consists of some code to set up the situation being tested, and some code called an _expectation_ that defines the expected outcome.
|
51
53
|
If an expectation fails, an exception is raised, the example stops executing, and a failure message is displayed.
|
52
54
|
Expectations look like this:
|
53
55
|
|
@@ -71,7 +73,7 @@ Here is a concrete, runnable example:
|
|
71
73
|
end
|
72
74
|
end
|
73
75
|
|
74
|
-
First, the code adds 1 to 5 and
|
76
|
+
First, the code adds 1 to 5 and stores the result.
|
75
77
|
Then the number 6 is passed as the first argument to `eq`, making an equality matcher that tests whether the result is equal to 6.
|
76
78
|
Note that parentheses are not required when calling a method in Ruby: you can write `eq(6)` or `eq 6`.
|
77
79
|
|
@@ -155,7 +157,8 @@ The first argument is the name of a variable to define.
|
|
155
157
|
The `let` method is passed a block that computes the value of the variable, and the block will be called if the value of the variable is ever needed.
|
156
158
|
In other words, `let` variables are lazily evaluated.
|
157
159
|
|
158
|
-
The example below shows how a `let` variable could be useful for making your tests more readable
|
160
|
+
The example below shows how a `let` variable could be useful for making your tests more readable.
|
161
|
+
In this case, `let` allows us to separate the description of the expected behavior (the car can shift gears) from the arbitrary value (2) that we used to test it.
|
159
162
|
|
160
163
|
!!!ruby
|
161
164
|
describe "my car" do
|
data/docs/IntroductionToRuby.md
CHANGED
@@ -13,7 +13,7 @@ This manual comes with plenty of concrete, usable examples that you can start wi
|
|
13
13
|
You should be able to accomplish a lot with RPicSim by just copying the examples in this manual, without any specific study of the Ruby language.
|
14
14
|
However, knowing Ruby will allow you to condense repetitive parts of your tests, enable you to express complex concepts, and make it much easier to troubleshoot problems.
|
15
15
|
|
16
|
-
If you are new to Ruby,
|
16
|
+
If you are new to Ruby, it would be a good idea to spend an afternoon perusing the [Documentation page on ruby-lang.org](https://www.ruby-lang.org/en/documentation/).
|
17
17
|
If you want more, there are many books you can buy that teach Ruby.
|
18
18
|
If you have any particular questions, try searching Google and then try asking on [StackOverflow](http://www.stackoverflow.com).
|
19
19
|
Your question will probably be answered within hours, but remember to provide all the necessary information in your first post (see [SSCCE.org](http://www.sscce.org)).
|
@@ -76,7 +76,7 @@ Blocks
|
|
76
76
|
|
77
77
|
Whenever you see code between the Ruby keywords `do` and `end`, or between `{` and `}`, that code is inside a Ruby _block_.
|
78
78
|
A block is a chunk of executable code that can be easily created, passed around, and called like a method.
|
79
|
-
Any given block could be called once, multiple times, or never depending on the situation.
|
79
|
+
Any given block could be called once, multiple times, or never, depending on the situation.
|
80
80
|
|
81
81
|
For example, here is some code that passes a black to a method called `foo_method`.
|
82
82
|
The block prints "hello world" to the standard output.
|
data/docs/KnownIssues.md
CHANGED
@@ -4,14 +4,8 @@ Known issues
|
|
4
4
|
This page documents all the known issues RPicSim has that could affect its users.
|
5
5
|
Some issues are caused by the MPLAB X simulator and would need to be addressed by Microchip.
|
6
6
|
|
7
|
-
RPicSim has only been tested with the
|
8
|
-
|
9
|
-
* 1.85
|
10
|
-
* 1.90
|
11
|
-
* 1.95
|
12
|
-
* 2.00
|
13
|
-
|
14
|
-
If you are using a different version of MPLAB X, some of the issues might not apply to you.
|
7
|
+
RPicSim has only been tested with the versions of MPLAB X that are listed on the {file:Introduction.md} page.
|
8
|
+
If you are using a different version of MPLAB X, you might have different issues.
|
15
9
|
|
16
10
|
Many of these issues have only been reproduced on a single model of PIC microcontroller and they may or may not affect other models.
|
17
11
|
|
@@ -51,7 +45,7 @@ _MPLAB X versions affected: all tested versions_
|
|
51
45
|
|
52
46
|
In Windows, a bug in MPLAB X prevents RPicSim from using an MPLAB X installed on any drive other than the C drive.
|
53
47
|
|
54
|
-
This issue is tested in `spec/
|
48
|
+
This issue is tested in `spec/mplab/path_retrieval_spec.rb`.
|
55
49
|
|
56
50
|
|
57
51
|
Firmware under test must be inside a folder named "dist"
|
@@ -60,52 +54,14 @@ _Type: MPLAB X bug_
|
|
60
54
|
|
61
55
|
_MPLAB X versions affected: all tested versions_
|
62
56
|
|
63
|
-
This issue is tested in `spec/
|
64
|
-
|
65
|
-
|
66
|
-
Limited number of variable types supported
|
67
|
-
----
|
68
|
-
_Type: RPicSim missing feature_
|
69
|
-
|
70
|
-
There is no support for variables larger than 32 bits.
|
71
|
-
There is no support for arrays or structs of variables.
|
72
|
-
There is also no support for reading and writing directly from the simulated device's RAM, Flash, EEPROM, and stack memories from Ruby.
|
73
|
-
|
74
|
-
No EEPROM support
|
75
|
-
----
|
76
|
-
_Type: RPicSim missing feature_
|
77
|
-
|
78
|
-
RPicSim does not support reading or writing from EEPROM from Ruby.
|
79
|
-
|
80
|
-
|
81
|
-
Dissasembly is limited to midrange and baseline PIC microcontrollers
|
82
|
-
----
|
83
|
-
_Type: RPicSim missing feature_
|
84
|
-
|
85
|
-
The disassembled instruction graph created by {RPicSim::ProgramFile} currently only supports baseline and midrange PICs, but it should be easy to expand to other PICs.
|
86
|
-
This is a side feature of RPicSim, and not required for simulation.
|
87
|
-
|
88
|
-
|
89
|
-
Stack trace will show slightly wrong values for PIC18 microcontrollers
|
90
|
-
----
|
91
|
-
_Type: RPicSim bug_
|
92
|
-
|
93
|
-
For the PIC18, {RPicSim::Sim#stack_trace} will probably show values that are too high by one because it does not account for the fact that PIC18 instructions take two bytes.
|
57
|
+
This issue is tested in `spec/mplab/program_file_spec.rb`.
|
94
58
|
|
95
59
|
|
96
60
|
Cannot detect PIC model from COF file
|
97
61
|
----
|
98
62
|
_Type: RPicSim missing feature_
|
99
63
|
|
100
|
-
|
101
|
-
Currently RPicSim requires the user to always specify the PIC device name.
|
102
|
-
|
103
|
-
|
104
|
-
Not tested on Linux and Mac OS X
|
105
|
-
----
|
106
|
-
_Type: RPicSim missing feature_
|
107
|
-
|
108
|
-
RPicSim has not been tested on Linux and Mac OS X. See {file:SupportedOperatingSystems.md Supported operating systems} for more information.
|
64
|
+
Currently RPicSim requires the user to always specify the PIC device name when creating a {RPicSim::ProgramFile} or a subclass of {RPicSim::Sim}, even though it might be possible to get that information from the COF file.
|
109
65
|
|
110
66
|
|
111
67
|
Variables defined in user ID space are not read from the COF file
|
@@ -114,8 +70,8 @@ _Type: MPLAB X bug_
|
|
114
70
|
|
115
71
|
_MPLAB X version affected: all tested versions_
|
116
72
|
|
117
|
-
|
118
|
-
This issue is tested in `spec/integration/
|
73
|
+
If your firmware uses variables stored in user ID space, the workaround for this issue is to simply set any variables defined in user ID space to the correct values from Ruby before running the simulation.
|
74
|
+
This issue is tested in `spec/integration/program_memory_variable_spec.rb`.
|
119
75
|
|
120
76
|
|
121
77
|
Simulated firmware cannot write to the first user ID location
|
@@ -124,7 +80,7 @@ _Type: MPLAB X bug_
|
|
124
80
|
|
125
81
|
_MPLAB X versions affected: 1.85, 1.90_
|
126
82
|
|
127
|
-
This issue is tested in `spec/integration/
|
83
|
+
This issue is tested in `spec/integration/program_memory_variable_spec.rb`.
|
128
84
|
It has been {http://www.microchip.com/forums/m743214.aspx reported to Microchip} and was fixed in later versions.
|
129
85
|
|
130
86
|
|
@@ -167,25 +123,58 @@ RAM watcher is useless because all of RAM seems to change on every step
|
|
167
123
|
----
|
168
124
|
_Type: MPLAB X bug_
|
169
125
|
|
170
|
-
_MPLAB X versions affected: 1.95, 2.
|
126
|
+
_MPLAB X versions affected: 1.95, 2.00, 2.05_
|
171
127
|
|
172
|
-
This issue is tested in `spec/
|
128
|
+
This issue is tested in `spec/mplab/memory_attach_spec.rb`.
|
173
129
|
If you want to use the {file:RamWatcher.md RAM watcher}, you should use MPLAB X version 1.85 or 1.90.
|
174
130
|
|
175
131
|
|
176
|
-
RAM watcher reports a write to PORTA
|
132
|
+
RAM watcher reports a write to PORTA and LATA when LATA is written
|
177
133
|
----
|
178
134
|
_Type: MPLAB X bug_
|
179
135
|
|
180
136
|
_MPLAB X versions affected: all tested versions_
|
181
137
|
|
182
|
-
The {file:RamWatcher.md RAM watcher}, when testing code that writes to LATA, might actually report
|
183
|
-
This issue has been observed on a PIC10F322 but it probably affects other PORTx and LATx registers.
|
138
|
+
The {file:RamWatcher.md RAM watcher}, when testing code that writes to LATA, might actually report both a write to LATA and a write to PORTA.
|
139
|
+
This issue has been observed on a PIC10F322 but it probably affects other PORTx and LATx registers on other devices.
|
140
|
+
|
141
|
+
This issue is tested in `spec/integration/ram_watcher_spec.rb`.
|
142
|
+
This issue could not be tested on MPLAB X versions affected by the "RAM watcher is useless" issue above.
|
143
|
+
|
144
|
+
|
145
|
+
RAM watcher reports extra writes on devices where registers have multiple addresses
|
146
|
+
----
|
147
|
+
_Type: RPicSim missing feature_
|
148
|
+
|
149
|
+
_MPLAB X versions affected: all tested verisons_
|
150
|
+
|
151
|
+
On certain devices, some registers are available at multiple addresses.
|
152
|
+
When the value of the register changes, the RAM watcher will report writes to each of the addresses that the register occupies, which makes the resulting hash large and hard to work with.
|
153
|
+
|
154
|
+
For example, on the PIC16F1459, PCL occupies the third byte of each of the 32 banks of RAM, so it
|
155
|
+
can be accessed no matter which bank is selected.
|
156
|
+
Whenever the program counter advances, the RAM watcher reports writes to all 32 addresses that PCL occupies.
|
157
|
+
|
158
|
+
One workaround is to write a helper function that filters uninteresting addresses out of the hash returned by the RAM watcher.
|
184
159
|
|
185
160
|
This issue is tested in `spec/integration/ram_watcher_spec.rb`.
|
186
161
|
This issue could not be tested on MPLAB X versions affected by the "RAM watcher is useless" issue above.
|
187
162
|
|
188
163
|
|
164
|
+
RAM watchers cannot be garbage collected until the end of the simulation
|
165
|
+
----
|
166
|
+
_Type: RPicSim missing feature_
|
167
|
+
|
168
|
+
_MPLAB X versions affected: all_
|
169
|
+
|
170
|
+
Any instance of {RPicSim::MemoryWatcher}, including RAM watchers, cannot be garbage collected until the associated {RPicSim::Sim} object gets garbage collected.
|
171
|
+
This is because some internal objects managed by the Sim class need to hold on to a reference to the RAM watcher in order to send updates to it.
|
172
|
+
|
173
|
+
Therefore, creating a large number of RAM watcher objects for a single simulation could cause performance problems.
|
174
|
+
|
175
|
+
This problem could be fixed in the future by using Ruby's WeakRef class to make weak references.
|
176
|
+
|
177
|
+
|
189
178
|
Midrange ADC gives incorrect readings
|
190
179
|
----
|
191
180
|
_Type: MPLAB X bug_
|
data/docs/Labels.md
CHANGED
@@ -5,7 +5,7 @@ RPicSim automatically processes the symbol table in your firmware's COF file.
|
|
5
5
|
Any symbol in program space is called a _label_ and RPicSim stores a {RPicSim::Label} object to represent it.
|
6
6
|
|
7
7
|
For an assembly program, RPicSim labels correspond to any assembly label defined in code space.
|
8
|
-
These will usually correspond to subroutines and goto targets but could also be variables stored in
|
8
|
+
These will usually correspond to subroutines and goto targets but could also be variables stored in program memory.
|
9
9
|
In firmware assembled by MPASM, all labels are exported publicly by default, so they will all be available to RPicSim.
|
10
10
|
|
11
11
|
For a C program, RPicSim labels usually correspond to functions.
|
@@ -18,7 +18,8 @@ To get a Label object, call {RPicSim::Sim#label} and pass it the name of the lab
|
|
18
18
|
!!!ruby
|
19
19
|
sim.label(:loopStart) # => returns a Label object
|
20
20
|
|
21
|
-
C compilers will generally put an underscore at the beginning of any labels they generate.
|
21
|
+
C compilers will generally put an underscore at the beginning of any labels they generate.
|
22
|
+
Therefore, to get the address of a C function named `foo`, you might have to access a label named `_foo` using code like this:
|
22
23
|
|
23
24
|
!!!ruby
|
24
25
|
sim.label(:_foo)
|
@@ -26,13 +27,13 @@ C compilers will generally put an underscore at the beginning of any labels they
|
|
26
27
|
If RPicSim cannot find the label you want to use, you might troubleshoot it by printing out a list of all the known labels:
|
27
28
|
|
28
29
|
!!!ruby
|
29
|
-
p sim.
|
30
|
+
p sim.program_file.labels.keys
|
30
31
|
|
31
32
|
|
32
33
|
Using a Label object
|
33
34
|
----
|
34
35
|
|
35
|
-
|
36
|
+
There are three main things you can do with a Label object:
|
36
37
|
|
37
38
|
* Get its name by calling {RPicSim::Label#name}.
|
38
39
|
* Get its address by calling {RPicSim::Label#address}.
|
data/docs/Manual.md
CHANGED
@@ -18,7 +18,7 @@ This is the table of contents for the RPicSim manual.
|
|
18
18
|
* {file:Labels.md}
|
19
19
|
* {file:Running.md Running the simulation}
|
20
20
|
* {file:Variables.md}
|
21
|
-
* {file:
|
21
|
+
* {file:Memories.md}
|
22
22
|
* {file:RamWatcher.md RAM watcher}
|
23
23
|
* {file:PreventingCallStackOverflow.md Preventing call stack overflow}
|
24
24
|
* Testing firmware with RPicSim and RSpec
|
data/docs/Memories.md
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
Memories
|
2
|
+
====
|
3
|
+
|
4
|
+
RPicSim uses the {RPicSim::Memory} class to provide access to the RAM, EEPROM, and program memory of the simulated device.
|
5
|
+
This is useful if you want to interact with variables and data structures in your firmware that are too complex to be handled by RPicSim's {file:Variables.md} feature, like strings, structs, and buffers.
|
6
|
+
|
7
|
+
RAM and EEPROM
|
8
|
+
----
|
9
|
+
|
10
|
+
To get the {RPicSim::Memory Memory} object that represents RAM, call {RPicSim::Sim#ram}.
|
11
|
+
To get the {RPicSim::Memory Memory} object that represents EEPROM, call {RPicSim::Sim#eeprom}.
|
12
|
+
The two main methods to use on these objects are:
|
13
|
+
|
14
|
+
* `read_byte(address)`: This method takes a byte address and returns the value of that byte.
|
15
|
+
* `write_byte(address, value)`: This method takes a byte address and a value between 0 and 255, and writes the value to the specified byte.
|
16
|
+
|
17
|
+
For example, if you are using RPicSim's {file:RSpecIntegration RSpec integration} you can read and write from `ram` like this:
|
18
|
+
|
19
|
+
ram.write_byte(0x200, 0x80)
|
20
|
+
expect(ram.read_byte(0x200)).to eq 0x80
|
21
|
+
|
22
|
+
|
23
|
+
Program memory
|
24
|
+
----
|
25
|
+
|
26
|
+
To get the {RPicSim::Memory Memory} object that represents program memory, call {RPicSim::Sim#program_memory}.
|
27
|
+
In addition to letting you access the main part of program memory which contains the program, this object also allows access to the configuration words and user ID words.
|
28
|
+
The program memory is also known as flash, ROM, and code space.
|
29
|
+
|
30
|
+
The program memory object behaves differently depending on whether your are simulating a PIC18 device or a non-PIC18 device, as described below.
|
31
|
+
|
32
|
+
### Program memory on a non-PIC18 devices
|
33
|
+
|
34
|
+
On non-PIC18 devices, the program memory is divided into _words_ that are either 12 bits wide or 14 bits wide.
|
35
|
+
In RPicSim, non-PIC18 program memory addresses are always specified as _word addresses_.
|
36
|
+
For example, the address 0 corresponds to the first _word_, while the address 1 corresponds to the second word.
|
37
|
+
The {RPicSim::Memory Memory} object provides two methods for reading and writing from these words:
|
38
|
+
|
39
|
+
* `read_word(address)`: This method takes a word address and returns the value of that word.
|
40
|
+
* `write_word(address, value)`: This method takes a word address and a numerical value, and writes the value to the specified word.
|
41
|
+
|
42
|
+
The program memory on a non-PIC18 device can also be thought of as a series of bytes, and it is often represented this way in HEX files.
|
43
|
+
Each word can be thought of as two consecutive bytes, with the lower 8 bits residing in the first byte and upper 4 bits or 6 bits residing in the second byte.
|
44
|
+
The valid range of values for the second byte, therefore, is limited.
|
45
|
+
|
46
|
+
The {RPicSim::Memory Memory} object provides two methods for reading and writing the least-significant bytes of the words in program memory:
|
47
|
+
|
48
|
+
* `read_byte(address)`: This method takes a _word_ address and returns the lower 8 bits of that word, ignoring the upper bits.
|
49
|
+
* `write_byte(address)`: This method takes a _word_ address and a value between 0 and 255 and writes the value to the lower 8 bits of that word, leaving the upper bits unchanged.
|
50
|
+
|
51
|
+
Since these methods take word addresses instead of byte addresses, they cannot access the upper bits of a program memory word.
|
52
|
+
|
53
|
+
|
54
|
+
### Program memory on PIC18 devices
|
55
|
+
|
56
|
+
On PIC18 devices, the program memory is divided into 16-bit words.
|
57
|
+
Since each word can hold exactly two bytes, the program memory is often treated as a series of bytes in development tools.
|
58
|
+
In RPicSim, PIC18 program memory addresses are always specified as _byte addresses_.
|
59
|
+
|
60
|
+
The {RPicSim::Memory Memory} object provides two methods for reading and writing words from program memory:
|
61
|
+
|
62
|
+
* `read_word(address)`: This method takes a byte address and returns the value of the 2-byte word starting at that address.
|
63
|
+
* `write_word(address, value)`: This method takes a byte address and a numerical value, and writes the value to the 2-byte word starting at the specified address.
|
64
|
+
|
65
|
+
If you supply an odd address to `read_word` or `write_word`, the operation will apply to two bytes that are actually from two different words.
|
66
|
+
|
67
|
+
The {RPicSim::Memory Memory} object provides two methods for reading and writing bytes from program memory:
|
68
|
+
|
69
|
+
* `read_byte(address)`: This method takes a _byte_ address and returns the value of that byte.
|
70
|
+
* `write_byte(address)`: This method takes a _byte_ address and a value between 0 and 255 and writes the value to that byte, leaving other bytes unchanged.
|