rpicsim 0.1.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +1 -1
  3. data/Gemfile +7 -6
  4. data/Introduction.md +3 -1
  5. data/README.md +2 -2
  6. data/docs/ChangeLog.md +6 -0
  7. data/docs/Contributing.md +1 -1
  8. data/docs/DefiningSimulationClass.md +11 -10
  9. data/docs/HowMPLABXIsFound.md +1 -1
  10. data/docs/IntegrationTesting.md +1 -1
  11. data/docs/IntroductionToRSpec.md +8 -5
  12. data/docs/IntroductionToRuby.md +2 -2
  13. data/docs/KnownIssues.md +46 -57
  14. data/docs/Labels.md +5 -4
  15. data/docs/Manual.md +1 -1
  16. data/docs/Memories.md +70 -0
  17. data/docs/PersistentExpectations.md +31 -2
  18. data/docs/Pins.md +5 -7
  19. data/docs/PreventingCallStackOverflow.md +4 -6
  20. data/docs/QuickStartGuide.md +5 -5
  21. data/docs/RSpecIntegration.md +2 -2
  22. data/docs/RamWatcher.md +22 -11
  23. data/docs/Running.md +4 -6
  24. data/docs/Stubbing.md +4 -4
  25. data/docs/SupportedDevices.md +2 -11
  26. data/docs/SupportedMPLABXVersions.md +1 -0
  27. data/docs/SupportedOperatingSystems.md +3 -2
  28. data/docs/UnitTesting.md +1 -1
  29. data/docs/Variables.md +81 -25
  30. data/lib/rpicsim.rb +0 -12
  31. data/lib/rpicsim/call_stack_info.rb +43 -47
  32. data/lib/rpicsim/composite_memory.rb +53 -0
  33. data/lib/rpicsim/flaws.rb +34 -22
  34. data/lib/rpicsim/instruction.rb +204 -48
  35. data/lib/rpicsim/label.rb +4 -4
  36. data/lib/rpicsim/memory.rb +44 -23
  37. data/lib/rpicsim/memory_watcher.rb +14 -22
  38. data/lib/rpicsim/mplab.rb +38 -119
  39. data/lib/rpicsim/mplab/mplab_assembly.rb +23 -18
  40. data/lib/rpicsim/mplab/mplab_device_info.rb +9 -9
  41. data/lib/rpicsim/mplab/mplab_disassembler.rb +5 -6
  42. data/lib/rpicsim/mplab/mplab_instruction.rb +87 -16
  43. data/lib/rpicsim/mplab/mplab_loader.rb +106 -0
  44. data/lib/rpicsim/mplab/mplab_memory.rb +19 -6
  45. data/lib/rpicsim/mplab/mplab_nmmr_info.rb +4 -4
  46. data/lib/rpicsim/mplab/mplab_observer.rb +15 -10
  47. data/lib/rpicsim/mplab/mplab_pin.rb +3 -3
  48. data/lib/rpicsim/mplab/mplab_processor.rb +5 -5
  49. data/lib/rpicsim/mplab/mplab_program_file.rb +29 -17
  50. data/lib/rpicsim/mplab/mplab_register.rb +5 -5
  51. data/lib/rpicsim/mplab/mplab_sfr_info.rb +4 -4
  52. data/lib/rpicsim/mplab/mplab_simulator.rb +27 -30
  53. data/lib/rpicsim/pin.rb +6 -6
  54. data/lib/rpicsim/program_counter.rb +3 -3
  55. data/lib/rpicsim/program_file.rb +39 -81
  56. data/lib/rpicsim/rspec/be_predicate.rb +1 -1
  57. data/lib/rpicsim/rspec/helpers.rb +1 -1
  58. data/lib/rpicsim/rspec/persistent_expectations.rb +17 -2
  59. data/lib/rpicsim/rspec/sim_diagnostics.rb +5 -5
  60. data/lib/rpicsim/search.rb +1 -1
  61. data/lib/rpicsim/sim.rb +153 -228
  62. data/lib/rpicsim/stack_pointer.rb +41 -0
  63. data/lib/rpicsim/stack_trace.rb +1 -1
  64. data/lib/rpicsim/storage/memory_integer.rb +235 -0
  65. data/lib/rpicsim/{register.rb → storage/register.rb} +18 -18
  66. data/lib/rpicsim/variable.rb +25 -211
  67. data/lib/rpicsim/variable_set.rb +93 -0
  68. data/lib/rpicsim/version.rb +2 -2
  69. metadata +9 -4
  70. data/docs/SFRs.md +0 -71
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 68c98fd21ee27688b36375bd75f7a3a7e3755c8d
4
- data.tar.gz: 9cf6e19491d34d6d59ab2d8ecd80a730bf72eb42
3
+ metadata.gz: fc6566720b23fde2a19df4092b2baac88204bb67
4
+ data.tar.gz: 13c9e4d36aa0cde5b1a30a9f91d6680a9afc5d52
5
5
  SHA512:
