% 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.

<%= Origen.app.namespace %> (<%= Origen.app.version %>)

### Purpose This library provides register and memory read/write and debug control capability via the ARM Debug Interface v5 Spec. ### How To Import In your Gemfile add: ~~~ruby gem "origen_arm_debug", ">= <%= Origen.app.version %>" ~~~ or if your application is a plugin add this to your .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 => # ~~~ Follow the instructions here if you want to make a 3rd party app workspace use your development copy of the OrigenARMDebug plugin: [Setting up a Plugin Development Environment](http://origen-sdk.org/origen/guides/plugins) This plugin also contains a test suite, makes sure this passes before committing any changes! ~~~ origen examples ~~~ <%= disqus_comments %> % end