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 22KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687
  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 BOTH(HAS_TFT_LVGL_UI, MKS_WIFI_MODULE)
  24. #include "draw_ui.h"
  25. #include "wifi_module.h"
  26. #include "wifi_upload.h"
  27. #include "../../../MarlinCore.h"
  28. #include "../../../sd/cardreader.h"
  29. #define WIFI_SET() WRITE(WIFI_RESET_PIN, HIGH);
  30. #define WIFI_RESET() WRITE(WIFI_RESET_PIN, LOW);
  31. #define WIFI_IO1_SET() WRITE(WIFI_IO1_PIN, HIGH);
  32. #define WIFI_IO1_RESET() WRITE(WIFI_IO1_PIN, LOW);
  33. extern SZ_USART_FIFO WifiRxFifo;
  34. extern int readUsartFifo(SZ_USART_FIFO *fifo, int8_t *buf, int32_t len);
  35. extern int writeUsartFifo(SZ_USART_FIFO * fifo, int8_t * buf, int32_t len);
  36. void esp_port_begin(uint8_t interrupt);
  37. extern int usartFifoAvailable(SZ_USART_FIFO *fifo);
  38. void wifi_delay(int n);
  39. #define ARRAY_SIZE(a) sizeof(a) / sizeof((a)[0])
  40. //typedef signed char bool;
  41. // ESP8266 command codes
  42. const uint8_t ESP_FLASH_BEGIN = 0x02;
  43. const uint8_t ESP_FLASH_DATA = 0x03;
  44. const uint8_t ESP_FLASH_END = 0x04;
  45. const uint8_t ESP_MEM_BEGIN = 0x05;
  46. const uint8_t ESP_MEM_END = 0x06;
  47. const uint8_t ESP_MEM_DATA = 0x07;
  48. const uint8_t ESP_SYNC = 0x08;
  49. const uint8_t ESP_WRITE_REG = 0x09;
  50. const uint8_t ESP_READ_REG = 0x0A;
  51. // MAC address storage locations
  52. const uint32_t ESP_OTP_MAC0 = 0x3FF00050;
  53. const uint32_t ESP_OTP_MAC1 = 0x3FF00054;
  54. const uint32_t ESP_OTP_MAC2 = 0x3FF00058;
  55. const uint32_t ESP_OTP_MAC3 = 0x3FF0005C;
  56. const size_t EspFlashBlockSize = 0x0400; // 1K byte blocks
  57. const uint8_t ESP_IMAGE_MAGIC = 0xE9;
  58. const uint8_t ESP_CHECKSUM_MAGIC = 0xEF;
  59. const uint32_t ESP_ERASE_CHIP_ADDR = 0x40004984; // &SPIEraseChip
  60. const uint32_t ESP_SEND_PACKET_ADDR = 0x40003C80; // &send_packet
  61. const uint32_t ESP_SPI_READ_ADDR = 0x40004B1C; // &SPIRead
  62. const uint32_t ESP_UNKNOWN_ADDR = 0x40001121; // not used
  63. const uint32_t ESP_USER_DATA_RAM_ADDR = 0x3FFE8000; // &user data ram
  64. const uint32_t ESP_IRAM_ADDR = 0x40100000; // instruction RAM
  65. const uint32_t ESP_FLASH_ADDR = 0x40200000; // address of start of Flash
  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. static SdFile update_file, *update_curDir;
  75. // Messages corresponding to result codes, should make sense when followed by " error"
  76. const char *resultMessages[] = {
  77. "no",
  78. "timeout",
  79. "comm write",
  80. "connect",
  81. "bad reply",
  82. "file read",
  83. "empty file",
  84. "response header",
  85. "slip frame",
  86. "slip state",
  87. "slip data"
  88. };
  89. // A note on baud rates.
  90. // The ESP8266 supports 921600, 460800, 230400, 115200, 74880 and some lower baud rates.
  91. // 921600b is not reliable because even though it sometimes succeeds in connecting, we get a bad response during uploading after a few blocks.
  92. // Probably our UART ISR cannot receive bytes fast enough, perhaps because of the latency of the system tick ISR.
  93. // 460800b doesn't always manage to connect, but if it does then uploading appears to be reliable.
  94. // 230400b always manages to connect.
  95. static const uint32_t uploadBaudRates[] = { 460800, 230400, 115200, 74880 };
  96. signed char IsReady() {
  97. return esp_upload.state == upload_idle;
  98. }
  99. void uploadPort_write(const uint8_t *buf, const size_t len) {
  100. for (size_t i = 0; i < len; i++)
  101. WIFISERIAL.write(*(buf + i));
  102. }
  103. char uploadPort_read() {
  104. uint8_t retChar;
  105. retChar = WIFISERIAL.read();
  106. return _MAX(retChar, 0);
  107. }
  108. int uploadPort_available() {
  109. return usartFifoAvailable(&WifiRxFifo);
  110. }
  111. void uploadPort_begin() {
  112. esp_port_begin(1);
  113. }
  114. void uploadPort_close() {
  115. //WIFI_COM.end();
  116. //WIFI_COM.begin(115200, true);
  117. esp_port_begin(0);
  118. }
  119. void flushInput() {
  120. while (uploadPort_available() != 0) {
  121. (void)uploadPort_read();
  122. //IWDG_ReloadCounter();
  123. }
  124. }
  125. // Extract 1-4 bytes of a value in little-endian order from a buffer beginning at a specified offset
  126. uint32_t getData(unsigned byteCnt, const uint8_t *buf, int ofst) {
  127. uint32_t val = 0;
  128. if (buf && byteCnt) {
  129. unsigned int shiftCnt = 0;
  130. NOMORE(byteCnt, 4U);
  131. do {
  132. val |= (uint32_t)buf[ofst++] << shiftCnt;
  133. shiftCnt += 8;
  134. } while (--byteCnt);
  135. }
  136. return val;
  137. }
  138. // Put 1-4 bytes of a value in little-endian order into a buffer beginning at a specified offset.
  139. void putData(uint32_t val, unsigned byteCnt, uint8_t *buf, int ofst) {
  140. if (buf && byteCnt) {
  141. NOMORE(byteCnt, 4U);
  142. do {
  143. buf[ofst++] = (uint8_t)(val & 0xFF);
  144. val >>= 8;
  145. } while (--byteCnt);
  146. }
  147. }
  148. // Read a byte optionally performing SLIP decoding. The return values are:
  149. //
  150. // 2 - an escaped byte was read successfully
  151. // 1 - a non-escaped byte was read successfully
  152. // 0 - no data was available
  153. // -1 - the value 0xC0 was encountered (shouldn't happen)
  154. // -2 - a SLIP escape byte was found but the following byte wasn't available
  155. // -3 - a SLIP escape byte was followed by an invalid byte
  156. int ReadByte(uint8_t *data, signed char slipDecode) {
  157. if (uploadPort_available() == 0) return 0;
  158. // At least one byte is available
  159. *data = uploadPort_read();
  160. if (!slipDecode) return 1;
  161. if (*data == 0xC0) return -1; // This shouldn't happen
  162. if (*data != 0xDB) return 1; // If not the SLIP escape, we're done
  163. // SLIP escape, check availability of subsequent byte
  164. if (uploadPort_available() == 0) return -2;
  165. // process the escaped byte
  166. *data = uploadPort_read();
  167. if (*data == 0xDC) { *data = 0xC0; return 2; }
  168. if (*data == 0xDD) { *data = 0xDB; return 2; }
  169. return -3; // invalid
  170. }
  171. // When we write a sync packet, there must be no gaps between most of the characters.
  172. // So use this function, which does a block write to the UART buffer in the latest CoreNG.
  173. void _writePacketRaw(const uint8_t *buf, size_t len) {
  174. uploadPort_write(buf, len);
  175. }
  176. // Write a byte to the serial port optionally SLIP encoding. Return the number of bytes actually written.
  177. void WriteByteRaw(uint8_t b) {
  178. uploadPort_write((const uint8_t *)&b, 1);
  179. }
  180. // Write a byte to the serial port optionally SLIP encoding. Return the number of bytes actually written.
  181. void WriteByteSlip(const uint8_t b) {
  182. if (b == 0xC0) {
  183. WriteByteRaw(0xDB);
  184. WriteByteRaw(0xDC);
  185. }
  186. else if (b == 0xDB) {
  187. WriteByteRaw(0xDB);
  188. WriteByteRaw(0xDD);
  189. }
  190. else
  191. uploadPort_write((const uint8_t *)&b, 1);
  192. }
  193. // Wait for a data packet to be returned. If the body of the packet is
  194. // non-zero length, return an allocated buffer indirectly containing the
  195. // data and return the data length. Note that if the pointer for returning
  196. // the data buffer is nullptr, the response is expected to be two bytes of zero.
  197. //
  198. // If an error occurs, return a negative value. Otherwise, return the number
  199. // of bytes in the response (or zero if the response was not the standard "two bytes of zero").
  200. EspUploadResult readPacket(uint8_t op, uint32_t *valp, size_t *bodyLen, uint32_t msTimeout) {
  201. typedef enum {
  202. begin = 0,
  203. header,
  204. body,
  205. end,
  206. done
  207. } PacketState;
  208. uint8_t resp, opRet;
  209. const size_t headerLength = 8;
  210. uint32_t startTime = getWifiTick();
  211. uint8_t hdr[headerLength];
  212. uint16_t hdrIdx = 0;
  213. uint16_t bodyIdx = 0;
  214. uint8_t respBuf[2];
  215. // wait for the response
  216. uint16_t needBytes = 1;
  217. PacketState state = begin;
  218. *bodyLen = 0;
  219. while (state != done) {
  220. uint8_t c;
  221. EspUploadResult stat;
  222. //IWDG_ReloadCounter();
  223. watchdog_refresh();
  224. if (getWifiTickDiff(startTime, getWifiTick()) > msTimeout)
  225. return timeout;
  226. if (uploadPort_available() < needBytes) {
  227. // insufficient data available
  228. // preferably, return to Spin() here
  229. continue;
  230. }
  231. // sufficient bytes have been received for the current state, process them
  232. switch (state) {
  233. case begin: // expecting frame start
  234. c = uploadPort_read();
  235. if (c == (uint8_t)0xC0) break;
  236. state = header;
  237. needBytes = 2;
  238. break;
  239. case end: // expecting frame end
  240. c = uploadPort_read();
  241. if (c != (uint8_t)0xC0) return slipFrame;
  242. state = done;
  243. break;
  244. case header: // reading an 8-byte header
  245. case body: { // reading the response body
  246. int rslt;
  247. // retrieve a byte with SLIP decoding
  248. rslt = ReadByte(&c, 1);
  249. if (rslt != 1 && rslt != 2) {
  250. // some error occurred
  251. stat = (rslt == 0 || rslt == -2) ? slipData : slipFrame;
  252. return stat;
  253. }
  254. else if (state == header) {
  255. //store the header byte
  256. hdr[hdrIdx++] = c;
  257. if (hdrIdx >= headerLength) {
  258. // get the body length, prepare a buffer for it
  259. *bodyLen = (uint16_t)getData(2, hdr, 2);
  260. // extract the value, if requested
  261. if (valp)
  262. *valp = getData(4, hdr, 4);
  263. if (*bodyLen != 0)
  264. state = body;
  265. else {
  266. needBytes = 1;
  267. state = end;
  268. }
  269. }
  270. }
  271. else {
  272. // Store the response body byte, check for completion
  273. if (bodyIdx < ARRAY_SIZE(respBuf))
  274. respBuf[bodyIdx] = c;
  275. if (++bodyIdx >= *bodyLen) {
  276. needBytes = 1;
  277. state = end;
  278. }
  279. }
  280. } break;
  281. default: return slipState; // this shouldn't happen
  282. }
  283. }
  284. // Extract elements from the header
  285. resp = (uint8_t)getData(1, hdr, 0);
  286. opRet = (uint8_t)getData(1, hdr, 1);
  287. // Sync packets often provoke a response with a zero opcode instead of ESP_SYNC
  288. if (resp != 0x01 || opRet != op) return respHeader;
  289. return success;
  290. }
  291. // Send a block of data performing SLIP encoding of the content.
  292. void _writePacket(const uint8_t *data, size_t len) {
  293. unsigned char outBuf[2048] = {0};
  294. unsigned int outIndex = 0;
  295. while (len != 0) {
  296. if (*data == 0xC0) {
  297. outBuf[outIndex++] = 0xDB;
  298. outBuf[outIndex++] = 0xDC;
  299. }
  300. else if (*data == 0xDB) {
  301. outBuf[outIndex++] = 0xDB;
  302. outBuf[outIndex++] = 0xDD;
  303. }
  304. else {
  305. outBuf[outIndex++] = *data;
  306. }
  307. data++;
  308. --len;
  309. }
  310. uploadPort_write((const uint8_t *)outBuf, outIndex);
  311. }
  312. // Send a packet to the serial port while performing SLIP framing. The packet data comprises a header and an optional data block.
  313. // A SLIP packet begins and ends with 0xC0. The data encapsulated has the bytes
  314. // 0xC0 and 0xDB replaced by the two-byte sequences {0xDB, 0xDC} and {0xDB, 0xDD} respectively.
  315. void writePacket(const uint8_t *hdr, size_t hdrLen, const uint8_t *data, size_t dataLen) {
  316. WriteByteRaw(0xC0); // send the packet start character
  317. _writePacket(hdr, hdrLen); // send the header
  318. _writePacket(data, dataLen); // send the data block
  319. WriteByteRaw(0xC0); // send the packet end character
  320. }
  321. // Send a packet to the serial port while performing SLIP framing. The packet data comprises a header and an optional data block.
  322. // 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.
  323. void writePacketRaw(const uint8_t *hdr, size_t hdrLen, const uint8_t *data, size_t dataLen) {
  324. WriteByteRaw(0xC0); // send the packet start character
  325. _writePacketRaw(hdr, hdrLen); // send the header
  326. _writePacketRaw(data, dataLen); // send the data block in raw mode
  327. WriteByteRaw(0xC0); // send the packet end character
  328. }
  329. // Send a command to the attached device together with the supplied data, if any.
  330. // The data is supplied via a list of one or more segments.
  331. void sendCommand(uint8_t op, uint32_t checkVal, const uint8_t *data, size_t dataLen) {
  332. // populate the header
  333. uint8_t hdr[8];
  334. putData(0, 1, hdr, 0);
  335. putData(op, 1, hdr, 1);
  336. putData(dataLen, 2, hdr, 2);
  337. putData(checkVal, 4, hdr, 4);
  338. // send the packet
  339. if (op == ESP_SYNC)
  340. writePacketRaw(hdr, sizeof(hdr), data, dataLen);
  341. else
  342. writePacket(hdr, sizeof(hdr), data, dataLen);
  343. }
  344. // Send a command to the attached device together with the supplied data, if any, and get the response
  345. EspUploadResult doCommand(uint8_t op, const uint8_t *data, size_t dataLen, uint32_t checkVal, uint32_t *valp, uint32_t msTimeout) {
  346. size_t bodyLen;
  347. EspUploadResult stat;
  348. sendCommand(op, checkVal, data, dataLen);
  349. stat = readPacket(op, valp, &bodyLen, msTimeout);
  350. if (stat == success && bodyLen != 2)
  351. stat = badReply;
  352. return stat;
  353. }
  354. // Send a synchronising packet to the serial port in an attempt to induce
  355. // the ESP8266 to auto-baud lock on the baud rate.
  356. EspUploadResult Sync(uint16_t timeout) {
  357. uint8_t buf[36];
  358. EspUploadResult stat;
  359. int i ;
  360. // compose the data for the sync attempt
  361. memset(buf, 0x55, sizeof(buf));
  362. buf[0] = 0x07;
  363. buf[1] = 0x07;
  364. buf[2] = 0x12;
  365. buf[3] = 0x20;
  366. stat = doCommand(ESP_SYNC, buf, sizeof(buf), 0, 0, timeout);
  367. // If we got a response other than sync, discard it and wait for a sync response. This happens at higher baud rates.
  368. for (i = 0; i < 10 && stat == respHeader; ++i) {
  369. size_t bodyLen;
  370. stat = readPacket(ESP_SYNC, 0, &bodyLen, timeout);
  371. }
  372. if (stat == success) {
  373. // Read and discard additional replies
  374. for (;;) {
  375. size_t bodyLen;
  376. EspUploadResult rc = readPacket(ESP_SYNC, 0, &bodyLen, defaultTimeout);
  377. watchdog_refresh();
  378. if (rc != success || bodyLen != 2) break;
  379. }
  380. }
  381. //DEBUG
  382. //else debug//printf("stat=%d\n", (int)stat);
  383. return stat;
  384. }
  385. // Send a command to the device to begin the Flash process.
  386. EspUploadResult flashBegin(uint32_t addr, uint32_t size) {
  387. // determine the number of blocks represented by the size
  388. uint32_t blkCnt;
  389. uint8_t buf[16];
  390. uint32_t timeout;
  391. blkCnt = (size + EspFlashBlockSize - 1) / EspFlashBlockSize;
  392. // ensure that the address is on a block boundary
  393. addr &= ~(EspFlashBlockSize - 1);
  394. // begin the Flash process
  395. putData(size, 4, buf, 0);
  396. putData(blkCnt, 4, buf, 4);
  397. putData(EspFlashBlockSize, 4, buf, 8);
  398. putData(addr, 4, buf, 12);
  399. timeout = (size != 0) ? eraseTimeout : defaultTimeout;
  400. return doCommand(ESP_FLASH_BEGIN, buf, sizeof(buf), 0, 0, timeout);
  401. }
  402. // Send a command to the device to terminate the Flash process
  403. EspUploadResult flashFinish(signed char reboot) {
  404. uint8_t buf[4];
  405. putData(reboot ? 0 : 1, 4, buf, 0);
  406. return doCommand(ESP_FLASH_END, buf, sizeof(buf), 0, 0, defaultTimeout);
  407. }
  408. // Compute the checksum of a block of data
  409. uint16_t checksum(const uint8_t *data, uint16_t dataLen, uint16_t cksum) {
  410. if (data) while (dataLen--) cksum ^= (uint16_t)*data++;
  411. return cksum;
  412. }
  413. EspUploadResult flashWriteBlock(uint16_t flashParmVal, uint16_t flashParmMask) {
  414. const uint32_t blkSize = EspFlashBlockSize;
  415. int i;
  416. // Allocate a data buffer for the combined header and block data
  417. const uint16_t hdrOfst = 0;
  418. const uint16_t dataOfst = 16;
  419. const uint16_t blkBufSize = dataOfst + blkSize;
  420. uint32_t blkBuf32[blkBufSize/4];
  421. uint8_t * const blkBuf = (uint8_t*)(blkBuf32);
  422. uint32_t cnt;
  423. uint16_t cksum;
  424. EspUploadResult stat;
  425. // Prepare the header for the block
  426. putData(blkSize, 4, blkBuf, hdrOfst + 0);
  427. putData(esp_upload.uploadBlockNumber, 4, blkBuf, hdrOfst + 4);
  428. putData(0, 4, blkBuf, hdrOfst + 8);
  429. putData(0, 4, blkBuf, hdrOfst + 12);
  430. // Get the data for the block
  431. cnt = update_file.read(blkBuf + dataOfst, blkSize); //->Read(reinterpret_cast<char *>(blkBuf + dataOfst), blkSize);
  432. if (cnt != blkSize) {
  433. if (update_file.curPosition() == esp_upload.fileSize) {
  434. // partial last block, fill the remainder
  435. memset(blkBuf + dataOfst + cnt, 0xFF, blkSize - cnt);
  436. }
  437. else
  438. return fileRead;
  439. }
  440. // Patch the flash parameters into the first block if it is loaded at address 0
  441. if (esp_upload.uploadBlockNumber == 0 && esp_upload.uploadAddress == 0 && blkBuf[dataOfst] == ESP_IMAGE_MAGIC && flashParmMask != 0) {
  442. // update the Flash parameters
  443. uint32_t flashParm = getData(2, blkBuf + dataOfst + 2, 0) & ~(uint32_t)flashParmMask;
  444. putData(flashParm | flashParmVal, 2, blkBuf + dataOfst + 2, 0);
  445. }
  446. // Calculate the block checksum
  447. cksum = checksum(blkBuf + dataOfst, blkSize, ESP_CHECKSUM_MAGIC);
  448. for (i = 0; i < 3; i++)
  449. if ((stat = doCommand(ESP_FLASH_DATA, blkBuf, blkBufSize, cksum, 0, blockWriteTimeout)) == success)
  450. break;
  451. return stat;
  452. }
  453. void upload_spin() {
  454. switch (esp_upload.state) {
  455. case resetting:
  456. if (esp_upload.connectAttemptNumber == 9) {
  457. esp_upload.uploadResult = connected;
  458. esp_upload.state = done;
  459. }
  460. else {
  461. uploadPort_begin();
  462. wifi_delay(2000);
  463. flushInput();
  464. esp_upload.lastAttemptTime = esp_upload.lastResetTime = getWifiTick();
  465. esp_upload.state = connecting;
  466. }
  467. break;
  468. case connecting:
  469. if ((getWifiTickDiff(esp_upload.lastAttemptTime, getWifiTick()) >= connectAttemptInterval) && (getWifiTickDiff(esp_upload.lastResetTime, getWifiTick()) >= 500)) {
  470. EspUploadResult res = Sync(5000);
  471. esp_upload.lastAttemptTime = getWifiTick();
  472. if (res == success)
  473. esp_upload.state = erasing;
  474. else {
  475. esp_upload.connectAttemptNumber++;
  476. if (esp_upload.connectAttemptNumber % retriesPerReset == 0)
  477. esp_upload.state = resetting;
  478. }
  479. }
  480. break;
  481. case erasing:
  482. if (getWifiTickDiff(esp_upload.lastAttemptTime, getWifiTick()) >= blockWriteInterval) {
  483. uint32_t eraseSize;
  484. const uint32_t sectorsPerBlock = 16;
  485. const uint32_t sectorSize = 4096;
  486. const uint32_t numSectors = (esp_upload.fileSize + sectorSize - 1)/sectorSize;
  487. const uint32_t startSector = esp_upload.uploadAddress/sectorSize;
  488. uint32_t headSectors = sectorsPerBlock - (startSector % sectorsPerBlock);
  489. NOMORE(headSectors, numSectors);
  490. eraseSize = (numSectors < 2 * headSectors)
  491. ? (numSectors + 1) / 2 * sectorSize
  492. : (numSectors - headSectors) * sectorSize;
  493. esp_upload.uploadResult = flashBegin(esp_upload.uploadAddress, eraseSize);
  494. if (esp_upload.uploadResult == success) {
  495. esp_upload.uploadBlockNumber = 0;
  496. esp_upload.uploadNextPercentToReport = percentToReportIncrement;
  497. esp_upload.lastAttemptTime = getWifiTick();
  498. esp_upload.state = uploading;
  499. }
  500. else
  501. esp_upload.state = done;
  502. }
  503. break;
  504. case uploading:
  505. // The ESP needs several milliseconds to recover from one packet before it will accept another
  506. if (getWifiTickDiff(esp_upload.lastAttemptTime, getWifiTick()) >= 15) {
  507. unsigned int percentComplete;
  508. const uint32_t blkCnt = (esp_upload.fileSize + EspFlashBlockSize - 1) / EspFlashBlockSize;
  509. if (esp_upload.uploadBlockNumber < blkCnt) {
  510. esp_upload.uploadResult = flashWriteBlock(0, 0);
  511. esp_upload.lastAttemptTime = getWifiTick();
  512. if (esp_upload.uploadResult != success)
  513. esp_upload.state = done;
  514. percentComplete = (100 * esp_upload.uploadBlockNumber)/blkCnt;
  515. ++esp_upload.uploadBlockNumber;
  516. if (percentComplete >= esp_upload.uploadNextPercentToReport)
  517. esp_upload.uploadNextPercentToReport += percentToReportIncrement;
  518. }
  519. else
  520. esp_upload.state = done;
  521. }
  522. break;
  523. case done:
  524. update_file.close();
  525. esp_upload.state = upload_idle;
  526. break;
  527. default: break;
  528. }
  529. }
  530. // Try to upload the given file at the given address
  531. void SendUpdateFile(const char *file, uint32_t address) {
  532. const char * const fname = card.diveToFile(false, update_curDir, ESP_FIRMWARE_FILE);
  533. if (!update_file.open(update_curDir, fname, O_READ)) return;
  534. esp_upload.fileSize = update_file.fileSize();
  535. if (esp_upload.fileSize == 0) {
  536. update_file.close();
  537. return;
  538. }
  539. esp_upload.uploadAddress = address;
  540. esp_upload.connectAttemptNumber = 0;
  541. esp_upload.state = resetting;
  542. }
  543. static const uint32_t FirmwareAddress = 0x00000000, WebFilesAddress = 0x00100000;
  544. void ResetWiFiForUpload(int begin_or_end) {
  545. //#if 0
  546. uint32_t start, now;
  547. start = getWifiTick();
  548. now = start;
  549. if (begin_or_end == 0) {
  550. SET_OUTPUT(WIFI_IO0_PIN);
  551. WRITE(WIFI_IO0_PIN, LOW);
  552. }
  553. else
  554. SET_INPUT_PULLUP(WIFI_IO0_PIN);
  555. WIFI_RESET();
  556. while (getWifiTickDiff(start, now) < 500) now = getWifiTick();
  557. WIFI_SET();
  558. //#endif
  559. }
  560. int32_t wifi_upload(int type) {
  561. esp_upload.retriesPerBaudRate = 9;
  562. ResetWiFiForUpload(0);
  563. switch (type) {
  564. case 0: SendUpdateFile(ESP_FIRMWARE_FILE, FirmwareAddress); break;
  565. case 1: SendUpdateFile(ESP_WEB_FIRMWARE_FILE, FirmwareAddress); break;
  566. case 2: SendUpdateFile(ESP_WEB_FILE, WebFilesAddress); break;
  567. default: return -1;
  568. }
  569. while (esp_upload.state != upload_idle) {
  570. upload_spin();
  571. watchdog_refresh();
  572. }
  573. ResetWiFiForUpload(1);
  574. return esp_upload.uploadResult == success ? 0 : -1;
  575. }
  576. #endif // HAS_TFT_LVGL_UI && MKS_WIFI_MODULE