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
@@ -0,0 +1,93 @@
|
|
1
|
+
require_relative 'storage/memory_integer'
|
2
|
+
require_relative 'variable'
|
3
|
+
|
4
|
+
module RPicSim
|
5
|
+
# This class is used internally by {Sim} to manage user-defined variables.
|
6
|
+
class VariableSet
|
7
|
+
attr_writer :address_increment
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@memory_types = []
|
11
|
+
@symbols_for_memory = {}
|
12
|
+
@vars_for_memory = {}
|
13
|
+
@vars_for_memory_by_address = {}
|
14
|
+
end
|
15
|
+
|
16
|
+
def def_memory_type(name, symbols)
|
17
|
+
name = name.to_sym
|
18
|
+
@memory_types << name
|
19
|
+
@symbols_for_memory[name] = symbols
|
20
|
+
@vars_for_memory[name] = {}
|
21
|
+
@vars_for_memory_by_address[name] = {}
|
22
|
+
end
|
23
|
+
|
24
|
+
def def_var(name, type, opts={})
|
25
|
+
allowed_keys = [:memory, :symbol, :address]
|
26
|
+
invalid_keys = opts.keys - allowed_keys
|
27
|
+
if !invalid_keys.empty?
|
28
|
+
raise ArgumentError, "Unrecognized options: #{invalid_keys.join(', ')}"
|
29
|
+
end
|
30
|
+
|
31
|
+
name = name.to_sym
|
32
|
+
|
33
|
+
memory_type = opts.fetch(:memory, :ram)
|
34
|
+
if !@memory_types.include?(memory_type)
|
35
|
+
raise "Invalid memory type '#{memory_type.inspect}'."
|
36
|
+
end
|
37
|
+
|
38
|
+
symbol_addresses = @symbols_for_memory[memory_type]
|
39
|
+
|
40
|
+
if opts[:address]
|
41
|
+
address = opts[:address].to_i
|
42
|
+
else
|
43
|
+
symbol = (opts[:symbol] || name).to_sym
|
44
|
+
if symbol.to_s.include?('@')
|
45
|
+
raise 'Limitations in MPLAB X code prevent us from accessing ' +
|
46
|
+
"variables with '@' in the name like '#{symbol}'"
|
47
|
+
end
|
48
|
+
address = symbol_addresses[symbol] or raise ArgumentError, "Cannot find variable in #{memory_type} named '#{symbol}'."
|
49
|
+
end
|
50
|
+
|
51
|
+
klass = case type
|
52
|
+
when Class then type
|
53
|
+
when :word then Storage::MemoryWord
|
54
|
+
when :uint8 then Storage::MemoryUInt8
|
55
|
+
when :int8 then Storage::MemoryInt8
|
56
|
+
when :uint16 then Storage::MemoryUInt16
|
57
|
+
when :int16 then Storage::MemoryInt16
|
58
|
+
when :uint24 then Storage::MemoryUInt24
|
59
|
+
when :int24 then Storage::MemoryInt24
|
60
|
+
when :uint32 then Storage::MemoryUInt32
|
61
|
+
when :int32 then Storage::MemoryInt32
|
62
|
+
else raise ArgumentError, "Unknown type '#{type}'."
|
63
|
+
end
|
64
|
+
|
65
|
+
variable = klass.new(name, address)
|
66
|
+
|
67
|
+
if variable.is_a?(Storage::MemoryWord) && memory_type == :program_memory
|
68
|
+
variable.size = @address_increment
|
69
|
+
end
|
70
|
+
|
71
|
+
vars_by_address = @vars_for_memory_by_address[memory_type]
|
72
|
+
variable.addresses.each do |address|
|
73
|
+
if vars_by_address[address]
|
74
|
+
raise 'Variable %s overlaps with %s at 0x%x' %
|
75
|
+
[variable, @vars_by_address[address], address]
|
76
|
+
end
|
77
|
+
vars_by_address[address] = variable
|
78
|
+
end
|
79
|
+
|
80
|
+
@vars_for_memory[memory_type][name] = variable
|
81
|
+
end
|
82
|
+
|
83
|
+
def bind(memories)
|
84
|
+
vars = {}
|
85
|
+
memories.each do |memory_type, memory|
|
86
|
+
@vars_for_memory[memory_type].each do |name, unbound_var|
|
87
|
+
vars[name] = Variable.new(unbound_var.bind(memory))
|
88
|
+
end
|
89
|
+
end
|
90
|
+
vars
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
data/lib/rpicsim/version.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
1
|
module RPicSim
|
2
|
-
VERSION = '0.1
|
3
|
-
end
|
2
|
+
VERSION = '0.2.1'
|
3
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rpicsim
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Pololu
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-03-07 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description:
|
14
14
|
email:
|
@@ -34,6 +34,7 @@ files:
|
|
34
34
|
- docs/Labels.md
|
35
35
|
- docs/MakingTestsRunFaster.md
|
36
36
|
- docs/Manual.md
|
37
|
+
- docs/Memories.md
|
37
38
|
- docs/PersistentExpectations.md
|
38
39
|
- docs/Pins.md
|
39
40
|
- docs/PreventingCallStackOverflow.md
|
@@ -41,7 +42,6 @@ files:
|
|
41
42
|
- docs/RSpecIntegration.md
|
42
43
|
- docs/RamWatcher.md
|
43
44
|
- docs/Running.md
|
44
|
-
- docs/SFRs.md
|
45
45
|
- docs/Stubbing.md
|
46
46
|
- docs/SupportedCompilers.md
|
47
47
|
- docs/SupportedDevices.md
|
@@ -51,6 +51,7 @@ files:
|
|
51
51
|
- docs/Variables.md
|
52
52
|
- lib/rpicsim.rb
|
53
53
|
- lib/rpicsim/call_stack_info.rb
|
54
|
+
- lib/rpicsim/composite_memory.rb
|
54
55
|
- lib/rpicsim/flaws.rb
|
55
56
|
- lib/rpicsim/instruction.rb
|
56
57
|
- lib/rpicsim/label.rb
|
@@ -61,6 +62,7 @@ files:
|
|
61
62
|
- lib/rpicsim/mplab/mplab_device_info.rb
|
62
63
|
- lib/rpicsim/mplab/mplab_disassembler.rb
|
63
64
|
- lib/rpicsim/mplab/mplab_instruction.rb
|
65
|
+
- lib/rpicsim/mplab/mplab_loader.rb
|
64
66
|
- lib/rpicsim/mplab/mplab_memory.rb
|
65
67
|
- lib/rpicsim/mplab/mplab_nmmr_info.rb
|
66
68
|
- lib/rpicsim/mplab/mplab_observer.rb
|
@@ -73,7 +75,6 @@ files:
|
|
73
75
|
- lib/rpicsim/pin.rb
|
74
76
|
- lib/rpicsim/program_counter.rb
|
75
77
|
- lib/rpicsim/program_file.rb
|
76
|
-
- lib/rpicsim/register.rb
|
77
78
|
- lib/rpicsim/rspec.rb
|
78
79
|
- lib/rpicsim/rspec/be_predicate.rb
|
79
80
|
- lib/rpicsim/rspec/helpers.rb
|
@@ -81,8 +82,12 @@ files:
|
|
81
82
|
- lib/rpicsim/rspec/sim_diagnostics.rb
|
82
83
|
- lib/rpicsim/search.rb
|
83
84
|
- lib/rpicsim/sim.rb
|
85
|
+
- lib/rpicsim/stack_pointer.rb
|
84
86
|
- lib/rpicsim/stack_trace.rb
|
87
|
+
- lib/rpicsim/storage/memory_integer.rb
|
88
|
+
- lib/rpicsim/storage/register.rb
|
85
89
|
- lib/rpicsim/variable.rb
|
90
|
+
- lib/rpicsim/variable_set.rb
|
86
91
|
- lib/rpicsim/version.rb
|
87
92
|
homepage: https://github.com/pololu/rpicsim
|
88
93
|
licenses:
|
data/docs/SFRs.md
DELETED
@@ -1,71 +0,0 @@
|
|
1
|
-
SFRs
|
2
|
-
====
|
3
|
-
|
4
|
-
The Special Function Registers (SFRs) on a microcontroller enable the firmware to interact with the microcontroller's peripherals and talk to the outside world.
|
5
|
-
RPicSim supports reading and writing these SFRs from Ruby.
|
6
|
-
This can be useful if you want to put your PIC into a particular state and see how a part of your firmware responds.
|
7
|
-
Each SFR is represented as an instance of the {RPicSim::Register} class.
|
8
|
-
|
9
|
-
|
10
|
-
Getting a Register object
|
11
|
-
----
|
12
|
-
|
13
|
-
The {RPicSim::Sim#sfr} method can be called on your simulation object to retrieve a {RPicSim::Register} object:
|
14
|
-
|
15
|
-
!!!ruby
|
16
|
-
sim.sfr(:LATA) # => returns a Register object
|
17
|
-
|
18
|
-
If you are using RPicSim's {file:RSpecIntegration.md RSpec integration}, the `sfr` method inside an example automatically redirects to the `@sim` object:
|
19
|
-
|
20
|
-
!!!ruby
|
21
|
-
it "works" do
|
22
|
-
sfr(:LATA) # => returns a Register object
|
23
|
-
end
|
24
|
-
|
25
|
-
The first argument of {RPicSim::Sim#sfr} should be a symbol containing the name of the SFR.
|
26
|
-
The name comes from the MPLAB X code, but it should match the name given in the microcontroller's datasheet.
|
27
|
-
|
28
|
-
|
29
|
-
Using a register
|
30
|
-
----
|
31
|
-
|
32
|
-
Once you have obtained the {RPicSim::Register Register} object using one of the methods above, you can read and write the value of the SFR using the `value` attribute:
|
33
|
-
|
34
|
-
!!!ruby
|
35
|
-
sfr(:LATA).value = 0x7B
|
36
|
-
expect(sfr(:LATA).value).to eq 0x7B
|
37
|
-
|
38
|
-
|
39
|
-
Protected bits
|
40
|
-
----
|
41
|
-
|
42
|
-
When you write to the register with {RPicSim::Register#value=}, you are probably writing to it in the same way that the simulated microcontroller would write to it.
|
43
|
-
This means that some bits might not be writable or might have restrictions on what value can be written to them.
|
44
|
-
For example, the TO and PD bits of the STATUS register on the PIC10F322 are not writable by the microcontroller.
|
45
|
-
|
46
|
-
To get around this, you can use {RPicSim::Register#memory_value=} instead, which should allow you to write to any of the bits.
|
47
|
-
|
48
|
-
|
49
|
-
Peripheral updating
|
50
|
-
----
|
51
|
-
|
52
|
-
The MPLAB X code contains various objects that simulate the peripherals on a chip, such as the ADC.
|
53
|
-
It has not been determined whether writing to SFRs using the {RPicSim::Register} object updates the simulation of those peripherals in the proper way.
|
54
|
-
Also, whether the peripherals get updated might depend on whether the `value` or the `memory_value` attribute is used for writing.
|
55
|
-
|
56
|
-
|
57
|
-
Non-memory-mapped registers
|
58
|
-
----
|
59
|
-
|
60
|
-
The MPLAB X code considers "SFRs" to only be the special registers that have an address in memory.
|
61
|
-
The special registers without a memory address are called Non-Memory-Mapped Registers (NMMRs).
|
62
|
-
To access these registers, you can use {RPicSim::Sim#nmmr} which is similar to {RPicSim::Sim#sfr}.
|
63
|
-
|
64
|
-
On some chips, WREG and STKPTR are SFRs and on other chips they are NMMRs. To make it easier to access these two registers, RPicSim provides the methods {RPicSim::Sim#wreg} and {RPicSim::Sim#stkptr}. Those methods can be called directly in RSpec examples thanks to RPicSim's {file:RSpecIntegration.md RSpec integration}:
|
65
|
-
|
66
|
-
!!!ruby
|
67
|
-
it "sets W to 5" do
|
68
|
-
expect(wreg.value).to eq 5
|
69
|
-
end
|
70
|
-
|
71
|
-
To access other registers without worrying about what type they are, you can use {RPicSim::Sim#sfr_or_nmmr}.
|