From a92e0eb5e60b26756d0174e670b35e81f8e8661c Mon Sep 17 00:00:00 2001 From: Nic Limper Date: Mon, 11 Sep 2023 00:48:08 +0200 Subject: [PATCH] flashing ESP32-C6 from ESP32 via serial connection from webinterface To flash the C6, place bootloader.bin, partition-table.bin and OpenEPaperLink_esp32_C6.bin in the file system root. APconfig -> update -> advanced options -> update ESP32-C6 This should also work with a previous unconfigured C6. Compatible with Yellow-AP. --- .../flashid-dump-esptool.txt | 281 ++++++++++++++++++ .../flashid-dump-s3.txt | 96 ++++++ .../OpenEPaperLink_esp32_C6_AP/main/main.c | 27 +- .../OpenEPaperLink_esp32_C6_AP/main/radio.c | 47 ++- .../OpenEPaperLink_esp32_C6_AP/main/radio.h | 2 +- .../main/second_uart.c | 9 +- .../data/www/content_cards.json.gz | Bin 2900 -> 2913 bytes ESP32_AP-Flasher/data/www/index.html.gz | Bin 3515 -> 3549 bytes ESP32_AP-Flasher/data/www/main.css.gz | Bin 2718 -> 2727 bytes ESP32_AP-Flasher/data/www/main.js.gz | Bin 9333 -> 9398 bytes ESP32_AP-Flasher/data/www/ota.js.gz | Bin 4051 -> 4086 bytes ESP32_AP-Flasher/include/esp32_port.h | 59 ++++ ESP32_AP-Flasher/include/espflasher.h | 4 + ESP32_AP-Flasher/include/ota.h | 1 + ESP32_AP-Flasher/include/serialap.h | 7 +- ESP32_AP-Flasher/platformio.ini | 31 +- ESP32_AP-Flasher/src/espflasher.cpp | 185 ++++++++++++ ESP32_AP-Flasher/src/ota.cpp | 56 ++++ ESP32_AP-Flasher/src/serialap.cpp | 98 +++--- ESP32_AP-Flasher/src/web.cpp | 1 + ESP32_AP-Flasher/wwwroot/index.html | 5 +- ESP32_AP-Flasher/wwwroot/main.css | 5 + ESP32_AP-Flasher/wwwroot/ota.js | 19 ++ 23 files changed, 851 insertions(+), 82 deletions(-) create mode 100644 ARM_Tag_FW/ESP32_S3_to_C6_Flasher_Test/flashid-dump-esptool.txt create mode 100644 ARM_Tag_FW/ESP32_S3_to_C6_Flasher_Test/flashid-dump-s3.txt create mode 100644 ESP32_AP-Flasher/include/esp32_port.h create mode 100644 ESP32_AP-Flasher/include/espflasher.h create mode 100644 ESP32_AP-Flasher/src/espflasher.cpp diff --git a/ARM_Tag_FW/ESP32_S3_to_C6_Flasher_Test/flashid-dump-esptool.txt b/ARM_Tag_FW/ESP32_S3_to_C6_Flasher_Test/flashid-dump-esptool.txt new file mode 100644 index 00000000..6c3a5f1f --- /dev/null +++ b/ARM_Tag_FW/ESP32_S3_to_C6_Flasher_Test/flashid-dump-esptool.txt @@ -0,0 +1,281 @@ + + +TRACE +0.008 command op=0x0a data len=4 wait_response=1 timeout=3.000 data=00100040 +TRACE +0.000 Write 14 bytes: c0000a04000000000000100040c0 +TRACE +0.002 Read 1 bytes: c0 +TRACE +0.000 Read 13 bytes: 010a04006f80e02c00000000c0 +TRACE +0.000 Received full packet: 010a04006f80e02c00000000 + +Detecting chip type... + +TRACE +0.000 command op=0x14 data len=0 wait_response=1 timeout=3.000 data= +TRACE +0.000 Write 10 bytes: c00014000000000000c0 +TRACE +0.008 Read 1 bytes: c0 +TRACE +0.000 Read 33 bytes: + 011418006f80e02c 0000000000000000 | ....o..,........ + 0000000c0d000000 0000000000000000 | ................ + c0 | . +TRACE +0.000 Received full packet: + 011418006f80e02c 0000000000000000 | ....o..,........ + 0000000c0d000000 0000000000000000 | ................ + +TRACE +0.000 command op=0x0a data len=4 wait_response=1 timeout=3.000 data=80f58740 +TRACE +0.000 Write 14 bytes: c0000a04000000000080f58740c0 +TRACE +0.002 Read 1 bytes: c0 +TRACE +0.000 Read 13 bytes: 010a04000000000000000000c0 +TRACE +0.000 Received full packet: 010a04000000000000000000 + +TRACE +0.000 command op=0x0a data len=4 wait_response=1 timeout=3.000 data=50080b60 +TRACE +0.000 Write 14 bytes: c0000a04000000000050080b60c0 +TRACE +0.000 Read 1 bytes: c0 +TRACE +0.000 Read 13 bytes: 010a04000000000800000000c0 +TRACE +0.000 Received full packet: 010a04000000000800000000 + +TRACE +0.008 command op=0x0a data len=4 wait_response=1 timeout=3.000 data=50080b60 +TRACE +0.000 Write 14 bytes: c0000a04000000000050080b60c0 +TRACE +0.002 Read 1 bytes: c0 +TRACE +0.000 Read 13 bytes: 010a04000000000800000000c0 +TRACE +0.000 Received full packet: 010a04000000000800000000 + +TRACE +0.000 command op=0x0a data len=4 wait_response=1 timeout=3.000 data=50080b60 +TRACE +0.000 Write 14 bytes: c0000a04000000000050080b60c0 +TRACE +0.000 Read 1 bytes: c0 +TRACE +0.000 Read 13 bytes: 010a04000000000800000000c0 +TRACE +0.000 Received full packet: 010a04000000000800000000 + +Chip is ESP32-C6 (QFN40) (revision v0.0) +Features: WiFi 6, BT 5, IEEE802.15.4 +Crystal is 40MHz + +TRACE +0.000 command op=0x0a data len=4 wait_response=1 timeout=3.000 data=44080b60 +TRACE +0.000 Write 14 bytes: c0000a04000000000044080b60c0 +TRACE +0.010 Read 1 bytes: c0 +TRACE +0.000 Read 13 bytes: 010a0400e85342ca00000000c0 +TRACE +0.000 Received full packet: 010a0400e85342ca00000000 + +TRACE +0.000 command op=0x0a data len=4 wait_response=1 timeout=3.000 data=48080b60 +TRACE +0.000 Write 14 bytes: c0000a04000000000048080b60c0 +TRACE +0.000 Read 1 bytes: c0 +TRACE +0.000 Read 13 bytes: 010a04004c40feff00000000c0 +TRACE +0.000 Received full packet: 010a04004c40feff00000000 + +MAC: 40:4c:ca:ff:fe:42:53:e8 + +TRACE +0.000 command op=0x0a data len=4 wait_response=1 timeout=3.000 data=44080b60 +TRACE +0.000 Write 14 bytes: c0000a04000000000044080b60c0 +TRACE +0.008 Read 1 bytes: c0 +TRACE +0.000 Read 13 bytes: 010a0400e85342ca00000000c0 +TRACE +0.000 Received full packet: 010a0400e85342ca00000000 + +TRACE +0.002 command op=0x0a data len=4 wait_response=1 timeout=3.000 data=48080b60 +TRACE +0.000 Write 14 bytes: c0000a04000000000048080b60c0 +TRACE +0.000 Read 1 bytes: c0 +TRACE +0.000 Read 13 bytes: 010a04004c40feff00000000c0 +TRACE +0.000 Received full packet: 010a04004c40feff00000000 + +BASE MAC: 40:4c:ca:42:53:e8 + +TRACE +0.000 command op=0x0a data len=4 wait_response=1 timeout=3.000 data=44080b60 +TRACE +0.000 Write 14 bytes: c0000a04000000000044080b60c0 +TRACE +0.008 Read 1 bytes: c0 +TRACE +0.000 Read 13 bytes: 010a0400e85342ca00000000c0 +TRACE +0.000 Received full packet: 010a0400e85342ca00000000 + +!!! TRACE +0.000 command op=0x0a data len=4 wait_response=1 timeout=3.000 data=48080b60 +TRACE +0.000 Write 14 bytes: c0000a04000000000048080b60c0 +TRACE +0.002 Read 1 bytes: c0 +TRACE +0.000 Read 13 bytes: 010a04004c40feff00000000c0 +TRACE +0.000 Received full packet: 010a04004c40feff00000000 + +MAC_EXT: ff:fe + +Enabling default SPI flash mode... + +!!!! TRACE +0.000 command op=0x0d data len=8 wait_response=1 timeout=3.000 data=0000000000000000 +TRACE +0.000 Write 18 bytes: + c0000d0800000000 0000000000000000 | ................ + 00c0 | .. +TRACE +0.000 Read 1 bytes: c0 +TRACE +0.000 Read 13 bytes: 010d04004c40feff00000000c0 +TRACE +0.000 Received full packet: 010d04004c40feff00000000 + +v TRACE +0.008 command op=0x0a data len=4 wait_response=1 timeout=3.000 data=18300060 +TRACE +0.000 Write 14 bytes: c0000a04000000000018300060c0 +TRACE +0.002 Read 1 bytes: c0 +TRACE +0.000 Read 13 bytes: 010a04000000008000000000c0 +TRACE +0.000 Received full packet: 010a04000000008000000000 + +v TRACE +0.000 command op=0x0a data len=4 wait_response=1 timeout=3.000 data=20300060 +TRACE +0.000 Write 14 bytes: c0000a04000000000020300060c0 +TRACE +0.000 Read 1 bytes: c0 +TRACE +0.000 Read 13 bytes: 010a04000000007000000000c0 +TRACE +0.000 Received full packet: 010a04000000007000000000 + +v TRACE +0.000 command op=0x09 data len=16 wait_response=1 timeout=3.000 data=2830006017000000ffffffff00000000 +TRACE +0.000 Write 26 bytes: + c000091000000000 0028300060170000 | .........(0.`... + 00ffffffff000000 00c0 | .......... +TRACE +0.010 Read 1 bytes: c0 +TRACE +0.000 Read 13 bytes: 010904000000007000000000c0 +TRACE +0.000 Received full packet: 010904000000007000000000 + +TRACE +0.000 command op=0x09 data len=16 wait_response=1 timeout=3.000 data=1830006000000090ffffffff00000000 +TRACE +0.000 Write 26 bytes: + c000091000000000 0018300060000000 | ..........0.`... + 90ffffffff000000 00c0 | .......... +TRACE +0.000 Read 1 bytes: c0 +TRACE +0.000 Read 13 bytes: 010904000000007000000000c0 +TRACE +0.000 Received full packet: 010904000000007000000000 + +TRACE +0.008 command op=0x09 data len=16 wait_response=1 timeout=3.000 data=203000609f000070ffffffff00000000 +TRACE +0.000 Write 26 bytes: + c000091000000000 00203000609f0000 | ......... 0.`... + 70ffffffff000000 00c0 | p......... +TRACE +0.002 Read 1 bytes: c0 +TRACE +0.000 Read 13 bytes: 010904000000007000000000c0 +TRACE +0.000 Received full packet: 010904000000007000000000 + +TRACE +0.000 command op=0x09 data len=16 wait_response=1 timeout=3.000 data=5830006000000000ffffffff00000000 +TRACE +0.000 Write 26 bytes: + c000091000000000 0058300060000000 | .........X0.`... + 00ffffffff000000 00c0 | .......... +TRACE +0.008 Read 1 bytes: c0 +TRACE +0.000 Read 13 bytes: 010904000000007000000000c0 +TRACE +0.000 Received full packet: 010904000000007000000000 + +TRACE +0.000 command op=0x09 data len=16 wait_response=1 timeout=3.000 data=0030006000000400ffffffff00000000 +TRACE +0.000 Write 26 bytes: + c000091000000000 0000300060000004 | ..........0.`... + 00ffffffff000000 00c0 | .......... +TRACE +0.002 Read 1 bytes: c0 +TRACE +0.000 Read 13 bytes: 010904000000007000000000c0 +TRACE +0.000 Received full packet: 010904000000007000000000 + +TRACE +0.000 command op=0x0a data len=4 wait_response=1 timeout=3.000 data=00300060 +TRACE +0.000 Write 14 bytes: c0000a04000000000000300060c0 +TRACE +0.008 Read 1 bytes: c0 +TRACE +0.000 Read 13 bytes: 010a04000000000000000000c0 +TRACE +0.000 Received full packet: 010a04000000000000000000 + +!!! TRACE +0.000 command op=0x0a data len=4 wait_response=1 timeout=3.000 data=58300060 +TRACE +0.000 Write 14 bytes: c0000a04000000000058300060c0 +TRACE +0.002 Read 1 bytes: c0 +TRACE +0.000 Read 13 bytes: 010a0400c840170000000000c0 +TRACE +0.000 Received full packet: 010a0400c840170000000000 + +!!! TRACE +0.000 command op=0x09 data len=16 wait_response=1 timeout=3.000 data=1830006000000080ffffffff00000000 +TRACE +0.000 Write 26 bytes: + c000091000000000 0018300060000000 | ..........0.`... + 80ffffffff000000 00c0 | .......... +TRACE +0.000 Read 1 bytes: c0 +TRACE +0.008 Read 13 bytes: 01090400c840170000000000c0 +TRACE +0.000 Received full packet: 01090400c840170000000000 + +TRACE +0.000 command op=0x09 data len=16 wait_response=1 timeout=3.000 data=2030006000000070ffffffff00000000 +TRACE +0.000 Write 26 bytes: + c000091000000000 0020300060000000 | ......... 0.`... + 70ffffffff000000 00c0 | p......... +TRACE +0.002 Read 1 bytes: c0 +TRACE +0.000 Read 13 bytes: 01090400c840170000000000c0 +TRACE +0.000 Received full packet: 01090400c840170000000000 + +TRACE +0.000 command op=0x0a data len=4 wait_response=1 timeout=3.000 data=18300060 +TRACE +0.000 Write 14 bytes: c0000a04000000000018300060c0 +TRACE +0.008 Read 1 bytes: c0 +TRACE +0.000 Read 13 bytes: 010a04000000008000000000c0 +TRACE +0.000 Received full packet: 010a04000000008000000000 + +TRACE +0.000 command op=0x0a data len=4 wait_response=1 timeout=3.000 data=20300060 +TRACE +0.000 Write 14 bytes: c0000a04000000000020300060c0 +TRACE +0.002 Read 1 bytes: c0 +TRACE +0.000 Read 13 bytes: 010a04000000007000000000c0 +TRACE +0.000 Received full packet: 010a04000000007000000000 + +TRACE +0.000 command op=0x09 data len=16 wait_response=1 timeout=3.000 data=2830006007000000ffffffff00000000 +TRACE +0.000 Write 26 bytes: + c000091000000000 0028300060070000 | .........(0.`... + 00ffffffff000000 00c0 | .......... +TRACE +0.008 Read 1 bytes: c0 +TRACE +0.000 Read 13 bytes: 010904000000007000000000c0 +TRACE +0.000 Received full packet: 010904000000007000000000 + +TRACE +0.000 command op=0x09 data len=16 wait_response=1 timeout=3.000 data=1c3000600700005cffffffff00000000 +TRACE +0.000 Write 26 bytes: + c000091000000000 001c300060070000 | ..........0.`... + 5cffffffff000000 00c0 | \......... +TRACE +0.002 Read 1 bytes: c0 +TRACE +0.000 Read 13 bytes: 010904000000007000000000c0 +TRACE +0.000 Received full packet: 010904000000007000000000 + +TRACE +0.000 command op=0x09 data len=16 wait_response=1 timeout=3.000 data=18300060000000f0ffffffff00000000 +TRACE +0.000 Write 26 bytes: + c000091000000000 0018300060000000 | ..........0.`... + f0ffffffff000000 00c0 | .......... +TRACE +0.008 Read 1 bytes: c0 +TRACE +0.000 Read 13 bytes: 010904000000007000000000c0 +TRACE +0.000 Received full packet: 010904000000007000000000 + +TRACE +0.000 command op=0x09 data len=16 wait_response=1 timeout=3.000 data=203000605a000070ffffffff00000000 +TRACE +0.000 Write 26 bytes: + c000091000000000 00203000605a0000 | ......... 0.`Z.. + 70ffffffff000000 00c0 | p......... +TRACE +0.000 Read 1 bytes: c0 +TRACE +0.000 Read 13 bytes: 010904000000007000000000c0 +TRACE +0.000 Received full packet: 010904000000007000000000 + +TRACE +0.000 command op=0x09 data len=16 wait_response=1 timeout=3.000 data=0430006010000000ffffffff00000000 +TRACE +0.000 Write 26 bytes: + c000091000000000 0004300060100000 | ..........0.`... + 00ffffffff000000 00c0 | .......... +TRACE +0.012 Read 1 bytes: c0 +TRACE +0.000 Read 13 bytes: 010904000000007000000000c0 +TRACE +0.000 Received full packet: 010904000000007000000000 + +TRACE +0.000 command op=0x09 data len=16 wait_response=1 timeout=3.000 data=5830006000000000ffffffff00000000 +TRACE +0.000 Write 26 bytes: + c000091000000000 0058300060000000 | .........X0.`... + 00ffffffff000000 00c0 | .......... +TRACE +0.000 Read 1 bytes: c0 +TRACE +0.000 Read 13 bytes: 010904000000007000000000c0 +TRACE +0.000 Received full packet: 010904000000007000000000 + +TRACE +0.000 command op=0x09 data len=16 wait_response=1 timeout=3.000 data=0030006000000400ffffffff00000000 +TRACE +0.000 Write 26 bytes: + c000091000000000 0000300060000004 | ..........0.`... + 00ffffffff000000 00c0 | .......... +TRACE +0.010 Read 1 bytes: c0 +TRACE +0.000 Read 13 bytes: 010904000000007000000000c0 +TRACE +0.000 Received full packet: 010904000000007000000000 + +TRACE +0.000 command op=0x0a data len=4 wait_response=1 timeout=3.000 data=00300060 +TRACE +0.000 Write 14 bytes: c0000a04000000000000300060c0 +TRACE +0.000 Read 1 bytes: c0 +TRACE +0.000 Read 13 bytes: 010a04000000000000000000c0 +TRACE +0.000 Received full packet: 010a04000000000000000000 + +TRACE +0.000 command op=0x0a data len=4 wait_response=1 timeout=3.000 data=58300060 +TRACE +0.000 Write 14 bytes: c0000a04000000000058300060c0 +TRACE +0.010 Read 1 bytes: c0 +TRACE +0.000 Read 13 bytes: 010a0400c800000000000000c0 +TRACE +0.000 Received full packet: 010a0400c800000000000000 + +TRACE +0.000 command op=0x09 data len=16 wait_response=1 timeout=3.000 data=1830006000000080ffffffff00000000 +TRACE +0.000 Write 26 bytes: + c000091000000000 0018300060000000 | ..........0.`... + 80ffffffff000000 00c0 | .......... +TRACE +0.000 Read 1 bytes: c0 +TRACE +0.000 Read 13 bytes: 01090400c800000000000000c0 +TRACE +0.000 Received full packet: 01090400c800000000000000 + +TRACE +0.000 command op=0x09 data len=16 wait_response=1 timeout=3.000 data=2030006000000070ffffffff00000000 +TRACE +0.000 Write 26 bytes: + c000091000000000 0020300060000000 | ......... 0.`... + 70ffffffff000000 00c0 | p......... +TRACE +0.010 Read 1 bytes: c0 +TRACE +0.000 Read 13 bytes: 01090400c800000000000000c0 +TRACE +0.000 Received full packet: 01090400c800000000000000 + +Manufacturer: c8 +Device: 4017 +Detected flash size: 8MB + diff --git a/ARM_Tag_FW/ESP32_S3_to_C6_Flasher_Test/flashid-dump-s3.txt b/ARM_Tag_FW/ESP32_S3_to_C6_Flasher_Test/flashid-dump-s3.txt new file mode 100644 index 00000000..d3ea4b83 --- /dev/null +++ b/ARM_Tag_FW/ESP32_S3_to_C6_Flasher_Test/flashid-dump-s3.txt @@ -0,0 +1,96 @@ +C6 flash starting + +Write 1 bytes: c000082400000000000707122055555555 +55555555555555555555555555555555 +555555555555555555555555c0 +Read 1 bytes: 004553502d524f4d3a657370333263362d32303232303931390d0a4275696c643a53657020313920323032320d0a7273743a3078312028504f5745524f4e292c626f6f743a307836362028444f574e4c4f4144285553422f55415254302f5344494f5f5245495f46454f29290d0a77616974696e6720666f7220646f776e6c6f61640d0a + +Write 1 bytes: c000082400000000000707122055555555 +55555555555555555555555555555555 +555555555555555555555555c0 +Read 1 bytes: c0010804000707122000000000c0 + +Write 1 bytes: c0000a04000000000000100040c0 +Read 1 bytes: c0010804000707122000000000c0 +c0010804000707122000000000c0 +c0010804000707122000000000c0 +c0010804000707122000000000c0 +c0010804000707122000000000c0 +c0010804000707122000000000c0 +c0010804000707122000000000c0 +c0010a04006f80e02c00000000c0 + +Write 1 bytes: c0000a04000000000048080b60c0 600b0848!!! read 0x12 + c0000a04000000000044080b60c0 600b0844 read 0x11 +Read 1 bytes: c0010a04004c40feff00000000c0 + c0010a0400e85342ca00000000c0 + esptool: c0010a04004c40feff00000000c0 + +>>>>> Write 1 bytes: c0000a0400000000004c080b60c0 600b084C!!! read 0x13 + esptool: c0000a04000000000048080b60c0 600b0848 read 0x12 +Read 1 bytes: c0010a04000000000000000000c0 + esptool: c0010a04004c40feff00000000c0 + +command op=0x0d data len=8 +>>>>> Write 1 bytes: c0000d080000000000feff000000000000c0 + esptool:c0000d0800000000000000000000000000c0 +>>>>> Read 1 bytes: c0010d04000000000000000000c0 + esptool: c0010d04004c40feff00000000c0 + +Connected to target +Connected to ESP32-C6 +bootloader +size: 21248 +Erasing flash (this may take a while)... +esp_loader_flash_start +block_size 1024 +detect_flash_size + +spi_flash_command 159 0 24 +v Write 1 bytes: c0000a04000000000018300060c0 +Read 1 bytes: c0010a04000000008000000000c0 + +v Write 1 bytes: c0000a04000000000020300060c0 +Read 1 bytes: c0010a04000000007000000000c0 + +v Write 1 bytes: c000091000000000002830006017000000 +ffffffff00000000c0 +Read 1 bytes: c0010904000000007000000000c0 + +v Write 1 bytes: c000091000000000001830006000000090 +ffffffff00000000c0 +Read 1 bytes: c0010904000000007000000000c0 + +v Write 1 bytes: c00009100000000000203000609f000070 +ffffffff00000000c0 +Read 1 bytes: c0010904000000007000000000c0 + +v Write 1 bytes: c000091000000000005830006000000000 +ffffffff00000000c0 +Read 1 bytes: c0010904000000007000000000c0 + +v Write 1 bytes: c000091000000000000030006000000400 +ffffffff00000000c0 +Read 1 bytes: c0010904000000007000000000c0try 9 + +v Write 1 bytes: c0000a04000000000000300060c0 +Read 1 bytes: c0010a04000000000000000000c0 + +Write 1 bytes: c0000a04000000000058300060c0 +!!! Read 1 bytes: c0010a0400ffffff0000000000c0 + +Write 1 bytes: c000091000000000001830006000000080 +ffffffff00000000c0 +!!! Read 1 bytes: c001090400ffffff0000000000c0 + +Write 1 bytes: c000091000000000002030006000000070 +ffffffff00000000c0 +Read 1 bytes: c001090400ffffff0000000000c0 + +size_id 255 +DEBUG: Flash size detection failed, falling back to default + +Write 1 bytes: c000021400000000000053000015000000 +000400000000000000000000c0 +Read 0 bytes: +Erasing flash failed with error 2. diff --git a/ARM_Tag_FW/OpenEPaperLink_esp32_C6_AP/main/main.c b/ARM_Tag_FW/OpenEPaperLink_esp32_C6_AP/main/main.c index 568aaf3d..1d2c5e9e 100644 --- a/ARM_Tag_FW/OpenEPaperLink_esp32_C6_AP/main/main.c +++ b/ARM_Tag_FW/OpenEPaperLink_esp32_C6_AP/main/main.c @@ -66,7 +66,7 @@ uint32_t lastBlockRequest = 0; uint8_t lastBlockMac[8]; uint8_t lastTagReturn[8]; -uint8_t curChannel = 11; +uint8_t curChannel = 25; uint8_t curPower = 10; uint8_t curPendingData = 0; @@ -326,13 +326,15 @@ void processSerial(uint8_t lastchar) { } goto SCPfailed; SCPchannelFound: - curChannel = scp->channel; - curPower = scp->power; - radioSetChannel(scp->channel); + pr("ACK>"); + if (curChannel != scp->channel) { + radioSetChannel(scp->channel); + curChannel = scp->channel; + } + curPower = scp->power; radioSetTxPower(scp->power); ESP_LOGI(TAG, "Set channel: %d power: %d", curChannel, curPower); - pr("ACK>"); - } else { + } else { SCPfailed: pr("NOK>"); } @@ -682,25 +684,24 @@ void sendPong(void *buf) { } void app_main(void) { + esp_event_loop_create_default(); + init_nvs(); - init_led(); + init_led(); init_second_uart(); - esp_event_loop_create_default(); - - radio_init(); - requestedData.blockId = 0xFF; // clear the array with pending information memset(pendingDataArr, 0, sizeof(pendingDataArr)); - radioSetChannel(curChannel); + radio_init(curChannel); radioSetTxPower(10); pr("RES>"); pr("RDY>"); + ESP_LOGI(TAG, "C6 ready!"); - housekeepingTimer = getMillis(); + housekeepingTimer = getMillis(); while (1) { while ((getMillis() - housekeepingTimer) < ((1000 * HOUSEKEEPING_INTERVAL) - 100)) { int8_t ret = commsRxUnencrypted(radiorxbuffer); diff --git a/ARM_Tag_FW/OpenEPaperLink_esp32_C6_AP/main/radio.c b/ARM_Tag_FW/OpenEPaperLink_esp32_C6_AP/main/radio.c index 62c3710a..f40f9e43 100644 --- a/ARM_Tag_FW/OpenEPaperLink_esp32_C6_AP/main/radio.c +++ b/ARM_Tag_FW/OpenEPaperLink_esp32_C6_AP/main/radio.c @@ -47,19 +47,44 @@ void esp_ieee802154_transmit_done(const uint8_t *frame, const uint8_t *ack, esp_ ESP_EARLY_LOGI(TAG, "TX %d", frame[0]); } -void radio_init() { - packet_buffer = xQueueCreate(32, 130); - esp_ieee802154_enable(); - radioSetChannel(11); - esp_ieee802154_set_panid(PROTO_PAN_ID); - esp_ieee802154_set_promiscuous(false); // Filter for our mac and PAN +void radio_init(uint8_t ch) { + if (packet_buffer == NULL) packet_buffer = xQueueCreate(32, 130); + + // this will trigger a "IEEE802154 MAC sleep init failed" when called a second time, but it works + esp_ieee802154_enable(); + esp_ieee802154_set_channel(ch); + // esp_ieee802154_set_txpower(int8_t power); + esp_ieee802154_set_panid(PROTO_PAN_ID); + esp_ieee802154_set_promiscuous(false); esp_ieee802154_set_coordinator(false); esp_ieee802154_set_pending_mode(ESP_IEEE802154_AUTO_PENDING_ZIGBEE); - esp_read_mac(mSelfMac, ESP_MAC_IEEE802154); - esp_ieee802154_set_extended_address(mSelfMac); - esp_ieee802154_set_short_address(0xFFFE); + + // esp_ieee802154_set_extended_address needs the MAC in reversed byte order + esp_read_mac(mSelfMac, ESP_MAC_IEEE802154); + uint8_t eui64_rev[8] = {0}; + for (int i = 0; i < 8; i++) { + eui64_rev[7 - i] = mSelfMac[i]; + } + esp_ieee802154_set_extended_address(eui64_rev); + esp_ieee802154_get_extended_address(mSelfMac); + + esp_ieee802154_set_short_address(0xFFFE); esp_ieee802154_set_rx_when_idle(true); esp_ieee802154_receive(); + + led_flash(1); + vTaskDelay(100 / portTICK_PERIOD_MS); + led_flash(0); + vTaskDelay(100 / portTICK_PERIOD_MS); + led_flash(1); + vTaskDelay(100 / portTICK_PERIOD_MS); + led_flash(0); + + ESP_LOGI(TAG, "Receiver ready, panId=0x%04x, channel=%d, long=%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x, short=%04x", + esp_ieee802154_get_panid(), esp_ieee802154_get_channel(), + mSelfMac[0], mSelfMac[1], mSelfMac[2], mSelfMac[3], + mSelfMac[4], mSelfMac[5], mSelfMac[6], mSelfMac[7], + esp_ieee802154_get_short_address()); } uint32_t lastZbTx = 0; @@ -77,7 +102,9 @@ bool radioTx(uint8_t *packet) { return true; } -void radioSetChannel(uint8_t ch) { esp_ieee802154_set_channel(ch); } +void radioSetChannel(uint8_t ch) { + radio_init(ch); +} void radioSetTxPower(uint8_t power) {} diff --git a/ARM_Tag_FW/OpenEPaperLink_esp32_C6_AP/main/radio.h b/ARM_Tag_FW/OpenEPaperLink_esp32_C6_AP/main/radio.h index 2f50c751..73cd5286 100644 --- a/ARM_Tag_FW/OpenEPaperLink_esp32_C6_AP/main/radio.h +++ b/ARM_Tag_FW/OpenEPaperLink_esp32_C6_AP/main/radio.h @@ -4,7 +4,7 @@ extern uint8_t mSelfMac[8]; -void radio_init(); +void radio_init(uint8_t ch); bool radioTx(uint8_t *packet); void radioSetChannel(uint8_t ch); void radioSetTxPower(uint8_t power); diff --git a/ARM_Tag_FW/OpenEPaperLink_esp32_C6_AP/main/second_uart.c b/ARM_Tag_FW/OpenEPaperLink_esp32_C6_AP/main/second_uart.c index d6dadca0..b64e14ba 100644 --- a/ARM_Tag_FW/OpenEPaperLink_esp32_C6_AP/main/second_uart.c +++ b/ARM_Tag_FW/OpenEPaperLink_esp32_C6_AP/main/second_uart.c @@ -32,7 +32,8 @@ volatile int curr_buff_pos = 0; volatile int worked_buff_pos = 0; volatile uint8_t buff_pos[MAX_BUFF_POS + 5]; - +#define S3_TX_PIN 3 +#define S3_RX_PIN 2 static void uart_event_task(void *pvParameters); void init_second_uart() { @@ -46,9 +47,9 @@ void init_second_uart() { }; ESP_ERROR_CHECK(uart_driver_install(1, BUF_SIZE * 2, BUF_SIZE * 2, 20, &uart0_queue, 0)); ESP_ERROR_CHECK(uart_param_config(1, &uart_config)); - ESP_ERROR_CHECK(uart_set_pin(1, 3, 2, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE)); + ESP_ERROR_CHECK(uart_set_pin(1, S3_TX_PIN, S3_RX_PIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE)); - xTaskCreate(uart_event_task, "uart_event_task", 16384, NULL, 12, NULL); + xTaskCreate(uart_event_task, "uart_event_task", 16384, NULL, 12, NULL); } void uart_switch_speed(int baudrate) { @@ -92,7 +93,7 @@ static void uart_event_task(void *pvParameters) { } break; default: - ESP_LOGI(TAG, "uart event type: %d", event.type); + // ESP_LOGI(TAG, "uart event type: %d", event.type); break; } } diff --git a/ESP32_AP-Flasher/data/www/content_cards.json.gz b/ESP32_AP-Flasher/data/www/content_cards.json.gz index d99a68778fcebb085fd28ce0ce865c89fcbb2e26..f5382ff304cbae23b9df97bb976fbe6a6c8637dc 100644 GIT binary patch delta 2909 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 HWIF%=*o2du delta 2896 zcmV-W3$OIy7StAyA%Eny5&j+^|ABBnoDHn^yz95S_Cv9LySlY~SKHUL2!ensjaG~$ zQWYt$7eRhj|3H6PXGlpaOO(%Vxwx$Z#3yqoiZk=fa9-%|zx{@>pXmoq3@j1GBoJv9=HmMHizSOI2Bol4jsG&ZV{=BN zU{umxsM_8ol7BDNNt;}4aFVJ*8n&7WSs2i3xIb?2htN(}Y%Y?7w6|c_JQ3lLT_OX9 z&sZvEv0+jfmV?fe3|R_X&ST`&%Mt4Lehh^IWt4lFIj|%lXI@?|i(ImpCy`MSSXj*^ zsUxgZ6yfG+iZC=Zk3r%joh5uhv$9wjrHAYY=aTgGfPXDi!KPpcmkID|U?QSryzFU6 zATYN`DlvkLQQfy}a3g}qyD zj&~JxTUoaic3WvJ9W@V`+Gg)z!<&B0$9M+zf`8r;Us3;9)W72W(RhDu^l$Z@U~}Nj zXrQB}l0IbLxd%GSIGZlm#|-59DHu@0K&3AXoC$`76dQO^apEIZe4p7cvb1Pn78H+B ztfpC^5gA6YM5(JHb8#j&Zxe-%frK((T-pgGoEUdOfDtBnY7F{2{F0xS)_5HkBZsC4 zfq$)PFpL*Qr8YmXLD>u>%>($zC*&gsBQn|s$6jK07G9cH!kaf8Unw!O~Hy$3&zH2*! z%C>Po5O8fe-k?2!9^4^@5XSTiLw5=gpMT&be%%D~)gQe2gI9mho8IoU9l~BAK;}H; z-N4|WFhR_6j-gV9v62WZd$%2enJX7N57|eVEZAJ-S8hsWh?+tzntul5FA_8rZS7?b zl9?#d;k{hNt6O+=3-{jK-8S&PZ35>P7c7EhVo~qw1Lby@6;uDYcQ;8PRjVvd9y^%RN8we*LIO5{AUez}l*K{BmM@Hyn4{a6Gof;)cXJc&y9% zuCCkwrM??}U#rUhR2W#khRjI<9%j+0bUkejbhFdgJTn#LtZ<99dX_d9g*kG97*`2QM)xKyym?~+4W z&z0c@!XevNiORLB=1;5Q_{)T>!$*zT2=G8B7EXl}X^|3TvwCCrR3MK!j(_#fnz}TQ zA~HS2^A4JSYEJ(jMD;EHhU@~sCQXMK&mcb$@(M9^C2Dj!*xHvI;PI6V0uf;#!Ei6^ z<2gQf8)^@S-{bpoM|DT;<#YLXBRiH1vti35LKgQmz)-i>?rIQ!Ez|3ClK*i`D`m?>ECQrQ{v z0p1q(9UJ|E;yeAy4@%7v{2E7t@g{YZOKo;7$=4QHpi+V=&oYJEOo93$t2WCUZ@DCI z&0RO(to0Sli7*X}C@^sE~Kuhsn20#;V6nm#5Drdj2cFA+xzabl}@7-k7Fzpmi z9_7nAcNNYdRR-GLwtvyObzT;AU)BiFpr#Zzgd&Q-dbUXrU~<4dsYc(fp^DzUbb81a z=-o8TtXJ&papPCL-YD?3lD_47UtE0EMpOa~yZUN8u zRG=jbprZB8*4Idep01AVt~yZUL7@$XCMTaSJ1RN+`=`V6SpUQu=_6-T=}%n}D> z&O{jEnr+-{Yz*v=;c)nLLGOA6y|2;~<3&I4IXY`gc95on5Fg+M0z9+-fCmSaWE6$N zMddP)4Z3tz*!zVcTtlL=6r_1+mta!=#gqNh119{pPJbpr@45Jp-0q#v{am7C@%)R# z%%cdDCrQ5SM>(%k{$jm|hVn)eqi}|NNC*)x64QJIT~x{!R1l+o=yECoEr{!!fxe)@ zP+eZXv>=CTGgZo;zU?Vu1x&2M-e|LQt99uSUqMr&Za9iVlF22{(-b_jYq9obm;FEd zq$T=VeSdcymw7bjSNYfd*&IqodZ=WOw_NeGee=0a+K}~g54|BFa9|!u3Qc#88>MoW7u~+v!QyUU?Cr8XR9o3e7s=DE;v;sa+F=9|5RM^^nP~P4v zg{jM__If40`Q#?P714Snqd`};wP+tIKV)N$zIfW#&_#c=M@M{)uv(;3a# zHh-IxZ^+Y6-4bugH3)1(D~D0y*D5j8EvTsauu)q)!rNVnb*8zlAc6&CCm{Xy%dO?2~ zij^dvETQqvhVyLW;m&nSLgQ^m8xOZTq<^i7wACSPR;0}iXByJ!qy;D#1 z1t+k5&y4zRo-HSrr$tN3LSpt|&z_%@kk52yX;K)~J}N9GN2B)ewjJJXOU%h@qoWx+ z+?l;&hj-e;yLNc@5%-3;~3RYby&`CBo2FxnCHQG>2LwVI#pPW#SJI$I&^W#EBs=r-B uR7&*;3Ve#OQ?r4S*p`z-Tu72}>LWyfRm$CVK|{FQ^jf6k$(9VIrYV&2g*`*-p`XLUogs3KM^)xTmOohC(W2 zRdcb#%}bG55?aY%b2oKUqe@LD(lwzu6Iit?r~|+i(~-gu_LbC`H5QiJe0LMhA@qg| zgiXX#q39H)nt$qoT5U2Kk3;f?hENR($HknhCkAU5*RWXz1xco{vlW6TOvn`*e+q?T z4dh2*#I;8?>ihfYeII{%0_V6YROyRpa}T+dw7m|rK?mY)8ge$_W|52pR4$`QNF{9P zM`CR(d!x?A2KsDFg_eRxtn-eMR`*?c#hK@CzfHr`0^Xt^rj;|F8ae1Aa_sXYjg+NH zv&vk1I`SvPe}FA~{_w#JxwpBqhM!|hSM~79@YGMR3Y>J$4fcPYi(UzEPALen(T!)#BGYB}HGCnFJIVh^{tR-E zP3+e5^i6-!<8*)5E&N4kDfN6)FfpV|TD`a`YgmB|RwlAOn@m-uzgP5R`XUBdMSt(A zr4qjCrA?+G+bD8QJ2h+5_(i;7Bct=9<(@T*{FmKYg0%UIWJq6H84U7hgAXNuO0xKA-5Lq{cTsGOvF&A1kfhb4UmO#s( zp6&&n$i&(5BB?lLZNom`HCGQE1lu1pg)OhX<`Za+seTCn#+6>6>bjmneGlo({mrLb zzx(6ST)%&0IeTj3S)GbGTV<%98z`a^SaSxuQ4e&ZBdcbKk$Tgh?=@77cXE7ueD-6; zyL?fcuZH7{jxOwAbi6DP3q$&KpWZR3*#e;R|M1rD)yv`&y!`H7ECgkvXayj9c$#go ztTiob;H)DR(^#5S(C-}8ziCf5-R6CH%|0;Kug=XI|NjB1 KAlt_MF8~1Eoy+S0 delta 897 zcmV-{1AhG78@n5@H40lfh$sxzlHX~+%PwQ>$>1r|JBIvCSc-6=X7tfE)Nz2`nMa9$ z%|D;cv5JZIx+o{}^4fl>#UxCx?A1j_bxK&`DBu-QkdoyLd{R&)>M6pWh{8ldpAuoL z55AMH3K)MUtEZ@bhC(W2Rdcb#&FhU?5?aY%!!>o&g-(|<(si2Ir?0LxbfhqZ zeI<2fA!aahbM@U#IEQc;E)X_RNQH+}lq&zJTWGb(Xgm(d8yZ4|CL9-YuCD#p=ssn$ zbW};Ev9lF|Crro{yL$?SV-4g-VZ^nSH|qQQ=^cL@dIIOTDtze6VskgRm9)L0vw;9& zVHyTD;bzf=1XM0PJfsq~*(0$wzU0oUl)LAt7QR!j8EJLjrPq#m{`T86On&wj1u?Ch z`E+7XdIA^rnwtMdl}X2`wG?f-v*-86!d)ba%T)6brY?6Te= z9wUDZ{tMXJ8xBRzGS6PU6qs*%3-c4K)wO-qH#ep!Z`)eoo%XI=uNH0ai9r^G60jqG zu006-e9TH~FNU?4_Is^Sth;Icajxnyl;NqLMHM*do*V4{JQuwZ;G9wrVxt?+nnk9| z?rZo$B6qs}ll&RvAe(Hh=jq$`qQ~j3TljyA((>l{reI=7nY4OwRo1Wq8>~!ZeO{QV zN`J5D$@E1GvWouRRZAs&)$5l`L$*=moOWu~rtyn-!{$QgN6S5H7Wpr`wFGJN7s-&m zelj9tZ=nhjWW8E|?15DN_1CJAtj{~SVkwt{AP%bn#>qYO((Qb%S`PV8Svo16O8kFe z;n7>Zz=1M^PSs?5%w|~Rh?wqGvrYj_XxKDr1JY(}op{{BT#FE#_ykrkSRt}*3b|~u znPV=rYywe^t}TIrw{L?FyE#(d!sj%WW)<`s@^2a1(@nQ| X^Ifx#zV%CR^X~qCV^Pk|u_2(+$8bz{LWdX*2oDNN+;wU-ICiFJB85`=WXX>di53N(L;hkK`L zUT=XJseca#1NC_lU}G3t@E{SLP|t#rabXjYEKqXWTuveokFvY0-<$o6@T8yT9Dch! zo-h|YNfC1zVHJNcQqbD06*Bwt6<_xZfP9}QfS0G|nX2jqE3S8QO242fu0 zNRz)aUo!G=*2?IdTbbLT4MU38j9qHqRU2a+YTe4xP(G5N8=V?2O?2C0<6Xn;v$@X>M0ZZAPNO9|-~GCgBn0`B^r6J#_&xe=CfexplX>n)5q|v-ed|~>H7Ec8NxB+( delta 548 zcmV+<0^9wk6`mEah6sOn204}IFWYQ0+-ClZPk*IdA9myN$t}Osl#4Vp!dU53uYRF5 zVkx#!T)D`S%)Lf*j=$Z@BXMfN!|l_@kK|Rc8l_L+Y;l#d=FH25HvSdcS#b$QzQ< zL}flpP+KLQg+3Vz1#1=%w@>y^r!=%6+z;@XfOkNShE#vU28PIxh*pC%`8)FkArB+1 zjLx~0x!u(;q-7Z|itKF7nbdy7S$y m3Q0ncKS>-PN<5CeqwiIsO*%iB=Z+NN*Z%-|P*cP4CjbC%gc3>s diff --git a/ESP32_AP-Flasher/data/www/main.js.gz b/ESP32_AP-Flasher/data/www/main.js.gz index dab5e85533f8b9307042489094878e5d3da51973..412ebb5e39977f2cffdbeb18754098592e17064b 100644 GIT binary patch literal 9398 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 literal 9333 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 diff --git a/ESP32_AP-Flasher/data/www/ota.js.gz b/ESP32_AP-Flasher/data/www/ota.js.gz index e4fa1810e19b9abf3a0330f61cc03d6e82513d08..80be0e9c6d72f82b8244815088bac0f9f48a0633 100644 GIT binary patch delta 4044 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 delta 4035 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 diff --git a/ESP32_AP-Flasher/include/esp32_port.h b/ESP32_AP-Flasher/include/esp32_port.h new file mode 100644 index 00000000..c098762d --- /dev/null +++ b/ESP32_AP-Flasher/include/esp32_port.h @@ -0,0 +1,59 @@ +/* Copyright 2020-2023 Espressif Systems (Shanghai) CO LTD + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + #pragma once + +#include "esp_loader_io.h" +#include "freertos/FreeRTOS.h" +#include "freertos/queue.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct +{ + uint32_t baud_rate; /*!< Initial baud rate, can be changed later */ + uint32_t uart_port; /*!< UART port */ + uint32_t uart_rx_pin; /*!< This pin will be configured as UART Rx pin */ + uint32_t uart_tx_pin; /*!< This pin will be configured as UART Tx pin */ + uint32_t reset_trigger_pin; /*!< This pin will be used to reset target chip */ + uint32_t gpio0_trigger_pin; /*!< This pin will be used to toggle set IO0 of target chip */ + uint32_t rx_buffer_size; /*!< Set to zero for default RX buffer size */ + uint32_t tx_buffer_size; /*!< Set to zero for default TX buffer size */ + uint32_t queue_size; /*!< Set to zero for default UART queue size */ + QueueHandle_t *uart_queue; /*!< Set to NULL, if UART queue handle is not + necessary. Otherwise, it will be assigned here */ +} loader_esp32_config_t; + +/** + * @brief Initializes serial interface. + * + * @param baud_rate[in] Communication speed. + * + * @return + * - ESP_LOADER_SUCCESS Success + * - ESP_LOADER_ERROR_FAIL Initialization failure + */ +esp_loader_error_t loader_port_esp32_init(const loader_esp32_config_t *config); + +/** + * @brief Deinitialize serial interface. + */ +void loader_port_esp32_deinit(void); + +#ifdef __cplusplus +} +#endif diff --git a/ESP32_AP-Flasher/include/espflasher.h b/ESP32_AP-Flasher/include/espflasher.h new file mode 100644 index 00000000..10599252 --- /dev/null +++ b/ESP32_AP-Flasher/include/espflasher.h @@ -0,0 +1,4 @@ +#include +#include + +bool doC6flash(); diff --git a/ESP32_AP-Flasher/include/ota.h b/ESP32_AP-Flasher/include/ota.h index 5bbce278..e46fb9ad 100644 --- a/ESP32_AP-Flasher/include/ota.h +++ b/ESP32_AP-Flasher/include/ota.h @@ -9,4 +9,5 @@ void handleUpdateOTA(AsyncWebServerRequest* request); void firmwareUpdateTask(void* parameter); void updateFirmware(const char* url, const char* expectedMd5, const size_t size); void handleRollback(AsyncWebServerRequest* request); +void handleUpdateC6(AsyncWebServerRequest* request); void handleUpdateActions(AsyncWebServerRequest* request); diff --git a/ESP32_AP-Flasher/include/serialap.h b/ESP32_AP-Flasher/include/serialap.h index 8d9ea599..7b934f18 100644 --- a/ESP32_AP-Flasher/include/serialap.h +++ b/ESP32_AP-Flasher/include/serialap.h @@ -29,7 +29,8 @@ void APTask(void* parameter); bool sendCancelPending(struct pendingData* pending); bool sendDataAvail(struct pendingData* pending); bool sendPing(); - void APEnterEarlyReset(); - -bool sendChannelPower(struct espSetChannelPower* scp); \ No newline at end of file +bool sendChannelPower(struct espSetChannelPower* scp); +void rxSerialTask2(void* parameter); +void APTagReset(); +bool bringAPOnline(); \ No newline at end of file diff --git a/ESP32_AP-Flasher/platformio.ini b/ESP32_AP-Flasher/platformio.ini index fb1832c2..3b7de77f 100644 --- a/ESP32_AP-Flasher/platformio.ini +++ b/ESP32_AP-Flasher/platformio.ini @@ -64,7 +64,7 @@ build_flags = -D FLASHER_LED=15 -D FLASHER_RGB_LED=33 build_src_filter = - +<*>-- + +<*>--- board_build.psram_type=qspi_opi board_upload.maximum_size = 4194304 board_upload.maximum_ram_size = 327680 @@ -99,7 +99,7 @@ build_flags = -D FLASHER_LED=15 -D FLASHER_RGB_LED=-1 build_src_filter = - +<*>-- + +<*>--- board_build.psram_type=qspi_opi board_upload.maximum_size = 4194304 board_upload.maximum_ram_size = 327680 @@ -157,6 +157,8 @@ build_flags = -D FLASHER_ALT_TEST=13 -D FLASHER_LED=21 -D FLASHER_RGB_LED=48 +build_src_filter = + +<*>- board_build.flash_mode=qio board_build.arduino.memory_type = qio_opi board_build.psram_type=qspi_opi @@ -186,7 +188,7 @@ build_flags = -D FLASHER_AP_RXD=16 -D FLASHER_LED=22 build_src_filter = - +<*>-- + +<*>--- ; ---------------------------------------------------------------------------------------- ; !!! this configuration expects an wemos_d1_mini32 @@ -212,7 +214,7 @@ build_flags = -D FLASHER_AP_RXD=17 -D FLASHER_LED=22 build_src_filter = - +<*>-- + +<*>--- ; ---------------------------------------------------------------------------------------- ; !!! this configuration expects an m5stack esp32 @@ -249,7 +251,7 @@ build_flags = -D ILI9341_DRIVER -D SMOOTH_FONT build_src_filter = - +<*>-- + +<*>--- ; ---------------------------------------------------------------------------------------- ; !!! this configuration expects an ESP32-S3 16MB Flash 8MB RAM ; @@ -258,9 +260,11 @@ build_src_filter = board = esp32-s3-devkitc-1 board_build.partitions = large_spiffs_16MB.csv build_unflags = - -D ARDUINO_USB_MODE=1 - -D CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC=y - -D ILI9341_DRIVER + -D ARDUINO_USB_MODE=1 + -D CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC=y + -D ILI9341_DRIVER +lib_deps = + ${env.lib_deps} build_flags = ${env.build_flags} -D YELLOW_IPS_AP @@ -282,6 +286,7 @@ build_flags = -D FLASHER_AP_RXD=18 -D FLASHER_DEBUG_TXD=19 -D FLASHER_DEBUG_RXD=20 + -D FLASHER_DEBUG_PROG=21 -D FLASHER_LED=16 -D HAS_RGB_LED -D FLASHER_RGB_LED=48 @@ -297,6 +302,10 @@ build_flags = -D TFT_RGB_ORDER=TFT_BGR -D USE_HSPI_PORT -D LOAD_FONT2 + -D MD5_ENABLED=1 + -D SERIAL_FLASHER_INTERFACE_UART=1 + -D SERIAL_FLASHER_BOOT_HOLD_TIME_MS=50 + -D SERIAL_FLASHER_RESET_HOLD_TIME_MS=100 build_src_filter = +<*>-- board_build.flash_mode=qio @@ -331,7 +340,7 @@ build_flags = -D FLASHER_AP_RXD=23 -D FLASHER_LED=2 build_src_filter = - +<*>-- + +<*>--- board_build.psram_type=qspi_opi board_upload.maximum_size = 4194304 board_upload.maximum_ram_size = 327680 @@ -366,7 +375,7 @@ build_flags = -D FLASHER_LED=2 -D FLASHER_RGB_LED=-1 build_src_filter = - +<*>-- + +<*>--- board_build.psram_type=qspi_opi board_upload.maximum_size = 4194304 board_upload.maximum_ram_size = 327680 @@ -405,7 +414,7 @@ build_flags = -D FLASHER_LED=21 -D FLASHER_RGB_LED=38 build_src_filter = - +<*>-- + +<*>--- board_build.flash_mode=opi board_build.arduino.memory_type = opi_opi board_build.psram_type=qspi_opi diff --git a/ESP32_AP-Flasher/src/espflasher.cpp b/ESP32_AP-Flasher/src/espflasher.cpp new file mode 100644 index 00000000..3b8c3ab4 --- /dev/null +++ b/ESP32_AP-Flasher/src/espflasher.cpp @@ -0,0 +1,185 @@ +#include +#include + +#include "esp32_port.h" +#include "esp_littlefs.h" +#include "storage.h" +#include "web.h" + +esp_loader_error_t connect_to_target(uint32_t higher_transmission_rate) { + esp_loader_connect_args_t connect_config = ESP_LOADER_CONNECT_DEFAULT(); + esp_loader_error_t err = esp_loader_connect(&connect_config); + if (err != ESP_LOADER_SUCCESS) { + printf("Cannot connect to target. Error: %u\n", err); + return err; + } + printf("Connected to target\n"); + + if (higher_transmission_rate && esp_loader_get_target() != ESP8266_CHIP) { + err = esp_loader_change_transmission_rate(higher_transmission_rate); + if (err == ESP_LOADER_ERROR_UNSUPPORTED_FUNC) { + printf("ESP8266 does not support change transmission rate command."); + return err; + } else if (err != ESP_LOADER_SUCCESS) { + printf("Unable to change transmission rate on target."); + return err; + } else { + err = loader_port_change_transmission_rate(higher_transmission_rate); + if (err != ESP_LOADER_SUCCESS) { + printf("Unable to change transmission rate."); + return err; + } + printf("Transmission rate changed\n"); + } + } + return ESP_LOADER_SUCCESS; +} + +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#define MIN(a, b) ((a) < (b) ? (a) : (b)) + +esp_loader_error_t flash_binary(const char *file_path, size_t address) { + esp_loader_error_t err; + + wsSerial("Flashing " + String(file_path)); + + File file = contentFS->open(file_path, "rb"); + if (!file) { + wsSerial("Failed to open file"); + return ESP_LOADER_ERROR_FAIL; + } + + size_t size = file.size(); + static uint8_t payload[1024]; + Serial.println("file size: " + String(size)); + + printf("Erasing flash (this may take a while)...\n"); + err = esp_loader_flash_start(address, size, sizeof(payload)); + if (err != ESP_LOADER_SUCCESS) { + wsSerial("Erasing flash failed"); + file.close(); + return err; + } + printf("Start programming\n"); + + size_t written = 0; + size_t sizeleft = size; + uint32_t t = millis(); + while (sizeleft > 0) { + size_t to_read = MIN(sizeleft, sizeof(payload)); + size_t bytes_read = file.readBytes(reinterpret_cast(payload), to_read); + + if (bytes_read != to_read) { + wsSerial("Failed to read file."); + file.close(); + return ESP_LOADER_ERROR_FAIL; + } + + err = esp_loader_flash_write(payload, to_read); + if (err != ESP_LOADER_SUCCESS) { + wsSerial("Packet could not be written!"); + file.close(); + return err; + } + + sizeleft -= to_read; + written += to_read; + + if (millis() - t > 250) { + uint32_t progress = written * 100 / size; + // printf("\rProgress: %d%%", progress); + wsSerial("Progress: " + String(progress) + "%"); + fflush(stdout); + t = millis(); + } + }; + wsSerial("Progress: 100%"); + + file.close(); + printf("\nFinished programming\n"); + +#if MD5_ENABLED + err = esp_loader_flash_verify(); + if (err == ESP_LOADER_ERROR_UNSUPPORTED_FUNC) { + printf("ESP8266 does not support flash verify command."); + return err; + } else if (err != ESP_LOADER_SUCCESS) { + wsSerial("MD5 does not match."); + return err; + } + wsSerial("Flash verified"); +#endif + + vTaskDelay(1000 / portTICK_PERIOD_MS); + return ESP_LOADER_SUCCESS; +} + +bool doC6flash() { + const loader_esp32_config_t config = { + .baud_rate = 115200, + .uart_port = 2, + .uart_rx_pin = FLASHER_DEBUG_TXD, + .uart_tx_pin = FLASHER_DEBUG_RXD, + .reset_trigger_pin = FLASHER_AP_RESET, + .gpio0_trigger_pin = FLASHER_DEBUG_PROG, + }; + + if (loader_port_esp32_init(&config) != ESP_LOADER_SUCCESS) { + wsSerial("Serial initialization failed"); + loader_port_esp32_deinit(); + return false; + } + + if (connect_to_target(230400) == ESP_LOADER_SUCCESS) { + if (esp_loader_get_target() == ESP32C6_CHIP) { + wsSerial("Connected to ESP32-C6"); + int maxRetries = 5; + esp_loader_error_t err; + + for (int retry = 0; retry < maxRetries; retry++) { + err = flash_binary("/bootloader.bin", 0x0); + if (err == ESP_LOADER_SUCCESS) break; + Serial.printf("Flash failed with error %d. Retrying...\n", err); + delay(1000); + } + if (err != ESP_LOADER_SUCCESS) { + loader_port_esp32_deinit(); + return false; + } + + for (int retry = 0; retry < maxRetries; retry++) { + err = flash_binary("/partition-table.bin", 0x8000); + if (err == ESP_LOADER_SUCCESS) break; + Serial.printf("Flash failed with error %d. Retrying...\n", err); + delay(1000); + } + if (err != ESP_LOADER_SUCCESS) { + loader_port_esp32_deinit(); + return false; + } + + for (int retry = 0; retry < maxRetries; retry++) { + err = flash_binary("/OpenEPaperLink_esp32_C6.bin", 0x10000); + if (err == ESP_LOADER_SUCCESS) break; + Serial.printf("Flash failed with error %d. Retrying...\n", err); + delay(1000); + } + if (err != ESP_LOADER_SUCCESS) { + loader_port_esp32_deinit(); + return false; + } + + Serial.println("Done!"); + } else { + wsSerial("Connected to wrong ESP32 type"); + loader_port_esp32_deinit(); + return false; + } + } else { + wsSerial("Connection failed"); + loader_port_esp32_deinit(); + return false; + } + loader_port_esp32_deinit(); + return true; +} diff --git a/ESP32_AP-Flasher/src/ota.cpp b/ESP32_AP-Flasher/src/ota.cpp index f899622c..c64b5a23 100644 --- a/ESP32_AP-Flasher/src/ota.cpp +++ b/ESP32_AP-Flasher/src/ota.cpp @@ -7,6 +7,8 @@ #include #include +#include "espflasher.h" +#include "serialap.h" #include "storage.h" #include "tag_db.h" #include "util.h" @@ -234,6 +236,60 @@ void handleRollback(AsyncWebServerRequest* request) { } } +void C6firmwareUpdateTask(void* parameter) { + wsSerial("Stopping AP service"); + + apInfo.isOnline = false; + apInfo.state = AP_STATE_FLASHING; + config.runStatus = RUNSTATUS_STOP; + extern bool rxSerialStopTask2; + rxSerialStopTask2 = true; + Serial1.end(); + delay(250); + + wsSerial("C6 flash starting"); + + bool result = doC6flash(); + + wsSerial("C6 flash end"); + + if (result) { + apInfo.state = AP_STATE_OFFLINE; + + wsSerial("Finishing config..."); + vTaskDelay(3000 / portTICK_PERIOD_MS); + + wsSerial("starting monitor"); + Serial1.begin(115200, SERIAL_8N1, FLASHER_AP_RXD, FLASHER_AP_TXD); + rxSerialStopTask2 = false; +#ifdef FLASHER_DEBUG_RXD + xTaskCreate(rxSerialTask2, "rxSerialTask2", 1750, NULL, configMAX_PRIORITIES - 4, NULL); +#endif + vTaskDelay(1000 / portTICK_PERIOD_MS); + + wsSerial("resetting AP"); + APTagReset(); + vTaskDelay(1000 / portTICK_PERIOD_MS); + + wsSerial("bringing AP online"); + if (bringAPOnline()) config.runStatus = RUNSTATUS_RUN; + + wsSerial("Finished!"); + } else { + wsSerial("Flashing failed. :-("); + } + vTaskDelete(NULL); +} + +void handleUpdateC6(AsyncWebServerRequest* request) { +#ifdef YELLOW_IPS_AP + xTaskCreate(C6firmwareUpdateTask, "OTAUpdateTask", 6144, NULL, 10, NULL); + request->send(200, "Ok"); +#else + request->send(400, "C6 flashing not implemented"); +#endif +} + void handleUpdateActions(AsyncWebServerRequest* request) { wsSerial("Performing cleanup"); File file = contentFS->open("/update_actions.json", "r"); diff --git a/ESP32_AP-Flasher/src/serialap.cpp b/ESP32_AP-Flasher/src/serialap.cpp index b851f5c7..5c00d44f 100644 --- a/ESP32_AP-Flasher/src/serialap.cpp +++ b/ESP32_AP-Flasher/src/serialap.cpp @@ -15,6 +15,7 @@ #include "zbs_interface.h" QueueHandle_t rxCmdQueue; + SemaphoreHandle_t txActive; // If a command is sent, it will wait for a reply here @@ -25,8 +26,9 @@ SemaphoreHandle_t txActive; volatile uint8_t cmdReplyValue = CMD_REPLY_WAIT; #define AP_SERIAL_PORT Serial1 +volatile bool rxSerialStopTask2 = false; -uint8_t channelList[6]; + uint8_t channelList[6]; struct espSetChannelPower curChannel = {0, 11, 10}; #define RX_CMD_RQB 0x01 @@ -264,6 +266,7 @@ bool sendChannelPower(struct espSetChannelPower* scp) { return false; } bool sendPing() { + if (apInfo.state == AP_STATE_FLASHING) return true; Serial.print("ping"); int t = millis(); if (!txStart()) return false; @@ -582,13 +585,16 @@ void rxSerialTask(void* parameter) { void rxSerialTask2(void* parameter) { char lastchar = 0; Serial2.begin(115200, SERIAL_8N1, FLASHER_DEBUG_TXD, FLASHER_DEBUG_RXD); - while (1) { + while (rxSerialStopTask2 == false) { while (Serial2.available()) { lastchar = Serial2.read(); Serial.write(lastchar); } vTaskDelay(1 / portTICK_PERIOD_MS); } + Serial2.end(); + Serial.println("Exiting AP serial monitor"); + vTaskDelete(NULL); } #endif @@ -640,6 +646,7 @@ void segmentedShowIp() { } bool bringAPOnline() { + if (apInfo.state == AP_STATE_FLASHING) return false; apInfo.isOnline = false; apInfo.state = AP_STATE_OFFLINE; // try without rebooting @@ -651,6 +658,7 @@ bool bringAPOnline() { vTaskDelay(300 / portTICK_PERIOD_MS); } if (!APrdy) { + if (apInfo.state == AP_STATE_FLASHING) return false; APTagReset(); vTaskDelay(500 / portTICK_PERIOD_MS); bootTimeout = millis(); @@ -733,39 +741,42 @@ void APTask(void* parameter) { updateContent(apInfo.mac); } - uint16_t fsversion; - fsversion = getAPUpdateVersion(apInfo.type); - if ((fsversion) && (apInfo.version != fsversion) && (FLASHER_AP_MOSI != -1)) { - Serial.printf("Firmware version on LittleFS: %04X\n", fsversion); - Serial.printf("We're going to try to update the AP's FW in\n"); - flashCountDown(30); - Serial.printf("\n"); - notifySegmentedFlash(); - apInfo.isOnline = false; - apInfo.state = AP_STATE_FLASHING; - if (doAPUpdate(apInfo.type)) { - checkWaitPowerCycle(); - Serial.printf("Flash completed, let's try to boot the AP!\n"); - if (bringAPOnline()) { - // AP works - ShowAPInfo(); - setAPchannel(); + uint16_t fsversion; + if (FLASHER_AP_MOSI != -1) { + fsversion = getAPUpdateVersion(apInfo.type); + if ((fsversion) && (apInfo.version != fsversion)) { + Serial.printf("Firmware version on LittleFS: %04X\n", fsversion); + + Serial.printf("We're going to try to update the AP's FW in\n"); + flashCountDown(30); + Serial.printf("\n"); + notifySegmentedFlash(); + apInfo.isOnline = false; + apInfo.state = AP_STATE_FLASHING; + if (doAPUpdate(apInfo.type)) { + checkWaitPowerCycle(); + Serial.printf("Flash completed, let's try to boot the AP!\n"); + if (bringAPOnline()) { + // AP works + ShowAPInfo(); + setAPchannel(); + } else { + Serial.printf("Failed to bring up the AP after flashing seemed successful... That's not supposed to happen!\n"); + Serial.printf("This can be caused by a bad AP firmware, failed or failing hardware, or the inability to fully power-cycle the AP\n"); + apInfo.state = AP_STATE_FAILED; + #ifdef HAS_RGB_LED + showColorPattern(CRGB::Red, CRGB::Yellow, CRGB::Red); + #endif + } } else { - Serial.printf("Failed to bring up the AP after flashing seemed successful... That's not supposed to happen!\n"); - Serial.printf("This can be caused by a bad AP firmware, failed or failing hardware, or the inability to fully power-cycle the AP\n"); apInfo.state = AP_STATE_FAILED; -#ifdef HAS_RGB_LED - showColorPattern(CRGB::Red, CRGB::Yellow, CRGB::Red); -#endif + checkWaitPowerCycle(); + Serial.println("Failed to update version on the AP :(\n"); + #ifdef HAS_RGB_LED + showColorPattern(CRGB::Red, CRGB::Red, CRGB::Red); + #endif } - } else { - apInfo.state = AP_STATE_FAILED; - checkWaitPowerCycle(); - Serial.println("Failed to update version on the AP :(\n"); -#ifdef HAS_RGB_LED - showColorPattern(CRGB::Red, CRGB::Red, CRGB::Red); -#endif } } refreshAllPending(); @@ -774,14 +785,23 @@ void APTask(void* parameter) { #define FLASH_TIMEOUT 30 #endif - // AP unavailable, maybe time to flash? - apInfo.isOnline = false; - apInfo.state = AP_STATE_OFFLINE; - Serial.printf("I wasn't able to connect to a ZBS (AP) tag.\n"); - Serial.printf("This could be the first time this AP is booted and the AP-tag may be unflashed.\n"); - Serial.printf("If this tag was previously flashed succesfully but this message still shows up, there's probably something wrong with the serial connections.\n"); - Serial.printf("The build of this firmware expects an AP tag with TXD/RXD on ESP32 pins %d and %d, does this match with your wiring?\n", FLASHER_AP_RXD, FLASHER_AP_TXD); - if (FLASHER_AP_MOSI != -1) { + if (FLASHER_AP_MOSI == -1) { + Serial.printf("I wasn't able to connect to the AP radio. Did you flash it?\n"); + Serial.printf("The build of this firmware expects an AP tag with TXD/RXD on ESP32 pins %d and %d, does this match with your wiring?\n", FLASHER_AP_RXD, FLASHER_AP_TXD); +#ifdef HAS_RGB_LED + showColorPattern(CRGB::Red, CRGB::Yellow, CRGB::Red); +#endif + apInfo.isOnline = false; + apInfo.state = AP_STATE_FAILED; + } else { + // AP unavailable, maybe time to flash? + apInfo.isOnline = false; + apInfo.state = AP_STATE_OFFLINE; + + Serial.printf("I wasn't able to connect to a ZBS (AP) tag.\n"); + Serial.printf("This could be the first time this AP is booted and the AP-tag may be unflashed.\n"); + Serial.printf("If this tag was previously flashed succesfully but this message still shows up, there's probably something wrong with the serial connections.\n"); + Serial.printf("The build of this firmware expects an AP tag with TXD/RXD on ESP32 pins %d and %d, does this match with your wiring?\n", FLASHER_AP_RXD, FLASHER_AP_TXD); Serial.printf("Performing firmware flash in about %d seconds!\n", FLASH_TIMEOUT); flashCountDown(FLASH_TIMEOUT); if (doAPFlash()) { diff --git a/ESP32_AP-Flasher/src/web.cpp b/ESP32_AP-Flasher/src/web.cpp index ee845054..28c0f9c5 100644 --- a/ESP32_AP-Flasher/src/web.cpp +++ b/ESP32_AP-Flasher/src/web.cpp @@ -578,6 +578,7 @@ void init_web() { server.on("/sysinfo", HTTP_GET, handleSysinfoRequest); server.on("/check_file", HTTP_GET, handleCheckFile); server.on("/rollback", HTTP_POST, handleRollback); + server.on("/update_c6", HTTP_POST, handleUpdateC6); server.on("/update_actions", HTTP_POST, handleUpdateActions); server.on("/update_ota", HTTP_POST, [](AsyncWebServerRequest *request) { handleUpdateOTA(request); diff --git a/ESP32_AP-Flasher/wwwroot/index.html b/ESP32_AP-Flasher/wwwroot/index.html index 364bb9da..cdbd1048 100644 --- a/ESP32_AP-Flasher/wwwroot/index.html +++ b/ESP32_AP-Flasher/wwwroot/index.html @@ -224,7 +224,10 @@ to save file system space">
- +
+ +
+
diff --git a/ESP32_AP-Flasher/wwwroot/main.css b/ESP32_AP-Flasher/wwwroot/main.css index aad740d8..38904656 100644 --- a/ESP32_AP-Flasher/wwwroot/main.css +++ b/ESP32_AP-Flasher/wwwroot/main.css @@ -532,6 +532,11 @@ ul.messages li.new { display: none; } +#advanceddiv div:nth-child(2) { + display: flex; + gap: 10px; +} + #releasetable { margin: 10px 0px; } diff --git a/ESP32_AP-Flasher/wwwroot/ota.js b/ESP32_AP-Flasher/wwwroot/ota.js index 7b41b106..b77d9312 100644 --- a/ESP32_AP-Flasher/wwwroot/ota.js +++ b/ESP32_AP-Flasher/wwwroot/ota.js @@ -336,6 +336,25 @@ $('#rollbackBtn').onclick = function () { disableButtons(false); } +$('#updateC6Btn').onclick = function () { + if (running) return; + disableButtons(true); + running = true; + errors = 0; + const consoleDiv = document.getElementById('updateconsole'); + consoleDiv.scrollTop = consoleDiv.scrollHeight; + + print("Flashing ESP32-C6..."); + + fetch("/update_c6", { + method: "POST", + body: '' + }) + + running = false; + disableButtons(false); +} + export function print(line, color = "white") { const consoleDiv = document.getElementById('updateconsole'); if (consoleDiv) {