Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(105)

Side by Side Diff: tools/battor_agent/battor_agent.cc

Issue 1991403002: [battor agent] Fix the init sequence so it retries inits instead of resets. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fixed comment Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « tools/battor_agent/battor_agent.h ('k') | tools/battor_agent/battor_agent_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "tools/battor_agent/battor_agent.h" 5 #include "tools/battor_agent/battor_agent.h"
6 6
7 #include <iomanip> 7 #include <iomanip>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/threading/thread_task_runner_handle.h" 10 #include "base/threading/thread_task_runner_handle.h"
11 #include "tools/battor_agent/battor_connection_impl.h" 11 #include "tools/battor_agent/battor_connection_impl.h"
12 #include "tools/battor_agent/battor_sample_converter.h" 12 #include "tools/battor_agent/battor_sample_converter.h"
13 13
14 using std::vector; 14 using std::vector;
15 15
16 namespace battor { 16 namespace battor {
17 17
18 namespace { 18 namespace {
19 19
20 // The number of seconds that it takes a BattOr to reset. 20 // The maximum number of times to retry when init'ing a battor.
21 const uint8_t kBattOrResetTimeSeconds = 5; 21 const uint8_t kMaxInitAttempts = 20;
22
23 // The number of milliseconds to wait before trying to init again.
24 const uint16_t kInitRetryDelayMilliseconds = 100;
22 25
23 // The maximum number of times to retry when reading a message. 26 // The maximum number of times to retry when reading a message.
24 const uint8_t kMaxReadAttempts = 20; 27 const uint8_t kMaxReadAttempts = 20;
25 28
26 // The number of milliseconds to wait before trying to read a message again. 29 // The number of milliseconds to wait before trying to read a message again.
27 const uint8_t kReadRetryDelayMilliseconds = 1; 30 const uint8_t kReadRetryDelayMilliseconds = 1;
28 31
29 // The amount of time we need to wait after recording a clock sync marker in 32 // The amount of time we need to wait after recording a clock sync marker in
30 // order to ensure that the sample we synced to doesn't get thrown out. 33 // order to ensure that the sample we synced to doesn't get thrown out.
31 const uint8_t kStopTracingClockSyncDelayMilliseconds = 100; 34 const uint8_t kStopTracingClockSyncDelayMilliseconds = 100;
32 35
33 // The number of seconds allowed for a given action before timing out. 36 // The number of seconds allowed for a given action before timing out.
34 const uint8_t kBattOrTimeoutSeconds = 10; 37 const uint8_t kBattOrTimeoutSeconds = 4;
35 38
36 // Returns true if the specified vector of bytes decodes to a message that is an 39 // Returns true if the specified vector of bytes decodes to a message that is an
37 // ack for the specified control message type. 40 // ack for the specified control message type.
38 bool IsAckOfControlCommand(BattOrMessageType message_type, 41 bool IsAckOfControlCommand(BattOrMessageType message_type,
39 BattOrControlMessageType control_message_type, 42 BattOrControlMessageType control_message_type,
40 const vector<char>& msg) { 43 const vector<char>& msg) {
41 if (message_type != BATTOR_MESSAGE_TYPE_CONTROL_ACK) 44 if (message_type != BATTOR_MESSAGE_TYPE_CONTROL_ACK)
42 return false; 45 return false;
43 46
44 if (msg.size() != sizeof(BattOrControlMessageAck)) 47 if (msg.size() != sizeof(BattOrControlMessageAck))
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
112 Listener* listener, 115 Listener* listener,
113 scoped_refptr<base::SingleThreadTaskRunner> file_thread_task_runner, 116 scoped_refptr<base::SingleThreadTaskRunner> file_thread_task_runner,
114 scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner) 117 scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner)
115 : connection_(new BattOrConnectionImpl(path, 118 : connection_(new BattOrConnectionImpl(path,
116 this, 119 this,
117 file_thread_task_runner, 120 file_thread_task_runner,
118 ui_thread_task_runner)), 121 ui_thread_task_runner)),
119 listener_(listener), 122 listener_(listener),
120 last_action_(Action::INVALID), 123 last_action_(Action::INVALID),
121 command_(Command::INVALID), 124 command_(Command::INVALID),
125 num_init_attempts_(0),
122 num_read_attempts_(0) { 126 num_read_attempts_(0) {
123 // We don't care what thread the constructor is called on - we only care that 127 // We don't care what thread the constructor is called on - we only care that
124 // all of the other method invocations happen on the same thread. 128 // all of the other method invocations happen on the same thread.
125 thread_checker_.DetachFromThread(); 129 thread_checker_.DetachFromThread();
126 } 130 }
127 131
128 BattOrAgent::~BattOrAgent() { 132 BattOrAgent::~BattOrAgent() {
129 DCHECK(thread_checker_.CalledOnValidThread()); 133 DCHECK(thread_checker_.CalledOnValidThread());
130 } 134 }
131 135
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
167 return; 171 return;
168 timeout_callback_.Cancel(); 172 timeout_callback_.Cancel();
169 173
170 if (!success) { 174 if (!success) {
171 CompleteCommand(BATTOR_ERROR_CONNECTION_FAILED); 175 CompleteCommand(BATTOR_ERROR_CONNECTION_FAILED);
172 return; 176 return;
173 } 177 }
174 178
175 switch (command_) { 179 switch (command_) {
176 case Command::START_TRACING: 180 case Command::START_TRACING:
177 // TODO(charliea): Ideally, we'd just like to send an init, and the BattOr 181 num_init_attempts_ = 1;
178 // firmware can handle whether a reset is necessary or not, sending an 182 PerformAction(Action::SEND_INIT);
179 // init ack regardless. This reset can be removed once this is true.
180 // https://github.com/aschulm/battor/issues/30 tracks this.
181 PerformAction(Action::SEND_RESET);
182 return; 183 return;
183 case Command::STOP_TRACING: 184 case Command::STOP_TRACING:
184 PerformAction(Action::SEND_EEPROM_REQUEST); 185 PerformAction(Action::SEND_EEPROM_REQUEST);
185 return; 186 return;
186 case Command::RECORD_CLOCK_SYNC_MARKER: 187 case Command::RECORD_CLOCK_SYNC_MARKER:
187 PerformAction(Action::SEND_CURRENT_SAMPLE_REQUEST); 188 PerformAction(Action::SEND_CURRENT_SAMPLE_REQUEST);
188 return; 189 return;
189 case Command::INVALID: 190 case Command::INVALID:
190 NOTREACHED(); 191 NOTREACHED();
191 } 192 }
192 } 193 }
193 194
194 void BattOrAgent::OnBytesSent(bool success) { 195 void BattOrAgent::OnBytesSent(bool success) {
195 DCHECK(thread_checker_.CalledOnValidThread()); 196 DCHECK(thread_checker_.CalledOnValidThread());
196 197
197 // Return immediately if whatever action we were trying to perform already 198 // Return immediately if whatever action we were trying to perform already
198 // timed out. 199 // timed out.
199 if (timeout_callback_.IsCancelled()) 200 if (timeout_callback_.IsCancelled())
200 return; 201 return;
201 timeout_callback_.Cancel(); 202 timeout_callback_.Cancel();
202 203
203 if (!success) { 204 if (!success) {
204 CompleteCommand(BATTOR_ERROR_SEND_ERROR); 205 CompleteCommand(BATTOR_ERROR_SEND_ERROR);
205 return; 206 return;
206 } 207 }
207 208
208 switch (last_action_) { 209 switch (last_action_) {
209 case Action::SEND_RESET:
210 // TODO(charliea): Ideally, we'd just like to send an init, and the BattOr
211 // firmware can handle whether a reset is necessary or not, sending an
212 // init ack regardless. This reset can be removed once this is true.
213 // https://github.com/aschulm/battor/issues/30 tracks this.
214
215 // Wait for the reset to happen before sending the init message.
216 PerformDelayedAction(Action::SEND_INIT, base::TimeDelta::FromSeconds(
217 kBattOrResetTimeSeconds));
218 return;
219 case Action::SEND_INIT: 210 case Action::SEND_INIT:
220 PerformAction(Action::READ_INIT_ACK); 211 PerformAction(Action::READ_INIT_ACK);
221 return; 212 return;
222 case Action::SEND_SET_GAIN: 213 case Action::SEND_SET_GAIN:
223 PerformAction(Action::READ_SET_GAIN_ACK); 214 PerformAction(Action::READ_SET_GAIN_ACK);
224 return; 215 return;
225 case Action::SEND_START_TRACING: 216 case Action::SEND_START_TRACING:
226 PerformAction(Action::READ_START_TRACING_ACK); 217 PerformAction(Action::READ_START_TRACING_ACK);
227 return; 218 return;
228 case Action::SEND_EEPROM_REQUEST: 219 case Action::SEND_EEPROM_REQUEST:
(...skipping 30 matching lines...) Expand all
259 case Action::READ_CURRENT_SAMPLE: 250 case Action::READ_CURRENT_SAMPLE:
260 if (++num_read_attempts_ > kMaxReadAttempts) { 251 if (++num_read_attempts_ > kMaxReadAttempts) {
261 CompleteCommand(BATTOR_ERROR_RECEIVE_ERROR); 252 CompleteCommand(BATTOR_ERROR_RECEIVE_ERROR);
262 return; 253 return;
263 } 254 }
264 255
265 PerformDelayedAction(last_action_, base::TimeDelta::FromMilliseconds( 256 PerformDelayedAction(last_action_, base::TimeDelta::FromMilliseconds(
266 kReadRetryDelayMilliseconds)); 257 kReadRetryDelayMilliseconds));
267 return; 258 return;
268 259
260 // Retry sending an INIT if it an ACK is not received.
261 case Action::SEND_INIT:
262 case Action::READ_INIT_ACK:
263 if (num_init_attempts_++ < kMaxInitAttempts) {
264 PerformDelayedAction(Action::SEND_INIT,
265 base::TimeDelta::FromMilliseconds(kInitRetryDelayMilliseconds));
266 } else {
267 CompleteCommand(BATTOR_ERROR_TOO_MANY_INIT_RETRIES);
268 }
269
270 return;
271
269 default: 272 default:
270 CompleteCommand(BATTOR_ERROR_RECEIVE_ERROR); 273 CompleteCommand(BATTOR_ERROR_RECEIVE_ERROR);
271 return; 274 return;
272 } 275 }
273 } 276 }
274 277
275 switch (last_action_) { 278 switch (last_action_) {
276 case Action::READ_INIT_ACK: 279 case Action::READ_INIT_ACK:
277 if (!IsAckOfControlCommand(type, BATTOR_CONTROL_MESSAGE_TYPE_INIT, 280 if (!IsAckOfControlCommand(type, BATTOR_CONTROL_MESSAGE_TYPE_INIT,
278 *bytes)) { 281 *bytes)) {
279 CompleteCommand(BATTOR_ERROR_UNEXPECTED_MESSAGE); 282 if (num_init_attempts_++ < kMaxInitAttempts) {
283 PerformDelayedAction(Action::SEND_INIT,
284 base::TimeDelta::FromMilliseconds(kInitRetryDelayMilliseconds));
285 } else {
286 CompleteCommand(BATTOR_ERROR_TOO_MANY_INIT_RETRIES);
287 }
288
280 return; 289 return;
281 } 290 }
282 291
283 PerformAction(Action::SEND_SET_GAIN); 292 PerformAction(Action::SEND_SET_GAIN);
284 return; 293 return;
285 294
286 case Action::READ_SET_GAIN_ACK: 295 case Action::READ_SET_GAIN_ACK:
287 if (!IsAckOfControlCommand(type, BATTOR_CONTROL_MESSAGE_TYPE_SET_GAIN, 296 if (!IsAckOfControlCommand(type, BATTOR_CONTROL_MESSAGE_TYPE_SET_GAIN,
288 *bytes)) { 297 *bytes)) {
289 CompleteCommand(BATTOR_ERROR_UNEXPECTED_MESSAGE); 298 CompleteCommand(BATTOR_ERROR_UNEXPECTED_MESSAGE);
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
393 base::TimeDelta::FromSeconds(kBattOrTimeoutSeconds)); 402 base::TimeDelta::FromSeconds(kBattOrTimeoutSeconds));
394 403
395 last_action_ = action; 404 last_action_ = action;
396 405
397 switch (action) { 406 switch (action) {
398 case Action::REQUEST_CONNECTION: 407 case Action::REQUEST_CONNECTION:
399 BeginConnect(); 408 BeginConnect();
400 return; 409 return;
401 410
402 // The following actions are required for StartTracing: 411 // The following actions are required for StartTracing:
403 case Action::SEND_RESET:
404 // Reset the BattOr to clear any preexisting state. After sending the
405 // reset signal, we need to wait for the reset to finish before issuing
406 // further commands.
407 SendControlMessage(BATTOR_CONTROL_MESSAGE_TYPE_RESET, 0, 0);
408 return;
409 case Action::SEND_INIT: 412 case Action::SEND_INIT:
410 // After resetting the BattOr, we need to make sure to flush the serial 413 // Clear out the serial data that may exist from prior init attempts.
411 // stream. Strange data may have been written into it during the reset.
412 connection_->Flush(); 414 connection_->Flush();
413 415
414 SendControlMessage(BATTOR_CONTROL_MESSAGE_TYPE_INIT, 0, 0); 416 SendControlMessage(BATTOR_CONTROL_MESSAGE_TYPE_INIT, 0, 0);
415 return; 417 return;
416 case Action::READ_INIT_ACK: 418 case Action::READ_INIT_ACK:
417 connection_->ReadMessage(BATTOR_MESSAGE_TYPE_CONTROL_ACK); 419 connection_->ReadMessage(BATTOR_MESSAGE_TYPE_CONTROL_ACK);
418 return; 420 return;
419 case Action::SEND_SET_GAIN: 421 case Action::SEND_SET_GAIN:
420 // Set the BattOr's gain. Setting the gain tells the BattOr the range of 422 // Set the BattOr's gain. Setting the gain tells the BattOr the range of
421 // power measurements that we expect to see. 423 // power measurements that we expect to see.
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
476 } 478 }
477 } 479 }
478 480
479 void BattOrAgent::PerformDelayedAction(Action action, base::TimeDelta delay) { 481 void BattOrAgent::PerformDelayedAction(Action action, base::TimeDelta delay) {
480 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( 482 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
481 FROM_HERE, base::Bind(&BattOrAgent::PerformAction, AsWeakPtr(), action), 483 FROM_HERE, base::Bind(&BattOrAgent::PerformAction, AsWeakPtr(), action),
482 delay); 484 delay);
483 } 485 }
484 486
485 void BattOrAgent::OnActionTimeout() { 487 void BattOrAgent::OnActionTimeout() {
486 CompleteCommand(BATTOR_ERROR_TIMEOUT); 488 switch (last_action_) {
489 case Action::READ_INIT_ACK:
490 if (num_init_attempts_++ < kMaxInitAttempts) {
491 // OnMessageRead() will fail and retry SEND_INIT.
492 connection_->CancelReadMessage();
493 } else {
494 CompleteCommand(BATTOR_ERROR_TOO_MANY_INIT_RETRIES);
495 }
496
497 return;
498
499 default:
500 CompleteCommand(BATTOR_ERROR_TIMEOUT);
501 }
502
487 timeout_callback_.Cancel(); 503 timeout_callback_.Cancel();
488 } 504 }
489 505
490 void BattOrAgent::SendControlMessage(BattOrControlMessageType type, 506 void BattOrAgent::SendControlMessage(BattOrControlMessageType type,
491 uint16_t param1, 507 uint16_t param1,
492 uint16_t param2) { 508 uint16_t param2) {
493 DCHECK(thread_checker_.CalledOnValidThread()); 509 DCHECK(thread_checker_.CalledOnValidThread());
494 510
495 BattOrControlMessage msg{type, param1, param2}; 511 BattOrControlMessage msg{type, param1, param2};
496 connection_->SendBytes(BATTOR_MESSAGE_TYPE_CONTROL, &msg, sizeof(msg)); 512 connection_->SendBytes(BATTOR_MESSAGE_TYPE_CONTROL, &msg, sizeof(msg));
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
561 if (clock_sync_marker != clock_sync_markers_.end()) 577 if (clock_sync_marker != clock_sync_markers_.end())
562 trace_stream << " <" << clock_sync_marker->second << ">"; 578 trace_stream << " <" << clock_sync_marker->second << ">";
563 579
564 trace_stream << std::endl; 580 trace_stream << std::endl;
565 } 581 }
566 582
567 return trace_stream.str(); 583 return trace_stream.str();
568 } 584 }
569 585
570 } // namespace battor 586 } // namespace battor
OLDNEW
« no previous file with comments | « tools/battor_agent/battor_agent.h ('k') | tools/battor_agent/battor_agent_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698