Skip to content

Commit 0288306

Browse files
authored
Merge branch 'master' into master
2 parents fe37c24 + f1b5e81 commit 0288306

File tree

41 files changed

+1456
-12
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+1456
-12
lines changed
Lines changed: 295 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,295 @@
1+
/*
2+
ESP32BootROM - part of the Firmware Updater for the
3+
Arduino MKR WiFi 1010, Arduino MKR Vidor 4000, and Arduino UNO WiFi Rev.2.
4+
5+
Copyright (c) 2018 Arduino SA. All rights reserved.
6+
7+
This library is free software; you can redistribute it and/or
8+
modify it under the terms of the GNU Lesser General Public
9+
License as published by the Free Software Foundation; either
10+
version 2.1 of the License, or (at your option) any later version.
11+
12+
This library is distributed in the hope that it will be useful,
13+
but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15+
Lesser General Public License for more details.
16+
17+
You should have received a copy of the GNU Lesser General Public
18+
License along with this library; if not, write to the Free Software
19+
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20+
*/
21+
22+
#include "ESP32BootROM.h"
23+
24+
extern ESP32BootROMClass ESP32BootROM;
25+
26+
//#define DEBUG 1
27+
28+
ESP32BootROMClass::ESP32BootROMClass(HardwareSerial& serial, int gpio0Pin, int resetnPin) :
29+
_serial(&serial),
30+
_gpio0Pin(gpio0Pin),
31+
_resetnPin(resetnPin)
32+
{
33+
34+
}
35+
36+
int ESP32BootROMClass::begin(unsigned long baudrate)
37+
{
38+
_serial->begin(115200);
39+
40+
pinMode(_gpio0Pin, OUTPUT);
41+
pinMode(_resetnPin, OUTPUT);
42+
43+
digitalWrite(_gpio0Pin, LOW);
44+
45+
digitalWrite(_resetnPin, LOW);
46+
delay(10);
47+
digitalWrite(_resetnPin, HIGH);
48+
delay(100);
49+
50+
int synced = 0;
51+
52+
for (int retries = 0; !synced && (retries < 5); retries++) {
53+
synced = sync();
54+
}
55+
56+
if (!synced) {
57+
return 0;
58+
}
59+
60+
#if defined(ARDUINO_SAMD_MKRVIDOR4000) || defined(ARDUINO_AVR_UNO_WIFI_REV2)
61+
(void)baudrate;
62+
#else
63+
if (baudrate != 115200) {
64+
if (!changeBaudrate(baudrate)) {
65+
return 0;
66+
}
67+
68+
delay(100);
69+
70+
_serial->end();
71+
_serial->begin(baudrate);
72+
}
73+
#endif
74+
75+
if (!spiAttach()) {
76+
return 0;
77+
}
78+
79+
return 1;
80+
}
81+
82+
void ESP32BootROMClass::end() {
83+
_serial->end();
84+
}
85+
86+
int ESP32BootROMClass::sync()
87+
{
88+
const uint8_t data[] = {
89+
0x07, 0x07, 0x12, 0x20,
90+
0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55
91+
};
92+
93+
command(0x08, data, sizeof(data));
94+
95+
int results[8];
96+
97+
for (int i = 0; i < 8; i++) {
98+
results[i] = response(0x08, 100);
99+
}
100+
101+
return (results[0] == 0);
102+
}
103+
104+
int ESP32BootROMClass::changeBaudrate(unsigned long baudrate)
105+
{
106+
const uint32_t data[2] = {
107+
baudrate,
108+
0
109+
};
110+
111+
command(0x0f, data, sizeof(data));
112+
113+
return (response(0x0f, 3000) == 0);
114+
}
115+
116+
int ESP32BootROMClass::spiAttach()
117+
{
118+
const uint8_t data[] = {
119+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
120+
};
121+
122+
command(0x0d, data, sizeof(data));
123+
124+
return (response(0x0d, 3000) == 0);
125+
}
126+
127+
int ESP32BootROMClass::beginFlash(uint32_t offset, uint32_t size, uint32_t chunkSize) {
128+
const uint32_t data[4] = {
129+
size,
130+
size / chunkSize,
131+
chunkSize,
132+
offset
133+
};
134+
135+
command(0x02, data, sizeof(data));
136+
137+
_flashSequenceNumber = 0;
138+
_chunkSize = chunkSize;
139+
140+
return (response(0x02, 120000) == 0);
141+
}
142+
143+
int ESP32BootROMClass::dataFlash(const void* data, uint32_t length)
144+
{
145+
uint32_t cmdData[4 + (_chunkSize / 4)];
146+
147+
cmdData[0] = length;
148+
cmdData[1] = _flashSequenceNumber++;
149+
cmdData[2] = 0;
150+
cmdData[3] = 0;
151+
152+
memcpy(&cmdData[4], data, length);
153+
154+
if (length < _chunkSize) {
155+
memset(&cmdData[4 + (length / 4)], 0xff, _chunkSize - length);
156+
}
157+
158+
command(0x03, cmdData, sizeof(cmdData));
159+
160+
return (response(0x03, 3000) == 0);
161+
}
162+
163+
int ESP32BootROMClass::endFlash(uint32_t reboot) {
164+
const uint32_t data[1] = {
165+
reboot
166+
};
167+
168+
command(0x04, data, sizeof(data));
169+
170+
return (response(0x04, 3000) == 0);
171+
}
172+
173+
int ESP32BootROMClass::md5Flash(uint32_t offset, uint32_t size, uint8_t* result)
174+
{
175+
const uint32_t data[4] = {
176+
offset,
177+
size,
178+
0,
179+
0
180+
};
181+
182+
command(0x13, data, sizeof(data));
183+
184+
uint8_t asciiResult[32];
185+
186+
if (response(0x13, 3000, asciiResult) != 0) {
187+
return 0;
188+
}
189+
190+
char temp[3] = { 0, 0, 0 };
191+
192+
for (int i = 0; i < 16; i++) {
193+
temp[0] = asciiResult[i * 2];
194+
temp[1] = asciiResult[i * 2 + 1];
195+
196+
result[i] = strtoul(temp, NULL, 16);
197+
}
198+
199+
return 1;
200+
}
201+
202+
void ESP32BootROMClass::command(int opcode, const void* data, uint16_t length)
203+
{
204+
uint32_t checksum = 0;
205+
206+
if (opcode == 0x03) {
207+
checksum = 0xef; // seed
208+
209+
for (uint16_t i = 16; i < length; i++) {
210+
checksum ^= ((const uint8_t*)data)[i];
211+
}
212+
}
213+
214+
_serial->write(0xc0);
215+
_serial->write((uint8_t)0x00); // direction
216+
_serial->write(opcode);
217+
_serial->write((uint8_t*)&length, sizeof(length));
218+
writeEscapedBytes((uint8_t*)&checksum, sizeof(checksum));
219+
writeEscapedBytes((uint8_t*)data, length);
220+
_serial->write(0xc0);
221+
#ifdef ARDUINO_SAMD_MKRVIDOR4000
222+
// _serial->flush(); // doesn't work!
223+
#else
224+
_serial->flush();
225+
#endif
226+
}
227+
228+
int ESP32BootROMClass::response(int opcode, unsigned long timeout, void* body)
229+
{
230+
uint8_t data[10 + 256];
231+
uint16_t index = 0;
232+
233+
uint8_t responseLength = 4;
234+
235+
for (unsigned long start = millis(); (index < (uint16_t)(10 + responseLength)) && (millis() - start) < timeout;) {
236+
if (_serial->available()) {
237+
data[index] = _serial->read();
238+
239+
if (index == 3) {
240+
responseLength = data[index];
241+
}
242+
243+
index++;
244+
}
245+
}
246+
247+
#ifdef DEBUG
248+
if (index) {
249+
for (int i = 0; i < index; i++) {
250+
byte b = data[i];
251+
252+
if (b < 0x10) {
253+
Serial.print('0');
254+
}
255+
256+
Serial.print(b, HEX);
257+
Serial.print(' ');
258+
}
259+
Serial.println();
260+
}
261+
#endif
262+
263+
if (index != (uint16_t)(10 + responseLength)) {
264+
return -1;
265+
}
266+
267+
if (data[0] != 0xc0 || data[1] != 0x01 || data[2] != opcode || data[responseLength + 5] != 0x00 || data[responseLength + 6] != 0x00 || data[responseLength + 9] != 0xc0) {
268+
return -1;
269+
}
270+
271+
if (body) {
272+
memcpy(body, &data[9], responseLength - 4);
273+
}
274+
275+
return data[responseLength + 5];
276+
}
277+
278+
void ESP32BootROMClass::writeEscapedBytes(const uint8_t* data, uint16_t length)
279+
{
280+
uint16_t written = 0;
281+
282+
while (written < length) {
283+
uint8_t b = data[written++];
284+
285+
if (b == 0xdb) {
286+
_serial->write(0xdb);
287+
_serial->write(0xdd);
288+
} else if (b == 0xc0) {
289+
_serial->write(0xdb);
290+
_serial->write(0xdc);
291+
} else {
292+
_serial->write(b);
293+
}
294+
}
295+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*
2+
ESP32BootROM - part of the Firmware Updater for the
3+
Arduino MKR WiFi 1010, Arduino MKR Vidor 4000, and Arduino UNO WiFi Rev.2.
4+
5+
Copyright (c) 2018 Arduino SA. All rights reserved.
6+
7+
This library is free software; you can redistribute it and/or
8+
modify it under the terms of the GNU Lesser General Public
9+
License as published by the Free Software Foundation; either
10+
version 2.1 of the License, or (at your option) any later version.
11+
12+
This library is distributed in the hope that it will be useful,
13+
but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15+
Lesser General Public License for more details.
16+
17+
You should have received a copy of the GNU Lesser General Public
18+
License along with this library; if not, write to the Free Software
19+
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20+
*/
21+
22+
#include <Arduino.h>
23+
24+
class ESP32BootROMClass {
25+
public:
26+
ESP32BootROMClass(HardwareSerial& hwSerial, int gpio0Pin, int resetnPin);
27+
28+
int begin(unsigned long baudrate);
29+
void end();
30+
31+
int beginFlash(uint32_t offset, uint32_t size, uint32_t chunkSize);
32+
int dataFlash(const void* data, uint32_t length);
33+
int endFlash(uint32_t reboot);
34+
35+
int md5Flash(uint32_t offset, uint32_t size, uint8_t* result);
36+
37+
private:
38+
int sync();
39+
int changeBaudrate(unsigned long baudrate);
40+
int spiAttach();
41+
42+
void command(int opcode, const void* data, uint16_t length);
43+
int response(int opcode, unsigned long timeout, void* body = NULL);
44+
45+
void writeEscapedBytes(const uint8_t* data, uint16_t length);
46+
47+
private:
48+
HardwareSerial* _serial;
49+
int _gpio0Pin;
50+
int _resetnPin;
51+
52+
uint32_t _flashSequenceNumber;
53+
uint32_t _chunkSize;
54+
};
55+
56+
extern ESP32BootROMClass ESP32BootROM;

0 commit comments

Comments
 (0)