serial_comm.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429
  1. /* Copyright 2020 Espressif Systems (Shanghai) PTE LTD
  2. *
  3. * Licensed under the Apache License, Version 2.0 (the "License");
  4. * you may not use this file except in compliance with the License.
  5. * You may obtain a copy of the License at
  6. *
  7. * http://www.apache.org/licenses/LICENSE-2.0
  8. *
  9. * Unless required by applicable law or agreed to in writing, software
  10. * distributed under the License is distributed on an "AS IS" BASIS,
  11. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. * See the License for the specific language governing permissions and
  13. * limitations under the License.
  14. */
  15. #include "serial_comm_prv.h"
  16. #include "serial_comm.h"
  17. #include "serial_io.h"
  18. #include <stddef.h>
  19. #include <string.h>
  20. #define CMD_SIZE(cmd) ( sizeof(cmd) - sizeof(command_common_t) )
  21. static uint32_t s_sequence_number = 0;
  22. static const uint8_t DELIMITER = 0xC0;
  23. static const uint8_t C0_REPLACEMENT[2] = {0xDB, 0xDC};
  24. static const uint8_t DB_REPLACEMENT[2] = {0xDB, 0xDD};
  25. static esp_loader_error_t check_response(command_t cmd, uint32_t *reg_value, void* resp, uint32_t resp_size);
  26. static inline esp_loader_error_t serial_read(uint8_t *buff, size_t size)
  27. {
  28. return loader_port_serial_read(buff, size, loader_port_remaining_time());
  29. }
  30. static inline esp_loader_error_t serial_write(const uint8_t *buff, size_t size)
  31. {
  32. return loader_port_serial_write(buff, size, loader_port_remaining_time());
  33. }
  34. static uint8_t compute_checksum(const uint8_t *data, uint32_t size)
  35. {
  36. uint8_t checksum = 0xEF;
  37. while (size--) {
  38. checksum ^= *data++;
  39. }
  40. return checksum;
  41. }
  42. static esp_loader_error_t SLIP_receive_data(uint8_t *buff, uint32_t size)
  43. {
  44. uint8_t ch;
  45. for (int i = 0; i < size; i++) {
  46. RETURN_ON_ERROR( serial_read(&ch, 1)) ;
  47. if (ch == 0xDB) {
  48. RETURN_ON_ERROR( serial_read(&ch, 1) );
  49. if (ch == 0xDC) {
  50. buff[i] = 0xC0;
  51. } else if (ch == 0xDD) {
  52. buff[i] = 0xDB;
  53. } else {
  54. return ESP_LOADER_ERROR_INVALID_RESPONSE;
  55. }
  56. } else {
  57. buff[i] = ch;
  58. }
  59. }
  60. return ESP_LOADER_SUCCESS;
  61. }
  62. static esp_loader_error_t SLIP_receive_packet(uint8_t *buff, uint32_t size)
  63. {
  64. uint8_t ch;
  65. // Wait for delimiter
  66. do {
  67. RETURN_ON_ERROR( serial_read(&ch, 1) );
  68. } while (ch != DELIMITER);
  69. // Workaround: bootloader sends two dummy(0xC0) bytes after response when baud rate is changed.
  70. do {
  71. RETURN_ON_ERROR( serial_read(&ch, 1) );
  72. } while (ch == DELIMITER);
  73. buff[0] = ch;
  74. RETURN_ON_ERROR( SLIP_receive_data(&buff[1], size - 1) );
  75. // Wait for delimiter
  76. do {
  77. RETURN_ON_ERROR( serial_read(&ch, 1) );
  78. } while (ch != DELIMITER);
  79. return ESP_LOADER_SUCCESS;
  80. }
  81. static esp_loader_error_t SLIP_send(const uint8_t *data, uint32_t size)
  82. {
  83. uint32_t to_write = 0;
  84. uint32_t written = 0;
  85. for (int i = 0; i < size; i++) {
  86. if (data[i] != 0xC0 && data[i] != 0xDB) {
  87. to_write++;
  88. continue;
  89. }
  90. if (to_write > 0) {
  91. RETURN_ON_ERROR( serial_write(&data[written], to_write) );
  92. }
  93. if (data[i] == 0xC0) {
  94. RETURN_ON_ERROR( serial_write(C0_REPLACEMENT, 2) );
  95. } else {
  96. RETURN_ON_ERROR( serial_write(DB_REPLACEMENT, 2) );
  97. }
  98. written = i + 1;
  99. to_write = 0;
  100. }
  101. if (to_write > 0) {
  102. RETURN_ON_ERROR( serial_write(&data[written], to_write) );
  103. }
  104. return ESP_LOADER_SUCCESS;
  105. }
  106. static esp_loader_error_t SLIP_send_delimiter(void)
  107. {
  108. return serial_write(&DELIMITER, 1);
  109. }
  110. static esp_loader_error_t send_cmd(const void *cmd_data, uint32_t size, uint32_t *reg_value)
  111. {
  112. response_t response;
  113. command_t command = ((command_common_t *)cmd_data)->command;
  114. RETURN_ON_ERROR( SLIP_send_delimiter() );
  115. RETURN_ON_ERROR( SLIP_send((const uint8_t *)cmd_data, size) );
  116. RETURN_ON_ERROR( SLIP_send_delimiter() );
  117. return check_response(command, reg_value, &response, sizeof(response));
  118. }
  119. static esp_loader_error_t send_cmd_with_data(const void *cmd_data, size_t cmd_size,
  120. const void *data, size_t data_size)
  121. {
  122. response_t response;
  123. command_t command = ((command_common_t *)cmd_data)->command;
  124. RETURN_ON_ERROR( SLIP_send_delimiter() );
  125. RETURN_ON_ERROR( SLIP_send((const uint8_t *)cmd_data, cmd_size) );
  126. RETURN_ON_ERROR( SLIP_send(data, data_size) );
  127. RETURN_ON_ERROR( SLIP_send_delimiter() );
  128. return check_response(command, NULL, &response, sizeof(response));
  129. }
  130. static esp_loader_error_t send_cmd_md5(const void *cmd_data, size_t cmd_size, uint8_t md5_out[MD5_SIZE])
  131. {
  132. rom_md5_response_t response;
  133. command_t command = ((command_common_t *)cmd_data)->command;
  134. RETURN_ON_ERROR( SLIP_send_delimiter() );
  135. RETURN_ON_ERROR( SLIP_send((const uint8_t *)cmd_data, cmd_size) );
  136. RETURN_ON_ERROR( SLIP_send_delimiter() );
  137. RETURN_ON_ERROR( check_response(command, NULL, &response, sizeof(response)) );
  138. memcpy(md5_out, response.md5, MD5_SIZE);
  139. return ESP_LOADER_SUCCESS;
  140. }
  141. static void log_loader_internal_error(error_code_t error)
  142. {
  143. loader_port_debug_print("Error: ");
  144. switch (error) {
  145. case INVALID_CRC: loader_port_debug_print("INVALID_CRC"); break;
  146. case INVALID_COMMAND: loader_port_debug_print("INVALID_COMMAND"); break;
  147. case COMMAND_FAILED: loader_port_debug_print("COMMAND_FAILED"); break;
  148. case FLASH_WRITE_ERR: loader_port_debug_print("FLASH_WRITE_ERR"); break;
  149. case FLASH_READ_ERR: loader_port_debug_print("FLASH_READ_ERR"); break;
  150. case READ_LENGTH_ERR: loader_port_debug_print("READ_LENGTH_ERR"); break;
  151. case DEFLATE_ERROR: loader_port_debug_print("DEFLATE_ERROR"); break;
  152. default: loader_port_debug_print("UNKNOWN ERROR"); break;
  153. }
  154. loader_port_debug_print("\n");
  155. }
  156. static esp_loader_error_t check_response(command_t cmd, uint32_t *reg_value, void* resp, uint32_t resp_size)
  157. {
  158. esp_loader_error_t err;
  159. common_response_t *response = (common_response_t *)resp;
  160. do {
  161. err = SLIP_receive_packet(resp, resp_size);
  162. if (err != ESP_LOADER_SUCCESS) {
  163. return err;
  164. }
  165. } while ((response->direction != READ_DIRECTION) || (response->command != cmd));
  166. response_status_t *status = (response_status_t *)(resp + resp_size - sizeof(response_status_t));
  167. if (status->failed) {
  168. log_loader_internal_error(status->error);
  169. return ESP_LOADER_ERROR_INVALID_RESPONSE;
  170. }
  171. if (reg_value != NULL) {
  172. *reg_value = response->value;
  173. }
  174. return ESP_LOADER_SUCCESS;
  175. }
  176. esp_loader_error_t loader_flash_begin_cmd(uint32_t offset,
  177. uint32_t erase_size,
  178. uint32_t block_size,
  179. uint32_t blocks_to_write,
  180. target_chip_t target)
  181. {
  182. size_t encription = target == ESP32S2_CHIP ? 0 : sizeof(uint32_t);
  183. begin_command_t begin_cmd = {
  184. .common = {
  185. .direction = WRITE_DIRECTION,
  186. .command = FLASH_BEGIN,
  187. .size = CMD_SIZE(begin_cmd) - encription,
  188. .checksum = 0
  189. },
  190. .erase_size = erase_size,
  191. .packet_count = blocks_to_write,
  192. .packet_size = block_size,
  193. .offset = offset,
  194. .encrypted = 0
  195. };
  196. s_sequence_number = 0;
  197. return send_cmd(&begin_cmd, sizeof(begin_cmd) - encription, NULL);
  198. }
  199. esp_loader_error_t loader_flash_data_cmd(const uint8_t *data, uint32_t size)
  200. {
  201. data_command_t data_cmd = {
  202. .common = {
  203. .direction = WRITE_DIRECTION,
  204. .command = FLASH_DATA,
  205. .size = CMD_SIZE(data_cmd) + size,
  206. .checksum = compute_checksum(data, size)
  207. },
  208. .data_size = size,
  209. .sequence_number = s_sequence_number++,
  210. };
  211. return send_cmd_with_data(&data_cmd, sizeof(data_cmd), data, size);
  212. }
  213. esp_loader_error_t loader_flash_end_cmd(bool stay_in_loader)
  214. {
  215. flash_end_command_t end_cmd = {
  216. .common = {
  217. .direction = WRITE_DIRECTION,
  218. .command = FLASH_END,
  219. .size = CMD_SIZE(end_cmd),
  220. .checksum = 0
  221. },
  222. .stay_in_loader = stay_in_loader
  223. };
  224. return send_cmd(&end_cmd, sizeof(end_cmd), NULL);
  225. }
  226. esp_loader_error_t loader_sync_cmd(void)
  227. {
  228. sync_command_t sync_cmd = {
  229. .common = {
  230. .direction = WRITE_DIRECTION,
  231. .command = SYNC,
  232. .size = CMD_SIZE(sync_cmd),
  233. .checksum = 0
  234. },
  235. .sync_sequence = {
  236. 0x07, 0x07, 0x12, 0x20,
  237. 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
  238. 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
  239. 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
  240. 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
  241. }
  242. };
  243. return send_cmd(&sync_cmd, sizeof(sync_cmd), NULL);
  244. }
  245. esp_loader_error_t loader_write_reg_cmd(uint32_t address, uint32_t value,
  246. uint32_t mask, uint32_t delay_us)
  247. {
  248. write_reg_command_t write_cmd = {
  249. .common = {
  250. .direction = WRITE_DIRECTION,
  251. .command = WRITE_REG,
  252. .size = CMD_SIZE(write_cmd),
  253. .checksum = 0
  254. },
  255. .address = address,
  256. .value = value,
  257. .mask = mask,
  258. .delay_us = delay_us
  259. };
  260. return send_cmd(&write_cmd, sizeof(write_cmd), NULL);
  261. }
  262. esp_loader_error_t loader_read_reg_cmd(uint32_t address, uint32_t *reg)
  263. {
  264. read_reg_command_t read_cmd = {
  265. .common = {
  266. .direction = WRITE_DIRECTION,
  267. .command = READ_REG,
  268. .size = CMD_SIZE(read_cmd),
  269. .checksum = 0
  270. },
  271. .address = address,
  272. };
  273. return send_cmd(&read_cmd, sizeof(read_cmd), reg);
  274. }
  275. esp_loader_error_t loader_spi_attach_cmd(uint32_t config)
  276. {
  277. spi_attach_command_t attach_cmd = {
  278. .common = {
  279. .direction = WRITE_DIRECTION,
  280. .command = SPI_ATTACH,
  281. .size = CMD_SIZE(attach_cmd),
  282. .checksum = 0
  283. },
  284. .configuration = config,
  285. .zero = 0
  286. };
  287. return send_cmd(&attach_cmd, sizeof(attach_cmd), NULL);
  288. }
  289. esp_loader_error_t loader_change_baudrate_cmd(uint32_t baudrate)
  290. {
  291. change_baudrate_command_t baudrate_cmd = {
  292. .common = {
  293. .direction = WRITE_DIRECTION,
  294. .command = CHANGE_BAUDRATE,
  295. .size = CMD_SIZE(baudrate_cmd),
  296. .checksum = 0
  297. },
  298. .new_baudrate = baudrate,
  299. .old_baudrate = 0 // ESP32 ROM only
  300. };
  301. return send_cmd(&baudrate_cmd, sizeof(baudrate_cmd), NULL);
  302. }
  303. esp_loader_error_t loader_md5_cmd(uint32_t address, uint32_t size, uint8_t *md5_out)
  304. {
  305. spi_flash_md5_command_t md5_cmd = {
  306. .common = {
  307. .direction = WRITE_DIRECTION,
  308. .command = SPI_FLASH_MD5,
  309. .size = CMD_SIZE(md5_cmd),
  310. .checksum = 0
  311. },
  312. .address = address,
  313. .size = size,
  314. .reserved_0 = 0,
  315. .reserved_1 = 0
  316. };
  317. return send_cmd_md5(&md5_cmd, sizeof(md5_cmd), md5_out);
  318. }
  319. esp_loader_error_t loader_spi_parameters(uint32_t total_size)
  320. {
  321. write_spi_command_t spi_cmd = {
  322. .common = {
  323. .direction = WRITE_DIRECTION,
  324. .command = SPI_SET_PARAMS,
  325. .size = 24,
  326. .checksum = 0
  327. },
  328. .id = 0,
  329. .total_size = total_size,
  330. .block_size = 64 * 1024,
  331. .sector_size = 4 * 1024,
  332. .page_size = 0x100,
  333. .status_mask = 0xFFFF,
  334. };
  335. return send_cmd(&spi_cmd, sizeof(spi_cmd), NULL);
  336. }
  337. __attribute__ ((weak)) void loader_port_debug_print(const char *str)
  338. {
  339. }