Class: Adept::JTAG::Connection

Inherits:
Object
  • Object
show all
Extended by:
ConnectionProvider
Defined in:
lib/adept/jtag/connection.rb

Overview

Represents a connection to a JTAG device.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from ConnectionProvider

extended, providers

Constructor Details

#initialize(device, port_number = 0) ⇒ Connection

Sets up a new JTAG connection.



21
22
23
24
25
26
27
28
29
30
31
32
33
# File 'lib/adept/jtag/connection.rb', line 21

def initialize(device, port_number=0)

  #Store the information regarding the owning device...
  @device = device

  #Initialize the chain to zero until enumeration occurs.
  @chain_length = 0
  @devices_in_chain = 0

  #... open a JTAG connection.
  LowLevel::JTAG::EnableEx(@device.handle, port_number)

end

Instance Attribute Details

#deviceObject (readonly)

Returns the value of attribute device.



16
17
18
# File 'lib/adept/jtag/connection.rb', line 16

def device
  @device
end

#tap_stateObject

Returns the value of attribute tap_state.



15
16
17
# File 'lib/adept/jtag/connection.rb', line 15

def tap_state
  @tap_state
end

Class Method Details

.register_device_type(type) ⇒ Object

Registers a device type to be handled by JTAG connections, allowing JTAGDevice instances to be automatically created upon device enumeration.

Device types typically are classes which include the JTAGDevice mixin,



234
235
236
# File 'lib/adept/jtag/connection.rb', line 234

def self.register_device_type(type)
  @device_types << type
end

.supported_by?(device) ⇒ Boolean

Determines if the given device can serve as the host for a JTAG connection.

Returns:

  • (Boolean)


241
242
243
# File 'lib/adept/jtag/connection.rb', line 241

def self.supported_by?(device)
  LowLevel::JTAG::supported?(device)
end

Instance Method Details

#closeObject

Closes the given JTAG connection.



38
39
40
# File 'lib/adept/jtag/connection.rb', line 38

def close
  LowLevel::JTAG::Disable(@device.handle)
end

#connected_devicesObject

Returns a list of the JTAG IDCodes for all connected devices.



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/adept/jtag/connection.rb', line 45

def connected_devices

  #Reset all targets' TAPs; this will automatically load the IDCODE instruction into the
  #instruction register
  reset_target

  devices = []
  chain_length = 0
  devices_in_chain = 0

  #Loop until we've enumerated all devices in the JTAG chain.
  loop do

    #Recieve a single 32-bit JTAG ID code, LSB first.
    idcode = receive_data(32, true)

    #If we've recieved the special "null" IDcode, we've finished enumerating.
    #(In this case, we'll choose to accept the technically-valid all-ones IDcode as null,
    #as it is returned by most system boards when their power is turned off, and isn't
    #otherwise supported.)
    break if idcode == "\x00\x00\x00\x00" or idcode == "\xFF\xFF\xFF\xFF"

    #Otherwise, add this idcode to the list...
    devices << JTAG::Device.from_idcode(idcode.reverse, self, devices_in_chain, chain_length)

    #... add its width the the known scan-chain length
    chain_length += devices.last.instruction_width
    devices_in_chain += 1

  end

  #Update the internal chain-length.
  @chain_length = chain_length
  @devices_in_chain = devices_in_chain

  #Return the list of IDCodes.
  devices.reverse

end

#receive_data(bit_count, do_not_finish = false, overlap = false) ⇒ Object

Recieve data from the JTAG data register.

bit_count: The amount of bits to receive. do_not_finish: If set, the transmission will be “left open” so additional data can be received.



185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
# File 'lib/adept/jtag/connection.rb', line 185

def receive_data(bit_count, do_not_finish=false, overlap=false)

  #Put the device into the desired state.
  self.tap_state = JTAG::TAPStates::ShiftDR

  #Transmit the data, and recieve the accompanying response.
  response = LowLevel::JTAG::receive(@device.handle, false, false, bit_count, overlap)

  #If a state_after was provided, place the device into that state.
  self.tap_state = JTAG::TAPStates::Exit1DR unless do_not_finish

  #Return the received response.
  response

end

#reset_targetObject

Force-resets the target device.



217
218
219
220
221
222
223
224
225
# File 'lib/adept/jtag/connection.rb', line 217

