test.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377
  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 "catch.hpp"
  16. #include "serial_comm.h"
  17. #include "serial_comm_prv.h"
  18. #include "serial_io_mock.h"
  19. #include "esp_loader.h"
  20. #include "serial_io.h"
  21. #include <string.h>
  22. #include <stdio.h>
  23. #include <array>
  24. #include <map>
  25. #include <iostream>
  26. #include <algorithm>
  27. using namespace std;
  28. #define TEST_SLIP_PACKET 0xdb, 'a', 'b', 'c', 0xc0, 0xdb, 'd', 'e', 0xc0, 'f', 0xdb
  29. #define SLIP_ENCODED_PACKET 0xdb, 0xdd, 'a', 'b', 'c', 0xdb, 0xdc, 0xdb, \
  30. 0xdd, 'd', 'e', 0xdb, 0xdc, 'f', 0xdb, 0xdd
  31. #define REQUIRE_SUCCESS(exp) REQUIRE( (exp) == ESP_LOADER_SUCCESS )
  32. // Helper function for debugging.
  33. __attribute__((unused))
  34. static void arrays_match(void *array_1, void *array_2, size_t size)
  35. {
  36. int8_t *arr_1 = (int8_t *)array_1;
  37. int8_t *arr_2 = (int8_t *)array_2;
  38. for (size_t i = 0; i < size; i++) {
  39. if (arr_1[i] != arr_2[i]) {
  40. printf("\nArrays do NOT match on index: %lu, with values %02hhx, %02hhx \n",
  41. i, arr_1[i], arr_2[i]);
  42. printf("\nExpected: ");
  43. for (uint32_t j = 0; j < size; j++) { printf("%02hhx ", arr_1[j]); }
  44. printf("\nActual: ");
  45. for (uint32_t j = 0; j < size; j++) { printf("%02hhx ", arr_2[j]); }
  46. return;
  47. }
  48. }
  49. printf("Arrays Match\n");
  50. }
  51. // Wrapper around command_t for convenience
  52. struct __attribute__((packed)) expected_response {
  53. expected_response(command_t cmd)
  54. {
  55. data.common.direction = READ_DIRECTION;
  56. data.common.command = cmd;
  57. data.common.size = 16;
  58. data.common.value = 0;
  59. data.status.failed = STATUS_SUCCESS;
  60. data.status.error = 0;
  61. }
  62. response_t data;
  63. };
  64. static_assert(sizeof(expected_response) == sizeof(response_t), "Size NOT equal");
  65. inline void queue_response(expected_response &response, size_t size = sizeof(expected_response))
  66. {
  67. set_read_buffer(&response, size);
  68. }
  69. expected_response set_params_response(SPI_SET_PARAMS);
  70. expected_response flash_begin_response(FLASH_BEGIN);
  71. expected_response flash_data_response(FLASH_DATA);
  72. expected_response flash_end_response(FLASH_END);
  73. expected_response write_reg_response(WRITE_REG);
  74. expected_response read_reg_response(READ_REG);
  75. expected_response attach_response(SPI_ATTACH);
  76. expected_response sync_response(SYNC);
  77. const uint32_t reg_address = 0x1000;
  78. const uint32_t reg_value = 55;
  79. struct __attribute__((packed)) write_reg_cmd_response {
  80. uint8_t delimiter_1 = 0xc0;
  81. write_reg_command_t write_reg_cmd = {
  82. .common = {
  83. .direction = WRITE_DIRECTION,
  84. .command = WRITE_REG,
  85. .size = 16,
  86. .checksum = 0
  87. },
  88. .address = reg_address,
  89. .value = reg_value,
  90. .mask = 0xFFFFFFFF,
  91. .delay_us = 0
  92. };
  93. uint8_t delimiter_2 = 0xc0;
  94. };
  95. map<target_chip_t, uint32_t> chip_magic_value = {
  96. {ESP8266_CHIP, 0xfff0c101},
  97. {ESP32_CHIP, 0x00f01d83},
  98. {ESP32S2_CHIP, 0x000007c6},
  99. {ESP32C3_CHIP, 0x6921506f},
  100. {ESP32S3_CHIP, 0x00000009},
  101. };
  102. void queue_connect_response(target_chip_t target = ESP32_CHIP, uint32_t magic_value = 0)
  103. {
  104. // Set magic value register used for detection of attached chip
  105. auto magic_value_response = read_reg_response;
  106. magic_value_response.data.common.value = magic_value ? magic_value : chip_magic_value[target];
  107. clear_buffers();
  108. queue_response(sync_response);
  109. queue_response(magic_value_response);
  110. if (target == ESP8266_CHIP) {
  111. queue_response(flash_begin_response);
  112. } else {
  113. auto efuse_pin_config_reg_1 = read_reg_response;
  114. auto efuse_pin_config_reg_2 = read_reg_response;
  115. queue_response(efuse_pin_config_reg_1);
  116. queue_response(efuse_pin_config_reg_2);
  117. queue_response(attach_response);
  118. }
  119. }
  120. TEST_CASE( "chip_magic_value contains all supported chips " )
  121. {
  122. REQUIRE( chip_magic_value.size() == ESP_MAX_CHIP );
  123. }
  124. TEST_CASE( "Can connect within specified time " )
  125. {
  126. queue_connect_response();
  127. esp_loader_connect_args_t connect_config = {
  128. .sync_timeout = 10,
  129. .trials = 1
  130. };
  131. SECTION( "Can connect" ) {
  132. serial_set_time_delay(5);
  133. REQUIRE_SUCCESS( esp_loader_connect(&connect_config) );
  134. }
  135. SECTION( "Timeout error is returned when timeout expires" ) {
  136. serial_set_time_delay(20);
  137. REQUIRE ( esp_loader_connect(&connect_config) == ESP_LOADER_ERROR_TIMEOUT );
  138. }
  139. SECTION( "Can connect after several trials within specified time" ) {
  140. connect_config.trials = 5;
  141. serial_set_time_delay(40);
  142. REQUIRE_SUCCESS( esp_loader_connect(&connect_config) );
  143. serial_set_time_delay(60);
  144. REQUIRE( esp_loader_connect(&connect_config) == ESP_LOADER_ERROR_TIMEOUT );
  145. }
  146. serial_set_time_delay(0);
  147. }
  148. TEST_CASE( "Can detect attached target" )
  149. {
  150. esp_loader_connect_args_t connect_config = ESP_LOADER_CONNECT_DEFAULT();
  151. SECTION( "Can detect ESP32" ) {
  152. queue_connect_response(ESP32_CHIP);
  153. REQUIRE_SUCCESS( esp_loader_connect(&connect_config) );
  154. REQUIRE( esp_loader_get_target() == ESP32_CHIP );
  155. }
  156. SECTION( "Can detect ESP32S2" ) {
  157. queue_connect_response(ESP32S2_CHIP);
  158. REQUIRE_SUCCESS( esp_loader_connect(&connect_config) );
  159. REQUIRE( esp_loader_get_target() == ESP32S2_CHIP );
  160. }
  161. SECTION( "Can detect ESP32C3" ) {
  162. queue_connect_response(ESP32C3_CHIP);
  163. REQUIRE_SUCCESS( esp_loader_connect(&connect_config) );
  164. REQUIRE( esp_loader_get_target() == ESP32C3_CHIP );
  165. }
  166. SECTION( "Can detect ESP32C3 rev3" ) {
  167. queue_connect_response(ESP32C3_CHIP, 0x1b31506f);
  168. REQUIRE_SUCCESS( esp_loader_connect(&connect_config) );
  169. REQUIRE( esp_loader_get_target() == ESP32C3_CHIP );
  170. }
  171. SECTION( "Can detect ESP32S3" ) {
  172. queue_connect_response(ESP32S3_CHIP);
  173. REQUIRE_SUCCESS( esp_loader_connect(&connect_config) );
  174. REQUIRE( esp_loader_get_target() == ESP32S3_CHIP );
  175. }
  176. SECTION( "Can detect ESP8266" ) {
  177. queue_connect_response(ESP8266_CHIP);
  178. REQUIRE_SUCCESS( esp_loader_connect(&connect_config) );
  179. REQUIRE( esp_loader_get_target() == ESP8266_CHIP );
  180. }
  181. SECTION( "Can detect unknown chip" ) {
  182. queue_connect_response(ESP_UNKNOWN_CHIP, 0xaaaaaaaa);
  183. REQUIRE( esp_loader_connect(&connect_config) == ESP_LOADER_ERROR_INVALID_TARGET);
  184. }
  185. }
  186. TEST_CASE( "Register can be read correctly" )
  187. {
  188. clear_buffers();
  189. uint32_t reg_value = 0;
  190. read_reg_response.data.common.value = 55;
  191. queue_response(read_reg_response);
  192. REQUIRE_SUCCESS( esp_loader_read_register(0, &reg_value) );
  193. REQUIRE( reg_value == 55 );
  194. }
  195. TEST_CASE( "Register can be written correctly" )
  196. {
  197. write_reg_cmd_response expected;
  198. write_reg_response.data.common.value = 55;
  199. clear_buffers();
  200. queue_response(write_reg_response);
  201. REQUIRE_SUCCESS( esp_loader_write_register(reg_address, reg_value) );
  202. REQUIRE( memcmp(write_buffer_data(), &expected, sizeof(expected)) == 0 );
  203. }
  204. // -------------------- Serial comm test -----------------------
  205. TEST_CASE ( "SLIP is encoded correctly" )
  206. {
  207. loader_flash_begin_cmd(0, 0, 0, 0, ESP32_CHIP); // To reset sequence number counter
  208. uint8_t data[] = { TEST_SLIP_PACKET };
  209. uint8_t expected[] = {
  210. 0xc0, // Begin
  211. 0x00, // Write direction
  212. 0x03, // FLASH_DATA command
  213. 16 + sizeof(data), 0, // Number of characters to send
  214. 0x33, 0, 0, 0,// Checksum
  215. sizeof(data), 0, 0, 0, // Data size
  216. 0, 0, 0, 0, // Sequence number
  217. 0, 0, 0, 0, // zero
  218. 0, 0, 0, 0, // zero
  219. SLIP_ENCODED_PACKET,
  220. 0xc0, // End
  221. };
  222. // write_buffer_print();
  223. // print_array(expected, sizeof(expected));
  224. clear_buffers();
  225. queue_response(flash_data_response);
  226. REQUIRE_SUCCESS( loader_flash_data_cmd(data, sizeof(data)) );
  227. REQUIRE( memcmp(write_buffer_data(), expected, sizeof(expected)) == 0 );
  228. }
  229. TEST_CASE( "Sync command is constructed correctly" )
  230. {
  231. uint8_t expected[] = {
  232. 0xc0, // Begin
  233. 0x00, // Write direction
  234. 0x08, // SYNC command
  235. 36, 0, // Number of characters to send
  236. 0, 0, 0, 0, // Checksum is ignored for this command
  237. 0x07, 0x07, 0x12, 0x20,
  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. 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
  242. 0xc0, // End
  243. };
  244. clear_buffers();
  245. queue_response(sync_response);
  246. REQUIRE_SUCCESS( loader_sync_cmd() );
  247. REQUIRE( memcmp(write_buffer_data(), expected, sizeof(expected)) == 0 );
  248. }
  249. TEST_CASE( "Register can be read and decoded correctly" )
  250. {
  251. clear_buffers();
  252. read_reg_response.data.common.value = 55;
  253. queue_response(read_reg_response);
  254. uint32_t reg_value = 0;
  255. esp_loader_read_register(0, &reg_value);
  256. REQUIRE( reg_value == 55 );
  257. }
  258. TEST_CASE( "Received response (in SLIP format) is decoded correctly" )
  259. {
  260. clear_buffers();
  261. read_reg_response.data.common.value = 0xC0BD; // C0, BD has to be replaced
  262. queue_response(read_reg_response);
  263. uint32_t reg_value = 0;
  264. esp_loader_read_register(0, &reg_value);
  265. REQUIRE( reg_value == 0xC0BD );
  266. }
  267. // -------------------- Serial mock test -----------------------
  268. TEST_CASE( "Serial read works correctly" )
  269. {
  270. uint32_t reg_value = 5;
  271. uint8_t readout[sizeof(reg_value) + 2];
  272. uint8_t expected[] = { 0xc0, 5, 0, 0, 0, 0xc0 };
  273. clear_buffers();
  274. set_read_buffer(&reg_value, sizeof(reg_value));
  275. SECTION( "Read buffer can be read" ) {
  276. loader_port_serial_read(readout, sizeof(readout), 0);
  277. REQUIRE( memcmp(readout, expected, sizeof(readout)) == 0 );
  278. }
  279. SECTION ( "Read buffer can be read in smaller chunks" ) {
  280. loader_port_serial_read(&readout[0], 3, 0);
  281. loader_port_serial_read(&readout[3], 3, 0);
  282. REQUIRE( memcmp(readout, expected, sizeof(readout)) == 0 );
  283. }
  284. SECTION ( "Timeout is returned when requested amount of data is not available" ) {
  285. REQUIRE( loader_port_serial_read(readout, sizeof(readout) + 1, 0) == ESP_LOADER_ERROR_TIMEOUT);
  286. }
  287. SECTION ( "Read buffer is correctly SLIP encoded " ) {
  288. uint8_t data_to_encode[] = { TEST_SLIP_PACKET };
  289. uint8_t expected[] = { 0xc0, SLIP_ENCODED_PACKET, 0xc0};
  290. uint8_t encoded[sizeof(expected)];
  291. clear_buffers();
  292. fill(encoded, &encoded[sizeof(encoded)], 0);
  293. set_read_buffer(data_to_encode, sizeof(data_to_encode));
  294. loader_port_serial_read(encoded, sizeof(encoded), 0);
  295. REQUIRE( memcmp(expected, encoded, sizeof(expected)) == 0 );
  296. }
  297. }