Browse Source

Port over all the other commands

...but not it's obvious - we can't assume each packet nicely
encapsulates a single stage, it might all arrive in one go.
So the current "recv" implementation can't work. d'oh!
Brian Starkey 1 year ago
parent
commit
a57cac28f1
4 changed files with 491 additions and 13 deletions
  1. 5
    0
      CMakeLists.txt
  2. 477
    5
      main.c
  3. 4
    8
      tcp_comm.c
  4. 5
    0
      tcp_comm.h

+ 5
- 0
CMakeLists.txt View File

@@ -20,6 +20,11 @@ pico_add_extra_outputs(picowota)
20 20
 target_include_directories(picowota PRIVATE ${CMAKE_CURRENT_LIST_DIR})
21 21
 
22 22
 target_link_libraries(picowota
23
+	cmsis_core
24
+	hardware_dma
25
+	hardware_flash
26
+	hardware_resets
27
+	hardware_structs
23 28
 	pico_cyw43_arch_lwip_poll
24 29
 	pico_stdlib
25 30
 )

+ 477
- 5
main.c View File

@@ -10,6 +10,17 @@
10 10
 #include <string.h>
11 11
 #include <stdlib.h>
12 12
 
13
+#include "RP2040.h"
14
+#include "pico/time.h"
15
+#include "hardware/dma.h"
16
+#include "hardware/flash.h"
17
+#include "hardware/structs/dma.h"
18
+#include "hardware/structs/watchdog.h"
19
+#include "hardware/gpio.h"
20
+#include "hardware/resets.h"
21
+#include "hardware/uart.h"
22
+#include "hardware/watchdog.h"
23
+
13 24
 #include "pico/stdlib.h"
14 25
 #include "pico/cyw43_arch.h"
15 26
 
@@ -18,19 +29,36 @@
18 29
 extern const char *wifi_ssid;
19 30
 extern const char *wifi_pass;
20 31
 
32
+#define BOOTLOADER_ENTRY_PIN 15
33
+#define BOOTLOADER_ENTRY_MAGIC 0xb105f00d
34
+
21 35
 #define TCP_PORT 4242
22 36
 
23
-#define MAX_LEN 2048
37
+#define IMAGE_HEADER_OFFSET (360 * 1024)
38
+
39
+#define WRITE_ADDR_MIN (XIP_BASE + IMAGE_HEADER_OFFSET + FLASH_SECTOR_SIZE)
40
+#define ERASE_ADDR_MIN (XIP_BASE + IMAGE_HEADER_OFFSET)
41
+#define FLASH_ADDR_MAX (XIP_BASE + PICO_FLASH_SIZE_BYTES)
24 42
 
25 43
 #define CMD_SYNC          (('S' << 0) | ('Y' << 8) | ('N' << 16) | ('C' << 24))
26 44
 #define RSP_SYNC          (('W' << 0) | ('O' << 8) | ('T' << 16) | ('A' << 24))
45
+#define CMD_INFO          (('I' << 0) | ('N' << 8) | ('F' << 16) | ('O' << 24))
46
+
47
+#define CMD_READ   (('R' << 0) | ('E' << 8) | ('A' << 16) | ('D' << 24))
48
+#define CMD_CSUM   (('C' << 0) | ('S' << 8) | ('U' << 16) | ('M' << 24))
49
+#define CMD_CRC    (('C' << 0) | ('R' << 8) | ('C' << 16) | ('C' << 24))
50
+#define CMD_ERASE  (('E' << 0) | ('R' << 8) | ('A' << 16) | ('S' << 24))
51
+#define CMD_WRITE  (('W' << 0) | ('R' << 8) | ('I' << 16) | ('T' << 24))
52
+#define CMD_SEAL   (('S' << 0) | ('E' << 8) | ('A' << 16) | ('L' << 24))
53
+#define CMD_GO     (('G' << 0) | ('O' << 8) | ('G' << 16) | ('O' << 24))
54
+#define CMD_REBOOT (('B' << 0) | ('O' << 8) | ('O' << 16) | ('T' << 24))
27 55
 
