Class: Msp430Bsl::Uart::Connection

Inherits:
Object
  • Object
show all
Defined in:
lib/msp430_bsl/uart/connection.rb

Constant Summary collapse

UART_CONFIGS =
{ data_bits: 8, stop_bits: 1, parity: SerialPort::EVEN }.transform_keys(&:to_s).freeze
WAIT_FOR_ACK_MAX =
1000.millis
WAIT_FOR_RESPONSE_MAX =
1000.millis
MEM_START_MAIN_FLASH =
0x8000
CORE_COMMANDS_BUFFER_SIZE =
260

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(device_path, opts = {}) ⇒ Connection

Returns a new instance of Connection.



20
21
22
23
24
25
26
27
# File 'lib/msp430_bsl/uart/connection.rb', line 20

def initialize(device_path, opts = {})
  @device_path = device_path
  @logger = opts.fetch :logger, Logger.new(STDOUT)
  @cmd_buff_size = opts.fetch :cmd_buf_size, CORE_COMMANDS_BUFFER_SIZE

  @serial_port = SerialPort.new @device_path
  @serial_port.flow_control = SerialPort::NONE
end

Instance Attribute Details

#cmd_buff_sizeObject (readonly)

Returns the value of attribute cmd_buff_size.



18
19
20
# File 'lib/msp430_bsl/uart/connection.rb', line 18

def cmd_buff_size
  @cmd_buff_size
end

#device_pathObject (readonly)

Returns the value of attribute device_path.



18
19
20
# File 'lib/msp430_bsl/uart/connection.rb', line 18

def device_path
  @device_path
end

#loggerObject (readonly)

Returns the value of attribute logger.



18
19
20
# File 'lib/msp430_bsl/uart/connection.rb', line 18

def logger
  @logger
end

#serial_portObject (readonly)

Returns the value of attribute serial_port.



18
19
20
# File 'lib/msp430_bsl/uart/connection.rb', line 18

def serial_port
  @serial_port
end

Instance Method Details

#check_bsl_replyObject



33
34
35
# File 'lib/msp430_bsl/uart/connection.rb', line 33

def check_bsl_reply
  reply.length > 1 && reply[0] == BSL_MESSAGE && reply[1] == BSL_OK
end

#close_connectionObject



29
30
31
# File 'lib/msp430_bsl/uart/connection.rb', line 29

def close_connection
  serial_port.close
end

#enter_bslObject



37
38
39
40
41
# File 'lib/msp430_bsl/uart/connection.rb', line 37

def enter_bsl
  logger.info "Connecting to target board through UART on #{device_path}"
  set_uart_speed 9600
  invoke_bsl
end

#read_response_for(command) ⇒ Object

Raises:

  • (ArgumentError)


43
44
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
84
85
86
87
88
89
90
91
92
93
# File 'lib/msp430_bsl/uart/connection.rb', line 43

def read_response_for(command)
  raise ArgumentError, "an instance of Msp430Bsl::Command is expected as argument. Given: '#{command.class}'" unless command.is_a?(Command)

  # Wait for first response byte - UART's ACK/NACK
  ack = nil
  begin
    Timeout::timeout(WAIT_FOR_ACK_MAX) do
      ack = Ack.new serial_port.getbyte
    end
  rescue Timeout::Error => e
    logger.error 'Timeout occurred while waiting for UART ACK'
    raise e
  end

  # If we arrived here, ack has been populated
  if ack && ack.ok?
    logger.debug "IN  <- ACK (1 byte) 0x#{ack.value.to_hex_str}"
  else
    logger.error ack.reason
    raise Exceptions::Ack::NOK, ack.value
  end

  # If this command has not response, return
  unless command.configs[:response][:kind]
    return ack
  end

  # Wait for command response
  begin
    pi = PeripheralInterface.new
    Timeout::timeout(WAIT_FOR_RESPONSE_MAX) do
      loop do
        read = serial_port.readpartial cmd_buff_size
        pi.push read.unpack 'C*'
        break if pi.valid?
      end
    end
  rescue Timeout::Error => e
    logger.error 'Timeout occurred while fetching response from UART'
    raise e
  end

  # Unwrap PeripheralInterface and create Response
  logger.debug "IN  <- RES (#{pi.packet.size} bytes) #{pi.to_hex_ary_str}"
  response = pi.to_response
  unless response.is_ok_given_command? command
    raise Msp430Bsl::Exceptions::Response::NotValid, response.errors
  end

  response
end

#send_command(cmd_name, addr: nil, data: nil, log_only: false) ⇒ Object



95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/msp430_bsl/uart/connection.rb', line 95

def send_command(cmd_name, addr: nil, data: nil, log_only: false)
  command = Command.new cmd_name, addr: addr, data: data
  pi = PeripheralInterface.wrap command
  logger.debug "Sending command '#{command.name}' over UART"
  # Flush serial's output and input before sending a new command
  serial_port.flush_output
  serial_port.flush_input

  unless pi.valid?
    logger.error "PeripheralInterface not valid. Errors: #{pi.errors}"
    return nil
  end

  logger.debug "OUT -> (#{pi.packet.size} bytes) #{pi.to_hex_ary_str}"
  unless log_only
    serial_port.write pi.to_uart
    read_response_for command
  end
end

#set_uart_speed(baud) ⇒ Object

Raises:

  • (StandardError)


115
116
117
118
119
120
121
122
123
# File 'lib/msp430_bsl/uart/connection.rb', line 115

def set_uart_speed(baud)
  raise StandardError, "BAUD not supported. Supported BAUD: #{Configs::BAUD_RATES.keys}" unless Configs::BAUD_RATES.keys.include?(baud)

  logger.debug "Setting serial port BAUD to #{baud} bps"

  serial_port.set_modem_params UART_CONFIGS.merge('baud' => baud)  # We must use strings as keys
  test_pin_go :high
  reset_pin_go :low
end

#trigger_resetObject



125
126
127
128
129
130
131
132
# File 'lib/msp430_bsl/uart/connection.rb', line 125

def trigger_reset
  # slau319 pag. 5 - Fig. 1-1
  reset_pin_go :low
  test_pin_go :low
  sleep 5.millis
  reset_pin_go :high
  sleep 5.millis
end