% render "layouts/basic.html" do %# HTML tags can be embedded in mark down files if you want to do specific custom %# formatting like this, but in most cases that is not required.
.gemspec
~~~ruby
spec.add_development_dependency "origen_arm_debug", ">= <%= Origen.app.version %>"
~~~
__NOTE:__ You will also need to include require 'origen_arm_debug'
somewhere in your environment
if your app is a plugin.
### How To Use
The most common way to use the Arm Debugger plugin is through the Origen register API via
read_register
and write_register
methods.
You must include a compatible physical driver depending on what debug
interface your device has, one of the following can be used:
* [JTAG](http://origen-sdk.org/jtag)
* [Single Wire Debug](http://origen-sdk.org/swd)
~~~ruby
class DUT
include Origen::TopLevel
# Include the required physical driver, JTAG in this example
include OrigenJTAG
def initialize
reg :myreg, 0x0012, size: 16 do |reg|
reg.bits 15..8, :upper_byte
reg.bits 7..0, :lower_byte
end
# Simple example using default wait-states and latency:
# mem_ap: APSEL = 0x00 (base_address[31:24])
# mem2_ap: APSEL = 0x01 (base_address[31:24], is_axi: true) # is_axi: true for AXI-AP
mem_aps = {
mem_ap: { base_address: 0x00000000 },
mem2_ap: { base_address: 0x10000000 }
}
sub_block :arm_debug, class_name: 'OrigenARMDebug::DAP', mem_aps: mem_aps
end
# Hook the ARMDebug module into the register API, any register read
# requests will use the ARM Debug protocol by default
def read_register(reg, options={})
arm_debug.mem_ap.read_register(reg, options)
end
# As above for write requests
def write_register(reg, options={})
arm_debug.mem_ap.write_register(reg, options)
end
end
DUT.new.myreg.write!(0x55AA) # => Will generate the required vectors using the ARM debug protocol
~~~
You can access the lower-level API using conventional Origen register transactions:
~~~ruby
arm_debug.sw_dp.idcode.read!(0x2BA01477)
arm_debug.sw_dp.ctrlstat.write!(0x5000_0000) # Power-up
arm_debug.sw_dp.ctrlstat.read!(0xF0000000) # Verify
arm_debug.ahb_ap.idr.read!(0x24770011)
arm_debug.sw_dp.select.write!(0) # Select AHB-AP, bank 0
# Set the SIZE field of CSW to 0x2 (32-bit transfers) + AddrInc=1
arm_debug.ahb_ap.csw.write!(0x23000052)
~~~
You can also adjust the intermediate wait-states and latency parameters:
* [AP.apreg_access_wait](<%= path '/api/OrigenARMDebug/AP.html#apreg_access_wait-instance_method' %>)
* [MemAP.apmem_access_wait](<%= path '/api/OrigenARMDebug/MemAP.html#apmem_access_wait-instance_method' %>)
* [MemAP.latency](<%= path '/api/OrigenARMDebug/MemAP.html#latency-instance_method' %>)
* [MemAP.apacc_wait_states](<%= path '/api/OrigenARMDebug/MemAP.html#apacc_wait_states-instance_method' %>)
~~~ruby
# Assuming ahb_ap has been previously defined
dut.arm_debug.ahb_ap.apmem_access_wait = 16
dut.arm_debug.ahb_ap.apreg_access_wait = 12
dut.arm_debug.ahb_ap.latency = 8
# You can define these at instantiation as well
mem_aps = {
mem_ap: { base_address: 0x00000000, latency: 8, apreg_access_wait: 12, apmem_access_wait: 16 }
mem2_ap: { base_address: 0x10000000, latency: 8, apreg_access_wait: 12, apmem_access_wait: 16 }
}
sub_block :arm_debug, class_name: 'OrigenARMDebug::DAP', mem_aps: mem_aps
~~~
When used with the JTAG physical driver the default IR size is 4 and the default register select values are:
~~~
idcode_select = 0b1110
abort_select = 0b1000
dpacc_select = 0b1010
apacc_select = 0b1011
~~~
You can set non-default values at instantiation like this:
~~~ruby
mem_aps = {
mem_ap: { base_address: 0x00000000 }
mem2_ap: { base_address: 0x10000000 }
}
instantiation_options[:class_name] = 'OrigenARMDebug::DAP'
instantiation_options[:mem_aps] = mem_aps
instantiation_options[:ir_size] = 8
instantiation_options[:idcode_select] = 0xFE
instantiation_options[:abort_select] = 0xF8
instantiation_options[:dpacc_select] = 0xFA
instantiation_options[:apacc_select] = 0xFB
instantiation_options[:dp_select_reset] = 0xC2_0D00
sub_block :arm_debug, instantiation_options
~~~
### Company Customization
It may be the case that your application needs additional, customized Access Ports (AP) which are allowed but
not defined by the standard ARM Debug Interface. The following example shows how you can use the generic AP
class as a starting point and add extra registers as defined by your specific implementation.
~~~ruby
require 'origen_arm_debug'
module ARMDebugCOMPANY
# New AP class inherited from generic AP class provided by origen_arm_debug
class CustomAP < OrigenARMDebug::AP
# Initialize AP parameters and registers
def initialize(options = {})
super
instantiate_registers(options)
# Standard AP-register latency for most devices. Can be overriden by
# top-level if necessary
@apreg_access_wait = 8
end
# Add example registers associated with CustomAP.
#
# Custom registers can also be added by ARMDebug owner with add_reg or
# overloading entire instantiate_registers methd
#
# Ex: arm_debug.company_ap.add_reg(:custom_reg_3, 0x08)
def instantiate_registers(options = {})
add_reg :custom_reg_1, 0x00
add_reg :custom_reg_2, 0x04
end
end
end
class DUT
include Origen::TopLevel
include ARMDebugCOMPANY
# Also include the required physical driver, JTAG in this example
include OrigenJTAG
def initialize
reg :myreg, 0x0012, size: 16 do |reg|
reg.bits 15..8, :upper_byte
reg.bits 7..0, :lower_byte
end
# Some standard AP parameters values
std_memap_config = { latency: 16, apreg_access_wait: 8, apmem_access_wait: 8, csw_reset: 0x23000040 }
# 2 MemAPs using standard parameters (above)
mem_aps = {
mem_ap_0: { base_address: 0x00000000 }.merge(std_memap_config), # AP Select = 0x00
mem_ap_1: { base_address: 0x01000000 }.merge(std_memap_config), # AP Select = 0x01
}
# Add Company-Customized AP class @ APSEL = 0x04
custom_ap = {
company_ap: { class_name: 'ARMDebugCOMPANY::CustomAP', base_address: 0x04000000, apreg_access_wait: 8 }
}
sub_block :arm_debug, class_name: 'OrigenARMDebug::DAP',
base_address: 0,
mem_aps: mem_aps,
aps: custom_ap
end
end
DUT.new.arm_debug.company_ap.custom_reg_1.write!(0x55AA)
~~~
### How To Setup a Development Environment
[Clone the repository from Github](https://github.com/Origen-SDK/origen_arm_debug).
An instance of the OrigenARMDebug driver is hooked up to a dummy DUT
object for use in the console:
~~~
origen i
> dut.arm_debug
=> #