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

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: Cleaned up and ready for a 2nd review 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
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 #include <iostream>
8 9
9 #include "base/bind.h" 10 #include "base/bind.h"
10 #include "base/threading/thread_task_runner_handle.h" 11 #include "base/threading/thread_task_runner_handle.h"
11 #include "tools/battor_agent/battor_connection_impl.h" 12 #include "tools/battor_agent/battor_connection_impl.h"
12 #include "tools/battor_agent/battor_sample_converter.h" 13 #include "tools/battor_agent/battor_sample_converter.h"
13 14
14 using std::vector; 15 using std::vector;
15 16
16 namespace battor { 17 namespace battor {
17 18
18 namespace { 19 namespace {
19 20
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. 21 // The maximum number of times to retry when reading a message.
24 const uint8_t kMaxReadAttempts = 20; 22 const uint8_t kMaxReadAttempts = 20;
25 23
24 // The maximum number of times to retry when init'ing a battor.
charliea (OOO until 10-5) 2016/06/10 17:05:33 same nit about maybe putting this above the read a
aschulman 2016/06/10 18:27:25 Done.
25 const uint8_t kMaxInitAttempts = 20;
26
27 // The number of milliseconds to wait before trying to init again.
28 const uint16_t kInitRetryDelayMilliseconds = 100;
29
26 // The number of milliseconds to wait before trying to read a message again. 30 // The number of milliseconds to wait before trying to read a message again.
27 const uint8_t kReadRetryDelayMilliseconds = 1; 31 const uint8_t kReadRetryDelayMilliseconds = 1;
28 32
29 // The amount of time we need to wait after recording a clock sync marker in 33 // 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. 34 // order to ensure that the sample we synced to doesn't get thrown out.
31 const uint8_t kStopTracingClockSyncDelayMilliseconds = 100; 35 const uint8_t kStopTracingClockSyncDelayMilliseconds = 100;
32 36
33 // The number of seconds allowed for a given action before timing out. 37 // The number of seconds allowed for a given action before timing out.
34 const uint8_t kBattOrTimeoutSeconds = 10; 38 const uint8_t kBattOrTimeoutSeconds = 4;
35 39
36 // Returns true if the specified vector of bytes decodes to a message that is an 40 // Returns true if the specified vector of bytes decodes to a message that is an
37 // ack for the specified control message type. 41 // ack for the specified control message type.
38 bool IsAckOfControlCommand(BattOrMessageType message_type, 42 bool IsAckOfControlCommand(BattOrMessageType message_type,
39 BattOrControlMessageType control_message_type, 43 BattOrControlMessageType control_message_type,
40 const vector<char>& msg) { 44 const vector<char>& msg) {
41 if (message_type != BATTOR_MESSAGE_TYPE_CONTROL_ACK) 45 if (message_type != BATTOR_MESSAGE_TYPE_CONTROL_ACK)
42 return false; 46 return false;
43 47
44 if (msg.size() != sizeof(BattOrControlMessageAck)) 48 if (msg.size() != sizeof(BattOrControlMessageAck))
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
112 Listener* listener, 116 Listener* listener,
113 scoped_refptr<base::SingleThreadTaskRunner> file_thread_task_runner, 117 scoped_refptr<base::SingleThreadTaskRunner> file_thread_task_runner,
114 scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner) 118 scoped_refptr<base::SingleThreadTaskRunner> ui_thread_task_runner)
115 : connection_(new BattOrConnectionImpl(path, 119 : connection_(new BattOrConnectionImpl(path,
116 this, 120 this,
117 file_thread_task_runner, 121 file_thread_task_runner,
118 ui_thread_task_runner)), 122 ui_thread_task_runner)),
119 listener_(listener), 123 listener_(listener),
120 last_action_(Action::INVALID), 124 last_action_(Action::INVALID),
121 command_(Command::INVALID), 125 command_(Command::INVALID),
122 num_read_attempts_(0) { 126 num_read_attempts_(0),
127 num_init_attempts_(0) {
charliea (OOO until 10-5) 2016/06/10 17:05:33 same nit (swap init and read)
aschulman 2016/06/10 18:27:24 Done.
123 // We don't care what thread the constructor is called on - we only care that 128 // 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. 129 // all of the other method invocations happen on the same thread.
125 thread_checker_.DetachFromThread(); 130 thread_checker_.DetachFromThread();
126 } 131 }
127 132
128 BattOrAgent::~BattOrAgent() { 133 BattOrAgent::~BattOrAgent() {
129 DCHECK(thread_checker_.CalledOnValidThread()); 134 DCHECK(thread_checker_.CalledOnValidThread());
130 } 135 }
131 136
132 void BattOrAgent::StartTracing() { 137 void BattOrAgent::StartTracing() {
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
165 // Return immediately if opening the connection already timed out. 170 // Return immediately if opening the connection already timed out.
166 if (timeout_callback_.IsCancelled()) 171 if (timeout_callback_.IsCancelled())
167 return; 172 return;
168 timeout_callback_.Cancel(); 173 timeout_callback_.Cancel();
169 174
170 if (!success) { 175 if (!success) {
171 CompleteCommand(BATTOR_ERROR_CONNECTION_FAILED); 176 CompleteCommand(BATTOR_ERROR_CONNECTION_FAILED);
172 return; 177 return;
173 } 178 }
174 179
180
charliea (OOO until 10-5) 2016/06/10 17:05:33 nit: delete extra \n
aschulman 2016/06/10 18:27:25 Done.
175 switch (command_) { 181 switch (command_) {
176 case Command::START_TRACING: 182 case Command::START_TRACING:
177 // TODO(charliea): Ideally, we'd just like to send an init, and the BattOr 183 num_init_attempts_ = 1;
178 // firmware can handle whether a reset is necessary or not, sending an 184 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; 185 return;
183 case Command::STOP_TRACING: 186 case Command::STOP_TRACING:
184 PerformAction(Action::SEND_EEPROM_REQUEST); 187 PerformAction(Action::SEND_EEPROM_REQUEST);
185 return; 188 return;
186 case Command::RECORD_CLOCK_SYNC_MARKER: 189 case Command::RECORD_CLOCK_SYNC_MARKER:
187 PerformAction(Action::SEND_CURRENT_SAMPLE_REQUEST); 190 PerformAction(Action::SEND_CURRENT_SAMPLE_REQUEST);
188 return; 191 return;
189 case Command::INVALID: 192 case Command::INVALID:
190 NOTREACHED(); 193 NOTREACHED();
191 } 194 }
192 } 195 }
193 196
194 void BattOrAgent::OnBytesSent(bool success) { 197 void BattOrAgent::OnBytesSent(bool success) {
195 DCHECK(thread_checker_.CalledOnValidThread()); 198 DCHECK(thread_checker_.CalledOnValidThread());
196 199
197 // Return immediately if whatever action we were trying to perform already 200 // Return immediately if whatever action we were trying to perform already
198 // timed out. 201 // timed out.
199 if (timeout_callback_.IsCancelled()) 202 if (timeout_callback_.IsCancelled())
200 return; 203 return;
201 timeout_callback_.Cancel(); 204 timeout_callback_.Cancel();
202 205
203 if (!success) { 206 if (!success) {
204 CompleteCommand(BATTOR_ERROR_SEND_ERROR); 207 CompleteCommand(BATTOR_ERROR_SEND_ERROR);
205 return; 208 return;
206 } 209 }
207 210
208 switch (last_action_) { 211 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: 212 case Action::SEND_INIT:
220 PerformAction(Action::READ_INIT_ACK); 213 PerformAction(Action::READ_INIT_ACK);
221 return; 214 return;
222 case Action::SEND_SET_GAIN: 215 case Action::SEND_SET_GAIN:
223 PerformAction(Action::READ_SET_GAIN_ACK); 216 PerformAction(Action::READ_SET_GAIN_ACK);
224 return; 217 return;
225 case Action::SEND_START_TRACING: 218 case Action::SEND_START_TRACING:
226 PerformAction(Action::READ_START_TRACING_ACK); 219 PerformAction(Action::READ_START_TRACING_ACK);
227 return; 220 return;
228 case Action::SEND_EEPROM_REQUEST: 221 case Action::SEND_EEPROM_REQUEST:
(...skipping 30 matching lines...) Expand all
259 case Action::READ_CURRENT_SAMPLE: 252 case Action::READ_CURRENT_SAMPLE:
260 if (++num_read_attempts_ > kMaxReadAttempts) { 253 if (++num_read_attempts_ > kMaxReadAttempts) {
261 CompleteCommand(BATTOR_ERROR_RECEIVE_ERROR); 254 CompleteCommand(BATTOR_ERROR_RECEIVE_ERROR);
262 return; 255 return;
263 } 256 }
264 257
265 PerformDelayedAction(last_action_, base::TimeDelta::FromMilliseconds( 258 PerformDelayedAction(last_action_, base::TimeDelta::FromMilliseconds(
266 kReadRetryDelayMilliseconds)); 259 kReadRetryDelayMilliseconds));
267 return; 260 return;
268 261
262 // Retry sending an INIT if it an ACK is not received.
263 case Action::SEND_INIT:
264 case Action::READ_INIT_ACK:
265 if (++num_init_attempts_ < kMaxInitAttempts) {
charliea (OOO until 10-5) 2016/06/10 17:05:33 This definitely stems from problematic code that I
aschulman 2016/06/10 18:27:25 Done.
266 PerformDelayedAction(Action::SEND_INIT,
267 base::TimeDelta::FromMilliseconds(kInitRetryDelayMilliseconds));
268 } else {
269 CompleteCommand(BATTOR_ERROR_INIT_MAX_RETRIES);
270 }
271
272 return;
273
269 default: 274 default:
270 CompleteCommand(BATTOR_ERROR_RECEIVE_ERROR); 275 CompleteCommand(BATTOR_ERROR_RECEIVE_ERROR);
271 return; 276 return;
272 } 277 }
273 } 278 }
274 279
275 switch (last_action_) { 280 switch (last_action_) {
276 case Action::READ_INIT_ACK: 281 case Action::READ_INIT_ACK:
277 if (!IsAckOfControlCommand(type, BATTOR_CONTROL_MESSAGE_TYPE_INIT, 282 if (!IsAckOfControlCommand(type, BATTOR_CONTROL_MESSAGE_TYPE_INIT,
278 *bytes)) { 283 *bytes)) {
279 CompleteCommand(BATTOR_ERROR_UNEXPECTED_MESSAGE); 284 if (++num_init_attempts_ < kMaxInitAttempts) {
280 return; 285 PerformDelayedAction(Action::SEND_INIT,
286 base::TimeDelta::FromMilliseconds(kInitRetryDelayMilliseconds));
287 } else {
288 CompleteCommand(BATTOR_ERROR_INIT_MAX_RETRIES);
289 }
290
291 return;
charliea (OOO until 10-5) 2016/06/10 17:05:33 I think this return; is indented wrong (by one spa
aschulman 2016/06/10 18:27:24 Done.
281 } 292 }
282 293
283 PerformAction(Action::SEND_SET_GAIN); 294 PerformAction(Action::SEND_SET_GAIN);
284 return; 295 return;
285 296
286 case Action::READ_SET_GAIN_ACK: 297 case Action::READ_SET_GAIN_ACK:
287 if (!IsAckOfControlCommand(type, BATTOR_CONTROL_MESSAGE_TYPE_SET_GAIN, 298 if (!IsAckOfControlCommand(type, BATTOR_CONTROL_MESSAGE_TYPE_SET_GAIN,
288 *bytes)) { 299 *bytes)) {
289 CompleteCommand(BATTOR_ERROR_UNEXPECTED_MESSAGE); 300 CompleteCommand(BATTOR_ERROR_UNEXPECTED_MESSAGE);
290 return; 301 return;
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
393 base::TimeDelta::FromSeconds(kBattOrTimeoutSeconds)); 404 base::TimeDelta::FromSeconds(kBattOrTimeoutSeconds));
394 405
395 last_action_ = action; 406 last_action_ = action;
396 407
397 switch (action) { 408 switch (action) {
398 case Action::REQUEST_CONNECTION: 409 case Action::REQUEST_CONNECTION:
399 BeginConnect(); 410 BeginConnect();
400 return; 411 return;
401 412
402 // The following actions are required for StartTracing: 413 // 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: 414 case Action::SEND_INIT:
410 // After resetting the BattOr, we need to make sure to flush the serial 415 // 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(); 416 connection_->Flush();
413 417
414 SendControlMessage(BATTOR_CONTROL_MESSAGE_TYPE_INIT, 0, 0); 418 SendControlMessage(BATTOR_CONTROL_MESSAGE_TYPE_INIT, 0, 0);
415 return; 419 return;
416 case Action::READ_INIT_ACK: 420 case Action::READ_INIT_ACK:
417 connection_->ReadMessage(BATTOR_MESSAGE_TYPE_CONTROL_ACK); 421 connection_->ReadMessage(BATTOR_MESSAGE_TYPE_CONTROL_ACK);
418 return; 422 return;
419 case Action::SEND_SET_GAIN: 423 case Action::SEND_SET_GAIN:
420 // Set the BattOr's gain. Setting the gain tells the BattOr the range of 424 // Set the BattOr's gain. Setting the gain tells the BattOr the range of
421 // power measurements that we expect to see. 425 // power measurements that we expect to see.
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
476 } 480 }
477 } 481 }
478 482
479 void BattOrAgent::PerformDelayedAction(Action action, base::TimeDelta delay) { 483 void BattOrAgent::PerformDelayedAction(Action action, base::TimeDelta delay) {
480 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( 484 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
481 FROM_HERE, base::Bind(&BattOrAgent::PerformAction, AsWeakPtr(), action), 485 FROM_HERE, base::Bind(&BattOrAgent::PerformAction, AsWeakPtr(), action),
482 delay); 486 delay);
483 } 487 }
484 488
485 void BattOrAgent::OnActionTimeout() { 489 void BattOrAgent::OnActionTimeout() {
486 CompleteCommand(BATTOR_ERROR_TIMEOUT); 490 switch (last_action_) {
491 case Action::READ_INIT_ACK:
492 // Cancel INIT ACK read, OnReadMessage() will fail and retry SEND_INIT.
charliea (OOO until 10-5) 2016/06/10 17:05:33 I'd put this comment inside of the if clause, beca
charliea (OOO until 10-5) 2016/06/10 17:05:33 I think the function is OnMessageRead and not OnRe
aschulman 2016/06/10 18:27:24 Done.
aschulman 2016/06/10 18:27:25 Done.
493 if (++num_init_attempts_ < kMaxInitAttempts)
494 connection_->CancelReadMessage();
495 else
496 CompleteCommand(BATTOR_ERROR_INIT_MAX_RETRIES);
497
498 return;
499
500 default:
501 CompleteCommand(BATTOR_ERROR_TIMEOUT);
502 }
503
487 timeout_callback_.Cancel(); 504 timeout_callback_.Cancel();
488 } 505 }
489 506
490 void BattOrAgent::SendControlMessage(BattOrControlMessageType type, 507 void BattOrAgent::SendControlMessage(BattOrControlMessageType type,
491 uint16_t param1, 508 uint16_t param1,
492 uint16_t param2) { 509 uint16_t param2) {
493 DCHECK(thread_checker_.CalledOnValidThread()); 510 DCHECK(thread_checker_.CalledOnValidThread());
494 511
495 BattOrControlMessage msg{type, param1, param2}; 512 BattOrControlMessage msg{type, param1, param2};
496 connection_->SendBytes(BATTOR_MESSAGE_TYPE_CONTROL, &msg, sizeof(msg)); 513 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()) 578 if (clock_sync_marker != clock_sync_markers_.end())
562 trace_stream << " <" << clock_sync_marker->second << ">"; 579 trace_stream << " <" << clock_sync_marker->second << ">";
563 580
564 trace_stream << std::endl; 581 trace_stream << std::endl;
565 } 582 }
566 583
567 return trace_stream.str(); 584 return trace_stream.str();
568 } 585 }
569 586
570 } // namespace battor 587 } // namespace battor
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698