@@ -39,21 +39,23 @@ NoteI2c_Arduino::receive (
3939)
4040{
4141 const char *result = nullptr ;
42- uint8_t transmission_error = 0 ;
4342
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
4649 _i2cPort.beginTransmission (static_cast <uint8_t >(device_address_));
4750 _i2cPort.write (static_cast <uint8_t >(0 ));
4851 _i2cPort.write (static_cast <uint8_t >(requested_byte_count_));
4952 transmission_error = _i2cPort.endTransmission ();
5053
51- // Break out of loop on success
52- if (!transmission_error) {
53- break ;
54- }
55-
5654 switch (transmission_error) {
55+ case 0 :
56+ // I2C transmission was successful
57+ result = nullptr ;
58+ break ;
5759 case 1 :
5860 result = ERRSTR (" i2c: data too long to fit in transmit buffer {io}" ,i2cerr);
5961 break ;
@@ -72,42 +74,49 @@ NoteI2c_Arduino::receive (
7274 default :
7375 result = ERRSTR (" i2c: unknown error encounter during I2C transmission {io}" ,i2cerr);
7476 }
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;
10377
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 ;
107109 }
108110 }
109111 }
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));
111120
112121 return result;
113122}
0 commit comments