def reset_target

  #Reset the target device's JTAG controller by sending five bits of TMS='1'.
  LowLevel::JTAG::tick(@device.handle, true, false, 5)

  #Set the internal TAP state to reset.
  @tap_state = JTAG::TAPStates::Reset

end

#run_test(clock_ticks) ⇒ Object

Switches to run/test mode, and holds that state for the desired amount of clock ticks.



204
205
206
207
208
209
210
211
212
# File 'lib/adept/jtag/connection.rb', line 204

def run_test(clock_ticks)

  #Put the target into the Run-Test-Idle state.
  self.tap_state = JTAG::TAPStates::Idle

  #And "tick" the test clock for the desired amount of cycles.
  LowLevel::JTAG::tick(@device.handle, false, false, clock_ticks, false)

end

#transmit_data(bytes, bit_count, pad_to_chain_length = false, prefix_with_zeroes = 0, do_not_finish = false) ⇒ Object

Transmit data over the JTAG test access lines, to be placed into the JTAG data register.

bytes: A byte-string which contains the instruction to be transmitted. bit_count: The total amount of bits to be transmitted from the byte string.

pad_to_chain_length:

If set, the transmitted data will be suffixed with logic '1's until the chain length has been met,
*assuming that all devices other than the single target device are in bypass*.
This allows the transmitter to easily fill the bypass registers of all additional devices with zeroes.

prefix_with_zeroes:

Prefixes the transmitted data with the specified amount of logic '0's. Prefixing is skipped if this parameter
is not provided, or is set to zero.

do_not_finish:

If set, the device will be left in the ShiftIR state, so additional instructions data be transmitted.


163
164
165
166
167
168
169
170
171
172
173
174
175
176
# File 'lib/adept/jtag/connection.rb', line 163

def transmit_data(bytes, bit_count, pad_to_chain_length=false, prefix_with_zeroes=0, do_not_finish=false)

  #If the pad-to-chain length option is selected, compute the total amount of padding required.
  #Otherwise, set the required padding to zero.
  padding_after = pad_to_chain_length ? [@devices_in_chain - prefix_with_zeroes - 1, 0].max : 0

  #Move to the Exit1IR state after transmission, allowing the recieved data to be processed,
  #unless the do_not_finish value is set.
  state_after = do_not_finish ? nil : TAPStates::Exit1DR

  #Transmit the actual instruction.
  transmit_in_state(TAPStates::ShiftDR, bytes, bit_count, state_after, false, prefix_with_zeroes, padding_after)

end

#transmit_instruction(bytes, bit_count, pad_to_chain_length = false, prefix_with_ones = 0, do_not_finish = false) ⇒ Object

Transmit an instruction over the JTAG test access lines, to be placed into the JTAG instruction register.

bytes: A byte-string which contains the instruction to be transmitted. bit_count: The total amount of bits to be transmitted from the byte string.

pad_to_chain_length:

If set, the transmitted data will be suffixed with logic '1's until the chain length has been met.
This allows the transmitter to easily put devices to the "left" of  afttarget device into bypass.

prefix_with_ones:

Prefixes the transmitted data with the specified amount of logic '1's. Prefixing is skipped if this parameter
is not provided, or is set to zero. This allows the transmitter to easily put devices to the "right" of a
target device into bypass.

do_not_finish:

If set, the device will be left in the ShiftIR state, so additional instructions data be transmitted.


129
130
131
132
133
134
135
136
137
138
139
140
141
142
# File 'lib/adept/jtag/connection.rb', line 129

def transmit_instruction(bytes, bit_count, pad_to_chain_length=false, prefix_with_ones=0, do_not_finish=false)

  #If the pad-to-chain length option is selected, compute the total amount of padding required.
  #Otherwise, set the required padding to zero.
  padding_after = pad_to_chain_length ? [@chain_length - prefix_with_ones - bit_count, 0].max : 0

  #Move to the Exit1IR state after transmission, allowing the recieved data to be processed,
  #unless the do_not_finish value is set.
  state_after = do_not_finish ? nil : TAPStates::Exit1IR

  #Transmit the actual instruction.
  transmit_in_state(TAPStates::ShiftIR, bytes, bit_count, state_after, true, prefix_with_ones, padding_after)

end