SingingCat 0
application
esp8266_flash.c
1#include "main-header.h"
2#include "espressif/esp8266_flash.h"
3#include "espressif/esp8266_flash.h"
4
5
6static int read_timeout = 12; /* a read from serial port 'blocks' at most this amount of seconds */
7static long started; /* keep note of when we started reading from the port */
8
9static int esp_flash_baud = 115200;
10static void writebyte(byte b);
11static void writebuf_escaped(const byte *buf, int len);
12static void writebyte_escaped(const byte b);
13static int read_response(struct espflash_response *response);
14static int readbyte();
15static void init_timer();
16static byte is_timer_expired();
17static int is_valid_response(struct espflash_response *response);
18
19extern struct ringbuffer esp_ringbuffer;
20/************************ HELPER ******************************/
21/*
22 * \brief send a packet (from C0 to C0). Escape bytes where necessary
23 */
24static void send_packet(const byte *buf) {
25 int len = 1;
26
27 while (buf[len] != 0xC0) {
28 len++;
29 }
30 writebyte(0xC0);
31 writebuf_escaped(buf + 1, len - 2);
32 writebyte(0xC0);
33}
34
35
36static void writebyte(byte b) {
37 write_serial_char(USART_ESP8266, b);
38 //printf("FLASHDEBUG-ESP8266_TX: 0x%x (%i)\r\n",b,b);
39}
40
41static void writebuf_escaped(const byte *buf, int len) {
42 int i;
43
44 for (i = 0; i < len; i++) {
45 writebyte_escaped(buf[i]);
46 }
47}
48static void writebyte_escaped(const byte b) {
49 if (b == 0xC0) {
50 writebyte(0xDB);
51 writebyte(0xDC);
52 } else if (b == 0xDB) {
53 writebyte(0xDB);
54 writebyte(0xDD);
55 } else {
56 writebyte(b);
57 }
58}
59
60static void write16bit_escaped(int num) {
61 writebyte_escaped(num & 0xFF);
62 writebyte_escaped((num >> 8) & 0xFF);
63}
64
65static void write32bit_escaped(long num) {
66 writebyte_escaped(num & 0xFF);
67 writebyte_escaped((num >> 8) & 0xFF);
68 writebyte_escaped((num >> 16) & 0xFF);
69 writebyte_escaped((num >> 24) & 0xFF);
70}
71
72/************************ BRIDGE ******************************/
73/*
74 * \brief bridge usb & wifi
75 */
76static void clear_serial_buf() {
77 ringbuffer_init(&esp_ringbuffer);
78}
79void espflash_settimeout(const int timeo) {
80 read_timeout = timeo;
81}
82
83/************************ SYNC ******************************/
84/*
85 * \brief sync esp flash romloader
86 */
87int espflash_sync() {
88 struct espflash_response response;
89 const byte syncbytes[] = { 0xC0, 0, ESP_SYNC, 0x24, 0x07, 0x07, 0x12, 0x20,
90 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
91 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
92 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
93 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
94 0xC0 };
95 int i;
96 int res = 0;
97 int max_attempts = 8;
98
99 avoid_watchdog();
100 printf("Esp8266 off...\r\n");
101 mculib_pin_set(ESP8266_MCULIBHANDLE, PIN_ESP8266_CHPD, 0);
102 mculib_pin_set(ESP8266_MCULIBHANDLE, PIN_ESP8266_GPIO0, 0);
103 Delay(100);
104 clear_serial_buf();
105 printf("Esp8266 on...\r\n");
106 mculib_pin_set(ESP8266_MCULIBHANDLE, PIN_ESP8266_CHPD, 1);
107 //hard_reset_esp8266(WIFIMODE_FLASH);
108 set_esp8266_usart_mode(ESP8266_USART_PASSTHROUGH);
109 int baud = esp_flash_baud;
110
111 //baud = 74880;
112 if ((i = mculib_serialport_enable(ESP8266_MCULIBHANDLE, USART_ESP8266, baud))) {
113 printf("Failed to enable serialport #%i: %i\r\n", USART_ESP8266, i);
114 return 43;
115 }
116 printf("ESP8266 syncing @%i baud\r\n", baud);
117 espflash_settimeout(2);
118 // write_serial_char(USART_ESP8266,'\r');
119 // write_serial_char(USART_ESP8266,'\n');
120 avoid_watchdog();
121
122 // stupid test:
123 res = 1;
124 if (res == 0) {
125 // optional
126 long started = 0;
127 while (res < 10) {
128 if (started != mculib_get_seconds_since_boot()) {
129 send_packet(syncbytes);
130 res++;
131 started = mculib_get_seconds_since_boot();
132 printf("Sent sync packet #%i\r\n", res);
133 }
134 i = ringbuffer_get_byte(&esp_ringbuffer);
135 if (i != -1) {
136 printf("Received: %i (0x%x)\r\n", i, i);
137 }
138 }
139 }
140 res = 59;
141 // production...
142 espflash_settimeout(1);
143 for (i = 0; i < max_attempts; i++) {
144 printf("sync %i of %i)\r\n", (i + 1), max_attempts);
145 avoid_watchdog();
146 send_packet(syncbytes);
147 res = read_response(&response);
148 if (res != 0) {
149 printf("Failed to read response - error %i\r\n", res);
150 } else {
151 if (response.status != 0) {
152 printf("Sync Response Status: %i\r\n", response.status);
153 clear_serial_buf();
154 //return 31;
155 res = 31;
156 } else {
157 // it succeeded
158 espflash_settimeout(10);
159 printf("ESP8266 (or ESP32) synced @ %i baud\r\n", baud);
160 return 0;
161 }
162 }
163 }
164 // it failed
165 espflash_settimeout(10);
166 if (res == 0) {
167 Delay(50); // wait a bit in case esp sends more sync replies.
168 clear_serial_buf();
169 }
170 return res;
171}
172
173/************************ READ RESPONSE ******************************/
174/*
175 * \brief read esp sync reader
176 */
177
182static int readbyte() {
183 int esp;
184
185 init_timer();
186 while (((esp = ringbuffer_get_byte(&esp_ringbuffer)) >= 256) && (!is_timer_expired())) {
187 }
188 if (esp >= 256) {
189 return -1;
190 }
191 return esp;
192}
193
199static int read_response(struct espflash_response *response) {
200 int b;
201
202 response->status = 172;
203 b = 0;
204 long srr = mculib_get_seconds_since_boot(); // start_read_response ;-)
205
206 // read bytes until we hit 0xC0
207 while (((b = readbyte()) != -1) && (b != 0xc0)) {
208 if ((mculib_get_seconds_since_boot() - srr) > 10) {
209 return 4;
210 }
211 //printf("Received: %i\r\n",(int)b);
212 }
213 if (b == -1) {
214 return 8;
215 }
216 // we did read a 0xC0 which is either end of last packet or beginning of
217 // a new packet.
218 byte skipC0 = 1;
219 byte pos = 0;
220 byte *vb;
221
222 for (;;) {
223 avoid_watchdog();
224 if ((mculib_get_seconds_since_boot() - srr) > (read_timeout * 5)) {
225 return 6;
226 }
227 b = readbyte();
228 if (b == -1) {
229 printf("ESP8266-Flash: Whilst reading packet we got a timeout\r\n");
230 printf("ESP8266-Flash: Read %i bytes so far. skipC0=%i\r\n", pos, skipC0);
231 //timeout is always bad.
232 return 2;
233 }
234 // ignore all leading 0xC0 and read until we find a non-0xC0 byte,
235 // which then is definitely start of packet.
236 if ((skipC0) && (b == 0xC0)) {
237 continue;
238 }
239 skipC0 = 0; // no longer skip 0xC0's
240 if (b == 0xC0) {
241 // got end of packet!
242 // check validity!
243 if (!is_valid_response(response)) {
244 return 7; // packet was invalid
245 }
246 return 0;
247 }
248
249 if (pos == 1) {
250 response->command = b;
251 } else if (pos == 2) {
252 response->size = (b & 0xFF); // body-size
253 } else if (pos == 3) {
254 response->size = response->size | ((b & 0xFF) << 8); // body-size
255 } else if ((pos >= 4) && (pos <= 7)) {
256 vb = (byte *)&response->value;
257 vb[pos - 4] = (byte)(b & 0xff);
258 } else if (pos == 8) {
259 response->status = b;
260 } else if (pos == 9) {
261 response->error = b;
262 } else {
263 //return 10; // packet too long. weird.
264 }
265 pos++;
266 }
267 return 0;
268}
269
275static int wait_for_response(struct espflash_response *response, int command) {
276 for (;;) {
277 int res = read_response(response);
278 if ((res == 0) && (response->command == command)) {
279 return 0;
280 }
281 if (res != 0) {
282 return res;
283 }
284 }
285}
286
290static int is_valid_response(struct espflash_response *response) {
291 if (response == NULL) {
292 return 0;
293 }
294 CNWDEBUG("Command: %i\n", response->command);
295 if (response->command == ESP_SYNC) {
296 response->status = 0;
297 response->error = 0;
298 return 1;
299 }
300 return 0;
301}
302
303/********************************************************************
304 * timer helpers
305 */
306
310static byte is_timer_expired() {
311 if ((mculib_get_seconds_since_boot() - started) >= read_timeout) {
312 return 1;
313 }
314 return 0;
315}
319static void init_timer() {
320 started = mculib_get_seconds_since_boot();
321}
322
323/*
324 * \brief read a register, store result in *result
325 *
326 * return 0 if ok, otherwise errorcode
327 */
328int espflash_read_register(long regnum, long *result) {
329 struct espflash_response response;
330
331 clear_serial_buf();
332 writebyte(0xC0);
333 writebyte(0);
334 writebyte(ESP_READ_REG);
335 write16bit_escaped(4); // length
336 write32bit_escaped(0); // no checksum here
337 write32bit_escaped(regnum);
338 writebyte(0xC0);
339 int res = wait_for_response(&response, ESP_READ_REG);
340
341 if ((res == 0) && (response.status != 0)) {
342 printf("ESP8266 replied %i to read_reg()!\r\n", response.status);
343 return 53;
344 }
345 void *x;
346
347 x = (void *)response.value;
348 printf("Read register value: %p\r\n", x);
349 *result = response.value;
350 return res;
351}
352
353int esp8266_flash_from_serialport() {
354 return 0;
355}
356
357void espflash_set_baud(int baud) {
358 esp_flash_baud = baud;
359 printf("Flash baudrate set to %i\r\n", esp_flash_baud);
360}
361int espflash_finish() {
362 struct espflash_response response;
363 const byte finish[] = { 0xC0, 0, ESP_FLASH_END, 4, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0xC0 };
364
365 clear_serial_buf();
366 send_packet(finish);
367 int res = read_response(&response);
368
369 if ((res == 0) && (response.command != ESP_FLASH_END)) {
370 printf("We're confused. esp8266 replied with command %i to ESP_FLASH_END\r\n", response.command);
371 return 36;
372 }
373 if ((res == 0) && (response.status != 0)) {
374 printf("ESP8266 replied %i to flash finish()!\r\n", response.status);
375 return 31;
376 }
377 return res;
378}