28 56
 static uint32_t handle_sync(uint32_t *args_in, uint8_t *data_in, uint32_t *resp_args_out, uint8_t *resp_data_out)
29 57
 {
30 58
 	return RSP_SYNC;
31 59
 }
32 60
 
33
-const struct comm_command util_sync_cmd = {
61
+const struct comm_command sync_cmd = {
34 62
 	.opcode = CMD_SYNC,
35 63
 	.nargs = 0,
36 64
 	.resp_nargs = 0,
@@ -38,6 +66,441 @@ const struct comm_command util_sync_cmd = {
38 66
 	.handle = &handle_sync,
39 67
 };
40 68
 
69
+static uint32_t size_read(uint32_t *args_in, uint32_t *data_len_out, uint32_t *resp_data_len_out)
70
+{
71
+	uint32_t size = args_in[1];
72
+	if (size > TCP_COMM_MAX_DATA_LEN) {
73
+		return TCP_COMM_RSP_ERR;
74
+	}
75
+
76
+	// TODO: Validate address
77
+
78
+	*data_len_out = 0;
79
+	*resp_data_len_out = size;
80
+
81
+	return TCP_COMM_RSP_OK;
82
+}
83
+
84
+static uint32_t handle_read(uint32_t *args_in, uint8_t *data_in, uint32_t *resp_args_out, uint8_t *resp_data_out)
85
+{
86
+	uint32_t addr = args_in[0];
87
+	uint32_t size = args_in[1];
88
+
89
+	memcpy(resp_data_out, (void *)addr, size);
90
+
91
+	return TCP_COMM_RSP_OK;
92
+}
93
+
94
+const struct comm_command read_cmd = {
95
+	// READ addr len
96
+	// OKOK [data]
97
+	.opcode = CMD_READ,
98
+	.nargs = 2,
99
+	.resp_nargs = 0,
100
+	.size = &size_read,
101
+	.handle = &handle_read,
102
+};
103
+
104
+static uint32_t size_csum(uint32_t *args_in, uint32_t *data_len_out, uint32_t *resp_data_len_out)
105
+{
106
+	uint32_t addr = args_in[0];
107
+	uint32_t size = args_in[1];
108
+
109
+	if ((addr & 0x3) || (size & 0x3)) {
110
+		// Must be aligned
111
+		return TCP_COMM_RSP_ERR;
112
+	}
113
+
114
+	// TODO: Validate address
115
+
116
+	*data_len_out = 0;
117
+	*resp_data_len_out = 0;
118
+
119
+	return TCP_COMM_RSP_OK;
120
+}
121
+
122
+static uint32_t handle_csum(uint32_t *args_in, uint8_t *data_in, uint32_t *resp_args_out, uint8_t *resp_data_out)
123
+{
124
+	uint32_t dummy_dest;
125
+	uint32_t addr = args_in[0];
126
+	uint32_t size = args_in[1];
127
+
128
+	int channel = dma_claim_unused_channel(true);
129
+
130
+	dma_channel_config c = dma_channel_get_default_config(channel);
131
+	channel_config_set_transfer_data_size(&c, DMA_SIZE_32);
132
+	channel_config_set_read_increment(&c, true);
133
+	channel_config_set_write_increment(&c, false);
134
+	channel_config_set_sniff_enable(&c, true);
135
+
136
+	dma_hw->sniff_data = 0;
137
+	dma_sniffer_enable(channel, 0xf, true);
138
+
139
+	dma_channel_configure(channel, &c, &dummy_dest, (void *)addr, size / 4, true);
140
+
141
+	dma_channel_wait_for_finish_blocking(channel);
142
+
143
+	dma_sniffer_disable();
144
+	dma_channel_unclaim(channel);
145
+
146
+	*resp_args_out = dma_hw->sniff_data;
147
+
148
+	return TCP_COMM_RSP_OK;
149
+}
150
+
151
+struct comm_command csum_cmd = {
152
+	// CSUM addr len
153
+	// OKOK csum
154
+	.opcode = CMD_CSUM,
155
+	.nargs = 2,
156
+	.resp_nargs = 1,
157
+	.size = &size_csum,
158
+	.handle = &handle_csum,
159
+};
160
+
161
+static uint32_t size_crc(uint32_t *args_in, uint32_t *data_len_out, uint32_t *resp_data_len_out)
162
+{
163
+	uint32_t addr = args_in[0];
164
+	uint32_t size = args_in[1];
165
+
166
+	if ((addr & 0x3) || (size & 0x3)) {
167
+		// Must be aligned
168
+		return TCP_COMM_RSP_ERR;
169
+	}
170
+
171
+	// TODO: Validate address
172
+
173
+	*data_len_out = 0;
174
+	*resp_data_len_out = 0;
175
+
176
+	return TCP_COMM_RSP_OK;
177
+}
178
+
179
+// ptr must be 4-byte aligned and len must be a multiple of 4
180
+static uint32_t calc_crc32(void *ptr, uint32_t len)
181
+{
182
+	uint32_t dummy_dest, crc;
183
+
184
+	int channel = dma_claim_unused_channel(true);
185
+	dma_channel_config c = dma_channel_get_default_config(channel);
186
+	channel_config_set_transfer_data_size(&c, DMA_SIZE_32);
187
+	channel_config_set_read_increment(&c, true);
188
+	channel_config_set_write_increment(&c, false);
189
+	channel_config_set_sniff_enable(&c, true);
190
+
191
+	// Seed the CRC calculation
192
+	dma_hw->sniff_data = 0xffffffff;
193
+
194
+	// Mode 1, then bit-reverse the result gives the same result as
195
+	// golang's IEEE802.3 implementation
196
+	dma_sniffer_enable(channel, 0x1, true);
197
+	dma_hw->sniff_ctrl |= DMA_SNIFF_CTRL_OUT_REV_BITS;
198
+
199
+	dma_channel_configure(channel, &c, &dummy_dest, ptr, len / 4, true);
200
+
201
+	dma_channel_wait_for_finish_blocking(channel);
202
+
203
+	// Read the result before resetting
204
+	crc = dma_hw->sniff_data ^ 0xffffffff;
205
+
206
+	dma_sniffer_disable();
207
+	dma_channel_unclaim(channel);
208
+
209
+	return crc;
210
+}
211
+
212
+static uint32_t handle_crc(uint32_t *args_in, uint8_t *data_in, uint32_t *resp_args_out, uint8_t *resp_data_out)
213
+{
214
+	uint32_t addr = args_in[0];
215
+	uint32_t size = args_in[1];
216
+
217
+	resp_args_out[0] = calc_crc32((void *)addr, size);
218
+
219
+	return TCP_COMM_RSP_OK;
220
+}
221
+
222
+struct comm_command crc_cmd = {
223
+	// CRCC addr len
224
+	// OKOK crc
225
+	.opcode = CMD_CRC,
226
+	.nargs = 2,
227
+	.resp_nargs = 1,
228
+	.size = &size_crc,
229
+	.handle = &handle_crc,
230
+};
231
+
232
+static uint32_t handle_erase(uint32_t *args_in, uint8_t *data_in, uint32_t *resp_args_out, uint8_t *resp_data_out)
233
+{
234
+	uint32_t addr = args_in[0];
235
+	uint32_t size = args_in[1];
236
+
237
+	if ((addr < ERASE_ADDR_MIN) || (addr + size >= FLASH_ADDR_MAX)) {
238
+		// Outside flash
239
+		return TCP_COMM_RSP_ERR;
240
+	}
241
+
242
+	if ((addr & (FLASH_SECTOR_SIZE - 1)) || (size & (FLASH_SECTOR_SIZE - 1))) {
243
+		// Must be aligned
244
+		return TCP_COMM_RSP_ERR;
245
+	}
246
+
247
+	flash_range_erase(addr - XIP_BASE, size);
248
+
249
+	return TCP_COMM_RSP_OK;
250
+}
251
+
252
+struct comm_command erase_cmd = {
253
+	// ERAS addr len
254
+	// OKOK
255
+	.opcode = CMD_ERASE,
256
+	.nargs = 2,
257
+	.resp_nargs = 0,
258
+	.size = NULL,
259
+	.handle = &handle_erase,
260
+};
261
+
262
+static uint32_t size_write(uint32_t *args_in, uint32_t *data_len_out, uint32_t *resp_data_len_out)
263
+{
264
+	uint32_t addr = args_in[0];
265
+	uint32_t size = args_in[1];
266
+
267
+	if ((addr < WRITE_ADDR_MIN) || (addr + size >= FLASH_ADDR_MAX)) {
268
+		// Outside flash
269
+		return TCP_COMM_RSP_ERR;
270
+	}
271
+
272
+	if ((addr & (FLASH_PAGE_SIZE - 1)) || (size & (FLASH_PAGE_SIZE -1))) {
273
+		// Must be aligned
274
+		return TCP_COMM_RSP_ERR;
275
+	}
276
+
277
+	if (size > TCP_COMM_MAX_DATA_LEN) {
278
+		return TCP_COMM_RSP_ERR;
279
+	}
280
+
281
+	// TODO: Validate address
282
+
283
+	*data_len_out = size;
284
+	*resp_data_len_out = 0;
285
+
286
+	return TCP_COMM_RSP_OK;
287
+}
288
+
289
+static uint32_t handle_write(uint32_t *args_in, uint8_t *data_in, uint32_t *resp_args_out, uint8_t *resp_data_out)
290
+{
291
+	uint32_t addr = args_in[0];
292
+	uint32_t size = args_in[1];
293
+
294
+	flash_range_program(addr - XIP_BASE, data_in, size);
295
+
296
+	resp_args_out[0] = calc_crc32((void *)addr, size);
297
+
298
+	return TCP_COMM_RSP_OK;
299
+}
300
+
301
+struct comm_command write_cmd = {
302
+	// WRIT addr len [data]
303
+	// OKOK crc
304
+	.opcode = CMD_WRITE,
305
+	.nargs = 2,
306
+	.resp_nargs = 1,
307
+	.size = &size_write,
308
+	.handle = &handle_write,
309
+};
310
+
311
+struct image_header {
312
+	uint32_t vtor;
313
+	uint32_t size;
314
+	uint32_t crc;
315
+	uint8_t pad[FLASH_PAGE_SIZE - (3 * 4)];
316
+};
317
+static_assert(sizeof(struct image_header) == FLASH_PAGE_SIZE, "image_header must be FLASH_PAGE_SIZE bytes");
318
+
319
+static bool image_header_ok(struct image_header *hdr)
320
+{
321
+	uint32_t *vtor = (uint32_t *)hdr->vtor;
322
+
323
+	uint32_t calc = calc_crc32((void *)hdr->vtor, hdr->size);
324
+
325
+	// CRC has to match
326
+	if (calc != hdr->crc) {
327
+		return false;
328
+	}
329
+
330
+	// Stack pointer needs to be in RAM
331
+	if (vtor[0] < SRAM_BASE) {
332
+		return false;
333
+	}
334
+
335
+	// Reset vector should be in the image, and thumb (bit 0 set)
336
+	if ((vtor[1] < hdr->vtor) || (vtor[1] > hdr->vtor + hdr->size) || !(vtor[1] & 1)) {
337
+		return false;
338
+	}
339
+
340
+	// Looks OK.
341
+	return true;
342
+}
343
+
344
+
345
+static uint32_t handle_seal(uint32_t *args_in, uint8_t *data_in, uint32_t *resp_args_out, uint8_t *resp_data_out)
346
+{
347
+	struct image_header hdr = {
348
+		.vtor = args_in[0],
349
+		.size = args_in[1],
350
+		.crc = args_in[2],
351
+	};
352
+
353
+	if ((hdr.vtor & 0xff) || (hdr.size & 0x3)) {
354
+		// Must be aligned
355
+		return TCP_COMM_RSP_ERR;
356
+	}
357
+
358
+	if (!image_header_ok(&hdr)) {
359
+		return TCP_COMM_RSP_ERR;
360
+	}
361
+
362
+	flash_range_erase(IMAGE_HEADER_OFFSET, FLASH_SECTOR_SIZE);
363
+	flash_range_program(IMAGE_HEADER_OFFSET, (const uint8_t *)&hdr, sizeof(hdr));
364
+
365
+	struct image_header *check = (struct image_header *)(XIP_BASE + IMAGE_HEADER_OFFSET);
366
+	if (memcmp(&hdr, check, sizeof(hdr))) {
367
+		return TCP_COMM_RSP_ERR;
368
+	}
369
+
370
+	return TCP_COMM_RSP_OK;
371
+}
372
+
373
+struct comm_command seal_cmd = {
374
+	// SEAL vtor len crc
375
+	// OKOK
376
+	.opcode = CMD_SEAL,
377
+	.nargs = 3,
378
+	.resp_nargs = 0,
379
+	.size = NULL,
380
+	.handle = &handle_seal,
381
+};
382
+
383
+static void disable_interrupts(void)
384
+{
385
+	SysTick->CTRL &= ~1;
386
+
387
+	NVIC->ICER[0] = 0xFFFFFFFF;
388
+	NVIC->ICPR[0] = 0xFFFFFFFF;
389
+}
390
+
391
+static void reset_peripherals(void)
392
+{
393
+    reset_block(~(
394
+            RESETS_RESET_IO_QSPI_BITS |
395
+            RESETS_RESET_PADS_QSPI_BITS |
396
+            RESETS_RESET_SYSCFG_BITS |
397
+            RESETS_RESET_PLL_SYS_BITS
398
+    ));
399
+}
400
+
401
+static void jump_to_vtor(uint32_t vtor)
402
+{
403
+	// Derived from the Leaf Labs Cortex-M3 bootloader.
404
+	// Copyright (c) 2010 LeafLabs LLC.
405
+	// Modified 2021 Brian Starkey <stark3y@gmail.com>
406
+	// Originally under The MIT License
407
+	uint32_t reset_vector = *(volatile uint32_t *)(vtor + 0x04);
408
+
409
+	SCB->VTOR = (volatile uint32_t)(vtor);
410
+
411
+	asm volatile("msr msp, %0"::"g"
412
+			(*(volatile uint32_t *)vtor));
413
+	asm volatile("bx %0"::"r" (reset_vector));
414
+}
415
+
416
+
417
+static uint32_t handle_go(uint32_t *args_in, uint8_t *data_in, uint32_t *resp_args_out, uint8_t *resp_data_out)
418
+{
419
+	disable_interrupts();
420
+
421
+	reset_peripherals();
422
+
423
+	jump_to_vtor(args_in[0]);
424
+
425
+	while(1);
426
+
427
+	return TCP_COMM_RSP_ERR;
428
+}
429
+
430
+struct comm_command go_cmd = {
431
+	// GOGO vtor
432
+	// NO RESPONSE
433
+	.opcode = CMD_GO,
434
+	.nargs = 1,
435
+	.resp_nargs = 0,
436
+	.size = NULL,
437
+	.handle = &handle_go,
438
+};
439
+
440
+static uint32_t handle_info(uint32_t *args_in, uint8_t *data_in, uint32_t *resp_args_out, uint8_t *resp_data_out)
441
+{
442
+	resp_args_out[0] = WRITE_ADDR_MIN;
443
+	resp_args_out[1] = (XIP_BASE + PICO_FLASH_SIZE_BYTES) - WRITE_ADDR_MIN;
444
+	resp_args_out[2] = FLASH_SECTOR_SIZE;
445
+	resp_args_out[3] = FLASH_PAGE_SIZE;
446
+	resp_args_out[4] = TCP_COMM_MAX_DATA_LEN;
447
+
448
+	return TCP_COMM_RSP_OK;
449
+}
450
+
451
+const struct comm_command info_cmd = {
452
+	// INFO
453
+	// OKOK flash_start flash_size erase_size write_size max_data_len
454
+	.opcode = CMD_INFO,
455
+	.nargs = 0,
456
+	.resp_nargs = 5,
457
+	.size = NULL,
458
+	.handle = &handle_info,
459
+};
460
+
461
+static void do_reboot(bool to_bootloader)
462
+{
463
+	hw_clear_bits(&watchdog_hw->ctrl, WATCHDOG_CTRL_ENABLE_BITS);
464
+	if (to_bootloader) {
465
+		watchdog_hw->scratch[5] = BOOTLOADER_ENTRY_MAGIC;
466
+		watchdog_hw->scratch[6] = ~BOOTLOADER_ENTRY_MAGIC;
467
+	} else {
468
+		watchdog_hw->scratch[5] = 0;
469
+		watchdog_hw->scratch[6] = 0;
470
+	}
471
+	watchdog_reboot(0, 0, 0);
472
+	while (1) {
473
+		tight_loop_contents();
474
+		asm("");
475
+	}
476
+}
477
+
478
+static uint32_t size_reboot(uint32_t *args_in, uint32_t *data_len_out, uint32_t *resp_data_len_out)
479
+{
480
+	*data_len_out = 0;
481
+	*resp_data_len_out = 0;
482
+
483
+	return TCP_COMM_RSP_OK;
484
+}
485
+
486
+static uint32_t handle_reboot(uint32_t *args_in, uint8_t *data_in, uint32_t *resp_args_out, uint8_t *resp_data_out)
487
+{
488
+	// Will never return
489
+	do_reboot(args_in[0]);
490
+
491
+	return TCP_COMM_RSP_ERR;
492
+}
493
+
494
+struct comm_command reboot_cmd = {
495
+	// BOOT to_bootloader
496
+	// NO RESPONSE
497
+	.opcode = CMD_REBOOT,
498
+	.nargs = 1,
499
+	.resp_nargs = 0,
500
+	.size = &size_reboot,
501
+	.handle = &handle_reboot,
502
+};
503
+
41 504
 int main()
42 505
 {
43 506
 	stdio_init_all();
@@ -60,10 +523,19 @@ int main()
60 523
 	}
61 524
 
62 525
 	const struct comm_command *cmds[] = {
63
-		&util_sync_cmd,
526
+		&sync_cmd,
527
+		&read_cmd,
528
+		&csum_cmd,
529
+		&crc_cmd,
530
+		&erase_cmd,
531
+		&write_cmd,
532
+		//&seal_cmd,
533
+		//&go_cmd,
534
+		&info_cmd,
535
+		//&reboot_cmd,
64 536
 	};
65 537
 
66
-	struct tcp_comm_ctx *tcp = tcp_comm_new(cmds, 1, CMD_SYNC);
538
+	struct tcp_comm_ctx *tcp = tcp_comm_new(cmds, sizeof(cmds) / sizeof(cmds[0]), CMD_SYNC);
67 539
 
68 540
 	for ( ; ; ) {
69 541
 		err_t err = tcp_comm_listen(tcp, TCP_PORT);
@@ -75,7 +547,7 @@ int main()
75 547
 
76 548
 		while (!tcp_comm_server_done(tcp)) {
77 549
 			cyw43_arch_poll();
78
-			sleep_ms(10);
550
+			sleep_ms(1);
79 551
 		}
80 552
 	}
81 553
 

+ 4
- 8
tcp_comm.c View File

@@ -19,10 +19,6 @@
19 19
 #define POLL_TIME_S 5
20 20
 
21 21
 #define COMM_MAX_NARG     5
22
-#define COMM_MAX_DATA_LEN 1024
23
-
24
-#define COMM_RSP_OK       (('O' << 0) | ('K' << 8) | ('O' << 16) | ('K' << 24))
25
-#define COMM_RSP_ERR      (('E' << 0) | ('R' << 8) | ('R' << 16) | ('!' << 24))
26 22
 
27 23
 enum conn_state {
28 24
 	CONN_STATE_WAIT_FOR_SYNC,
@@ -41,7 +37,7 @@ struct tcp_comm_ctx {
41 37
 	enum conn_state conn_state;
42 38
 
43 39
 	struct tcp_pcb *client_pcb;
44
-	uint8_t buf[(sizeof(uint32_t) * (1 + COMM_MAX_NARG)) + COMM_MAX_DATA_LEN];
40
+	uint8_t buf[(sizeof(uint32_t) * (1 + COMM_MAX_NARG)) + TCP_COMM_MAX_DATA_LEN];
45 41
 	uint16_t rx_bytes_received;
46 42
 	uint16_t rx_bytes_remaining;
47 43
 
@@ -75,7 +71,7 @@ static const struct comm_command *find_command_desc(struct tcp_comm_ctx *ctx, ui
75 71
 
76 72
 static bool is_error(uint32_t status)
77 73
 {
78
-	return status == COMM_RSP_ERR;
74
+	return status == TCP_COMM_RSP_ERR;
79 75
 }
80 76
 
81 77
 static int tcp_comm_sync_begin(struct tcp_comm_ctx *ctx);
@@ -194,7 +190,7 @@ static int tcp_comm_data_complete(struct tcp_comm_ctx *ctx)
194 190
 		*COMM_BUF_OPCODE(ctx->buf) = status;
195 191
 	} else {
196 192
 		// TODO: Should we just assert(desc->handle)?
197
-		*COMM_BUF_OPCODE(ctx->buf) = COMM_RSP_OK;
193
+		*COMM_BUF_OPCODE(ctx->buf) = TCP_COMM_RSP_OK;
198 194
 	}
199 195
 
200 196
 	return tcp_comm_response_begin(ctx);
@@ -220,7 +216,7 @@ static int tcp_comm_error_begin(struct tcp_comm_ctx *ctx)
220 216
 	ctx->tx_bytes_sent = 0;
221 217
 	ctx->tx_bytes_remaining = sizeof(uint32_t);
222 218
 
223
-	*COMM_BUF_OPCODE(ctx->buf) = COMM_RSP_ERR;
219
+	*COMM_BUF_OPCODE(ctx->buf) = TCP_COMM_RSP_ERR;
224 220
 
225 221
 	err_t err = tcp_write(ctx->client_pcb, ctx->buf, ctx->tx_bytes_remaining, 0);
226 222
 	if (err != ERR_OK) {

+ 5
- 0
tcp_comm.h View File

@@ -9,6 +9,11 @@
9 9
 #include <stdint.h>
10 10
 #include <stdbool.h>
11 11
 
12
+#define TCP_COMM_MAX_DATA_LEN 1024
13
+#define TCP_COMM_RSP_OK       (('O' << 0) | ('K' << 8) | ('O' << 16) | ('K' << 24))
14
+#define TCP_COMM_RSP_ERR      (('E' << 0) | ('R' << 8) | ('R' << 16) | ('!' << 24))
15
+
16
+
12 17
 struct comm_command {
13 18
 	uint32_t opcode;
14 19
 	uint32_t nargs;

Loading…
Cancel
Save