test.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423
  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 <iostream>
  25. #include <algorithm>
  26. using namespace std;
  27. #define TEST_SLIP_PACKET 0xdb, 'a', 'b', 'c', 0xc0, 0xdb, 'd', 'e', 0xc0, 'f', 0xdb
  28. #define SLIP_ENCODED_PACKET 0xdb, 0xdd, 'a', 'b', 'c', 0xdb, 0xdc, 0xdb, \
  29. 0xdd, 'd', 'e', 0xdb, 0xdc, 'f', 0xdb, 0xdd
  30. // Helper function for debugging.
  31. __attribute__((unused))
  32. static void arrays_match(int8_t *array_1, int8_t *array_2, size_t size)
  33. {
  34. for (size_t i = 0; i < size; i++) {
  35. if (array_1[i] != array_2[i]) {
  36. printf("\nArrays do NOT match on index: %lu, with values %0x, %0x \n",
  37. i, array_1[i], array_2[i]);
  38. return;
  39. }
  40. }
  41. printf("Arrays Match\n");
  42. }
  43. // Wrapper around command_t for convenience
  44. struct __attribute__((packed)) expected_response {
  45. expected_response(command_t cmd)
  46. {
  47. data.common.direction = READ_DIRECTION;
  48. data.common.command = cmd;
  49. data.common.size = 16;
  50. data.common.value = 0;
  51. data.status.failed = STATUS_SUCCESS;
  52. data.status.error = 0;
  53. data.status.reserved_0 = 0;
  54. data.status.reserved_1 = 0;
  55. }
  56. response_t data;
  57. };
  58. static_assert(sizeof(expected_response) == sizeof(response_t), "Size NOT equal");
  59. inline void queue_response(expected_response &response, size_t size = sizeof(expected_response))
  60. {
  61. set_read_buffer(&response, size);
  62. }
  63. expected_response flash_begin_response(FLASH_BEGIN);
  64. expected_response flash_data_response(FLASH_DATA);
  65. expected_response flash_end_response(FLASH_END);
  66. expected_response write_reg_response(WRITE_REG);
  67. expected_response read_reg_response(READ_REG);
  68. expected_response attach_response(SPI_ATTACH);
  69. expected_response sync_response(SYNC);
  70. struct __attribute__((packed)) flash_start_frame {
  71. uint8_t delimiter_3 = 0xc0;
  72. begin_command_t begin_cmd = {
  73. .common = {
  74. .direction = WRITE_DIRECTION,
  75. .command = FLASH_BEGIN,
  76. .size = 16,
  77. .checksum = 0,
  78. },
  79. .erase_size = 0,
  80. .packet_count = 0,
  81. .packet_size = 0,
  82. .offset = 0,
  83. };
  84. uint8_t delimiter_4 = 0xc0;
  85. flash_start_frame(uint32_t offset, uint32_t image_size, uint32_t block_size)
  86. {
  87. uint32_t blocks_to_write = (image_size + block_size - 1) / block_size;
  88. begin_cmd.packet_count = blocks_to_write;
  89. begin_cmd.erase_size = blocks_to_write * block_size;
  90. begin_cmd.packet_size = block_size;
  91. begin_cmd.offset = offset;
  92. }
  93. };
  94. struct __attribute__((packed)) flash_finish_frame {
  95. uint8_t delimiter_1 = 0xc0;
  96. flash_end_command_t end_cmd = {
  97. .common = {
  98. .direction = WRITE_DIRECTION,
  99. .command = FLASH_END,
  100. .size = 4,
  101. .checksum = 0,
  102. },
  103. .stay_in_loader = 1,
  104. };
  105. uint8_t delimiter_2 = 0xc0;
  106. };
  107. template<size_t PAYLOAD_SIZE>
  108. struct __attribute__((packed)) flash_write_frame {
  109. uint8_t delimiter_1 = 0xc0;
  110. data_command_t data_cmd = {
  111. .common = {
  112. .direction = WRITE_DIRECTION,
  113. .command = FLASH_DATA,
  114. .size = 16 + PAYLOAD_SIZE,
  115. .checksum = 0xef,
  116. },
  117. .data_size = PAYLOAD_SIZE,
  118. .sequence_number = 0,
  119. .zero_0 = 0,
  120. .zero_1 = 0,
  121. };
  122. array<uint8_t, PAYLOAD_SIZE> payload;
  123. uint8_t delimiter_2 = 0xc0;
  124. flash_write_frame()
  125. {
  126. payload.fill(0xFF);
  127. data_cmd.sequence_number = seq_num++;
  128. }
  129. ~flash_write_frame()
  130. {
  131. seq_num--;
  132. }
  133. void fill(uint8_t data, size_t size = PAYLOAD_SIZE)
  134. {
  135. fill_n(payload.data(), size, data);
  136. }
  137. static uint32_t seq_num;
  138. };
  139. const uint32_t reg_address = 0x1000;
  140. const uint32_t reg_value = 55;
  141. struct __attribute__((packed)) write_reg_cmd_response {
  142. uint8_t delimiter_1 = 0xc0;
  143. write_reg_command_t write_reg_cmd = {
  144. .common = {
  145. .direction = WRITE_DIRECTION,
  146. .command = WRITE_REG,
  147. .size = 16,
  148. .checksum = 0
  149. },
  150. .address = reg_address,
  151. .value = reg_value,
  152. .mask = 0xFFFFFFFF,
  153. .delay_us = 0
  154. };
  155. uint8_t delimiter_2 = 0xc0;
  156. };
  157. template<size_t PAYLOAD_SIZE>
  158. uint32_t flash_write_frame<PAYLOAD_SIZE>::seq_num = 0;
  159. TEST_CASE( "Large payload that does not fit BLOCK_SIZE is split into \
  160. multiple data frames. Last data frame is padded with 0xFF" )
  161. {
  162. const uint32_t BLOCK_SIZE = 1024;
  163. uint8_t data[BLOCK_SIZE];
  164. memset(data, 0x11, BLOCK_SIZE);
  165. flash_write_frame<BLOCK_SIZE> expected_data[3];
  166. expected_data[0].fill(0x11);
  167. expected_data[1].fill(0x11);
  168. expected_data[2].fill(0x11, 200);
  169. flash_start_frame expected_start(0, sizeof(data) * 3, BLOCK_SIZE);
  170. // Check flash start operation
  171. clear_buffers();
  172. queue_response(flash_begin_response);
  173. REQUIRE ( esp_loader_flash_start(0, sizeof(data) * 3, BLOCK_SIZE) == ESP_LOADER_SUCCESS );
  174. REQUIRE( memcmp(write_buffer_data(), &expected_start, sizeof(expected_start)) == 0 );
  175. // Check flash write operation
  176. clear_buffers();
  177. queue_response(flash_data_response);
  178. queue_response(flash_data_response);
  179. queue_response(flash_data_response);
  180. REQUIRE( esp_loader_flash_write(data, sizeof(data)) == ESP_LOADER_SUCCESS );
  181. REQUIRE( esp_loader_flash_write(data, sizeof(data)) == ESP_LOADER_SUCCESS );
  182. REQUIRE( esp_loader_flash_write(data, 200) == ESP_LOADER_SUCCESS );
  183. REQUIRE( memcmp(write_buffer_data(), &expected_data, sizeof(expected_data)) == 0 );
  184. // queue_response(flash_end_response);
  185. }
  186. TEST_CASE( "Can connect within specified time " )
  187. {
  188. // Set date registers used for detection of attached chip
  189. auto uart_date_reg_1 = read_reg_response;
  190. auto uart_date_reg_2 = read_reg_response;
  191. uart_date_reg_1.data.common.value = 0x15122500;
  192. uart_date_reg_2.data.common.value = 0;
  193. clear_buffers();
  194. queue_response(sync_response);
  195. queue_response(uart_date_reg_1);
  196. queue_response(uart_date_reg_2);
  197. queue_response(attach_response);
  198. esp_loader_connect_args_t connect_config = {
  199. .sync_timeout = 10,
  200. .trials = 1
  201. };
  202. SECTION( "Can connect" ) {
  203. serial_set_time_delay(5);
  204. REQUIRE ( esp_loader_connect(&connect_config) == ESP_LOADER_SUCCESS );
  205. }
  206. SECTION( "Timeout error is returned when timeout expires" ) {
  207. serial_set_time_delay(20);
  208. REQUIRE ( esp_loader_connect(&connect_config) == ESP_LOADER_ERROR_TIMEOUT );
  209. }
  210. SECTION( "Can connect after several trials within specified time" ) {
  211. connect_config.trials = 5;
  212. serial_set_time_delay(40);
  213. REQUIRE ( esp_loader_connect(&connect_config) == ESP_LOADER_SUCCESS );
  214. serial_set_time_delay(60);
  215. REQUIRE ( esp_loader_connect(&connect_config) == ESP_LOADER_ERROR_TIMEOUT );
  216. }
  217. serial_set_time_delay(0);
  218. }
  219. TEST_CASE( "Register can be read correctly" )
  220. {
  221. clear_buffers();
  222. uint32_t reg_value = 0;
  223. read_reg_response.data.common.value = 55;
  224. queue_response(read_reg_response);
  225. REQUIRE( esp_loader_read_register(0, &reg_value) == ESP_LOADER_SUCCESS );
  226. REQUIRE( reg_value == 55 );
  227. }
  228. TEST_CASE( "Register can be written correctly" )
  229. {
  230. write_reg_cmd_response expected;
  231. write_reg_response.data.common.value = 55;
  232. clear_buffers();
  233. queue_response(write_reg_response);
  234. REQUIRE( esp_loader_write_register(reg_address, reg_value) == ESP_LOADER_SUCCESS );
  235. REQUIRE( memcmp(write_buffer_data(), &expected, sizeof(expected)) == 0 );
  236. }
  237. // -------------------- Serial comm test -----------------------
  238. TEST_CASE ( "SLIP is encoded correctly" )
  239. {
  240. loader_flash_begin_cmd(0, 0, 0, 0); // To reset sequence number counter
  241. uint8_t data[] = { TEST_SLIP_PACKET };
  242. uint8_t expected[] = {
  243. 0xc0, // Begin
  244. 0x00, // Write direction
  245. 0x03, // FLASH_DATA command
  246. 16 + sizeof(data), 0, // Number of characters to send
  247. 0x33, 0, 0, 0,// Checksum
  248. sizeof(data), 0, 0, 0, // Data size
  249. 0, 0, 0, 0, // Sequence number
  250. 0, 0, 0, 0, // zero
  251. 0, 0, 0, 0, // zero
  252. SLIP_ENCODED_PACKET,
  253. 0xc0, // End
  254. };
  255. // write_buffer_print();
  256. // print_array(expected, sizeof(expected));
  257. clear_buffers();
  258. queue_response(flash_data_response);
  259. REQUIRE( loader_flash_data_cmd(data, sizeof(data)) == ESP_LOADER_SUCCESS );
  260. REQUIRE( memcmp(write_buffer_data(), expected, sizeof(expected)) == 0 );
  261. }
  262. TEST_CASE( "Sync command is constructed correctly" )
  263. {
  264. uint8_t expected[] = {
  265. 0xc0, // Begin
  266. 0x00, // Write direction
  267. 0x08, // SYNC command
  268. 36, 0, // Number of characters to send
  269. 0, 0, 0, 0, // Checksum is ignored for this command
  270. 0x07, 0x07, 0x12, 0x20,
  271. 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
  272. 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
  273. 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
  274. 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
  275. 0xc0, // End
  276. };
  277. clear_buffers();
  278. queue_response(sync_response);
  279. REQUIRE( loader_sync_cmd() == ESP_LOADER_SUCCESS );
  280. REQUIRE( memcmp(write_buffer_data(), expected, sizeof(expected)) == 0 );
  281. }
  282. TEST_CASE( "Register can be read and decoded correctly" )
  283. {
  284. clear_buffers();
  285. read_reg_response.data.common.value = 55;
  286. queue_response(read_reg_response);
  287. uint32_t reg_value = 0;
  288. esp_loader_read_register(0, &reg_value);
  289. REQUIRE( reg_value == 55 );
  290. }
  291. TEST_CASE( "Received response (in SLIP format) is decoded correctly" )
  292. {
  293. clear_buffers();
  294. read_reg_response.data.common.value = 0xC0BD; // C0, BD has to be replaced
  295. queue_response(read_reg_response);
  296. uint32_t reg_value = 0;
  297. esp_loader_read_register(0, &reg_value);
  298. REQUIRE( reg_value == 0xC0BD );
  299. }
  300. // -------------------- Serial mock test -----------------------
  301. TEST_CASE( "Serial read works correctly" )
  302. {
  303. uint32_t reg_value = 5;
  304. uint8_t readout[sizeof(reg_value) + 2];
  305. uint8_t expected[] = { 0xc0, 5, 0, 0, 0, 0xc0 };
  306. clear_buffers();
  307. set_read_buffer(&reg_value, sizeof(reg_value));
  308. SECTION( "Read buffer can be read" ) {
  309. loader_port_serial_read(readout, sizeof(readout), 0);
  310. REQUIRE( memcmp(readout, expected, sizeof(readout)) == 0 );
  311. }
  312. SECTION ( "Read buffer can be read in smaller chunks" ) {
  313. loader_port_serial_read(&readout[0], 3, 0);
  314. loader_port_serial_read(&readout[3], 3, 0);
  315. REQUIRE( memcmp(readout, expected, sizeof(readout)) == 0 );
  316. }
  317. SECTION ( "Timeout is returned when requested amount of data is not available" ) {
  318. REQUIRE( loader_port_serial_read(readout, sizeof(readout) + 1, 0) == ESP_LOADER_ERROR_TIMEOUT);
  319. }
  320. SECTION ( "Read buffer is correctly SLIP encoded " ) {
  321. uint8_t data_to_encode[] = { TEST_SLIP_PACKET };
  322. uint8_t expected[] = { 0xc0, SLIP_ENCODED_PACKET, 0xc0};
  323. uint8_t encoded[sizeof(expected)];
  324. clear_buffers();
  325. fill(encoded, &encoded[sizeof(encoded)], 0);
  326. set_read_buffer(data_to_encode, sizeof(data_to_encode));
  327. loader_port_serial_read(encoded, sizeof(encoded), 0);
  328. REQUIRE( memcmp(expected, encoded, sizeof(expected)) == 0 );
  329. }
  330. }