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

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: Initial draft Created 4 years, 7 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
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.
21 const uint8_t kBattOrResetTimeSeconds = 5;
22
23 // The maximum number of times to retry when reading a message. 20 // The maximum number of times to retry when reading a message.
24 const uint8_t kMaxReadAttempts = 20; 21 const uint8_t kMaxReadAttempts = 20;
25 22
23 // The maximum number of times to retry when init'ing a battor.
24 const uint8_t kMaxInitAttempts = 20;
25
26 // The number of milliseconds to wait before trying to init again.
27 const uint8_t kInitRetryDelayMilliseconds = 100;
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 = 10;
35 38
(...skipping 76 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),
122 num_read_attempts_(0) { 125 num_read_attempts_(0),
126 num_init_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
132 void BattOrAgent::StartTracing() { 136 void BattOrAgent::StartTracing() {
(...skipping 34 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 // Reset the timeout because there is a failed read after it is canceled.
261 case Action::SEND_INIT:
charliea (OOO until 10-5) 2016/05/23 14:08:52 I'm not sure I understand why this part is necessa
aschulman 2016/06/10 07:22:59 You are right this is confusing, especially since
262 timeout_callback_.Reset(
263 base::Bind(&BattOrAgent::OnActionTimeout, AsWeakPtr()));
264 return;
265
266 // Retry sending an INIT if it an ACK is not received.
267 case Action::READ_INIT_ACK:
268 if (++num_init_attempts_ < kMaxInitAttempts)
charliea (OOO until 10-5) 2016/05/23 14:08:51 nit: any time that there are multiple lines inside
aschulman 2016/06/10 07:22:59 Done.
269 PerformDelayedAction(Action::SEND_INIT,
270 base::TimeDelta::FromMilliseconds(kInitRetryDelayMilliseconds));
271 else
272 CompleteCommand(BATTOR_ERROR_INIT_ERROR);
273 return;
274
269 default: 275 default:
270 CompleteCommand(BATTOR_ERROR_RECEIVE_ERROR); 276 CompleteCommand(BATTOR_ERROR_RECEIVE_ERROR);
271 return; 277 return;
272 } 278 }
273 } 279 }
274 280
275 switch (last_action_) { 281 switch (last_action_) {
276 case Action::READ_INIT_ACK: 282 case Action::READ_INIT_ACK:
277 if (!IsAckOfControlCommand(type, BATTOR_CONTROL_MESSAGE_TYPE_INIT, 283 if (!IsAckOfControlCommand(type, BATTOR_CONTROL_MESSAGE_TYPE_INIT,
278 *bytes)) { 284 *bytes)) {
279 CompleteCommand(BATTOR_ERROR_UNEXPECTED_MESSAGE); 285 if (++num_init_attempts_ < kMaxInitAttempts)
286 PerformDelayedAction(Action::SEND_INIT,
charliea (OOO until 10-5) 2016/05/23 14:08:51 (same not about braces as above)
aschulman 2016/06/10 07:22:59 Done.
287 base::TimeDelta::FromMilliseconds(kInitRetryDelayMilliseconds));
288 else
289 CompleteCommand(BATTOR_ERROR_INIT_ERROR);
280 return; 290 return;
281 } 291 }
282 292
283 PerformAction(Action::SEND_SET_GAIN); 293 PerformAction(Action::SEND_SET_GAIN);
284 return; 294 return;
285 295
286 case Action::READ_SET_GAIN_ACK: 296 case Action::READ_SET_GAIN_ACK:
287 if (!IsAckOfControlCommand(type, BATTOR_CONTROL_MESSAGE_TYPE_SET_GAIN, 297 if (!IsAckOfControlCommand(type, BATTOR_CONTROL_MESSAGE_TYPE_SET_GAIN,
288 *bytes)) { 298 *bytes)) {
289 CompleteCommand(BATTOR_ERROR_UNEXPECTED_MESSAGE); 299 CompleteCommand(BATTOR_ERROR_UNEXPECTED_MESSAGE);
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
393 base::TimeDelta::FromSeconds(kBattOrTimeoutSeconds)); 403 base::TimeDelta::FromSeconds(kBattOrTimeoutSeconds));
394 404
395 last_action_ = action; 405 last_action_ = action;
396 406
397 switch (action) { 407 switch (action) {
398 case Action::REQUEST_CONNECTION: 408 case Action::REQUEST_CONNECTION:
399 BeginConnect(); 409 BeginConnect();
400 return; 410 return;
401 411
402 // The following actions are required for StartTracing: 412 // The following actions are required for StartTracing:
403 case Action::SEND_RESET: 413 case Action::SEND_RESET:
charliea (OOO until 10-5) 2016/05/23 14:08:51 This can be deleted
aschulman 2016/06/10 07:22:59 Done.
404 // Reset the BattOr to clear any preexisting state. After sending the 414 // 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 415 // reset signal, we need to wait for the reset to finish before issuing
406 // further commands. 416 // further commands.
407 SendControlMessage(BATTOR_CONTROL_MESSAGE_TYPE_RESET, 0, 0); 417 SendControlMessage(BATTOR_CONTROL_MESSAGE_TYPE_RESET, 0, 0);
408 return; 418 return;
409 case Action::SEND_INIT: 419 case Action::SEND_INIT:
410 // After resetting the BattOr, we need to make sure to flush the serial 420 // After resetting the BattOr, we need to make sure to flush the serial
411 // stream. Strange data may have been written into it during the reset. 421 // stream. Strange data may have been written into it during the reset.
412 connection_->Flush(); 422 connection_->Flush();
413 423
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
476 } 486 }
477 } 487 }
478 488
479 void BattOrAgent::PerformDelayedAction(Action action, base::TimeDelta delay) { 489 void BattOrAgent::PerformDelayedAction(Action action, base::TimeDelta delay) {
480 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( 490 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
481 FROM_HERE, base::Bind(&BattOrAgent::PerformAction, AsWeakPtr(), action), 491 FROM_HERE, base::Bind(&BattOrAgent::PerformAction, AsWeakPtr(), action),
482 delay); 492 delay);
483 } 493 }
484 494
485 void BattOrAgent::OnActionTimeout() { 495 void BattOrAgent::OnActionTimeout() {
486 CompleteCommand(BATTOR_ERROR_TIMEOUT); 496 switch (last_action_) {
charliea (OOO until 10-5) 2016/05/23 14:08:51 nit: when it makes sense, Chromium prefers to "ear
aschulman 2016/06/10 07:22:59 Done.
487 timeout_callback_.Cancel(); 497 case Action::READ_INIT_ACK:
498 if (++num_init_attempts_ < kMaxInitAttempts)
499 {
500 connection_->CancelReadMessage();
501 PerformAction(Action::SEND_INIT);
502 }
503 else
504 CompleteCommand(BATTOR_ERROR_INIT_ERROR);
505 return;
506
507 default:
508 CompleteCommand(BATTOR_ERROR_TIMEOUT);
509 timeout_callback_.Cancel();
510 }
488 } 511 }
489 512
490 void BattOrAgent::SendControlMessage(BattOrControlMessageType type, 513 void BattOrAgent::SendControlMessage(BattOrControlMessageType type,
491 uint16_t param1, 514 uint16_t param1,
492 uint16_t param2) { 515 uint16_t param2) {
493 DCHECK(thread_checker_.CalledOnValidThread()); 516 DCHECK(thread_checker_.CalledOnValidThread());
494 517
495 BattOrControlMessage msg{type, param1, param2}; 518 BattOrControlMessage msg{type, param1, param2};
496 connection_->SendBytes(BATTOR_MESSAGE_TYPE_CONTROL, &msg, sizeof(msg)); 519 connection_->SendBytes(BATTOR_MESSAGE_TYPE_CONTROL, &msg, sizeof(msg));
497 } 520 }
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
561 if (clock_sync_marker != clock_sync_markers_.end()) 584 if (clock_sync_marker != clock_sync_markers_.end())
562 trace_stream << " <" << clock_sync_marker->second << ">"; 585 trace_stream << " <" << clock_sync_marker->second << ">";
563 586
564 trace_stream << std::endl; 587 trace_stream << std::endl;
565 } 588 }
566 589
567 return trace_stream.str(); 590 return trace_stream.str();
568 } 591 }
569 592
570 } // namespace battor 593 } // namespace battor
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698