6
- metadata.gz: 38b585a3818466ed83a7bc012b9cbc5606f89413f39a7d05bc1784d3de243cf23a41043bc3931f41cea0d6ab3a2089434450b9eb207d3d1048dc2b7dd1de0592
7
- data.tar.gz: d47eccfcfe720bb7805a4a5131e4f251d1d5c0479ee2d39131e2f4502c96e99a67e4c9231e1f76627ef2252b1b0da299744ccb59084fc3973a116b762028b473
6
+ metadata.gz: 361c891fa97b5d82a56c1c318266efdfa8d8c93000094b108e732bc6af8b7eb57a84c7a731d96374083f10504117fff6757ec1e4c606bd367a3173bc2b85a3eb
7
+ data.tar.gz: 95a33a23ebf8e60e82fe40e6c9ce80ffdf6f16631a5ec8420b6d467d21ab9113c3fb7cded0408838975f2e63ee80ca559a7adec85c8ecf9a30b90a8362efe813
data/.yardopts CHANGED
@@ -16,7 +16,7 @@ docs/Manual.md
16
16
  docs/Labels.md
17
17
  docs/Running.md
18
18
  docs/Variables.md
19
- docs/SFRs.md
19
+ docs/Memories.md
20
20
  docs/RamWatcher.md
21
21
  docs/PreventingCallStackOverflow.md
22
22
 
data/Gemfile CHANGED
@@ -1,10 +1,11 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
3
  group :development do
4
- gem "rspec"
5
- gem "rake"
6
- gem "simplecov"
7
- gem "deg-yard" # my little fork of the yard gem that fixes some bugs with the legacy parse
8
- gem "guard"
9
- gem "guard-rspec"
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
@@ -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.00.
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.00.
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://www.davidegrayson.com/hold/rpicsim/_index.html) and the [RPicSim manual](http://www.davidegrayson.com/hold/rpicsim/file.Manual.html).</github>
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
 
@@ -1,6 +1,12 @@
1
1
  Change log
2
2
  ====
3
3
 
4
+ 0.2.1
5
+ ----
6
+
7
+ Released on 2014-03-07.
8
+ This release includes many, many breaking changes.
9
+
4
10
  0.1.0
5
11
  ----
6
12
 
@@ -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 a github page and create a new issue.
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
- device_is "PIC10F322"
8
- filename_is File.dirname(__FILE__) + "../firmware/dist/firmware.cof"
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#device_is device_is} 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 `device_is` should be a simple string containing the official name of the PIC device, like "PIC10F322".
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#filename_is filename_is} to specify the path to your COF or HEX file. This must be done after calling `device_is`.
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 `filename_is` line.
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} to define a variable in RAM, and {RPicSim::Sim::ClassDefinitionMethods#def_flash_var def_flash_var} to define a variable in flash. For more information, see {file:Variables.md}.
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
- device_is "PIC10F322"
43
- filename_is File.dirname(__FILE__) + "../firmware/dist/firmware.cof"
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 clearer to the reader and makes it easier to adapt them to change.
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
 
@@ -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/mplab_x.rb` in the source code of 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.
@@ -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 flash memory at the beginning of the simulation if that memory is used to store settings.
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
 
@@ -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/), but I think it is not very easy to follow. This page goes over the most important things you should know about RSpec.
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. If an example fails then a string about the expected behavior is produced by concatenating all the provided strings, from outermost to innermost.
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 that called an _expectation_ that defines the expected outcome.
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 then expects it to equal 6.
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; I only had to write the number 2 once. 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.
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
@@ -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, I recommend spending an afternoon perusing the [Documentation page on ruby-lang.org](https://www.ruby-lang.org/en/documentation/).
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.
@@ -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 following versions of MPLAB X:
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/mplab_x/path_retrieval_spec.rb`.
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/mplab_x/program_file_spec.rb`.
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
- The MPLAB X code might allow RPicSim to detect the PIC device name from the COF file so that the user does not have to specify it when creating a {RPicSim::ProgramFile} or a subclass of {RPicSim::Sim}.
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
- The workaround is to simply set any variables defined in user ID space to the correct values from Ruby before running the simulation.
118
- This issue is tested in `spec/integration/flash_variable_spec.rb`.
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/flash_variable_spec.rb`.
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.00_
126
+ _MPLAB X versions affected: 1.95, 2.00, 2.05_
171
127
 
172
- This issue is tested in `spec/mplab_x/memory_attach_spec.rb`.
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 instead of to LATA
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 it as a write to PORTA instead of LATA.
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_
@@ -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 flash.
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. For example, to get the address of a C function named `foo`, you might have to access a label named `_foo` using code like this:
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.class.program_file.labels.keys
30
+ p sim.program_file.labels.keys
30
31
 
31
32
 
32
33
  Using a Label object
33
34
  ----
34
35
 
35
- You can basically only do three things with a Label object:
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}.
@@ -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:SFRs.md}
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
@@ -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.