@@ -39,21 +39,23 @@ NoteI2c_Arduino::receive (
39
39
)
40
40
{
41
41
const char *result = nullptr ;
42
- uint8_t transmission_error = 0 ;
43
42
44
- // Request response data from Notecard
45
- for (size_t i = 0 ; i < 3 ; ++i) {
43
+ const size_t retry_count = 3 ;
44
+ size_t i = 0 ;
45
+ do {
46
+ uint8_t transmission_error = 0 ;
47
+
48
+ // Request response data from Notecard
46
49
_i2cPort.beginTransmission (static_cast <uint8_t >(device_address_));
47
50
_i2cPort.write (static_cast <uint8_t >(0 ));
48
51
_i2cPort.write (static_cast <uint8_t >(requested_byte_count_));
49
52
transmission_error = _i2cPort.endTransmission ();
50
53
51
- // Break out of loop on success
52
- if (!transmission_error) {
53
- break ;
54
- }
55
-
56
54
switch (transmission_error) {
55
+ case 0 :
56
+ // I2C transmission was successful
57
+ result = nullptr ;
58
+ break ;
57
59
case 1 :
58
60
result = ERRSTR (" i2c: data too long to fit in transmit buffer {io}" ,i2cerr);
59
61
break ;
@@ -72,42 +74,49 @@ NoteI2c_Arduino::receive (
72
74
default :
73
75
result = ERRSTR (" i2c: unknown error encounter during I2C transmission {io}" ,i2cerr);
74
76
}
75
- }
76
-
77
- // Delay briefly ensuring that the Notecard can
78
- // deliver the data in real-time to the I2C ISR
79
- ::delay (2 );
80
-
81
- // Read and cache response from Notecard
82
- if (!transmission_error) {
83
- const int request_length = requested_byte_count_ + NoteI2c::REQUEST_HEADER_SIZE;
84
- const int response_length = _i2cPort.requestFrom ((int )device_address_, request_length);
85
- if (!response_length) {
86
- result = ERRSTR (" serial-over-i2c: no response to read request {io}" ,i2cerr);
87
- } else if (response_length != request_length) {
88
- result = ERRSTR (" serial-over-i2c: unexpected raw byte count {io}" ,i2cerr);
89
- } else {
90
- // Ensure available byte count is within expected range
91
- static const size_t AVAILBLE_MAX = (NoteI2c::REQUEST_MAX_SIZE - NoteI2c::REQUEST_HEADER_SIZE);
92
- uint32_t available = _i2cPort.read ();
93
- if (available > AVAILBLE_MAX) {
94
- result = ERRSTR (" serial-over-i2c: available byte count greater than max allowed {io}" ,i2cerr);
95
- }
96
- // Ensure protocol response length matches size request
97
- else if (requested_byte_count_ != static_cast <uint8_t >(_i2cPort.read ())) {
98
- result = ERRSTR (" serial-over-i2c: unexpected protocol byte count {io}" ,i2cerr);
99
- }
100
- // Update available with remaining bytes
101
- else {
102
- *available_ = available;
103
77
104
- for (size_t i = 0 ; i < requested_byte_count_ ; ++i) {
105
- // TODO: Perf test against indexed buffer writes
106
- *buffer_++ = _i2cPort.read ();
78
+ // Read and cache response from Notecard
79
+ if (!transmission_error) {
80
+ // Delay briefly ensuring that the Notecard can
81
+ // deliver the data in real-time to the I2C ISR
82
+ ::delay (2 );
83
+
84
+ const int request_length = requested_byte_count_ + NoteI2c::REQUEST_HEADER_SIZE;
85
+ const int response_length = _i2cPort.requestFrom ((int )device_address_, request_length);
86
+ if (!response_length) {
87
+ result = ERRSTR (" serial-over-i2c: no response to read request {io}" ,i2cerr);
88
+ } else if (response_length != request_length) {
89
+ result = ERRSTR (" serial-over-i2c: unexpected raw byte count {io}" ,i2cerr);
90
+ } else {
91
+ // Ensure available byte count is within expected range
92
+ static const size_t AVAILABLE_MAX = (NoteI2c::REQUEST_MAX_SIZE - NoteI2c::REQUEST_HEADER_SIZE);
93
+ uint32_t available = _i2cPort.read ();
94
+ if (available > AVAILABLE_MAX) {
95
+ result = ERRSTR (" serial-over-i2c: available byte count greater than max allowed {io}" ,i2cerr);
96
+ } else if (requested_byte_count_ != static_cast <uint8_t >(_i2cPort.read ())) {
97
+ // Ensure protocol response length matches size request
98
+ result = ERRSTR (" serial-over-i2c: unexpected protocol byte count {io}" ,i2cerr);
99
+ } else {
100
+ // Update available with remaining bytes
101
+ *available_ = available;
102
+
103
+ for (size_t i = 0 ; i < requested_byte_count_ ; ++i) {
104
+ // TODO: Perf test against indexed buffer reads
105
+ *buffer_++ = _i2cPort.read ();
106
+ }
107
+ result = nullptr ;
108
+ break ;
107
109
}
108
110
}
109
111
}
110
- }
112
+
113
+ // Flash stalls have been observed on the Notecard ESP. Delaying
114
+ // between retries provides time for the Notecard to recover from
115
+ // the resource contention.
116
+ ::delay (1000 );
117
+ NOTE_C_LOG_ERROR (result);
118
+ NOTE_C_LOG_WARN (" serial-over-i2c: reattempting to read Notecard response" );
119
+ } while (result && (i++ < retry_count));
111
120
112
121
return result;
113
122
}
0 commit comments