My Marlin configs for Fabrikator Mini and CTC i3 Pro B
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

wifi_upload.cpp 25KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847
  1. /**
  2. * Marlin 3D Printer Firmware
  3. * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
  4. *
  5. * Based on Sprinter and grbl.
  6. * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
  7. *
  8. * This program is free software: you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation, either version 3 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  20. *
  21. */
  22. #include "../../../../inc/MarlinConfigPre.h"
  23. #if HAS_TFT_LVGL_UI
  24. #include "draw_ui.h"
  25. #include "wifi_module.h"
  26. #include "wifi_upload.h"
  27. #include "../../../../MarlinCore.h"
  28. #define WIFI_SET() WRITE(WIFI_RESET_PIN, HIGH);
  29. #define WIFI_RESET() WRITE(WIFI_RESET_PIN, LOW);
  30. #define WIFI_IO1_SET() WRITE(WIFI_IO1_PIN, HIGH);
  31. #define WIFI_IO1_RESET() WRITE(WIFI_IO1_PIN, LOW);
  32. extern SZ_USART_FIFO WifiRxFifo;
  33. extern int readUsartFifo(SZ_USART_FIFO *fifo, int8_t *buf, int32_t len);
  34. extern int writeUsartFifo(SZ_USART_FIFO * fifo, int8_t * buf, int32_t len);
  35. extern void esp_port_begin(uint8_t interrupt);
  36. extern int usartFifoAvailable(SZ_USART_FIFO *fifo);
  37. extern void wifi_delay(int n);
  38. #define ARRAY_SIZE(a) sizeof(a) / sizeof((a)[0])
  39. //typedef signed char bool;
  40. // ESP8266 command codes
  41. const uint8_t ESP_FLASH_BEGIN = 0x02;
  42. const uint8_t ESP_FLASH_DATA = 0x03;
  43. const uint8_t ESP_FLASH_END = 0x04;
  44. const uint8_t ESP_MEM_BEGIN = 0x05;
  45. const uint8_t ESP_MEM_END = 0x06;
  46. const uint8_t ESP_MEM_DATA = 0x07;
  47. const uint8_t ESP_SYNC = 0x08;
  48. const uint8_t ESP_WRITE_REG = 0x09;
  49. const uint8_t ESP_READ_REG = 0x0a;
  50. // MAC address storage locations
  51. const uint32_t ESP_OTP_MAC0 = 0x3ff00050;
  52. const uint32_t ESP_OTP_MAC1 = 0x3ff00054;
  53. const uint32_t ESP_OTP_MAC2 = 0x3ff00058;
  54. const uint32_t ESP_OTP_MAC3 = 0x3ff0005c;
  55. const size_t EspFlashBlockSize = 0x0400; // 1K byte blocks
  56. const uint8_t ESP_IMAGE_MAGIC = 0xe9;
  57. const uint8_t ESP_CHECKSUM_MAGIC = 0xef;
  58. const uint32_t ESP_ERASE_CHIP_ADDR = 0x40004984; // &SPIEraseChip
  59. const uint32_t ESP_SEND_PACKET_ADDR = 0x40003c80; // &send_packet
  60. const uint32_t ESP_SPI_READ_ADDR = 0x40004b1c; // &SPIRead
  61. const uint32_t ESP_UNKNOWN_ADDR = 0x40001121; // not used
  62. const uint32_t ESP_USER_DATA_RAM_ADDR = 0x3ffe8000; // &user data ram
  63. const uint32_t ESP_IRAM_ADDR = 0x40100000; // instruction RAM
  64. const uint32_t ESP_FLASH_ADDR = 0x40200000; // address of start of Flash
  65. //const uint32_t ESP_FLASH_READ_STUB_BEGIN = IRAM_ADDR + 0x18;
  66. UPLOAD_STRUCT esp_upload;
  67. static const unsigned int retriesPerReset = 3;
  68. static const uint32_t connectAttemptInterval = 50;
  69. static const unsigned int percentToReportIncrement = 5; // how often we report % complete
  70. static const uint32_t defaultTimeout = 500;
  71. static const uint32_t eraseTimeout = 15000;
  72. static const uint32_t blockWriteTimeout = 200;
  73. static const uint32_t blockWriteInterval = 15; // 15ms is long enough, 10ms is mostly too short
  74. // Messages corresponding to result codes, should make sense when followed by " error"
  75. const char *resultMessages[] = {
  76. "no",
  77. "timeout",
  78. "comm write",
  79. "connect",
  80. "bad reply",
  81. "file read",
  82. "empty file",
  83. "response header",
  84. "slip frame",
  85. "slip state",
  86. "slip data"
  87. };
  88. // A note on baud rates.
  89. // The ESP8266 supports 921600, 460800, 230400, 115200, 74880 and some lower baud rates.
  90. // 921600b is not reliable because even though it sometimes succeeds in connecting, we get a bad response during uploading after a few blocks.
  91. // Probably our UART ISR cannot receive bytes fast enough, perhaps because of the latency of the system tick ISR.
  92. // 460800b doesn't always manage to connect, but if it does then uploading appears to be reliable.
  93. // 230400b always manages to connect.
  94. static const uint32_t uploadBaudRates[] = { 460800, 230400, 115200, 74880 };
  95. signed char IsReady() {
  96. return esp_upload.state == upload_idle;
  97. }
  98. void uploadPort_write(const uint8_t *buf, size_t len) {
  99. #if 0
  100. int i;
  101. for(i = 0; i < len; i++) {
  102. while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
  103. USART_SendData(USART1, *(buf + i));
  104. }
  105. #endif
  106. }
  107. char uploadPort_read() {
  108. uint8_t retChar;
  109. if (readUsartFifo(&WifiRxFifo, (int8_t *)&retChar, 1) == 1)
  110. return retChar;
  111. else
  112. return 0;
  113. }
  114. int uploadPort_available() {
  115. return usartFifoAvailable(&WifiRxFifo);
  116. }
  117. void uploadPort_begin() {
  118. esp_port_begin(1);
  119. }
  120. void uploadPort_close() {
  121. //WIFI_COM.end();
  122. //WIFI_COM.begin(115200, true);
  123. esp_port_begin(0);
  124. }
  125. void flushInput() {
  126. while (uploadPort_available() != 0) {
  127. (void)uploadPort_read();
  128. //IWDG_ReloadCounter();
  129. }
  130. }
  131. // Extract 1-4 bytes of a value in little-endian order from a buffer beginning at a specified offset
  132. uint32_t getData(unsigned byteCnt, const uint8_t *buf, int ofst) {
  133. uint32_t val = 0;
  134. if (buf && byteCnt) {
  135. unsigned int shiftCnt = 0;
  136. if (byteCnt > 4)
  137. byteCnt = 4;
  138. do{
  139. val |= (uint32_t)buf[ofst++] << shiftCnt;
  140. shiftCnt += 8;
  141. } while (--byteCnt);
  142. }
  143. return(val);
  144. }
  145. // Put 1-4 bytes of a value in little-endian order into a buffer beginning at a specified offset.
  146. void putData(uint32_t val, unsigned byteCnt, uint8_t *buf, int ofst) {
  147. if (buf && byteCnt) {
  148. if (byteCnt > 4) {
  149. byteCnt = 4;
  150. }
  151. do {
  152. buf[ofst++] = (uint8_t)(val & 0xff);
  153. val >>= 8;
  154. } while (--byteCnt);
  155. }
  156. }
  157. // Read a byte optionally performing SLIP decoding. The return values are:
  158. //
  159. // 2 - an escaped byte was read successfully
  160. // 1 - a non-escaped byte was read successfully
  161. // 0 - no data was available
  162. // -1 - the value 0xc0 was encountered (shouldn't happen)
  163. // -2 - a SLIP escape byte was found but the following byte wasn't available
  164. // -3 - a SLIP escape byte was followed by an invalid byte
  165. int ReadByte(uint8_t *data, signed char slipDecode) {
  166. if (uploadPort_available() == 0) {
  167. return(0);
  168. }
  169. // at least one byte is available
  170. *data = uploadPort_read();
  171. if (!slipDecode) {
  172. return(1);
  173. }
  174. if (*data == 0xc0) {
  175. // this shouldn't happen
  176. return(-1);
  177. }
  178. // if not the SLIP escape, we're done
  179. if (*data != 0xdb) {
  180. return(1);
  181. }
  182. // SLIP escape, check availability of subsequent byte
  183. if (uploadPort_available() == 0) {
  184. return(-2);
  185. }
  186. // process the escaped byte
  187. *data = uploadPort_read();
  188. if (*data == 0xdc) {
  189. *data = 0xc0;
  190. return(2);
  191. }
  192. if (*data == 0xdd) {
  193. *data = 0xdb;
  194. return(2);
  195. }
  196. // invalid
  197. return(-3);
  198. }
  199. // When we write a sync packet, there must be no gaps between most of the characters.
  200. // So use this function, which does a block write to the UART buffer in the latest CoreNG.
  201. void _writePacketRaw(const uint8_t *buf, size_t len) {
  202. uploadPort_write(buf, len);
  203. }
  204. // Write a byte to the serial port optionally SLIP encoding. Return the number of bytes actually written.
  205. void WriteByteRaw(uint8_t b) {
  206. uploadPort_write((const uint8_t *)&b, 1);
  207. }
  208. // Write a byte to the serial port optionally SLIP encoding. Return the number of bytes actually written.
  209. void WriteByteSlip(uint8_t b) {
  210. if (b == 0xC0) {
  211. WriteByteRaw(0xDB);
  212. WriteByteRaw(0xDC);
  213. }
  214. else if (b == 0xDB) {
  215. WriteByteRaw(0xDB);
  216. WriteByteRaw(0xDD);
  217. }
  218. else {
  219. uploadPort_write((const uint8_t *)&b, 1);
  220. }
  221. }
  222. // Wait for a data packet to be returned. If the body of the packet is
  223. // non-zero length, return an allocated buffer indirectly containing the
  224. // data and return the data length. Note that if the pointer for returning
  225. // the data buffer is NULL, the response is expected to be two bytes of zero.
  226. //
  227. // If an error occurs, return a negative value. Otherwise, return the number
  228. // of bytes in the response (or zero if the response was not the standard "two bytes of zero").
  229. EspUploadResult readPacket(uint8_t op, uint32_t *valp, size_t *bodyLen, uint32_t msTimeout) {
  230. typedef enum {
  231. begin = 0,
  232. header,
  233. body,
  234. end,
  235. done
  236. } PacketState;
  237. uint8_t resp, opRet;
  238. const size_t headerLength = 8;
  239. uint32_t startTime = getWifiTick();
  240. uint8_t hdr[headerLength];
  241. uint16_t hdrIdx = 0;
  242. uint16_t bodyIdx = 0;
  243. uint8_t respBuf[2];
  244. // wait for the response
  245. uint16_t needBytes = 1;
  246. PacketState state = begin;
  247. *bodyLen = 0;
  248. while (state != done) {
  249. uint8_t c;
  250. EspUploadResult stat;
  251. //IWDG_ReloadCounter();
  252. if (getWifiTickDiff(startTime, getWifiTick()) > msTimeout) {
  253. return(timeout);
  254. }
  255. if (uploadPort_available() < needBytes) {
  256. // insufficient data available
  257. // preferably, return to Spin() here
  258. continue;
  259. }
  260. // sufficient bytes have been received for the current state, process them
  261. switch(state) {
  262. case begin: // expecting frame start
  263. c = uploadPort_read();
  264. if (c != (uint8_t)0xc0) {
  265. break;
  266. }
  267. state = header;
  268. needBytes = 2;
  269. break;
  270. case end: // expecting frame end
  271. c = uploadPort_read();
  272. if (c != (uint8_t)0xc0) {
  273. return slipFrame;
  274. }
  275. state = done;
  276. break;
  277. case header: // reading an 8-byte header
  278. case body: // reading the response body
  279. {
  280. int rslt;
  281. // retrieve a byte with SLIP decoding
  282. rslt = ReadByte(&c, 1);
  283. if (rslt != 1 && rslt != 2) {
  284. // some error occurred
  285. stat = (rslt == 0 || rslt == -2) ? slipData : slipFrame;
  286. return stat;
  287. }
  288. else if (state == header) {
  289. //store the header byte
  290. hdr[hdrIdx++] = c;
  291. if (hdrIdx >= headerLength) {
  292. // get the body length, prepare a buffer for it
  293. *bodyLen = (uint16_t)getData(2, hdr, 2);
  294. // extract the value, if requested
  295. if (valp != 0) {
  296. *valp = getData(4, hdr, 4);
  297. }
  298. if (*bodyLen != 0) {
  299. state = body;
  300. }
  301. else {
  302. needBytes = 1;
  303. state = end;
  304. }
  305. }
  306. }
  307. else {
  308. // Store the response body byte, check for completion
  309. if (bodyIdx < ARRAY_SIZE(respBuf)) {
  310. respBuf[bodyIdx] = c;
  311. }
  312. ++bodyIdx;
  313. if (bodyIdx >= *bodyLen) {
  314. needBytes = 1;
  315. state = end;
  316. }
  317. }
  318. }
  319. break;
  320. default: // this shouldn't happen
  321. return slipState;
  322. }
  323. }
  324. // Extract elements from the header
  325. resp = (uint8_t)getData(1, hdr, 0);
  326. opRet = (uint8_t)getData(1, hdr, 1);
  327. // Sync packets often provoke a response with a zero opcode instead of ESP_SYNC
  328. if (resp != 0x01 || opRet != op) {
  329. //debug//printf("resp %02x %02x\n", resp, opRet);
  330. return respHeader;
  331. }
  332. return success;
  333. }
  334. // Send a block of data performing SLIP encoding of the content.
  335. void _writePacket(const uint8_t *data, size_t len) {
  336. unsigned char outBuf[2048] = {0};
  337. unsigned int outIndex = 0;
  338. while (len != 0) {
  339. if (*data == 0xC0) {
  340. outBuf[outIndex++] = 0xDB;
  341. outBuf[outIndex++] = 0xDC;
  342. }
  343. else if (*data == 0xDB) {
  344. outBuf[outIndex++] = 0xDB;
  345. outBuf[outIndex++] = 0xDD;
  346. }
  347. else {
  348. outBuf[outIndex++] = *data;
  349. }
  350. data++;
  351. --len;
  352. }
  353. uploadPort_write((const uint8_t *)outBuf, outIndex);
  354. }
  355. // Send a packet to the serial port while performing SLIP framing. The packet data comprises a header and an optional data block.
  356. // A SLIP packet begins and ends with 0xc0. The data encapsulated has the bytes
  357. // 0xc0 and 0xdb replaced by the two-byte sequences {0xdb, 0xdc} and {0xdb, 0xdd} respectively.
  358. void writePacket(const uint8_t *hdr, size_t hdrLen, const uint8_t *data, size_t dataLen) {
  359. WriteByteRaw(0xc0); // send the packet start character
  360. _writePacket(hdr, hdrLen); // send the header
  361. _writePacket(data, dataLen); // send the data block
  362. WriteByteRaw(0xc0); // send the packet end character
  363. }
  364. // Send a packet to the serial port while performing SLIP framing. The packet data comprises a header and an optional data block.
  365. // This is like writePacket except that it does a fast block write for both the header and the main data with no SLIP encoding. Used to send sync commands.
  366. void writePacketRaw(const uint8_t *hdr, size_t hdrLen, const uint8_t *data, size_t dataLen) {
  367. WriteByteRaw(0xc0); // send the packet start character
  368. _writePacketRaw(hdr, hdrLen); // send the header
  369. _writePacketRaw(data, dataLen); // send the data block in raw mode
  370. WriteByteRaw(0xc0); // send the packet end character
  371. }
  372. // Send a command to the attached device together with the supplied data, if any.
  373. // The data is supplied via a list of one or more segments.
  374. void sendCommand(uint8_t op, uint32_t checkVal, const uint8_t *data, size_t dataLen) {
  375. // populate the header
  376. uint8_t hdr[8];
  377. putData(0, 1, hdr, 0);
  378. putData(op, 1, hdr, 1);
  379. putData(dataLen, 2, hdr, 2);
  380. putData(checkVal, 4, hdr, 4);
  381. // send the packet
  382. //flushInput();
  383. if (op == ESP_SYNC) {
  384. writePacketRaw(hdr, sizeof(hdr), data, dataLen);
  385. }
  386. else {
  387. writePacket(hdr, sizeof(hdr), data, dataLen);
  388. }
  389. }
  390. // Send a command to the attached device together with the supplied data, if any, and get the response
  391. EspUploadResult doCommand(uint8_t op, const uint8_t *data, size_t dataLen, uint32_t checkVal, uint32_t *valp, uint32_t msTimeout) {
  392. size_t bodyLen;
  393. EspUploadResult stat;
  394. sendCommand(op, checkVal, data, dataLen);
  395. stat = readPacket(op, valp, &bodyLen, msTimeout);
  396. if (stat == success && bodyLen != 2) {
  397. stat = badReply;
  398. }
  399. return stat;
  400. }
  401. // Send a synchronising packet to the serial port in an attempt to induce
  402. // the ESP8266 to auto-baud lock on the baud rate.
  403. EspUploadResult Sync(uint16_t timeout) {
  404. uint8_t buf[36];
  405. EspUploadResult stat;
  406. int i ;
  407. // compose the data for the sync attempt
  408. memset(buf, 0x55, sizeof(buf));
  409. buf[0] = 0x07;
  410. buf[1] = 0x07;
  411. buf[2] = 0x12;
  412. buf[3] = 0x20;
  413. stat = doCommand(ESP_SYNC, buf, sizeof(buf), 0, 0, timeout);
  414. // If we got a response other than sync, discard it and wait for a sync response. This happens at higher baud rates.
  415. for (i = 0; i < 10 && stat == respHeader; ++i) {
  416. size_t bodyLen;
  417. stat = readPacket(ESP_SYNC, 0, &bodyLen, timeout);
  418. }
  419. if (stat == success) {
  420. // Read and discard additional replies
  421. for (;;) {
  422. size_t bodyLen;
  423. EspUploadResult rc = readPacket(ESP_SYNC, 0, &bodyLen, defaultTimeout);
  424. if (rc != success || bodyLen != 2) {
  425. break;
  426. }
  427. }
  428. }
  429. //DEBUG
  430. //else debug//printf("stat=%d\n", (int)stat);
  431. return stat;
  432. }
  433. // Send a command to the device to begin the Flash process.
  434. EspUploadResult flashBegin(uint32_t addr, uint32_t size) {
  435. // determine the number of blocks represented by the size
  436. uint32_t blkCnt;
  437. uint8_t buf[16];
  438. uint32_t timeout;
  439. blkCnt = (size + EspFlashBlockSize - 1) / EspFlashBlockSize;
  440. // ensure that the address is on a block boundary
  441. addr &= ~(EspFlashBlockSize - 1);
  442. // begin the Flash process
  443. putData(size, 4, buf, 0);
  444. putData(blkCnt, 4, buf, 4);
  445. putData(EspFlashBlockSize, 4, buf, 8);
  446. putData(addr, 4, buf, 12);
  447. timeout = (size != 0) ? eraseTimeout : defaultTimeout;
  448. return doCommand(ESP_FLASH_BEGIN, buf, sizeof(buf), 0, 0, timeout);
  449. }
  450. // Send a command to the device to terminate the Flash process
  451. EspUploadResult flashFinish(signed char reboot) {
  452. uint8_t buf[4];
  453. putData(reboot ? 0 : 1, 4, buf, 0);
  454. return doCommand(ESP_FLASH_END, buf, sizeof(buf), 0, 0, defaultTimeout);
  455. }
  456. // Compute the checksum of a block of data
  457. uint16_t checksum(const uint8_t *data, uint16_t dataLen, uint16_t cksum) {
  458. if (data != NULL) {
  459. while (dataLen--) {
  460. cksum ^= (uint16_t)*data++;
  461. }
  462. }
  463. return(cksum);
  464. }
  465. EspUploadResult flashWriteBlock(uint16_t flashParmVal, uint16_t flashParmMask) {
  466. #if 0
  467. const uint32_t blkSize = EspFlashBlockSize;
  468. int i;
  469. // Allocate a data buffer for the combined header and block data
  470. const uint16_t hdrOfst = 0;
  471. const uint16_t dataOfst = 16;
  472. const uint16_t blkBufSize = dataOfst + blkSize;
  473. uint32_t blkBuf32[blkBufSize/4];
  474. uint8_t * const blkBuf = (uint8_t*)(blkBuf32);
  475. uint32_t cnt;
  476. uint16_t cksum;
  477. EspUploadResult stat;
  478. // Prepare the header for the block
  479. putData(blkSize, 4, blkBuf, hdrOfst + 0);
  480. putData(esp_upload.uploadBlockNumber, 4, blkBuf, hdrOfst + 4);
  481. putData(0, 4, blkBuf, hdrOfst + 8);
  482. putData(0, 4, blkBuf, hdrOfst + 12);
  483. // Get the data for the block
  484. f_read(&esp_upload.uploadFile, blkBuf + dataOfst, blkSize, &cnt );//->Read(reinterpret_cast<char *>(blkBuf + dataOfst), blkSize);
  485. if (cnt != blkSize) {
  486. if (f_tell(&esp_upload.uploadFile) == esp_upload.fileSize) {
  487. // partial last block, fill the remainder
  488. memset(blkBuf + dataOfst + cnt, 0xff, blkSize - cnt);
  489. }
  490. else {
  491. return fileRead;
  492. }
  493. }
  494. // Patch the flash parameters into the first block if it is loaded at address 0
  495. if (esp_upload.uploadBlockNumber == 0 && esp_upload.uploadAddress == 0 && blkBuf[dataOfst] == ESP_IMAGE_MAGIC && flashParmMask != 0) {
  496. // update the Flash parameters
  497. uint32_t flashParm = getData(2, blkBuf + dataOfst + 2, 0) & ~(uint32_t)flashParmMask;
  498. putData(flashParm | flashParmVal, 2, blkBuf + dataOfst + 2, 0);
  499. }
  500. // Calculate the block checksum
  501. cksum = checksum(blkBuf + dataOfst, blkSize, ESP_CHECKSUM_MAGIC);
  502. for (i = 0; i < 3; i++) {
  503. if ((stat = doCommand(ESP_FLASH_DATA, blkBuf, blkBufSize, cksum, 0, blockWriteTimeout)) == success) {
  504. break;
  505. }
  506. }
  507. //printf("Upload %d\%\n", ftell(&esp_upload.uploadFile) * 100 / esp_upload.fileSize);
  508. return stat;
  509. #endif
  510. }
  511. void upload_spin() {
  512. #if 0
  513. switch (esp_upload.state) {
  514. case resetting:
  515. if (esp_upload.connectAttemptNumber == 9) {
  516. // Time to give up
  517. //Network::ResetWiFi();
  518. esp_upload.uploadResult = connected;
  519. esp_upload.state = done;
  520. }
  521. else{
  522. // Reset the serial port at the new baud rate. Also reset the ESP8266.
  523. // const uint32_t baud = uploadBaudRates[esp_upload.connectAttemptNumber/esp_upload.retriesPerBaudRate];
  524. if (esp_upload.connectAttemptNumber % esp_upload.retriesPerBaudRate == 0) {
  525. }
  526. // uploadPort.begin(baud);
  527. // uploadPort_close();
  528. uploadPort_begin();
  529. wifi_delay(2000);
  530. flushInput();
  531. esp_upload.lastAttemptTime = esp_upload.lastResetTime = getWifiTick();
  532. esp_upload.state = connecting;
  533. }
  534. break;
  535. case connecting:
  536. if ((getWifiTickDiff(esp_upload.lastAttemptTime, getWifiTick()) >= connectAttemptInterval) && (getWifiTickDiff(esp_upload.lastResetTime, getWifiTick()) >= 500)) {
  537. // Attempt to establish a connection to the ESP8266.
  538. EspUploadResult res = Sync(5000);
  539. esp_upload.lastAttemptTime = getWifiTick();
  540. if (res == success) {
  541. // Successful connection
  542. // //MessageF(" success on attempt %d\n", (connectAttemptNumber % retriesPerBaudRate) + 1);
  543. //printf("connect success\n");
  544. esp_upload.state = erasing;
  545. }
  546. else {
  547. // This attempt failed
  548. esp_upload.connectAttemptNumber++;
  549. if (esp_upload.connectAttemptNumber % retriesPerReset == 0) {
  550. esp_upload.state = resetting; // try a reset and a lower baud rate
  551. }
  552. }
  553. }
  554. break;
  555. case erasing:
  556. if (getWifiTickDiff(esp_upload.lastAttemptTime, getWifiTick()) >= blockWriteInterval) {
  557. uint32_t eraseSize;
  558. const uint32_t sectorsPerBlock = 16;
  559. const uint32_t sectorSize = 4096;
  560. const uint32_t numSectors = (esp_upload.fileSize + sectorSize - 1)/sectorSize;
  561. const uint32_t startSector = esp_upload.uploadAddress/sectorSize;
  562. uint32_t headSectors = sectorsPerBlock - (startSector % sectorsPerBlock);
  563. if (numSectors < headSectors) {
  564. headSectors = numSectors;
  565. }
  566. eraseSize = (numSectors < 2 * headSectors)
  567. ? (numSectors + 1) / 2 * sectorSize
  568. : (numSectors - headSectors) * sectorSize;
  569. //MessageF("Erasing %u bytes...\n", fileSize);
  570. esp_upload.uploadResult = flashBegin(esp_upload.uploadAddress, eraseSize);
  571. if (esp_upload.uploadResult == success) {
  572. //MessageF("Uploading file...\n");
  573. esp_upload.uploadBlockNumber = 0;
  574. esp_upload.uploadNextPercentToReport = percentToReportIncrement;
  575. esp_upload.lastAttemptTime = getWifiTick();
  576. esp_upload.state = uploading;
  577. }
  578. else {
  579. //MessageF("Erase failed\n");
  580. esp_upload.state = done;
  581. }
  582. }
  583. break;
  584. case uploading:
  585. // The ESP needs several milliseconds to recover from one packet before it will accept another
  586. if (getWifiTickDiff(esp_upload.lastAttemptTime, getWifiTick()) >= 15) {
  587. unsigned int percentComplete;
  588. const uint32_t blkCnt = (esp_upload.fileSize + EspFlashBlockSize - 1) / EspFlashBlockSize;
  589. if (esp_upload.uploadBlockNumber < blkCnt) {
  590. esp_upload.uploadResult = flashWriteBlock(0, 0);
  591. esp_upload.lastAttemptTime = getWifiTick();
  592. if (esp_upload.uploadResult != success) {
  593. //MessageF("Flash block upload failed\n");
  594. esp_upload.state = done;
  595. }
  596. percentComplete = (100 * esp_upload.uploadBlockNumber)/blkCnt;
  597. ++esp_upload.uploadBlockNumber;
  598. if (percentComplete >= esp_upload.uploadNextPercentToReport) {
  599. //MessageF("%u%% complete\n", percentComplete);
  600. esp_upload.uploadNextPercentToReport += percentToReportIncrement;
  601. }
  602. }
  603. else {
  604. esp_upload.state = done;
  605. }
  606. }
  607. break;
  608. case done:
  609. f_close(&esp_upload.uploadFile);
  610. //uploadPort.end();
  611. //uploadPort_close();
  612. //WIFI_COM.begin(115200, true);
  613. //wifi_init();
  614. if (esp_upload.uploadResult == success) {
  615. //printf("upload successfully\n");
  616. }
  617. else {
  618. //printf("upload failed\n");
  619. }
  620. esp_upload.state = upload_idle;//idle;
  621. break;
  622. default:
  623. break;
  624. }
  625. #endif
  626. }
  627. // Try to upload the given file at the given address
  628. void SendUpdateFile(const char *file, uint32_t address) {
  629. #if 0
  630. FRESULT res = f_open(&esp_upload.uploadFile, file, FA_OPEN_EXISTING | FA_READ);
  631. if (res != FR_OK) return;
  632. esp_upload.fileSize = f_size(&esp_upload.uploadFile);
  633. if (esp_upload.fileSize == 0) {
  634. f_close(&esp_upload.uploadFile);
  635. return;
  636. }
  637. f_lseek(&esp_upload.uploadFile, 0);
  638. esp_upload.uploadAddress = address;
  639. esp_upload.connectAttemptNumber = 0;
  640. esp_upload.state = resetting;
  641. #endif
  642. }
  643. static const uint32_t FirmwareAddress = 0x00000000, WebFilesAddress = 0x00100000;
  644. void ResetWiFiForUpload(int begin_or_end) {
  645. #if 0
  646. uint32_t start, now;
  647. GPIO_InitTypeDef GPIO_InitStructure;
  648. #if V1_0_V1_1
  649. GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
  650. GPIO_InitStructure.Pin = GPIO_Pin_8;
  651. GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
  652. HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
  653. #else
  654. GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_LOW;
  655. GPIO_InitStructure.Pin = GPIO_Pin_13;
  656. GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;
  657. HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
  658. #endif
  659. start = getWifiTick();
  660. now = start;
  661. if (begin_or_end == 0) {
  662. #if V1_0_V1_1
  663. HAL_GPIO_WritePin(GPIOA,GPIO_Pin_8,GPIO_PIN_RESET); //update mode
  664. #else
  665. HAL_GPIO_WritePin(GPIOC,GPIO_Pin_13,GPIO_PIN_RESET); //update mode
  666. #endif
  667. }
  668. else {
  669. #if V1_0_V1_1
  670. #if V1_0_V1_1
  671. HAL_GPIO_WritePin(GPIOA,GPIO_Pin_8,GPIO_PIN_SET); //boot mode
  672. GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
  673. GPIO_InitStructure.Pin = GPIO_Pin_8;
  674. GPIO_InitStructure.Mode = GPIO_MODE_INPUT;
  675. HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
  676. #endif
  677. #else
  678. HAL_GPIO_WritePin(GPIOC,GPIO_Pin_13,GPIO_PIN_SET); //boot mode
  679. GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_LOW;
  680. GPIO_InitStructure.Pin = GPIO_Pin_13;
  681. GPIO_InitStructure.Mode = GPIO_MODE_INPUT;
  682. HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);
  683. #endif
  684. }
  685. WIFI_RESET();
  686. while (getWifiTickDiff(start, now) < 500) now = getWifiTick();
  687. WIFI_SET();
  688. #endif
  689. }
  690. int32_t wifi_upload(int type) {
  691. esp_upload.retriesPerBaudRate = 9;
  692. ResetWiFiForUpload(0);
  693. if (type == 0)
  694. SendUpdateFile(ESP_FIRMWARE_FILE, FirmwareAddress);
  695. else if (type == 1)
  696. SendUpdateFile(ESP_WEB_FIRMWARE_FILE, FirmwareAddress);
  697. else if (type == 2)
  698. SendUpdateFile(ESP_WEB_FILE, WebFilesAddress);
  699. else
  700. return -1;
  701. while (esp_upload.state != upload_idle) {
  702. upload_spin();
  703. //IWDG_ReloadCounter();
  704. }
  705. ResetWiFiForUpload(1);
  706. return esp_upload.uploadResult == success ? 0 : -1;
  707. }
  708. #endif // HAS_TFT_LVGL_UI