source: rtos_arduino/trunk/arduino_lib/libraries/Bridge/src/Bridge.cpp@ 136

Last change on this file since 136 was 136, checked in by ertl-honda, 8 years ago

ライブラリとOS及びベーシックなサンプルの追加.

File size: 6.2 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 cmd += key;
91 cmd += "\xFE";
92 cmd += value;
93 transfer((uint8_t*)cmd.c_str(), cmd.length());
94}
95
96unsigned int BridgeClass::get(const char *key, uint8_t *value, unsigned int maxlen) {
97 uint8_t cmd[] = {'d'};
98 unsigned int l = transfer(cmd, 1, (uint8_t *)key, strlen(key), value, maxlen);
99 if (l < maxlen)
100 value[l] = 0; // Zero-terminate string
101 return l;
102}
103
104#if defined(ARDUINO_ARCH_AVR)
105// AVR use an optimized implementation of CRC
106#include <util/crc16.h>
107#else
108// Generic implementation for non-AVR architectures
109uint16_t _crc_ccitt_update(uint16_t crc, uint8_t data)
110{
111 data ^= crc & 0xff;
112 data ^= data << 4;
113 return ((((uint16_t)data << 8) | ((crc >> 8) & 0xff)) ^
114 (uint8_t)(data >> 4) ^
115 ((uint16_t)data << 3));
116}
117#endif
118
119void BridgeClass::crcUpdate(uint8_t c) {
120 CRC = _crc_ccitt_update(CRC, c);
121}
122
123void BridgeClass::crcReset() {
124 CRC = 0xFFFF;
125}
126
127void BridgeClass::crcWrite() {
128 stream.write((char)(CRC >> 8));
129 stream.write((char)(CRC & 0xFF));
130}
131
132bool BridgeClass::crcCheck(uint16_t _CRC) {
133 return CRC == _CRC;
134}
135
136uint16_t BridgeClass::transfer(const uint8_t *buff1, uint16_t len1,
137 const uint8_t *buff2, uint16_t len2,
138 const uint8_t *buff3, uint16_t len3,
139 uint8_t *rxbuff, uint16_t rxlen)
140{
141 uint16_t len = len1 + len2 + len3;
142 uint8_t retries = 0;
143 for ( ; retries < max_retries; retries++, delay(100), dropAll() /* Delay for retransmission */) {
144 // Send packet
145 crcReset();
146 stream.write((char)0xFF); // Start of packet (0xFF)
147 crcUpdate(0xFF);
148 stream.write((char)index); // Message index
149 crcUpdate(index);
150 stream.write((char)((len >> 8) & 0xFF)); // Message length (hi)
151 crcUpdate((len >> 8) & 0xFF);
152 stream.write((char)(len & 0xFF)); // Message length (lo)
153 crcUpdate(len & 0xFF);
154 for (uint16_t i = 0; i < len1; i++) { // Payload
155 stream.write((char)buff1[i]);
156 crcUpdate(buff1[i]);
157 }
158 for (uint16_t i = 0; i < len2; i++) { // Payload
159 stream.write((char)buff2[i]);
160 crcUpdate(buff2[i]);
161 }
162 for (uint16_t i = 0; i < len3; i++) { // Payload
163 stream.write((char)buff3[i]);
164 crcUpdate(buff3[i]);
165 }
166 crcWrite(); // CRC
167
168 // Wait for ACK in 100ms
169 if (timedRead(100) != 0xFF)
170 continue;
171 crcReset();
172 crcUpdate(0xFF);
173
174 // Check packet index
175 if (timedRead(5) != index)
176 continue;
177 crcUpdate(index);
178
179 // Recv len
180 int lh = timedRead(10);
181 if (lh < 0)
182 continue;
183 crcUpdate(lh);
184 int ll = timedRead(10);
185 if (ll < 0)
186 continue;
187 crcUpdate(ll);
188 uint16_t l = lh;
189 l <<= 8;
190 l += ll;
191
192 // Recv data
193 for (uint16_t i = 0; i < l; i++) {
194 int c = timedRead(5);
195 if (c < 0)
196 continue;
197 // Cut received data if rxbuffer is too small
198 if (i < rxlen)
199 rxbuff[i] = c;
200 crcUpdate(c);
201 }
202
203 // Check CRC
204 int crc_hi = timedRead(5);
205 if (crc_hi < 0)
206 continue;
207 int crc_lo = timedRead(5);
208 if (crc_lo < 0)
209 continue;
210 if (!crcCheck((crc_hi << 8) + crc_lo))
211 continue;
212
213 // Increase index
214 index++;
215
216 // Return bytes received
217 if (l > rxlen)
218 return rxlen;
219 return l;
220 }
221
222 // Max retries exceeded
223 return TRANSFER_TIMEOUT;
224}
225
226int BridgeClass::timedRead(unsigned int timeout) {
227 int c;
228 unsigned long _startMillis = millis();
229 do {
230 c = stream.read();
231 if (c >= 0) return c;
232 } while (millis() - _startMillis < timeout);
233 return -1; // -1 indicates timeout
234}
235
236void BridgeClass::dropAll() {
237 while (stream.available() > 0) {
238 stream.read();
239 }
240}
241
242// Bridge instance
243#ifdef __AVR_ATmega32U4__
244// Leonardo variants (where HardwareSerial is Serial1)
245SerialBridgeClass Bridge(Serial1);
246#else
247SerialBridgeClass Bridge(Serial);
248#endif
Note: See TracBrowser for help on using the repository browser.