source: arduino-1-6-7/trunk/fuentes/arduino-ide-amd64/libraries/Bridge/src/Bridge.cpp @ 46

Last change on this file since 46 was 46, checked in by jrpelegrina, 4 years ago

First release to Xenial

File size: 7.0 KB
Line 
1/*
2  Copyright (c) 2013 Arduino LLC. All right reserved.
3
4  This library is free software; you can redistribute it and/or
5  modify it under the terms of the GNU Lesser General Public
6  License as published by the Free Software Foundation; either
7  version 2.1 of the License, or (at your option) any later version.
8
9  This library is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  Lesser General Public License for more details.
13
14  You should have received a copy of the GNU Lesser General Public
15  License along with this library; if not, write to the Free Software
16  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17*/
18
19#include "Bridge.h"
20
21BridgeClass::BridgeClass(Stream &_stream) :
22  index(0), stream(_stream), started(false), max_retries(0) {
23  // Empty
24}
25
26void BridgeClass::begin() {
27  if (started)
28    return;
29  started = true;
30
31  // Wait for U-boot to finish startup
32  do {
33    dropAll();
34    delay(1000);
35  } while (stream.available() > 0);
36
37  while (true) {
38    // Bridge interrupt:
39    // - Ask the bridge to close itself
40    uint8_t quit_cmd[] = {'X', 'X', 'X', 'X', 'X'};
41    max_retries = 1;
42    transfer(quit_cmd, 5);
43
44    // Bridge startup:
45    // - If the bridge is not running starts it safely
46    stream.print(CTRL_C);
47    delay(250);
48    stream.print(F("\n"));
49    delay(250);
50    stream.print(F("\n"));
51    delay(500);
52    // Wait for OpenWRT message
53    // "Press enter to activate console"
54    stream.print(F("run-bridge\n"));
55    delay(500);
56    dropAll();
57
58    // Reset the brigde to check if it is running
59    uint8_t cmd[] = {'X', 'X', '1', '0', '0'};
60    uint8_t res[4];
61    max_retries = 50;
62    uint16_t l = transfer(cmd, 5, res, 4);
63    if (l == TRANSFER_TIMEOUT) {
64      // Bridge didn't start...
65      // Maybe the board is starting-up?
66
67      // Wait and retry
68      delay(1000);
69      continue;
70    }
71    if (res[0] != 0)
72      while (true);
73
74    // Detect bridge version
75    if (l == 4) {
76      bridgeVersion = (res[1]-'0')*100 + (res[2]-'0')*10 + (res[3]-'0');
77    } else {
78      // Bridge v1.0.0 didn't send any version info
79      bridgeVersion = 100;
80    }
81
82    max_retries = 50;
83    return;
84  }
85}
86
87void BridgeClass::put(const char *key, const char *value) {
88  // TODO: do it in a more efficient way
89  String cmd = "D";
90  uint8_t res[1];
91  cmd += key;
92  cmd += "\xFE";
93  cmd += value;
94  transfer((uint8_t*)cmd.c_str(), cmd.length(), res, 1);
95}
96
97unsigned int BridgeClass::get(const char *key, uint8_t *value, unsigned int maxlen) {
98  uint8_t cmd[] = {'d'};
99  unsigned int l = transfer(cmd, 1, (uint8_t *)key, strlen(key), value, maxlen);
100  if (l < maxlen)
101    value[l] = 0; // Zero-terminate string
102  return l;
103}
104
105#if defined(ARDUINO_ARCH_AVR)
106// AVR use an optimized implementation of CRC
107#include <util/crc16.h>
108#else
109// Generic implementation for non-AVR architectures
110uint16_t _crc_ccitt_update(uint16_t crc, uint8_t data)
111{
112  data ^= crc & 0xff;
113  data ^= data << 4;
114  return ((((uint16_t)data << 8) | ((crc >> 8) & 0xff)) ^
115          (uint8_t)(data >> 4) ^
116          ((uint16_t)data << 3));
117}
118#endif
119
120void BridgeClass::crcUpdate(uint8_t c) {
121  CRC = _crc_ccitt_update(CRC, c);
122}
123
124void BridgeClass::crcReset() {
125  CRC = 0xFFFF;
126}
127
128void BridgeClass::crcWrite() {
129  stream.write((char)(CRC >> 8));
130  stream.write((char)(CRC & 0xFF));
131}
132
133bool BridgeClass::crcCheck(uint16_t _CRC) {
134  return CRC == _CRC;
135}
136
137uint16_t BridgeClass::transfer(const uint8_t *buff1, uint16_t len1,
138                               const uint8_t *buff2, uint16_t len2,
139                               const uint8_t *buff3, uint16_t len3,
140                               uint8_t *rxbuff, uint16_t rxlen)
141{
142  uint16_t len = len1 + len2 + len3;
143  uint8_t retries = 0;
144  for ( ; retries < max_retries; retries++, delay(100), dropAll() /* Delay for retransmission */) {
145    // Send packet
146    crcReset();
147    stream.write((char)0xFF);                // Start of packet (0xFF)
148    crcUpdate(0xFF);
149    stream.write((char)index);               // Message index
150    crcUpdate(index);
151    stream.write((char)((len >> 8) & 0xFF)); // Message length (hi)
152    crcUpdate((len >> 8) & 0xFF);
153    stream.write((char)(len & 0xFF));        // Message length (lo)
154    crcUpdate(len & 0xFF);
155    for (uint16_t i = 0; i < len1; i++) { // Payload
156      stream.write((char)buff1[i]);
157      crcUpdate(buff1[i]);
158    }
159    for (uint16_t i = 0; i < len2; i++) { // Payload
160      stream.write((char)buff2[i]);
161      crcUpdate(buff2[i]);
162    }
163    for (uint16_t i = 0; i < len3; i++) { // Payload
164      stream.write((char)buff3[i]);
165      crcUpdate(buff3[i]);
166    }
167    crcWrite();                     // CRC
168
169    // Wait for ACK in 100ms
170    if (timedRead(100) != 0xFF)
171      continue;
172    crcReset();
173    crcUpdate(0xFF);
174
175    // Check packet index
176    if (timedRead(5) != index)
177      continue;
178    crcUpdate(index);
179
180    // Recv len
181    int lh = timedRead(10);
182    if (lh < 0)
183      continue;
184    crcUpdate(lh);
185    int ll = timedRead(10);
186    if (ll < 0)
187      continue;
188    crcUpdate(ll);
189    uint16_t l = lh;
190    l <<= 8;
191    l += ll;
192
193    // Recv data
194    for (uint16_t i = 0; i < l; i++) {
195      // Cut received data if rxbuffer is too small
196      if (i >= rxlen)
197          break;
198      int c = timedRead(5);
199      if (c < 0)
200        continue;
201      rxbuff[i] = c;
202      crcUpdate(c);
203    }
204
205    // Check CRC
206    int crc_hi = timedRead(5);
207    if (crc_hi < 0)
208      continue;
209    int crc_lo = timedRead(5);
210    if (crc_lo < 0)
211      continue;
212    if (!crcCheck((crc_hi << 8) + crc_lo))
213      continue;
214
215    // Increase index
216    index++;
217
218    // Return bytes received
219    if (l > rxlen)
220      return rxlen;
221    return l;
222  }
223
224  // Max retries exceeded
225  return TRANSFER_TIMEOUT;
226}
227
228int BridgeClass::timedRead(unsigned int timeout) {
229  int c;
230  unsigned long _startMillis = millis();
231  do {
232    c = stream.read();
233    if (c >= 0) return c;
234  } while (millis() - _startMillis < timeout);
235  return -1;     // -1 indicates timeout
236}
237
238void BridgeClass::dropAll() {
239  while (stream.available() > 0) {
240    stream.read();
241  }
242}
243
244#if defined(ARDUINO_ARCH_SAM)
245#include <Reset.h>
246#endif
247
248#if defined(ARDUINO_ARCH_SAM)
249void checkForRemoteSketchUpdate(uint8_t pin) {
250  // The host force pin LOW to signal that a new sketch is coming
251  pinMode(pin, INPUT_PULLUP);
252  delay(50);
253  if (digitalRead(pin) == LOW) {
254    initiateReset(1);
255    while (true)
256      ; // Wait for reset to SAM-BA
257  }
258
259  // Restore in standard state
260  pinMode(pin, INPUT);
261}
262#else
263void checkForRemoteSketchUpdate(uint8_t /* pin */) {
264  // Empty, bootloader is enough.
265}
266#endif
267
268// Bridge instance
269#if defined(SERIAL_PORT_LINUXBRIDGE)
270SerialBridgeClass Bridge(SERIAL_PORT_LINUXBRIDGE);
271#elif defined(SERIAL_PORT_HARDWARE)
272SerialBridgeClass Bridge(SERIAL_PORT_HARDWARE);
273#elif defined(SERIAL_PORT_HARDWARE_OPEN)
274SerialBridgeClass Bridge(SERIAL_PORT_HARDWARE_OPEN);
275#elif defined(__AVR_ATmega32U4__) // Legacy fallback
276// Leonardo variants (where HardwareSerial is Serial1)
277SerialBridgeClass Bridge(Serial1);
278#else
279SerialBridgeClass Bridge(Serial);
280#endif
281
Note: See TracBrowser for help on using the repository browser.