835 Commits

Author SHA1 Message Date
atc1441
764747fb45 Also updated the .gz files 2025-09-12 11:32:01 +02:00
atc1441
6bb2e0362b Update main.js 2025-09-12 10:02:06 +02:00
atc1441
54dd05e698 Update main.js 2025-09-12 09:58:05 +02:00
atc1441
328f00a559 Update index.html 2025-09-12 09:54:20 +02:00
atc1441
14fda5c32a Update main.css 2025-09-12 09:19:15 +02:00
atc1441
624bf49ee3 Added DarkMode to AP Gui 2025-09-12 00:00:44 +02:00
Skip Hansen
2a5094993c Don't delay content generate when shorten latency is enabled and user is connected. 2025-07-20 11:39:20 -04:00
Skip Hansen
49d981f006 Updated Chroma29 entry in tagotaversions.json. 2025-07-19 10:35:44 -04:00
Skip Hansen
fb2abf933d Chroma29 v0015: fix high battery current on some tags (#459). 2025-07-18 14:51:54 -07:00
atc1441
b78e4a6099 Create 6F.json 2025-07-04 13:47:46 +02:00
Frank Kunz
e0df4490b3 fix build of serialap module (#475)
wifimanager need to be used to read local IP address.

Signed-off-by: Frank Kunz <mailinglists@kunz-im-inter.net>
Co-authored-by: Frank Kunz <mailinglists@kunz-im-inter.net>
2025-06-14 17:45:45 +02:00
atc1441
7226793e41 Merge pull request #474 from VstudioLAB/2f
Update 2F.json
2025-06-14 10:06:51 +02:00
Vstudio LAB
934d33f950 Update 2F.json 2025-06-14 10:05:29 +02:00
Vstudio LAB
a143b49492 Button 3 (#473) 2025-06-14 09:38:03 +02:00
Skip Hansen
f048cfb296 Added Chroma 74 BWR binaries version 0014. 2025-06-05 07:58:32 -07:00
atc1441
89fec64e91 Merge branch 'master' of https://github.com/OpenEPaperLink/OpenEPaperLink 2025-05-29 21:56:12 +02:00
atc1441
bdb1e8af82 TagType Update 2025-05-29 21:56:09 +02:00
atc1441
f40238a49d Update 45.json 2025-05-29 09:36:40 +02:00
Jelmer
957b94469f Create 2A.json 2025-05-28 00:52:01 +02:00
Jelmer
c2255a3de7 Create 28.json 2025-05-28 00:50:15 +02:00
Jelmer
caf5e49595 Create 29.json
Added 2.4" BWRY definition
2025-05-28 00:48:35 +02:00
Jonas Niesner
7782a37c97 Update conditional-build-test.yml 2025-05-27 12:01:47 +02:00
atc1441
f86f2ce587 Update 6E.json 2025-05-27 11:55:26 +02:00
atc1441
7d1b81690b Added more advanced Json template demo 2025-05-26 16:23:44 +02:00
atc1441
ac6a46262a Update main.c 2025-05-22 10:40:49 +02:00
atc1441
bde464e8c1 Edited 800x480 Template 2025-05-19 15:23:29 +02:00
atc1441
b2e73c9360 Added more TagTypes 2025-05-18 16:35:38 +02:00
atc1441
863e18a4d7 Create SOL_M2_26_SSD_0028.bin 2025-05-12 19:46:18 +02:00
Marcin Juszkiewicz
d90f4e181a css: fallback to 'monospace' for AP log view (#461)
Log view on firmware update page was not printed using fixed width font on my system.

Now it is.

Closes: #460
2025-04-27 14:52:15 +02:00
atc1441
33c7053121 Update oepl-definitions.h 2025-04-18 11:38:11 +02:00
atc1441
5f06f5b0a9 Update 49.json 2025-04-15 18:36:14 +02:00
Skip Hansen
18baa45433 Enable zlib_compression support. 2025-04-15 08:13:24 -07:00
atc1441
43c9a69f88 Added 5.81" BWR V2 because of UC Variant needs rotated image 2025-04-14 17:08:03 +02:00
Nic Limper
b313d07669 added sunrise/sunset/moon phase to date display 2025-04-12 19:51:57 +02:00
atc1441
eb00a1d9c4 Update 61.json 2025-04-07 13:54:11 +02:00
atc1441
f1c9ac0a75 Update 62.json 2025-04-07 11:24:22 +02:00
atc1441
0b2a8b38ac Update 69.json 2025-04-06 02:47:56 +02:00
atc1441
561dd82236 Added a Clock mode as content type 2025-04-06 02:26:59 +02:00
atc1441
66e0b5d9f6 Merge pull request #453 from jonasniesner/master
Add OpenEPaperLink_Nano_TLSR_C6 and ESP32_S3_16_8_4inch_AP to automat…
2025-04-05 17:47:58 +02:00
Jonas Niesner
08329b89c5 Add OpenEPaperLink_Nano_TLSR_C6 and ESP32_S3_16_8_4inch_AP to automatic builds 2025-04-05 17:00:24 +02:00
Nic Limper
e8eb87e7c1 fixes crash when dayahead data is unavailable 2025-04-05 14:00:05 +02:00
atc1441
c621050f18 Create 6A.json 2025-04-04 14:03:58 +02:00
Nic Limper
2fc5c54b8e new tagtype M3 2.7" and M3 11.6" layouts and other tweaks 2025-04-03 22:31:07 +02:00
Jelmer
e2fb26c0ad Update 47.json 2025-03-31 03:01:54 +02:00
Jelmer
d53cc834c4 Delete resources/tagtypes/49.json
47 already exists
2025-03-31 02:42:16 +02:00
Jelmer
5755e4aad9 Added 2.7" tagtype 2025-03-31 02:18:41 +02:00
Nic Limper
87ce6d949d OTA update tweaks 2025-03-28 10:47:48 +01:00
Nic Limper
e102f8e4e9 stability improvements in C6 flashing 2025-03-27 21:10:10 +01:00
Nic Limper
0fb0c6f74d more robust extended sleep time and 'no updates between' handling 2025-03-27 01:03:04 +01:00
Nic Limper
5dfd0e4582 Update release.yml 2025-03-27 00:59:22 +01:00
Frank Kunz
f311239c9c Add new AP hardware support OpenEPaperLink_ESP32-PoE-ISO_AP (#431)
* Fix filesystem mutex handling

This fixes the re-initialization of the filesystem mutex when the dyn storage
module is reinitialized. Using xSemaphoreCreateMutex would cause a memory leak
when the begin function is called multiple times and a semaphore leakage could
be caused by the re-initialization of the global fsMutex variable while the
semaphore is taken.

The fsMutex should not be taken while the logLine function is called as this
would cause a nested take of the fsMutex, which causes a deadlock.

Signed-off-by: Frank Kunz <mailinglists@kunz-im-inter.net>

* Fix hard coded littlefs in json upload

Signed-off-by: Frank Kunz <mailinglists@kunz-im-inter.net>

* Add new AP hardware support OpenEPaperLink_ESP32-PoE-ISO_AP

This is based on Olimex ESP32-PoE-ISO
https://www.olimex.com/Products/IoT/ESP32/ESP32-POE-ISO/open-source-hardware

It has a SD Card slot that is used to store all filesystem data on SD.
Use the prepare_sdcard.sh script to copy all needed data to an empty
SD card that is formatted with FAT filesystem. The AP firmware will format
the SD if an unformatted or from formatted card is used. This can be used
to intially prepare an empty SD card for usage.

For tag communication a ESP32-C6-WROOM-1(U) is used with the following
connection scheme:

ESP32-PoE-ISO  |  ESP32-C6-WROOM-1
---------------+------------------
  GPIO5        |    EN
  GPIO13       |    GPIO9
  GPIO36       |    GPIO3
  GPIO4        |    GPIO2
  GPIO33       |    GPIO24
  GPIO32       |    GPIO25
               |    GPIO8 pullup 5.1k

Signed-off-by: Frank Kunz <mailinglists@kunz-im-inter.net>

* Avoid error message log print when parsers.json is missing

Signed-off-by: Frank Kunz <mailinglists@kunz-im-inter.net>

* Workaround for IEEE802.15.4 modem stuck issue

The ESP32-C6 esp-idf based modem firmware can run into a case where it
does not receive data anymore from the tags. This can be detected when
it starts to print

"receive buffer full, drop the current frame"

and does not recover from that. In such a case a modem reset is triggered.

Signed-off-by: Frank Kunz <mailinglists@kunz-im-inter.net>

* Add OpenEPaperLink_ESP32-PoE-ISO_AP to release build

Signed-off-by: Frank Kunz <mailinglists@kunz-im-inter.net>

* Add OpenEPaperLink_ESP32-PoE-ISO_AP to condidional build

Signed-off-by: Frank Kunz <mailinglists@kunz-im-inter.net>

* Add Ethernet support

The ethernet support allows to make the network/internet connection
via LAN cable instead of WiFi. LAN is preferred, if a LAN cable is
connected and a valid IP configuration via DHCP can be obtained, WiFi
is switched off. If the LAN cable is disconnected, a fall back to
WiFi is done.

Use those defines in platform.ini for PHY settings:
ETHERNET_PHY_POWER: IO pin where the PHY can be switched of/on, can be
                    -1 if not used.
ETHERNET_CLK_MODE: PHY clock mode, see eth_clock_mode_t in ETH.h
ETHERNET_PHY_MDC: PHY MDC pin
ETHERNET_PHY_MDIO: PHY MDIO pin
ETHERNET_PHY_TYPE: PHY type, see eth_phy_type_t in ETH.h

Limitations:
- only DHCP is supported, no static IP configuration for LAN so far.
- If GPIO0 is used for one of the ETHERNET_CLK_MODE modes, then GPIO0
  cannot be used to clear the WiFi configuration.

Signed-off-by: Frank Kunz <mailinglists@kunz-im-inter.net>

---------

Signed-off-by: Frank Kunz <mailinglists@kunz-im-inter.net>
Co-authored-by: Frank Kunz <mailinglists@kunz-im-inter.net>
2025-03-27 00:48:05 +01:00
Skip Hansen
c3e729744a Added E5.json for Elcrow Advanced 2.8" AP. 2025-03-25 12:56:11 -07:00
Skip Hansen
447611ba4a Added support for Elcrow Advanced 2.8" AP. 2025-03-25 10:02:39 -07:00
Skip Hansen
6637405358 Added optional (compile time) debug logging to C6 & H2. 2025-03-25 08:12:53 -07:00
Skip Hansen
32c74ba5b4 Added support for Elecrow C6 wireless module. 2025-03-25 08:09:26 -07:00
Skip Hansen
177f93844c Display SN rather than MAC for wider range of Chroma tags. 2025-03-23 11:23:43 -07:00
Skip Hansen
d76d110f39 Repurpose unused type 0x81 for Chroma Aeon 74. 2025-03-23 07:16:42 -07:00
atc1441
1584f35624 Improved 4inchAP 2025-03-23 13:55:41 +01:00
atc1441
ac0c3ccfc9 Added Touch support for the 4inchAP 2025-03-22 23:28:53 +01:00
atc1441
3810fbf68c Added 5.81 BWR 2025-03-20 22:41:55 +01:00
Nic Limper
20b4f728e4 Update 2E.json 2025-03-20 17:07:42 +01:00
Nic Limper
047230de25 weather forecast enhancements 2025-03-20 13:43:21 +01:00
Nic Limper
107764c6be fixed y-axis labels on dayahead prices (https://github.com/OpenEPaperLink/OpenEPaperLink/issues/446) 2025-03-19 23:18:30 +01:00
Nic Limper
0819b19db2 follow redirects on getimgurl 2025-03-19 22:55:46 +01:00
Nic Limper
4aedce7839 sync gzipped files; update some tagtypes 2025-03-19 22:02:16 +01:00
Nic Limper
2d486d7c66 update to arduinojson 7.3.0, change ESPAsyncWebServer fork, Arduino 3.x compatibility, enabled comments within json files (#438)
* updated arduinojson to version 7.3.0, enabled comments within json files

* update ESPAsyncWebServer/AsyncTCP to the ESP32Async fork

ESP32Async/ESPAsyncWebServer and ESP32Async/AsyncTCP are much better maintained and it looks like a lot of bugs are fixed compared to the ESPHome version we used before.

* Arduino 3.x compatibility (while maintaining 2.x compatibility)
2025-03-19 21:48:06 +01:00
atc1441
ba8a5c6990 Merge branch 'master' of https://github.com/OpenEPaperLink/OpenEPaperLink 2025-03-17 13:51:05 +01:00
atc1441
1ae015c65f Update 2E.json 2025-03-17 13:50:48 +01:00
Nic Limper
92681aa4c5 Update 2E.json
update version number
2025-03-17 13:50:32 +01:00
Steel
004438cee9 Update 2E.json (#448)
Added weather forecast
2025-03-17 13:49:20 +01:00
atc1441
b7546cf6d4 Create 47.json 2025-03-11 20:32:46 +01:00
atc1441
cce5f56d67 Bug fix of LilyGo init 2025-03-02 16:09:00 +01:00
Nic Limper
eb58b7fc02 Update get_dayahead.js 2025-02-25 12:03:35 +01:00
atc1441
8f0362455a Create 5A.json 2025-02-21 18:19:55 +01:00
Skip Hansen
79fe05581c Add note of required version for CC1110 support to README. 2025-02-21 07:42:24 -08:00
atc1441
658b3b8635 Merge branch 'master' of https://github.com/OpenEPaperLink/OpenEPaperLink 2025-02-19 19:59:08 +01:00
atc1441
77da5964bf Update 63.json 2025-02-19 19:58:40 +01:00
Wheeze_NL
0232725711 Comment out defined ports (#426)
Without defined ports, platformio will autodetect the ports.
Best for most usecases.
2025-02-18 06:18:46 -08:00
Nic Limper
ff7f397705 added missing characters in vlw font 2025-02-16 15:41:32 +01:00
Nic Limper
d8fa96b20e support for multiple folder levels 2025-02-11 20:00:06 +01:00
Nic Limper
15a9728f45 Update get_dayahead.js 2025-02-11 09:59:04 +01:00
Skip Hansen
6c9439822b Nail ArduinoJson to version 7.1.0 to fix S2 Tag flasher build.
Thanks to discord user xRaZx.
2025-02-01 07:07:37 -08:00
Skip Hansen
4b667d0039 Coprocessor OTA changes (#425)
OTA changes to support C6/H2 OTA updates from configured repo.
2025-01-25 14:11:39 -08:00
Skip Hansen
19bbba5202 Added OEPL_TLSR_AP.bin from discord. 2025-01-16 06:59:35 -08:00
Skip Hansen
ad76d122e5 Added chroma29_8151_full_0013.bin & .hex. 2025-01-12 13:57:56 -08:00
Skip Hansen
5ec69153b5 Updated chroma29_8151_ota_0013.bin to fix screen orientation. 2025-01-12 11:05:47 -08:00
Nic Limper
45427148f6 {mac} placeholder in json template content card 2025-01-12 14:12:52 +01:00
Skip Hansen
c5fb16836f Added Chroma29 rev 'C' to tagotaversions.json. 2025-01-11 07:37:43 -08:00
Skip Hansen
63b6f911b6 Added Chroma29 firmware for Rev 'C' hardware. 2025-01-10 14:06:31 -08:00
Nic Limper
dec9b17655 add Portugal to dayahead prices options 2025-01-09 17:24:16 +01:00
atc1441
b8c4d4420e Added 4inch AP 2025-01-08 20:03:48 +01:00
atc1441
0b064a9cee Update 63.json 2025-01-04 12:38:31 +01:00
atc1441
4d186c81ff Added more options in the direct image upload 2025-01-03 22:43:46 +01:00
Skip Hansen
5cc7869c0f Disable builds for deprecated configurations,
OpenEPaperLink_Mini_AP, OpenEPaperLink_Nano_AP, Simple_AP, and
ESP_THREAD_BORDER_ROUTER.
2025-01-02 08:59:00 -08:00
atc1441
6a8450cbcb Added firmware.json file to be compatible to old download C6 method. while switching to new takes place 2024-12-30 00:08:09 +01:00
Skip Hansen
ca8781f956 Fix typos in firmware_C6.json. 2024-12-25 06:45:18 -08:00
Skip Hansen
311ae1a570 Added processor type to C6/H2 binary filenames. 2024-12-25 06:36:41 -08:00
atc1441
06b2718d7d Update ATC_Cheapo_BLE_OEPL_Watch.bin 2024-12-20 22:41:57 +01:00
atc1441
0f574bc3e8 Update ATC_Cheapo_BLE_OEPL_Watch.bin 2024-12-20 22:26:22 +01:00
Nic Limper
7e49c2a09e some small tweaks 2024-12-17 19:20:17 +01:00
Skip Hansen
23cbadb9f6 Merge branch 'master' of https://github.com/OpenEPaperLink/OpenEPaperLink into oepl_master 2024-12-17 09:28:00 -08:00
Skip Hansen
fce2e43ef7 Update C6 and H2 binaries to ver 001f. 2024-12-17 09:27:09 -08:00
Magnus Erler
4f7a381eed Update 2E.json (#416) 2024-12-17 17:14:18 +01:00
Magnus Erler
6a0f1310e1 Update 41.json (#406) 2024-12-17 16:54:36 +01:00
Skip Hansen
bb36185066 C6 Ver 001f - fix #410 & other C6 improvements
1. Only call esp_ieee802154_receive_handle_done() when ack != NULL.
2. Add 2 millisecond timeout for all SubGhz MISO wait loops to
   prevent watchdog timeouts when/if bad things happen (none observed
   during testing)
3. Make CC1101 detection more robust and less intrusive by testing
   MISO and CSn before trying to read chip version number.
4. Remove useless "error" messages which occur during normal operation.
5. Added missing \r in some log messages for EOL consistency.
2024-12-17 07:17:47 -08:00
mhwlng
be8eac2fc5 added E3.json for GDEM1085Z51 10.85" 1360x480 e-paper (#415)
mainly for use in home assistant (implemented only calendar and AP info screens)
2024-12-17 06:30:40 +01:00
atc1441
e4ecf08e29 Create ATC_Cheapo_BLE_OEPL_Watch.bin 2024-12-16 19:36:42 +01:00
atc1441
99c048a29d Merge branch 'master' of https://github.com/OpenEPaperLink/OpenEPaperLink 2024-12-16 17:33:12 +01:00
atc1441
f49731a240 Create E4.json 2024-12-16 17:33:11 +01:00
Jelmer
375662c69e Added 'Set Mac' datatype/content card 2024-12-15 23:11:19 +01:00
Nic Limper
e246ac578d optional border color and -width in box and rbox json template 2024-12-11 14:12:26 +01:00
Nic Limper
d8dcd498a3 optional colored google calendar events on BWR/BWY displays 2024-12-11 12:49:39 +01:00
Nic Limper
91b01c5fca gzipped wwwfiles 2024-12-10 23:01:28 +01:00
Nic Limper
30812dff49 color related improvements
- added "image" to json commands to insert a jpg image/icon from the flash partition
- added optional center/right alignment to "textbox" json command
- google calendar content: added optional colors, different color per calendarid
- improved ordered dithering, works also with unevenly spaced color tables. This is to be used with graphs etc., not suitable for photos (use floyd steinberg for photos)
- improved flyod steinberg dithering (fix some bugs)
- added preview rendering for 4bpp images
- log tab now scrolls to the top on entering
- added optional perceptual color table to tagtypes (for rendering previews, for example to display darker yellows on screen while keeping the 255,255,0 color to the tag
- drag/dropping in an image to a tag while holding shift key now uses ordered dithering (default is floyd steinberg)
- some tagtype improvements
2024-12-10 23:01:02 +01:00
Jelmer
31a90d1498 Fixed G5 overflow bug 2024-12-09 20:58:31 +01:00
atc1441
2d02da1574 Update 62.json 2024-12-09 14:22:54 +01:00
Nic Limper
33f77b2192 gzipped wwwroot 2024-12-08 20:55:59 +01:00
Nic Limper
e079c30c54 version compare bugfix 2024-12-08 20:48:58 +01:00
Nic Limper
eba9f54454 Update update_actions.json 2024-12-08 20:14:00 +01:00
Nic Limper
a0a39e98cd some polishing before release 2024-12-08 19:46:20 +01:00
Jelmer
2144bd58f9 Added binaries for some M2 tag types 2024-12-08 17:57:17 +01:00
Jelmer
fdd87779d7 Merge pull request #404 from OpenEPaperLink/G5-compress
Added G5 encoding
2024-12-08 15:59:29 +01:00
Nic Limper
44514e24d1 fix 2024-12-08 15:36:26 +01:00
Nic Limper
8857ecb669 DATATYPE_IMG_G5 2024-12-08 15:32:03 +01:00
Skip Hansen
1871f53b5a Fix #403: missing esp_ieee802154_receive_handle_done() function call causing stop of ZigBee reception. 2024-12-07 15:11:47 -08:00
Nic Limper
1de47b1133 bump tagtype version numbers 2024-12-07 22:27:23 +01:00
Nic Limper
2e38e9f218 added g5 preview to file editor 2024-12-07 22:25:23 +01:00
Nic Limper
a48511145c added header to g5 compressed buffer 2024-12-07 21:59:39 +01:00
Nic Limper
ae87ac1960 added javascript g5 decoder for previews 2024-12-07 20:46:25 +01:00
Jelmer
d84a5f6e75 Added G5 for Opticon 2024-12-06 13:21:47 +01:00
atc1441
f4025fb18f Added ATC BLE OEPL Sending 2024-12-05 09:45:58 +01:00
Jelmer
9d4e31b01b Added G5 to M2 (zbs243) tag types 2024-12-04 00:48:21 +01:00
atc1441
5950c5df4a Update 56.json 2024-12-01 12:23:07 +01:00
Jelmer
691b64d192 fixed the lut argument for g5-compressed images 2024-12-01 11:34:50 +01:00
Jelmer
573ba8c424 Added fallback, updated types 2024-12-01 10:41:24 +01:00
atc1441
511fa3e5dd Updated Tagtypes to support compression 2024-12-01 02:36:07 +01:00
atc1441
cc3128d22a Create FA.json 2024-11-30 19:09:02 +01:00
Jelmer
78e097738a Added G5 encoding 2024-11-29 15:30:24 +01:00
Jelmer
534c52cebf Update oepl-definitions.h 2024-11-29 00:48:18 +01:00
Skip Hansen
8cf6d01098 Chroma42_8176 v0011 release: Added support for BWR displays. 2024-11-21 10:10:17 -08:00
Skip Hansen
aadbe7652e Chroma v0010 release: Reset invalid NVRAM so we can connect to AP. 2024-11-21 10:08:17 -08:00
Skip Hansen
7735612a16 Enable SubGhz, changed CC1101 pin assigments for the Lilygo T-Panel. 2024-11-16 13:51:02 -08:00
Reletiv
c22de350f6 Added HS tagtypes from TLSR Alpha repo (#398)
* Add skadis mount for nebular

* Added tagtypes used in the Reletiv/OpenEpaperLink_TLSR Repo
* Be aware of the ALPHA state, these are very WIP and feel free to contribute and fix the templates

* Removed STL Due to files being moved to other Repo
2024-11-16 20:01:31 +01:00
Nic Limper
95d5aac01a add support for 3bpp ACeP buffers (7 color epaper) 2024-11-13 15:12:26 +01:00
Jelmer
7a31db91ba Added Opticon 7.5" / 09.json 2024-11-11 22:09:33 +01:00
Jelmer
344ded01ac Create 08.json 2024-11-11 22:08:31 +01:00
Jelmer
4747669df8 Added Opticon 2.9 / 07.json 2024-11-10 19:32:28 +01:00
Jelmer
a532c7c190 Added Opticon 2.2 / 06.json 2024-11-10 19:31:14 +01:00
Nic Limper
a6772c6fae fixes https://github.com/OpenEPaperLink/OpenEPaperLink/issues/389 and https://github.com/OpenEPaperLink/OpenEPaperLink/issues/392 2024-11-08 11:17:56 +01:00
Nic Limper
6ec580d267 Update 03.json 2024-11-05 00:04:41 +01:00
Nic Limper
7805ab2b46 new templates for M2 2.2" and M2 2.6" 2024-11-04 23:53:54 +01:00
Nic Limper
e6401f6840 cosmetic issue on update page 2024-11-03 21:10:49 +01:00
mhwlng
c1738936a9 change endianness lilygo t-panel in Arduino_ESP32RGBPanel to get rid of looping over all pixels (#388) 2024-11-03 19:33:29 +01:00
Nic Limper
4813f062f7 nightly reboot config option fix 2024-11-03 15:08:25 +01:00
Nic Limper
1052102032 improved AP status indicator 2024-11-03 13:33:30 +01:00
Jonas Niesner
61eb19dfe8 Enable S2 based APs in release scripts 2024-11-03 13:06:58 +01:00
Nic Limper
9eb0b303f3 breaking change for ESP32-S2 based AP's
- turn off Buienradar and Google Calendar content on ESP32-S2 based AP's because the firmware doesn't fit the flash memory anymore. If you need this and you use e.g. the mini AP v2, don't update. ESP32-S3 based AP's are not affected.
- On the update tab, the list of available versions now only shows the versions that are actually available for the build environment in use, so when we leave out S2-based builds in future releases, they won't show the new version.
2024-11-03 02:04:04 +01:00
Nic Limper
7abd5d9a84 painter now uses the color table of the tag instead of hardcoded black/red/white 2024-11-03 00:22:38 +01:00
Jonny Bergdahl
d4ccaf6027 Add option for AP discovery type (#351) 2024-11-02 23:10:00 +01:00
Nic Limper
a57c797542 various improvements, see desc
- nightly reboot is now optional (and rescheduled to 3:56 daily)
- lowbatt count in sys websocket messages (once a minute)
- new preview window, showing pending image on 1:1 size, great for debugging json template or other custom content. Right click tag and choose 'Tag preview'
2024-11-02 19:35:28 +01:00
Nic Limper
0cd76eebf0 smaller improvements
- dayahead Fixed surcharge now takes either one value (old behaviour) or an array with 24 elements for each hour, to add a surcharge depending on the time of day (as apparently they use in Denmark). The array should be entered like `[n,n,...,n]`
- added 1.54" template for dayahead prices
- in dayahead content, added option to only display the graph, without the current time/price/arrow. With this, the display only has to refresh one a day, which will save battery
- added the number of timedout tags to the 'sys' websocket message. The timeoutcount key/value is only present once a minute.
`{"sys":{"currtime":1730133055,"heap":194124,"recordcount":27,"dbsize":5488,"littlefsfree":5246976,"psfree":8350371,"apstate":1,"runstate":2,"rssi":-70,"wifistatus":3,"wifissid":"sensors","uptime":72,"timeoutcount":0}}`
- cosmetic: tagtype update now doesn't give an error when it tries to process readme.md
2024-10-28 17:40:40 +01:00
Nic Limper
d9a3bf8aac restrict fastled library version because of breaking change 2024-10-28 12:48:52 +01:00
Nic Limper
5e9238835e /save_cfg call: fixed crash by making all parameters optional 2024-10-28 11:58:50 +01:00
Nic Limper
dd5d96d1ee add dayahead prices to 4.2" displays; add custom interval to weather
don't forget to reboot the AP and clear browser cache after updating (or to open your browser developer tools and check 'disable cache' the first time you reload the UI)
2024-10-25 16:20:38 +02:00
atc1441
3f613407fe Update 03.json 2024-10-21 23:32:03 +02:00
atc1441
36f6705083 Update 03.json 2024-10-21 12:08:26 +02:00
atc1441
261aef13b4 Added 2 M2 Types 2024-10-21 09:13:01 +02:00
Skip Hansen
4c75234fa1 Enabled SubGhz support for ESP32_S3_C6_NANO_AP (thanks to discord user Ficu). 2024-10-10 11:42:29 -04:00
Magnus Erler
20e2106658 Update README.md (#381) 2024-10-08 12:36:03 +02:00
mhwlng
30bcd3b176 display brightness adjustment dropdown for lilygo panel now works gfx library now also supports t-panel LITE. fixed possible memory leak? (#378)
* display brightness adjustment dropdown now works

* add GFX library files for t-panel lite display controller

* add deleteSprilte after draw16bitRGBBitmap

* better handle t-panel LITE display

* file missing in last commit?
2024-10-06 13:07:23 +02:00
Jonas Niesner
8986967a4d Move Hardware directory to new separate repo (#377)
* Delete Hardware directory

* Create readme.md
2024-10-03 22:26:26 +02:00
Jonas Niesner
32072a3b25 Fix T-Panel AP builds (#373)
* Update release.yml

* Update conditional-build-test.yml

* fix builds for linux

* Update platformio.ini
2024-09-29 18:49:30 +02:00
mhwlng
8ff9826b3d add support for lilygo t-panel (#370)
* add support for lilygo t-panel

add support for lilygo t-panel (the rs485 version with an ESP32-S3 and ESP32-G2)
https://www.lilygo.cc/products/t-panel-s3

* refactor

* moved gfx library to lib2 folder and removed examples

* removed lib2\Arduino_GFX-1.3.7 and switch to moononournation/GFX Library for Arduino@^1.4.9

* added lilygo lib2\Arduino_GFX-1.3.7 back and removed all unused files. went from 166 files to 15 files!
2024-09-27 17:49:56 +02:00
atc1441
6a02f719da Added Gicisky TFT 2.13 Custom Firmware 2024-09-08 15:23:50 +02:00
atc1441
2a0c763ba0 Merge branch 'master' of https://github.com/OpenEPaperLink/OpenEPaperLink 2024-09-05 19:59:11 +02:00
atc1441
e1f4384813 Added one tagtype and 7,5" TLSR Firmware update 2024-09-05 19:59:08 +02:00
Reletiv
c96f380346 Add skadis mount for nebular (#344)
Added universal mount for Hanshow Nebular models.
be aware of up/down click mechanism.
Use combined with t clip
2024-09-05 10:57:41 +02:00
atc1441
b3978fb3cf Create 68.json 2024-09-02 16:36:59 +02:00
atc1441
80a75d7df2 Added new AP types, TLSR and C6 Nano 2024-08-23 14:16:07 +02:00
atc1441
b5d8852bd5 Added 12" Stand 2024-08-21 20:27:55 +02:00
atc1441
41fef2834c Merge pull request #357 from quack3d/master
Remix of jjwbruijn's Yellow AP Case
2024-08-12 19:49:18 +02:00
sepodele
a7929010e8 Remix of jjwbruijn's Yellow AP Case
Remixed to support the size of a Spaghetti AP
2024-08-12 19:38:51 +02:00
atc1441
b3a34beaae Added HS BWY 20 Type and Firmware 2024-08-11 11:45:38 +02:00
atc1441
af04d39ecb Added new TLSR Type 2024-08-11 02:29:15 +02:00
atc1441
f8e6dea9ce Added types M3 OTA Version increase 2024-08-05 16:31:18 +02:00
atc1441
3eaa59cc18 Merge branch 'master' of https://github.com/OpenEPaperLink/OpenEPaperLink 2024-08-04 19:42:54 +02:00
atc1441
169a2f5d5d Create 44.json 2024-08-04 19:42:34 +02:00
Skip Hansen
80cb4dc472 Added Chroma29 Flashing Jig by mindstormer7. 2024-08-04 10:37:08 -07:00
Skip Hansen
00d3e2b11c Added cc_interface.* files missed in earlier commit. 2024-07-30 09:54:21 -07:00
atc1441
90dd623d5b Create TLSR_Gicisky_BWR_29_ALPHA.bin 2024-07-30 16:41:02 +02:00
atc1441
acaa193093 Create TLSR_HS_BW_35_ALPHA.bin 2024-07-29 15:58:15 +02:00
atc1441
1f3962fbc9 Added CMD sending for 2 Tagtypes 2024-07-29 00:07:13 +02:00
atc1441
f9e73526df Increased thickness of YellowAP Printable Case because of new Ebyte module variant 2024-07-28 10:42:01 +02:00
Skip Hansen
73e472ec21 Added support for TI CCxxxx chips to Tag_Flasher, AP_and_Flasher and Mini_AP_v4. 2024-07-27 10:37:01 -07:00
atc1441
d0ccd8ff09 Added 3D Printable stand for 9.7" 2024-07-27 19:12:23 +02:00
atc1441
701f3a6429 Added Big AP 2024-07-26 12:27:19 +02:00
Skip Hansen
4276799777 Added chroma74y_ota_0007.bin missed in last commit. 2024-07-21 11:54:21 -07:00
Skip Hansen
cb4f3bdff0 Added v0007 chroma29r, chroma42 and chroma74y firmware images. 2024-07-20 07:02:51 -07:00
Skip Hansen
500f35f286 Modified auto update code to support chroma hardware variants. 2024-07-20 07:00:01 -07:00
Skip Hansen
be8ece2413 Remove "Ch" from SugGhz channel to fix LCD truncation on mini V4 AP. 2024-07-17 09:51:07 -07:00
atc1441
9fbafaf23e Changed repo to new repo organization in source 2024-07-17 00:07:45 +02:00
Skip Hansen
5c421648d1 Accept CC1101 chip version 4 was well as 20. Fixes Yellow APs
built with modules with older CC1101 chips.  Version 4 and 20
should cover all chips made from 2007 to 2021.
2024-07-16 13:48:04 -07:00
atc1441
fddf6169f1 Added 9.7" Case by Viktor Knall 2024-07-15 17:45:18 +02:00
atc1441
bf80cbff3e Create 2D.json 2024-07-13 20:36:51 +02:00
atc1441
76b6cc6d4c Update of release ESP32-C6 With SubGhz and Version increase 2024-07-11 20:04:23 +02:00
atc1441
ca657fd68c Merge branch 'master' of https://github.com/OpenEPaperLink/OpenEPaperLink 2024-07-11 00:07:06 +02:00
atc1441
309b76061d Fixed Position of GUI Text in CC Firmware 2024-07-11 00:07:00 +02:00
atc1441
cc6c0cb8f2 Fixed non working Zigbee and SubGhz 2024-07-10 10:15:05 -07:00
atc1441
8ba87800c1 Fixes some bugs in CC Display firmware 2024-07-10 14:05:03 +02:00
atc1441
2c04db25ec New Display cover for M2 4.2 2024-07-08 21:35:11 +02:00
Steven Cooreman
54bad5a08a Merge pull request #348 from stevew817/master
Add tag type for HD150 w/ modchip
2024-07-05 00:07:28 +02:00
Steven
2576043456 Add tag type 50 2024-07-04 23:06:06 +02:00
Jonas Niesner
468f6b77a1 Delete Hardware/9.7"_case directory 2024-07-01 22:56:18 +02:00
Jonas Niesner
0adf81ab79 Add 9.7" case 2024-06-30 17:53:56 +02:00
Skip Hansen
99fe067ba8 Another frequency error correction fix, FreqErr uint8_t -> uint8_t. 2024-06-26 09:21:59 -04:00
atc1441
79e3633e85 Addded 4.2" 3D Printed front made by Corwin 2024-06-24 23:40:31 +02:00
Stefan Krupop
8d0bd95288 Implement "erase" command to unprotect NRF52 based tags (#332) 2024-06-20 12:09:31 +02:00
Stefan Krupop
e22c40d097 Add small delay after powering on tag before accessing uC to allow voltage to stabilize (#331) 2024-06-20 12:07:51 +02:00
atc1441
f11f8e31fc Update syncedproto.c 2024-06-19 16:40:34 +02:00
Skip Hansen
564cd655fc Merge pull request #337 from mnyhlen/bugfix_calculating_nextcheckin
Bugfix: Update variable minutesUntilNextUpdate to 32-bit integer because of integer overflow
2024-06-15 09:02:56 -04:00
mnyhlen
6981171a6e Bugfix: Update variable minutesUntilNextUpdate to 32-bit integer because of integer overflow 2024-06-12 20:59:19 +02:00
Skip Hansen
1d1845580b Merge pull request #329 from skiphansen/oepl_pr_13
Change Fahrenheit/ mph /mm Units option to Fahrenheit / mph / in.
2024-06-04 08:23:18 -07:00
Skip Hansen
eca64ee3c3 Change Fahrenheit/ mph /mm Units option to Fahrenheit / mph / in. 2024-06-03 16:05:03 -07:00
Stefan Krupop
6a636b5b54 - ESP32_Flasher: Return new status "2" when connected, but nRF is locked (#327)
- OEPL-Flasher: Print "locked" message when flasher returns status 2
- ESP32_Flasher: Initialize idCode to zero as failed read attempts will not set it
- ESP32_Flasher: Print returned idCode when showDebug is enabled
2024-05-27 23:11:44 +02:00
Nic Limper
45849851af sync gzipped www folder 2024-05-26 00:39:47 +02:00
jjwbruijn
cc226f0b0a Moved ZBS-based to the Org repo 2024-05-25 22:43:51 +02:00
jjwbruijn
ea92165c22 Spring cleaning, moved files to the org repo 2024-05-25 22:37:06 +02:00
atc1441
8cddae3ba2 Create 12.json 2024-05-25 10:15:19 +02:00
atc1441
c8e6b7b834 Update TLSR_HS_BWY_35_SSD.bin 2024-05-21 22:05:11 +02:00
Skip Hansen
319814ac73 Fix Freq correction bug: the error accumulator must be signed! (#325) 2024-05-21 20:10:35 +02:00
atc1441
23527f2e4a Create TLSR_HS_BWY_35_SSD.bin 2024-05-21 16:51:01 +02:00
atc1441
935af0d4f2 Update ble_filter.cpp 2024-05-20 13:13:40 +02:00
Skip Hansen
f7208f84c7 Default tag alias to tag serial number rather than MAC for Chroma tags (#318) 2024-05-18 10:33:49 +02:00
Nic Limper
73db8d52a8 fix buienradar api call 2024-05-11 11:16:04 +02:00
Thomas B. Ruecker
e1bf5dc9a9 Consolidate serial output to \r\n (#309)
So far the serial output is a mix of \r\n for println() and \n for
sprintf() and such.
This commit consolidates this to a consistent \r\n.
There should be no noticeable difference for users of terminals that
auto-substitute a sole \n to \r\n.
This will however make the serial output friendly to default behavior of
various terminal emulators like 'screen' and 'minicom'.

This commit doesn't touch anything that is not serial output and also
leaves 'ets_printf' alone just in case.

Co-authored-by: Thomas B. Rücker <thomas.ruecker@relexsolutions.com>
2024-05-10 16:31:47 +02:00
Skip Hansen
1a35b9b23e Fix recent BLE only AP change which broke SubGhz. (#315)
* Added subGhz fixed channel support to tag config, added line accidentally dropped in pr7 merge.

* Fix recent BLE only AP change which broke SubGhz.
2024-05-10 05:32:46 +02:00
jjwbruijn
9dc15c28d4 moved seldom used radio's to the org repo 2024-05-10 01:07:38 +02:00
atc1441
e456e8c701 Update README.md 2024-05-09 11:54:26 +02:00
atc1441
cc426e2215 New NanoAP V2 Case added 2024-05-09 11:53:26 +02:00
Skip Hansen
9cce7c2e33 SubGhz C6 fixes: CRC error & automatic xtal frequency error correction (#314)
* Added subGhz fixed channel support to tag config, added line accidentally dropped in pr7 merge.

* C6 - Fixed CRC error detection, added xtal frequency error
correction support. The xtal on commercial tags is assumed
to be better than those on crapy CC1101 modules.
2024-05-09 06:36:06 +02:00
Jonas Niesner
a20ff17d24 BLE only AP (#313)
Add BLE only AP option

Fix some smaller stuff
2024-05-08 21:24:10 +02:00
Matthew Kelch
1ec762ffdb Conditional build / test pipeline (#287)
* POC: Conditional Build Jobs / Steps

Demonstrate a built/test pipeline which make use of both conditional jobs and steps.

* use paths-filter fallback (no token)

* fix typo in cache key

* remove test file

* add in nRF_Bootloader to confitional build
2024-05-06 21:01:22 +02:00
Thomas B. Ruecker
e4351c23f3 Updating 7.4in/640x384 templates (#308)
Maximising use of screen real estate. (It's free real estate!)
Within capabilities of current templating engine.
Further improvements will require changes to templating engine.

Co-authored-by: Thomas B. Rücker <thomas.ruecker@relexsolutions.com>
2024-05-06 15:28:31 +02:00
Bimmi
050978042d chroma74 flash jig (#311)
* Add files via upload

A JIG for flashing the Chroma74 Tag without soldering. Used P75 J1 pogo pins with https://de.aliexpress.com/item/1005003890769928.html?spm=a2g0o.order_list.order_list_main.4.3cbe5c5fYKVid5&gatewayAdapt=glo2deu

* Update readme.md

add chroma74 readme

* Update readme.md

* Update readme.md
2024-05-06 15:20:46 +02:00
atc1441
e3b76c8c5d More BLE Fixes 2024-05-05 22:41:40 +02:00
Jonas Niesner
a3e8eb136b Pin Arduino version 2024-05-05 17:14:22 +02:00
atc1441
b5a3c8db24 BLE Fix 2024-05-05 15:52:14 +02:00
jjwbruijn
f9ea040b33 M2 ZBS243 v0028 - Slideshow fix 2024-05-03 20:47:19 +02:00
atc1441
ab744c0d87 Now CC1310/CC2630 also with ADC / Battery status 2024-05-02 10:45:14 +02:00
atc1441
d26acf2998 Create CC2630_5.8_OEPL_alpha.bin 2024-05-01 19:22:07 +02:00
atc1441
23281b267e CC1310 2.9BWR Update 2024-05-01 13:39:56 +02:00
atc1441
c317711b7b Update CC1310_2.9BWR_1.6.0.bin 2024-04-30 23:59:37 +02:00
atc1441
503353b0bd Create CC1310_2.9BWR_1.6.0.bin 2024-04-29 17:10:47 +02:00
atc1441
8bdf24f2c2 TLSR Improvements 2024-04-25 09:30:10 +02:00
atc1441
c1171b2e99 Better TLSR Deep Sleep 2024-04-25 01:41:10 +02:00
atc1441
50e029d2dd Update TLSR_Gicisky_BWR_213_ALPHA.bin 2024-04-24 13:02:34 +02:00
atc1441
f51bcf84bb Adding and name changing of new TLSR Firmwares 2024-04-24 12:35:15 +02:00
atc1441
1373da4f09 Create 54.json 2024-04-24 12:22:06 +02:00
atc1441
9e9471181e Create TLSR_HS_BW_213_ALPHA.bin 2024-04-24 12:22:01 +02:00
atc1441
bd22b775fa Create TLSR_HS_266_ALPHA.bin 2024-04-24 10:55:07 +02:00
atc1441
f3f432b22d Create 56.json 2024-04-24 10:46:00 +02:00
jjwbruijn
a876609806 Fixed stupid mistake 2024-04-21 23:03:33 +02:00
Jelmer
577250cc00 Update 3C.json
id10T type error
2024-04-20 21:19:51 +02:00
jjwbruijn
f1010ad3cc Added support for Newton M3 4.2 Yellow #273 2024-04-20 21:02:48 +02:00
Skip Hansen
f4727483ad Added subGhz fixed channel support to tag config, added line accident… (#301)
* Added subGhz fixed channel support to tag config, added line accidentally dropped in pr7 merge.
2024-04-19 10:22:15 +02:00
Skip Hansen
d40ef83d03 SubGhz radio fixes. (#288)
* SubGhz radio fixes.
1. Don't for sending of BLOCK_MAX_PARTS parts for subGhz.
2. Fix CC1101 module detection logic.
3. Mitigate for lost CC1101 interrupts.

* Enabled SubGhz for OpenEPaperLink_Mini_AP_v4.
2024-04-19 10:21:36 +02:00
Nic Limper
b51dea8f5d gzipped files 2024-04-18 19:32:01 +02:00
Nic Limper
5d1570118b easyjig, add photos 2024-04-18 15:02:00 +02:00
Nic Limper
0ac2afa495 Update README.md 2024-04-18 14:56:26 +02:00
Nic Limper
f9171d132a Added easyjig flasher cable 2024-04-18 14:53:40 +02:00
Skip Hansen
b8f00f4cb6 Download template tag json file when needed. (#298) 2024-04-17 22:18:29 +02:00
atc1441
fe8056b791 Added more 3D Case and Holder 2024-04-13 11:57:48 +02:00
atc1441
7a8773ca07 Update tagtype_db.cpp 2024-04-12 09:01:11 +02:00
atc1441
925c87d6e0 Merge pull request #296 from chunkysteveo/master
Added BOM passives placement guide image (this time right placements!)
2024-04-11 14:12:05 +02:00
Stephen Ludgate
462e86e2e7 Delete Hardware/S3_C6_NanoAP by ATC1441/s3_c6_nano_v1_BOM_placement.jpg 2024-04-11 13:08:52 +01:00
Stephen Ludgate
13b8eff7a5 Wrong placement
measure twice, cut onc////
2024-04-11 13:08:35 +01:00
Stephen Ludgate
e53ab6e6c2 Add files via upload 2024-04-11 13:07:54 +01:00
Stephen Ludgate
f072a0b7de Messed up placement!
measure twice, cut onc////
2024-04-11 13:05:13 +01:00
Stephen Ludgate
52ff29c2af Update README.md 2024-04-11 12:59:20 +01:00
Stephen Ludgate
3f85955dac Added BOM Passives placement guide image. 2024-04-11 12:59:01 +01:00
Stephen Ludgate
d6520f1743 added s3_c6_nano_v1_BOM_placement.jpg 2024-04-11 12:57:35 +01:00
atc1441
57f3c7f0e5 Merge pull request #294 from chunkysteveo/patch-1
Update README.md - missing resistor for led
2024-04-11 10:42:51 +02:00
Stephen Ludgate
be8b59f4b4 Update README.md - missing resistor for led
BOM list was stating 2x resistors for LEDs, and there's 3x
2024-04-11 09:15:59 +01:00
jjwbruijn
abee7a8c93 Fixed nRF Bootloader PIO 2024-04-10 23:03:13 +02:00
Jelmer
43e4bafa81 Merge pull request #286 from kelchm/core-dir-improvements
Fix core directory interpolation and cleanup dependencies
2024-04-10 21:43:38 +02:00
jjwbruijn
5f77358bd0 Fixed transfers that wouldn't validate properly if size%99==0 2024-04-10 21:23:03 +02:00
Nic Limper
e92824335c remove tagtype files during next OTA update + minor fixes
the updated tagtype files will be downloaded automatically after the fw update
2024-04-07 12:41:58 +02:00
Nic Limper
268736b40b change ESPAsyncWebServer libraries to esphome version (thanks, @koswolf) 2024-04-07 12:38:35 +02:00
Matthew Kelch
5bf5ef8678 use more robust gitignore for core packages 2024-04-06 15:07:58 -04:00
Matthew Kelch
d9786c623b ensure any remaining $PROJECT_DIR directories are ignored globally 2024-04-06 14:30:12 -04:00
Matthew Kelch
0b18e90c83 core package cleanup + gitignore (for nrf52811_Platformio_AP) 2024-04-06 14:07:42 -04:00
Matthew Kelch
0c0761d0ba correct interpolation value for local core dir 2024-04-06 13:31:07 -04:00
Matthew Kelch
073dd0c50a Add support for M3 2.9 BW Variant (#278) 2024-04-05 13:48:58 +02:00
atc1441
4feb30f7e9 Merge pull request #283 from jjwbruijn/revert-281-oepl_pr_4
Revert "Fixed drag and drop image resizing."
2024-04-05 12:07:23 +02:00
Nic Limper
aa7f2673d1 Revert "Fixed drag and drop image resizing." 2024-04-05 12:00:19 +02:00
Skip Hansen
db64b689e3 Add display of subGhz channel to LCD when subGhz radio is present. (#282) 2024-04-05 11:51:01 +02:00
atc1441
701b130418 Merge pull request #281 from skiphansen/oepl_pr_4
Fixed drag and drop image resizing.
2024-04-04 22:06:14 +02:00
Skip Hansen
cc037bb143 Fixed drag and drop image resizing. 2024-04-04 12:55:23 -07:00
atc1441
93eba41376 Fixed no connected Radio handling 2024-03-29 23:29:36 +01:00
atc1441
d8196c76e2 Merge branch 'master' of https://github.com/jjwbruijn/OpenEPaperLink 2024-03-29 22:25:17 +01:00
atc1441
a2bdd1c245 More BLE gicisky types 2024-03-29 22:25:12 +01:00
Nic Limper
8fa5fa8b09 adds some characters; update to the tiny font for better readability 2024-03-27 21:28:22 +01:00
Nic Limper
303c07b4ef updated tiny font for better readability 2024-03-27 11:13:30 +01:00
atc1441
889d6b53c4 Added build option for Espressif ESP Thread Border Router /Zigbee Gateway including ESP32-H2 AP Firmware 2024-03-26 22:20:13 +01:00
Nic Limper
34ca60ba7a update templates
thanks to XiniX for donating some tags
2024-03-26 16:08:00 +01:00
Nic Limper
6197b8962e color table and various fixes
- use the actual color table in tagtype json for rendering images (until now, that color table was ignored)
- added proper ordered dithering (works with all colors now, not just gray and pink)
- on the static image content card, you can now choose floyd-steinberg or ordered dithering (or turn dithering off)
- added ÅÄÖ to twcondensed20 font
- small bugfixes
- fix serial passthrough via UART in OEPL-flasher.py
2024-03-26 01:13:02 +01:00
Nic Limper
cb2f3aed5a remove tagtypes from data folder (they are dynamically loaded now)
You will find the tagtype JSON files in /resources/tagtypes/. They are now automatically downloaded to the LittleFS partition when needed to avoid wasting valuable space. The tagtype definitions are updated during an OTA update, but there is also a separate update button for just syncing them. Additionally, they will only be updated when the version number within the JSON file is higher. If you have made custom changes to a tagtype, you can prevent it from being overwritten by giving it a very high version number.
2024-03-22 20:41:04 +01:00
Nic Limper
7bdc6e55b3 dynamic loading of tagtype files 2024-03-22 16:42:55 +01:00
Nic Limper
b7e0d1af93 added misc helper scripts 2024-03-22 11:55:11 +01:00
Nic Limper
587d7c86c0 various fixes
- added last updated time of a tag in tagdb
- day ahead prices choice of whole money units or cents
- optimization of file upload during updates
- show mac address in wifi setup
- fixed reload of display after unexpected reboot of tag
2024-03-21 20:11:12 +01:00
jjwbruijn
98d9dc61f3 fixes #275 - battery voltage display snafu 2024-03-20 13:45:33 +01:00
Nic Limper
3f1e45da28 content bugfix
- truncates long lines in calfeed (solves https://github.com/jjwbruijn/OpenEPaperLink/issues/202)
- displays button pointers correctly when rotated 180 degrees
https://github.com/jjwbruijn/OpenEPaperLink/issues/246
2024-03-18 22:09:05 +01:00
Nic Limper
59e2a5eeb8 Various fixes
- bugfix not recognizing identical image
https://github.com/jjwbruijn/OpenEPaperLink/issues/255
- Count number of updates
https://github.com/jjwbruijn/OpenEPaperLink/issues/247
- Optionally align interval of RSS/calendar/etc
https://github.com/jjwbruijn/OpenEPaperLink/issues/106
2024-03-18 16:39:44 +01:00
jjwbruijn
68d75782ba New Tag FW Pack 2024-03-17 22:40:20 +01:00
Karl Q
3ccbda8489 feat: add basic tag holder (#266)
Includes CAD source so modifications should be easy.
2024-03-17 07:09:37 +01:00
jjwbruijn
a861b40545 M3 v0027 re-release, including M3 1.3 peghook support 2024-03-14 19:03:14 +01:00
atc1441
57f0ba7edc Added definition for Silabs BLE Display 2024-03-13 00:29:21 +01:00
Nic Limper
a6e6183ce2 include °-symbol in Bahnschrift70; auto formatting tagtype json files 2024-03-11 10:47:22 +01:00
Skip Hansen
5d7d97fca6 Add support for SubGhz radio. Working end to end for tag registration. (#270) 2024-03-10 09:45:43 +01:00
Jelmer
2408b34c2b Merge pull request #263 from skiphansen/oepl_pr_2
Update SDCC build script to support SDCC's trunk
2024-03-06 18:47:16 +01:00
Jelmer
59d582ec93 Merge pull request #265 from kquinsland/feat/add-nrf-mac-patcher-scrip
Feat/add nrf mac patcher scrip
2024-03-06 18:45:43 +01:00
karl
f7ed2c8223 feat: add a uicr patcher tool
This is a cleaned up / documented version of the script I hacked together for restoring UICR partition to wiped tags.
2024-03-06 09:38:56 -08:00
karl
95b5116320 chore: lint fixes
- Make `mdlint` happy
- Trim extra newline from py
2024-03-06 09:37:38 -08:00
Nic Limper
d2c2963b3b gzipped files 2024-03-04 21:40:15 +01:00
Skip Hansen
ad981a8f53 1. Changed source repo from github mirror to SDCC's master SVN repo.
2. Added support for building trunk as well as named tags.
2024-03-04 10:46:35 -08:00
Nic Limper
a5d7282958 update tagtypes for M3 0027 firmware 2024-03-04 19:46:17 +01:00
jjwbruijn
f233d90b86 M3 Universal v0027 2024-03-04 19:04:15 +01:00
Nic Limper
739625f1c8 Squashed commit of the following:
commit d41ab4b27c
Author: Nic Limper <nic@xs4all.nl>
Date:   Mon Mar 4 13:16:15 2024 +0100

    remove subghz in platformio.ini

commit dfa1a5cecd
Author: Nic Limper <nic@xs4all.nl>
Date:   Mon Mar 4 13:15:14 2024 +0100

    Revert "Disable SubGhz support until C6 side is ready."

    This reverts commit 3bc96dc48e.

commit cdd26072fd
Author: Nic Limper <nic@xs4all.nl>
Date:   Mon Mar 4 13:14:46 2024 +0100

    Revert "Merge remote-tracking branch 'mine/oepl_pr_1' into oepl_pr_1"

    This reverts commit 39b1938263, reversing
    changes made to 3bc96dc48e.

commit 39b1938263
Merge: 3bc96dc4 2b62dff5
Author: Skip Hansen <skip@gfrn.org>
Date:   Mon Mar 4 03:54:35 2024 -0800

    Merge remote-tracking branch 'mine/oepl_pr_1' into oepl_pr_1

commit 3bc96dc48e
Author: Skip Hansen <skip@gfrn.org>
Date:   Mon Mar 4 03:43:12 2024 -0800

    Disable SubGhz support until C6 side is ready.

commit 2b62dff5f5
Author: Nic Limper <nic@xs4all.nl>
Date:   Mon Mar 4 11:44:06 2024 +0100

    fix gzip wwwfiles

    to prevent unchanged gzipped files showing up in the commit

commit 0864870540
Author: Skip Hansen <skip@gfrn.org>
Date:   Sun Mar 3 16:46:53 2024 -0800

    Added SubGhz channel support to AP Web GUI.
2024-03-04 13:21:58 +01:00
Jan-Henrik Bruhn
b527d3e57d Fix openepaperlink.eu proxy on https proxies (#251) 2024-03-04 12:03:55 +01:00
Cougar
ba82ab8628 Add Estonian language (#254) 2024-03-04 11:51:49 +01:00
Jelmer
085a642ed2 New M3 types by VstudioLAB 2024-03-04 11:39:45 +01:00
jjwbruijn
e2870825cf 88MZ100 v0028 - bugfix and commands 2024-03-03 21:56:00 +01:00
jjwbruijn
a4bdb4acab FW Pack for autoflasher 2024-03-02 12:13:05 +01:00
Jelmer
058016d208 Update tagotaversions.json 2024-03-02 02:58:30 +01:00
Jelmer
b14cd3909c Update tagotaversions.json - test 2024-03-02 02:40:14 +01:00
jjwbruijn
cd09a53e02 v0027 M2 ZBS Binaries 2024-03-02 02:09:27 +01:00
jjwbruijn
6bdf99a8e7 v0027 M2 ZBS243, fixes inadvertent redraw 2024-03-01 14:02:37 +01:00
Jelmer
1b256c3fba Create README.md 2024-03-01 01:41:27 +01:00
Jelmer
ec217a94d0 Merge branch 'master' of https://github.com/jjwbruijn/OpenEPaperLink 2024-03-01 01:29:34 +01:00
Jelmer
2b99ce7139 MiniAP V3 Case 2024-03-01 01:29:26 +01:00
Nic Limper
f6a8fa3d4d added Dansk (thanks Cokeman), added Nebular 213 templates, removed flasher icon in S2 based AP's 2024-02-29 17:37:35 +01:00
Jelmer
294ed5bd28 Create README.md 2024-02-29 17:08:54 +01:00
Jelmer
92c5d60cf8 Nano C6 case 2024-02-29 16:59:54 +01:00
leXorNet
7ca5461c33 Increased language count cap from 8 to 9 to support the latest language (#250) 2024-02-29 00:19:49 +01:00
Jelmer
aebbb22cde Update oepl-definitions.h 2024-02-28 20:03:10 +01:00
Nic Limper
14e96c72f7 bugfix miniAP doesn't display channel 27 2024-02-28 08:16:47 +01:00
Nic Limper
ebd1adc0d5 gzipped www files 2024-02-28 01:20:37 +01:00
Nic Limper
f4cb642142 add Denmark to dayahead electricity prices; enable it also for 2.9" UC8151 2024-02-28 01:11:01 +01:00
Nic Limper
9b2d76a6b6 bugfix: idlereq should not be queued, and only sent when queue is empty 2024-02-28 01:09:00 +01:00
leXorNet
ac979a3c52 Added Swedish content language (#245) 2024-02-27 12:11:13 +01:00
Jan-Henrik Bruhn
a606c4c1aa Use relative paths for fetch calls and websocket (#243)
This allows the OEPL Frontend to be put behind a reverse proxy like Home
Assistant Ingress to proxy it behind a relative path.
2024-02-27 01:47:36 +01:00
Jelmer
c22fe0d91b Merge pull request #241 from TheRealMrSteel/patch-1
Update content_cards.json
2024-02-27 00:37:42 +01:00
Jelmer
b29907a725 Merge pull request #242 from VstudioLAB/M3_58-26-29FREEZER
M3 58 26 29 freezer
2024-02-27 00:36:03 +01:00
Jelmer
8da475901d Support for rotating generated images based on tagtype profile 2024-02-27 00:32:09 +01:00
Vstudio LAB
e4ed0b13db Delete ARM_Tag_FW/Newton_M3_nRF52811/$PROJECT_DIR directory 2024-02-26 22:55:48 +01:00
VstudioLAB
0ffd0fbf0e Update .gitignore 2024-02-26 22:49:03 +01:00
Steel
1cba70b9cc Update content_cards.json
typo in id19
2024-02-26 22:47:50 +01:00
VstudioLAB
6b67f6df2b updates 2024-02-26 22:24:48 +01:00
Nic Limper
b9fe72de5c small bugfixes 2024-02-26 20:58:46 +01:00
Nic Limper
c458c6b29c bugfix: config screen is not populated when alias is empty 2024-02-26 11:47:56 +01:00
jjwbruijn
d3b9abf56a M2 7.5" v0027 fw 2024-02-26 01:27:40 +01:00
Jelmer
d2b17b7a97 added M2 7.5" BW tag type 2024-02-25 23:10:40 +01:00
Nic Limper
7e3e73a064 bugfix: no flasher-only detection on tag-based AP 2024-02-25 21:39:28 +01:00
Jelmer
9ca9007a1c Update oepl-definitions.h 2024-02-25 19:57:20 +01:00
Nic Limper
b03ad07179 bugfix, AP always reported C6 present 2024-02-25 15:26:01 +01:00
Nic Limper
56537e46be dirty fix for zlib compression
The miniz is used for zlib compression. But because that library has some bugs related to a smal window sizes (we need 4096), I had to make some patches to the library. The miniz library happens to also be part of esp-idf. To distinguish between our version and the esp-idf version, I created a `namespace Miniz` around our version. But nevertheless, the esp-idf version is called when I'm calling Miniz::tdefl_init and Miniz::tdefl_compress . Why??
Anyway, renamed tdefl_init and tdefl_compress to tdefl_initOEPL and tdefl_compressOEPL to get it working. This is ugly. If somebody has a better solution, please let me know!
2024-02-25 14:45:03 +01:00
Nic Limper
bc06ea74e8 gzipped web files 2024-02-24 14:04:47 +01:00
Nic Limper
9137c5acb1 add BLE to all ESP32-S3 based AP's (default disabled; enable in the config screen if needed) 2024-02-24 14:01:27 +01:00
Nic Limper
c0e59dadb4 webflasher serial passthrough, work in progress, turned off for now 2024-02-24 12:46:27 +01:00
Nic Limper
0dd3a8459b fix for mini AP 2024-02-23 17:19:08 +01:00
Nic Limper
ebd6b5289c lot of small fixes
- adds tag serial debug in webflasher and power up/down buttons
- fixes bug where esp32-s3 connected via usb cdc slows down when no terminal connection is present
- fix: ghost tags reporting a different channel id than the AP are now ignored
- webflasher now ramps up/down power to prevent spikes
- bugfix: C6 doesn't get reset anoymore by the watchdog during flashing
- bugfix: C6 could go in flash mode unintended
- a failed connection during swd write blocks is now reported back instead of silently ignored
- added 4 areas of Sweden to day ahead price content
- new context menu option 'Delete all inactive tags' (only when right clicking on an inactive tag).
- adjusted some timings
2024-02-23 17:08:52 +01:00
atc1441
65558360ef Added offline lines to TLSR FW, If the AP is not found the display will draw 5 lines to notify the user 2024-02-20 18:12:44 +01:00
atc1441
dd69fa029a Added ATC_MiThermometer to the BLE part. This allows to receive the Advertising data from the Custom firmware running on the Thermometer via BLE 2024-02-16 18:12:13 +01:00
atc1441
9bbd30b783 Fixed TLSR No AP useless refresh 2024-02-16 16:04:49 +01:00
jjwbruijn
691b688f46 added magic numbers to M2 7.5" 2024-02-16 01:17:11 +01:00
Jelmer
3d125c415f mkfs.OEPL README.md 2024-02-15 23:36:35 +01:00
jjwbruijn
f2dc16953d beta v0027 M2-7.5" FW 2024-02-15 18:51:10 +01:00
jjwbruijn
f38e121c94 More OEPLFS stuff for 88MZ100 2024-02-15 18:34:22 +01:00
VstudioLAB
f83667bcce Added support for the 2.6 BWR 2024-02-15 13:25:58 +01:00
VstudioLAB
bee51a23b6 5.85" Initial support and general preparation for BW only compatibility. 2024-02-15 00:09:25 +01:00
VstudioLAB
a787ac6ddf M3 5.85" cleanning 2024-02-14 22:09:50 +01:00
VstudioLAB
5561f82bf6 Original commit (5.85" BWR only)
First commit of that branch.
At the moment, only the M3 5.85" is added, but not finished.
2024-02-14 21:39:36 +01:00
VstudioLAB
b07eeb31ce initial commit 2024-02-14 00:56:38 +01:00
jjwbruijn
57748d825b Added compression to M3, moved stuff around 2024-02-13 22:38:36 +01:00
Jelmer
d7f6fee31f Update oepl-definitions.h 2024-02-11 14:57:57 +01:00
Jelmer
1cb948e0b6 Update oepl-definitions.h 2024-02-11 14:57:20 +01:00
atc1441
aca1dfc7a3 Added Gicisky / PICKSMART BLE E-Paper Display support. Can be activated via the -D HAS_BLE_WRITER definition in the platformio.ini
This enables direct BLE Image upload from the Main ESP32 SoC via BLE and allows an OEPL usage without soldering/flashing or extra ZigBee interface.
Currently tested on the 2.9" BW and 4.2" BWR version, tagtypes need to be added for more versions

Demo video:
https://youtu.be/_efgMQUA1F4

Official description of the BLE Protocol here:
https://zhuanlan.zhihu.com/p/633113543

Thanks to these wonderful guys for such a good overview:
https://github.com/fpoli/gicisky-tag
https://github.com/Cabalist/gicisky_image_notes
2024-02-10 23:02:34 +01:00
Jelmer
edb874029e Merge pull request #226 from VstudioLAB/ST‐GM29MT1
Adding support to the ST‐GM29MT1 BW (UC8151)
2024-02-08 20:45:49 +01:00
VstudioLAB
a1eba95ce2 Create 27.json 2024-02-08 17:51:38 +01:00
VstudioLAB
4f1252d839 Original commit for this support 2024-02-08 17:36:48 +01:00
Nic Limper
b4836e81f3 tag flasher / timestamp content / bugfixes (#217)
- added webinterface for tag flasher
- added tcp transport for communicating with tag flasher (OTG USB also still works)
- added content 'timestamp', makes use of preloaded images and buttons on the 2.9" M3
- webinterface is now aware of C6 and flasher capabilities
- AP can run without ieee801.15.4 radio (i.e. flasher only) by shorting FLASHER_AP_TXD and FLASHER_AP_RXD
- added tcp transport option to OEPL-Flasher.py (serial also still works)
- added new environment OpenEPaperLink_Mini_AP_v4
- lots of finetuning and bug fixes
2024-02-04 20:30:52 +01:00
Nic Limper
472f148b0c typo 2024-02-02 16:36:27 +01:00
Nic Limper
107c85e3cf bugfix: too long pending filenames after a few hours of uptime 2024-02-02 16:22:19 +01:00
Nic Limper
1835b1cda7 gzipped wwwroot 2024-01-30 11:56:19 +01:00
Nic Limper
b71844eac0 imgupload performance / Norway dayahead codes 2024-01-30 11:23:58 +01:00
Nic Limper
72c1b7bf40 bugfix dayahead 2024-01-30 00:49:49 +01:00
Nic Limper
1c7d45865d new content type: day ahead prices (S3-based AP only) 2024-01-30 00:33:22 +01:00
Nic Limper
7fd04d1ae3 esp32 support for compressed images to tag 2024-01-29 02:50:39 +01:00
Nic Limper
6292e73135 Pending queue (#210)
Pretty complex change here: pending images/commands are now queued.

A command (like LED flasher) will not overwrite a pending image anymore. Also, sending multiple preloaded images is possible.
Also works (at least, as far as I could test) in combination with Multi AP and mirroring tags ('display a copy' content type).

It you want to test this: don't forget to upload the changed files in /www (the pending icon is now displaying the amount of queued messages). Timing improvements will follow later (only one message can be transmitted every checkin. If multiple messages are queued, at this moment, you have to wait until the next checkin which takes 40-60 sec).

This comes also with the advantage of better stability if you upload multiple images to the same tag in succession. Before queuing, if was possible to replace the image between sending the pending message and the image transfer to the tag, causing md5 mismatches and instability.

Solves #47
2024-01-29 00:49:52 +01:00
Nic Limper
8c4627007f removed simple_AP from build-test.yml 2024-01-28 23:08:33 +01:00
jjwbruijn
e563358370 Sorry bit much. Major rewrite of the 88MZ100 firmware, now with compression support. Added beta M2 2.7" (sleep current needs work) and 1.6"(200px). Probably broke M3 building, it's font files have moved to a new 'common' directory 2024-01-28 11:08:42 +01:00
Nic Limper
c2ab7d6057 crispy fonts / HS 3.5 BWY template fix / remove DATATYPE_IMG_RAW_1BPP_DIRECT 2024-01-27 23:49:14 +01:00
Jelmer
5e62b2de1b Update oepl-definitions.h 2024-01-26 22:29:07 +01:00
atc1441
62b87da8c2 Merge branch 'master' of https://github.com/jjwbruijn/OpenEPaperLink 2024-01-26 16:41:06 +01:00
atc1441
9608c6e417 Allow for complete offline ESP32-C6 Updates 2024-01-26 16:41:03 +01:00
Jelmer
86a68cbba4 backlogged fixes 2024-01-26 16:10:00 +01:00
Jelmer
80298ed4a1 Update tag_md5_db.json 2024-01-25 14:41:19 +01:00
Jelmer
d6b1cc0eca added compressed datatypes 2024-01-25 12:10:00 +01:00
Jelmer
90284d0a81 Merge pull request #208 from Reletiv/dev
Added Skadis mounts for HS TLSR
2024-01-25 00:24:34 +01:00
Reletiv
f88c05b279 Added Skadis Solum mounts
Added Skadis Solum mounts 1.54" and 2.9"
Credits to: tdroza
2024-01-24 23:59:45 +01:00
Reletiv
d435d12c30 Added Skadis mounts for HS 2024-01-24 21:43:13 +01:00
Jelmer
af3b6c53c8 Merge pull request #206 from justinotherguy/master
add gerber file for combined flex pcb for nano ap
2024-01-21 14:34:45 +01:00
Justin Otherguy
6af250efbf add gerber file for combined flex pcb
this file for combined flex pcb: antenna and connection between ESP32 S2 mini and tag, so it can be produced in one flex pcb.
combined file has been kinldy provided by 123tztz321 - thank you :)
2024-01-21 14:24:45 +01:00
Nic Limper
83bd0ec177 stability improvements
- changed ESPAsyncWebServer and AsyncTCP (both not properly maintained for more than 5 years) to more recent fork with bugfixes
- fixed concurrency issues in /imgupload. Hurts the upload performance a lot, but probably that's not a real issue. Parallel uploads are now possible (still within the max 5 TCP connection limit)
2024-01-21 11:04:35 +01:00
atc1441
fd13cccdd9 Update README.md 2024-01-19 11:03:24 +01:00
Nic Limper
abc84e18ff change in ledflash http call + minor fixes 2024-01-18 22:25:11 +01:00
atc1441
4edba16674 Another flashing Bug fix
In case the flashing of the C6 is started before the full Boot sequence the AP will end in a failed state
2024-01-15 16:39:24 +01:00
atc1441
7703f6ce6c Fixed interrupted flashing bug
While the C6 would be flashed the recovery would trigger as no Ping was received from the RF-AP
2024-01-15 15:37:24 +01:00
Nic Limper
f00761db94 small improvements
- added short date format definition in language.json
- changed english date format to mm/dd
- added lightgrey (4)/darkgrey (5)/pink (6) colors in jsontemplate (uses pattern dither)
- fixed ntp init timing
2024-01-14 14:24:44 +01:00
atc1441
2655d6d065 Update README.md 2024-01-13 01:24:17 +01:00
Jonas Niesner
e734052697 Update build-test.yml 2024-01-12 17:20:17 +01:00
atc1441
f7b13d3dcb Added a "failsave" recovery to get the RF-AP back up running 2024-01-11 22:36:47 +01:00
Nic Limper
69a40e47aa localisation of date format; tag reverts back to previous content type after sending firmware. 2024-01-11 21:17:35 +01:00
atc1441
b737eb60ed Update TLSR_HS_35_ALPHA.bin 2024-01-11 17:52:50 +01:00
atc1441
1d0186fed0 Enabled cached uploads on the TLSR FW 2024-01-11 17:51:49 +01:00
Nic Limper
d01825a323 autosave tagDB in localstorage of the browser 2024-01-11 14:50:35 +01:00
atc1441
5abbead90b Better SubGHz ESP32-C6 Stability by doing housekeeping every 60 Seconds 2024-01-11 09:10:58 +01:00
Nic Limper
3b294be08a cache control for tagtypes; uptime display in statusbar 2024-01-10 00:53:13 +01:00
atc1441
59d08ea21e Update of the ESP32-C6 SubGHz handling, working Beta 2024-01-09 22:48:18 +01:00
Nic Limper
d2135a57bd bugfix 2024-01-09 21:35:42 +01:00
Jelmer
e77556ee9c Added M2 2.7 jig - updated Hanshow Jigs 2024-01-09 21:19:46 +01:00
Jonas Niesner
1aeea88696 Revert release file change 2024-01-09 20:33:51 +01:00
Nic Limper
837c5de1a8 minor fix in content 2024-01-09 17:58:29 +01:00
Jonas Niesner
d4f16f74e9 Update tagotaversions.json 2024-01-09 16:48:03 +01:00
Nic Limper
fdb4a3cbf1 weather forecast template 2.9" M3 and some minor fixes 2024-01-09 16:09:43 +01:00
Jelmer
5b7c96dcc0 Added 3 Hanshow Jigs 2024-01-09 13:25:16 +01:00
Jonas Niesner
c0a2bd01e5 CI cleanup (#195)
* Update release.yml

* Update platformio.ini

* Update build-test.yml
2024-01-09 08:59:06 +01:00
atc1441
bd8965174a Merge branch 'master' of https://github.com/jjwbruijn/OpenEPaperLink 2024-01-09 00:10:15 +01:00
atc1441
229962165a Added SubGHz Alpha 2024-01-09 00:10:11 +01:00
jjwbruijn
4dac6ab05c M2 v0026 firmware added 2024-01-08 21:59:51 +01:00
atc1441
f95e957361 Merge branch 'master' of https://github.com/jjwbruijn/OpenEPaperLink 2024-01-08 08:09:50 +01:00
atc1441
b8161f21fa Arduino ino file renaming 2024-01-08 07:40:07 +01:00
Nic Limper
950931b9a6 smaller UI improvements
- got rid of gamma correction during dithering for quality reasons
- smaller UI improvements and textual edits
- tag grouping in the interface is now sticky across sessions
- tag auto update now shows before/after version number
2024-01-08 01:01:06 +01:00
atc1441
af5e917cb3 Arduino port of the ESP32-C6 AP Firmware added (Not PlatformIO) 2024-01-08 00:36:34 +01:00
atc1441
8005ae71fc Create TLSR_HS_35_ALPHA.bin 2024-01-07 20:10:05 +01:00
atc1441
4965c68516 Added Telink TLSR Alpha release 2024-01-07 20:07:59 +01:00
Nic Limper
96e8fe8660 geocoding and other small improvements
- separated content types for 'not configured', 'static image', 'uploaded image' and 'home assistant' (which is all the same internally, but it confused the users to always see 'static image'
- changed channel reported by the AP to the ieee801.15.4 channel instead of the WiFi channel
- added geocoding to the 'location' fields (e.g. weather forecast). Now you can choose an ambiguous location from a dropdown.
- added 'firmware update rejected' wakeup reason
2024-01-07 19:32:56 +01:00
jjwbruijn
fcff10412d added wakeup-reason for failed OTA 2024-01-07 19:23:36 +01:00
Nic Limper
23c3611872 button to restore tagDB file from backup; cleanup 2024-01-07 02:40:55 +01:00
Nic Limper
7cb7eddc22 removed u8g2 library/fonts (+ automatic substitution for compatibilty) 2024-01-07 00:03:51 +01:00
Jonas Niesner
b68cd22eb1 Updated tag OTA (#193) 2024-01-06 21:16:48 +01:00
Nic Limper
b0cfa1b2b4 new week calendar added 2024-01-06 21:09:08 +01:00
Nic Limper
29589bc5b0 content template redesign / textbox / various
- Added Signika-SB.ttf and some small bitmap fonts
- Removed calibrib50/60/80/100/120/150 bitmap fonts, as they can be better rendered using truetype. Fallback is in place to auto translate to Signika-SB.ttf with the right size in case it is still used in a json template
- Renamed confusing tag type names to 'M2 + size' and 'M3 + size'. Because the universal firmware, there is no need to tell every subtile type change apart anymore.
- added `textbox` to json templates (https://github.com/jjwbruijn/OpenEPaperLink/wiki/Json-template#paragraph-text)
- redesign of count days/hours
- redesign of RSS feed
- designed Buienradar for more tag sizes
- on a scheduled or user initiated reboot, 'REBOOTING' is sent to the error channel of the websockets just before the connection is dropped
- phased out "hwtype": [] in content_cards.json (new location is in the tagtype json, which contains a list of valid content types)

In case of problems using this commit: keep in mind the heavy caching of the tagtypes in the browser. You might still unknowingly use the old contents.
2024-01-05 13:59:31 +01:00
Nic Limper
00ce785158 use latest version 6 of ArduinoJson, not 7 for now. 2024-01-04 20:07:15 +01:00
Pablo Gonzalez
9da9ac9395 Make WebSocket connection protocol dependent (#191)
Currently, the connection to WebSockets is hardcoded to the protocol "ws://".

If the server is put behind a proxy server (like Nginx) to support "https", the connection to websockets will fail (at least in Firefox) due to insecure protocol.

This change checks the current protocol and connects to "wss" if loaded via "https", which makes it work when loaded via proxy.
2024-01-04 19:18:14 +01:00
Jonas Niesner
022f72eee7 Add simple tag ota (#190)
and renamed files
2024-01-04 17:30:42 +01:00
Nic Limper
1d03eedfd6 bugfix in WiFi connection setup; + reset wifi settings using gpio0
- in rare cases, an AP didn't connect to a WiFi network due to some tight timing
- bringing GPIO0 to LOW for more than 5 seconds now resets the wifi settings, in case you're stuck with e.g. a wrong static ip configuration
2024-01-03 15:34:09 +01:00
Nic Limper
4f7a226312 last small fixes before release 2024-01-01 13:25:42 +01:00
Nic Limper
43fd751d1e moved language strings to json file
(don't forget to place languages.json in the file partition)
2023-12-31 17:26:17 +01:00
jjwbruijn
ab8cb3955a Fixed M2 0024 issue->0025 2023-12-31 15:07:26 +01:00
Jelmer
2694a0936f added universal M3 flasher jig 2023-12-31 14:52:28 +01:00
Jelmer
547d27e256 Better EEPROM handling (9.7") 2023-12-31 12:37:40 +01:00
Nic Limper
12f91fb293 fixed 9.7" image wrapping 2023-12-31 02:17:26 +01:00
Nic Limper
5973607ad7 firmware version in webinterface (for now, both dec and hex...) 2023-12-30 22:56:04 +01:00
Jonas Niesner
c4fb629ed4 Move content cards to tag types (#188) 2023-12-30 22:54:09 +01:00
Nic Limper
e14ec92d48 optional previewtype and previewlut parameters for /imgupload call
- optional previewtype and previewlut parameters for /imgupload call
- new 35.json for M3 6.0" (no template yet; coming up next)
- updated upload-demo.html
2023-12-30 22:25:04 +01:00
atc1441
b3887b6874 Added content IDs for 3.5" 2023-12-30 17:41:29 +01:00
Nic Limper
424cf2faf6 webinterface changes
- add tag resolution
- weather forecast card: enabled modify lat/lon coordinates
2023-12-30 15:41:22 +01:00
Nic Limper
0621dda3cc autosize QR code 2023-12-30 14:04:25 +01:00
Nic Limper
9f55d72f97 various small fixes
- prevent using html file for tag firmware update
- removed excessive logging
- fallback to .bak on tagDB load error
- scheduled reboot once at night around 4:00
2023-12-30 12:30:07 +01:00
Jelmer
3621d4b6e1 Merge branch 'master' of https://github.com/jjwbruijn/OpenEPaperLink 2023-12-30 11:50:42 +01:00
Jelmer
209f0f218a fixed M3 7.5 and 6.0 support in universal M3 fw 2023-12-30 11:50:30 +01:00
Nic Limper
9bb857329e re-rendered bitmap fonts for added languages 2023-12-30 00:38:45 +01:00
Miloš Krumpolc
b0d1e1da2c Add 4 new language: Czech, Slovak, Polish, Spanish (#162) 2023-12-29 23:57:55 +01:00
Nic Limper
d75a1d137f Fix automatic build for NRF 2023-12-29 23:42:22 +01:00
Vstudio LAB
19fc8c6594 Screen rotation in json (#173) 2023-12-29 23:35:47 +01:00
Nic Limper
bcd2a4618d bugfix deleting unknown tag / WIP locking
- bugfix: unable to delete unknown tag by right clicking
- work in progress: lock tag inventory, by rejecting new tags
2023-12-29 23:19:16 +01:00
Jelmer
a962828c4f Universal M3 binary 2023-12-29 19:32:40 +01:00
atc1441
45530085f9 Added S3_C6_NanoAP Gerbers 2023-12-28 09:15:57 +01:00
atc1441
ae4a5d5994 Added S3 C6 Nano AP 2023-12-27 23:09:06 +01:00
Jonas Niesner
bb11458167 M3 led control (#186)
Fixes led control for M3 based displays
2023-12-26 13:20:08 +01:00
atc1441
1f02a8288d Added 9.7" M3 Beta, still many bugs^^ 2023-12-23 13:53:43 +01:00
Jelmer
8065479557 Added 4.3" M3 definition 2023-12-22 00:30:37 +01:00
atc1441
ab65479917 Better Main Case for YellowAP 2023-12-20 18:38:54 +01:00
Jelmer
36596542c4 M3: Bugfix for buttons that would trigger multiple times on HA 2023-12-15 22:32:52 +01:00
Jelmer
eb66e4b7ec M3 v0024 - Slideshows and custom screens 2023-12-13 19:04:02 +01:00
Jelmer
8d15bb72fd Merge pull request #174 from VstudioLAB/M3_7.5BWR_support
Added M3 7.5" BWR EL075H3BRA tag to the AP
2023-12-13 15:10:29 +01:00
atc1441
4c43d76e09 Added YellowAP Case 2023-12-13 11:19:51 +01:00
Vstudio LAB
a1664daba4 Merge branch 'jjwbruijn:master' into M3_7.5BWR_support 2023-12-11 11:55:52 +01:00
jjwbruijn
60f9454bb2 M2 tag firmware v0024 2023-12-09 01:07:27 +01:00
VstudioLAB
db56860d26 Added M3 7.5" BWR EL075H3BRA tag to the AP 2023-12-09 00:54:17 +01:00
jjwbruijn
bb73069097 2.9 Slideshow builder 2023-12-09 00:31:03 +01:00
jjwbruijn
14e4d17b31 code cleanup, settings in eeprom, serial eeprom loader 2023-12-04 22:01:21 +01:00
Jelmer
a941cad902 Merge branch 'VstudioLAB-master' 2023-12-04 21:35:23 +01:00
Jelmer
80fc7997b7 remove content_cards.json.gz 2023-12-04 21:32:55 +01:00
Jelmer
ae0b44a424 Merge pull request #154 from skiphansen/master
Added scripts to build/use a local copy of sdcc version 4.2.0.
2023-12-04 19:56:35 +01:00
atc1441
372cb39c33 HS 3.5" BWY, BWR and BW Added 2023-12-02 13:43:52 +01:00
VstudioLAB
66c7ad6140 Added ST‐GM29XXF 2.9" Support
added ST‐GM29XXF 2.9" support
2023-11-29 00:26:15 +01:00
Skip Hansen
e95a1acae8 Merge branch 'jjwbruijn:master' into master 2023-11-26 18:41:35 -08:00
VstudioLAB
9410c47875 Added French
Added french langage as an option for tag content
2023-11-22 00:25:17 +01:00
Jelmer
220b4ae3e8 Restructured epd driver interface, support for UC-based tags 2023-11-12 10:24:36 +01:00
Skip Hansen
c64190709a Fix typos. 2023-11-04 09:48:40 -07:00
Skip Hansen
c446452b69 Added support for sdcc 4.0.7 used by https://dmitry.gr projects.
Make path's absolute, renamed scripts, added .gitignore
2023-11-04 08:20:51 -07:00
Skip Hansen
a24bccd1af Added scripts to build/use a local copy of sdcc version 4.2.0. 2023-11-03 16:21:02 -07:00
Nic Limper
246b234b22 small fix in follow redirects, and update of gzipped wwwroot 2023-10-29 22:07:58 +01:00
Milo Cesar
22c5bda4c5 Select currently configured files in tag editor (#152) 2023-10-29 22:04:18 +01:00
Sven-Ove Bjerkan
13f8dea68b Add support for Norwegian content (#149)
* Add support for Norwegian content
2023-10-23 19:06:00 +02:00
atc1441
696cb448fe Added Sub GHz YellowAP Gerber 2023-10-23 10:58:08 +02:00
Nic Limper
a4e19b19ab bugfixes: truetype rendering / fast luts / various
- no tag timeouts when tag is put to sleep
- small timing tweaks
- truetype render bugfix
- fix in fast lut setting
2023-10-22 13:20:54 +02:00
Sven-Ove Bjerkan
9d579e9515 Fix: Weather forecast showing yesterday as day 1 in some time zones (#146) (#148) 2023-10-19 16:27:15 +02:00
jjwbruijn
7faeb2eb54 slideshow builder for eeprom 2023-10-14 23:08:36 +02:00
Jelmer
5318f1fdc4 eeprom support OEPL-Flasher.py 2023-10-14 23:00:35 +02:00
Jelmer
4bf61c1dd0 added eeprom support for tag flasher 2023-10-14 22:59:11 +02:00
atc1441
c4beaa51c8 Model name typo 2023-10-13 11:07:31 +02:00
atc1441
26598fc408 Added NanoC6 Infos and Board definition 2023-10-12 17:20:42 +02:00
Nic Limper
06f3a5d524 small cosmetic changes 2023-10-12 17:06:57 +02:00
atc1441
0bed91ecc2 Update OpenEPaperLink_Yellow_AP_ESP32_C6_Gerber.zip 2023-10-12 13:26:40 +02:00
B0rax
1e76d690ec Add circle and rounded box to json template (#143) 2023-10-08 15:47:30 +02:00
Nic Limper
9c06cdf2d7 small fix for fw compile test 2023-10-08 15:44:02 +02:00
Nic Limper
7a0ca319e7 timing fix in getting version info for ota 2023-10-07 22:21:54 +02:00
Nic Limper
c095f4c881 created Python port for packagebinaries.php to create Tag_FW_Pack.bin 2023-10-06 22:30:09 +02:00
Nic Limper
c586c9f541 added negative sign to fonts; small improvements 2023-10-06 13:14:22 +02:00
Moritz Wirger
6c4f8ef35b Add ap_date and ap_time vars (#142)
* Add ap_date and ap_time vars
* Add convenience creation function for Timer
* Optimize timer
* Document timer
2023-10-04 21:43:28 +02:00
Nic Limper
c403c06b09 fix AP not responding + add more logs to investigate crashes 2023-10-04 15:33:22 +02:00
Nic Limper
ddd043f44f update esp32-C6 binaries 2023-10-02 15:09:29 +02:00
Nic Limper
81cc5ccc9a tiny oops 2023-10-02 13:51:11 +02:00
Nic Limper
be325b0e62 forgot to add gzipped files with previous commit 2023-10-02 13:45:03 +02:00
Nic Limper
3621c84cc4 various small fixes
- neopixel patterns optimized. The 'breathing' led state now is green colored if everything is okay, and blue if there are one or more tags timed out.
- time zone is now set before wifi connect to show correct time zone in the logs during startup
- concurrent image upload POST is now blocked. If an upload is in progress while you do a second http POST, http status 409 Conflict is returned.
- small synchronisation bug fix in web interface on loading tag type
- dialog window close bugfix in painter
- image upload is now logged in /log.txt
2023-10-02 13:43:53 +02:00
Nic Limper
ed82795e5f tweak timings 2023-10-02 11:54:36 +02:00
Marcel
5b9f8b324e New hardware profile: PoE AP (#141)
* New hardware profile: PoE AP

- added harware profiles for C6 firmware in menuconfig
- added free PSRAM stat in webinterface

* fix(fsfree): fixed var type of freesize of FS
2023-09-29 02:46:11 +02:00
Nic Limper
db80d23b52 several small improvements
- neopixel idle color now represents AP status
- option to invert colors (advanced options at tag card)
- filename dropdown in tag card when a filename is expected
- redrawing pending instead of raw, if previews are off and tag reboots
- tft brightness setting independent from neopixel brightness
2023-09-29 00:11:44 +02:00
jjwbruijn
125922f8e7 M2 2.2 - RFW for added RF Wake 2023-09-28 17:29:00 +02:00
Nic Limper
aa484575b8 update update screen to new design; ability to choose repo source for OTA 2023-09-28 11:40:29 +02:00
jjwbruijn
fa97daef3c M2 FW 2.2 - Preload and buttons 2023-09-28 01:03:29 +02:00
Jonas Niesner
0c591660bc Fix wrong domain
fixes #140
2023-09-27 20:33:54 +02:00
Jelmer
c8fb0ca4de ESP: Added feature to preload images 2023-09-27 14:04:48 +02:00
jjwbruijn
87ce823776 added new image type arguments for M3 2023-09-27 12:24:08 +02:00
Jonas Niesner
7fe4a1e6ad Rename bin files to the new standard (#139)
* Update release.yml
* Update genfilelist.py
* Rename files
* Create .gitignore
2023-09-27 08:33:32 +02:00
Nic Limper
29b8c9bc21 small fix in data parser 2023-09-26 22:53:59 +02:00
Moritz Wirger
2e44889b19 Add custom tag data parser (#132)
* Add formatString convenience function

* Use String& for wsLog, wsErr and wsSerial

* Add tag data parser and parse tag data

* Make logLine use String&

* Fix issue with formatString

* Reuse payloadLength in processTagReturnData

* Fix parsing of unsigned/signed inetegers and cleanup

* Use c++17 standard

* Cleanup logging
2023-09-26 22:51:57 +02:00
Nic Limper
4d08454fff Update README.md 2023-09-26 20:30:03 +02:00
Nic Limper
f131b5ce84 Update README.md 2023-09-26 20:29:23 +02:00
Nic Limper
33ba6a7aa7 updated web interface design 2023-09-26 10:27:57 +02:00
Nic Limper
75c6a6c0f9 previews now also show for tags connected to external AP; removed extra debug msg 2023-09-24 21:34:30 +02:00
Jonas Niesner
f7e2025487 M3 display led code fixes 2023-09-23 22:47:56 +02:00
Nic Limper
a91dd5c2a2 fix hangs on esp32-s2; refactor task runner; moved some json objects from the stack to the heap
temporary, there's some extra debug info on the terminal. Will be removed again in the near future.
2023-09-23 18:40:28 +02:00
Nic Limper
0ba287f734 mutex on file write; prevent other AP from stealing tag content; bigger heap for timeTask 2023-09-22 19:42:36 +02:00
Nic Limper
ad52c64b94 typo 2023-09-22 11:13:48 +02:00
Nic Limper
8c06bb04f3 typo 2023-09-22 11:13:15 +02:00
Nic Limper
07807afe08 add 4.2" mini stands design 2023-09-22 11:11:36 +02:00
onkelfunny
eb173e355f avoid loading *.raw files when preview is disabled (#136)
by @onkelfunny
2023-09-21 17:03:21 +02:00
onkelfunny
b792b71608 default configurable tag content (#134)
by @onkelfunny
2023-09-21 13:51:03 +02:00
Nic Limper
b0715fae97 cosmetic 2023-09-20 10:24:40 +02:00
Nic Limper
6e326009c3 finetuning C6 flashing, automatic retry on failing download 2023-09-20 10:15:55 +02:00
Jelmer
0a43c601fe M3 FW 0.1.6-beta3 2023-09-20 00:51:31 +02:00
Nic Limper
f92448992e remove debug info 2023-09-20 00:26:36 +02:00
Nic Limper
2d84583797 update button: download latest esp32-c6 firmware + flash from esp32-s3 2023-09-19 20:24:57 +02:00
atc1441
fac67eac7e Fixed Pull-up for C6 in YellowAP PCB for self flashing the C6 from ESP32-S3 2023-09-18 21:51:28 +02:00
Nic Limper
6cee005e92 esp32-c6 binaries for flashing by esp32-s3 2023-09-18 20:11:56 +02:00
Nic Limper
e68e549eaf bugfix, prevent duplicate dhcp hostnames 2023-09-15 09:50:56 +02:00
Jelmer
3eb4b94b06 Merge branch 'master' of https://github.com/jjwbruijn/OpenEPaperLink 2023-09-14 12:38:03 +02:00
Jelmer
9951dc5ce5 added and updated M3 jigs 2023-09-14 12:37:47 +02:00
Nic Limper
c53f33f8ec bugfix calculating expected next checkin 2023-09-11 20:40:05 +02:00
Nic Limper
abbc636948 custom partition table (with 3MB littlefs) for C6 2023-09-11 14:01:42 +02:00
Nic Limper
7e32a1a197 remove unused preview files from /current folder at startup 2023-09-11 13:50:37 +02:00
Nic Limper
95d0cf6804 esp-serial-flasher library (altered from the original) 2023-09-11 00:57:19 +02:00
Nic Limper
a92e0eb5e6 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.
2023-09-11 00:48:08 +02:00
Jelmer
c6c3c4f9f6 Update README.md 2023-09-10 22:45:48 +02:00
Nic Limper
2e64ed2f16 set dhcp hostname 2023-09-09 19:01:18 +02:00
Nic Limper
2780b7ce36 only send fast lut to capable tags 2023-09-08 23:58:52 +02:00
Nic Limper
9af2bd2a92 tagReturnData for C6 AP. It compiles, but other than that, untested 2023-09-08 20:27:18 +02:00
Nic Limper
92ff939adc bugfix gethwtype 2023-09-08 17:23:19 +02:00
Nic Limper
83ff8564a7 'flash led' command in context menu of webinterface 2023-09-08 17:07:48 +02:00
Jelmer
dc33ff5854 ESP32 return-data support 2023-09-08 11:19:33 +02:00
jjwbruijn
4176252b51 ZBS Tag Return-data support 2023-09-08 11:16:16 +02:00
Moritz Wirger
36c3c45510 Json url file template (#128)
json template url + file implementation. 
The file contains the json template, and can contain variables that will be extracted from the json in the url. The url is fetched at regular intervals.
2023-09-08 11:06:15 +02:00
jjwbruijn
abb9b195d3 updated oepl-wide definitions 2023-09-08 00:10:26 +02:00
Jonas Niesner
a3e30c549e Multiple 2.2" and build script improvements + housekeeping (#127)
* Update build-test.yml

* Update build-test.yml

* Update release.yml

* Create hextobin.py

* Update preparefiles.py

* Delete ARM_Tag_FW/nrf52811_Platformio_2.9 directory

* Delete ARM_Tag_FW/nrf52811_Platformio_7.4 directory

* Update release.yml

* Delete binaries/Tag_FW_M3_7.5.hex

* Delete binaries/Tag_FW_M3_2.9.hex

* Fix mac for 2.2"

* Fix bug in the release script and add comment about future plans

* fix 2.2" mac again
2023-09-04 22:26:52 +02:00
Jonas Niesner
02cd65d383 Add 2.2" to content cards 2023-09-04 19:44:52 +02:00
Jelmer
bc394e0d26 Added MD5 verification for nRF-based tags 2023-09-04 15:22:22 +02:00
Jelmer
22d3001996 added 6.0 jig 2023-09-04 12:54:21 +02:00
Jelmer
efb5a3cb55 added OTA for M3 tags 2023-09-04 01:18:33 +02:00
Jonas Niesner
8055de91f3 Merge pull request #125 from jonasniesner/master
Add multiple 2.2" M3 tag files
2023-09-03 20:09:56 +02:00
Jonas Niesner
0226f01ddb Add 2.2" tag type 2023-09-03 20:08:38 +02:00
Jonas Niesner
9cfadf1670 Add M3 2.2" to release scripts 2023-09-03 19:34:15 +02:00
Jonas Niesner
a1d06a2d34 Merge branch 'jjwbruijn:master' into master 2023-09-03 19:33:01 +02:00
Jonas Niesner
27665174b7 Merge branch 'master' of github.com:jonasniesner/OpenEPaperLink 2023-09-03 19:32:13 +02:00
Jonas Niesner
c23c3049bf 2.2" M3 config added 2023-09-03 19:31:38 +02:00
atc1441
55fe95903a Added C6 flasher, The S3 can flash the connected ESP32-C6 via UART 2023-09-03 10:47:16 +02:00
Jelmer
ea39ea0fc8 Merge pull request #124 from milo526/master
extend patch_mac script
2023-09-02 22:24:38 +02:00
Milo Cesar
f966bee5af extend patch_mac script 2023-09-02 22:19:46 +02:00
Jonas Niesner
8f9a9e44c2 Merge pull request #6 from jjwbruijn/master
Add NRF firmware building to release scripts
2023-09-02 18:59:30 +02:00
Jonas Niesner
214ddbf4e0 Merge branch 'master' into master 2023-09-02 18:59:17 +02:00
Jonas Niesner
65431e587e Update release.yml 2023-09-02 18:57:55 +02:00
Jonas Niesner
52fd9f1232 Update main.cpp 2023-09-02 18:38:42 +02:00
Jonas Niesner
76345fa794 Update release.yml 2023-09-02 17:59:30 +02:00
Jonas Niesner
12f5add21b Add files via upload 2023-09-02 17:57:12 +02:00
Jonas Niesner
eccd309a61 Add NRF firmware building to release scripts 2023-09-02 16:17:17 +02:00
Jonas Niesner
6a58d0143c Update release.yml 2023-09-02 15:20:46 +02:00
Jonas Niesner
70b4bd197c Update release.yml 2023-09-02 15:18:16 +02:00
jjwbruijn
aad5fe71eb updated beta 7.5" fw 2023-09-02 12:26:40 +02:00
Jelmer
8f7ec46f68 Merge pull request #122 from jonasniesner/master
M3 firmware improvements
2023-09-02 11:46:34 +02:00
Jonas Niesner
733078147d Merge branch 'jjwbruijn:master' into master 2023-09-02 11:40:58 +02:00
Jonas Niesner
ae8bc98619 Merge branch 'master' of github.com:jonasniesner/OpenEPaperLink 2023-09-02 11:38:48 +02:00
Jonas Niesner
bbe903bf90 Led LUT for M3 2023-09-02 11:36:07 +02:00
Nic Limper
73ecdd09b4 tiny bugfixes 2023-09-02 11:17:42 +02:00
Jonas Niesner
2674b733db Merge branch 'jjwbruijn:master' into master 2023-09-01 20:17:06 +02:00
Nic Limper
b919445ecc highspeed communication between S3<>C6 2023-08-31 21:10:36 +02:00
Nic Limper
eba0ea8a89 simple http call to test the led flasher 2023-08-31 20:12:49 +02:00
Nic Limper
15719126b8 render raw preview files within the file editor 2023-08-31 12:19:04 +02:00
Nic Limper
e45693bfe0 new version of 88MZ100 7.4" tag firmware + patch_mac.py for easy mac change
No need for HxD anymore for this firmware. See https://github.com/jjwbruijn/OpenEPaperLink/wiki/88MZ100-Programming-and-interfacing
2023-08-31 02:44:34 +02:00
Nic Limper
ab83cb03cc improvements for yellow ap / esp32-c6
- Wifi connection progress is now visible on the TFT
- passthrough serial logging from the C6 to the S3 terminal for easier debugging
- no checks on force_flash and APtag-firmware version when C6 is used
2023-08-31 02:13:45 +02:00
Nic Limper
714f7fffae clean up
- removed the custom printf function (inherited from the zbs code, but easier to just use the native printf)
- led flash timer
- proper HW_TYPE set, now reported as 0xC6
2023-08-30 22:20:08 +02:00
Nic Limper
9929d1646f small fixes
- fixed context menu position
- fixed free space sometimes displays 0
- added 12 byte payload to sendCommand
2023-08-29 22:11:05 +02:00
Jonas Niesner
b423ed4163 Update build-test.yml 2023-08-29 18:45:22 +02:00
Jonas Niesner
71d8aba77a NFC + button wake and LED 2023-08-28 15:41:19 +02:00
Jonas Niesner
81f5345237 Improved M3 firmware try 6 2023-08-28 13:54:59 +02:00
Jonas Niesner
bfe3561553 Improved M3 firmware try 5 2023-08-28 13:04:11 +02:00
Jonas Niesner
66a6a204c1 Improved M3 firmware try 2 2023-08-28 12:49:29 +02:00
Jonas Niesner
a6af0deaab Improved M3 firmware 2023-08-28 12:43:40 +02:00
Nic Limper
c9cc33f3d6 Update README.md 2023-08-27 22:34:40 +02:00
Jelmer
57c9962a67 fixed an especially dumb mistake in the tag flashr 2023-08-26 22:32:29 +02:00
Jelmer
c1e53e7c4f Merge branch 'master' of https://github.com/jjwbruijn/OpenEPaperLink 2023-08-26 22:21:10 +02:00
Jelmer
505e3d38af improved nRF flashing 2023-08-26 22:21:03 +02:00
Jelmer
00432bd9b5 Merge pull request #118 from kquinsland/bug/c6-include-path-fix
Make path to `soc/lp_uart_reg.{c,h}` consistent
2023-08-26 21:34:30 +02:00
karl
3a1c34f3a6 Make path to soc/lp_uart_reg.{c,h} consistent
Using _just_ the `/` character makes the paths "universal".

On *nix, `/` is the path separator and windows has support for `/` internally.
2023-08-26 12:32:24 -07:00
Jelmer
51087fa400 Merge pull request #116 from kquinsland/feat/add-m3-2.2-jig
Add my 2.2 inch pogo jig
2023-08-26 21:19:59 +02:00
Karl Quinsalnd
073972875a Add my 2.2 inch pogo jig 2023-08-26 12:10:05 -07:00
Jelmer
de38662a2a New clamp design 2.9 2023-08-26 20:48:26 +02:00
Jelmer
69bf4fe036 M3-2.2 Jig 2023-08-26 13:09:11 +02:00
Jelmer
fcedb8256a Merge branch 'master' of https://github.com/jjwbruijn/OpenEPaperLink 2023-08-24 22:57:06 +02:00
Jelmer
6252f81888 Added some M2 7.5 stuff 2023-08-24 22:57:02 +02:00
Jelmer
3223d7c861 Another update on the readme for tag flasher 2023-08-24 22:20:43 +02:00
Jelmer
99a36c4eb8 Updated Tag-Flasher README.md 2023-08-24 22:10:35 +02:00
Jelmer
3c77e375d9 Added the tag-flasher 2023-08-24 21:37:32 +02:00
Jelmer
891b7a83be Tag_Flasher README.md 2023-08-24 21:16:30 +02:00
Nic Limper
09f6f7b4b1 small fix in ota.js 2023-08-24 12:59:31 +02:00
Jelmer
ec7bac1f34 Moved flasher script, added support for 88mz100 2023-08-23 12:52:58 +02:00
Nic Limper
0df91096c2 little oops 2023-08-23 01:35:48 +02:00
Nic Limper
79efe473bf various small fixes
- clean up webproxy getExtUrl
- bugfix init multicast on wifi reconnect
- add ip address of remote AP that's taken over a tag
- renamed button 'edit contentFS' to 'file system'
2023-08-23 01:29:52 +02:00
Nic Limper
034521682c get rid of using eps32 as web proxy 2023-08-22 17:05:23 +02:00
Nic Limper
9ad847eb53 Update content_cards.json.gz 2023-08-22 13:15:03 +02:00
Nic Limper
f268c48717 add wifi events to log.txt 2023-08-22 13:06:42 +02:00
Nic Limper
a0ebf0d255 weather values in fahrenheit/mph 2023-08-21 01:05:43 +02:00
Nic Limper
6fcfe02b28 updated .gz-files for www folder 2023-08-20 20:18:58 +02:00
Nic Limper
2edbf27033 various fixes / sleep at night / resend image at tag boot
- apconfig: configure night time, where the system is not updating tags, and the tags are sleeping
- fixed bug calculating expected checkin
- throttle down apinfo update to once per minute
- fixed too many concurrent requests getting tagtypes
- resend current image when a tag reboots and the content type is 'static image' (all other content types were already regenerating the content)
- fixed timing of main loop
2023-08-20 20:16:34 +02:00
Nic Limper
46fb23b70f drop json files to a tagcard + small fixes 2023-08-19 20:31:25 +02:00
Moritz Wirger
fce6c16153 Optimize tagDB and reduce RAM usage (#113)
* Reduce code size by removing nullptr assignments

* Optimize tagDB for loops

* More tagDB optimizations

* Remove static from language arrays reducing RAM by 5128b

- Reduces Flash by 13060b

* Add missing extern in tag_db.h

* Fix deprecation warning of sntp.h

* Remove static from contentmanager, reduces RAM by 184b

* Use string reference in prepareDataAvail

- Remove some unneeded buffers
- Remove some gotos
2023-08-17 10:06:21 +02:00
atc1441
a31e1453d0 Now resending the Pending data on Reset of the Connected AP 2023-08-15 13:49:09 +02:00
Nic Limper
d17502cb63 contextmenu: right-click on a tagcard 2023-08-15 12:42:59 +02:00
atc1441
828679b6f3 Update README.md 2023-08-14 23:43:23 +02:00
atc1441
bff6794303 Added Yellow AP Gerber files 2023-08-14 21:40:34 +02:00
atc1441
2f86ea54d0 Precompiled ESP32-C6 AP 2023-08-14 21:28:03 +02:00
atc1441
80e0d9e5dd Added ESP32-C6 AP Release :) 2023-08-14 21:25:38 +02:00
atc1441
4d8cfeae63 Added nRF52811 AP Port 2023-08-14 12:12:44 +02:00
atc1441
3271f399c9 Auto template for AP Display disabled as currently to many refreshes break and reset the AP 2023-08-14 12:02:32 +02:00
atc1441
862c08c00b Set AP Info screen as default template on boot again to know IP of AP 2023-08-13 22:43:59 +02:00
Nic Limper
77cbf92281 bugfix getlocation 2023-08-13 01:48:32 +02:00
Moritz Wirger
c4022e45f9 Fix weather icons exception (#114) 2023-08-13 01:00:47 +02:00
atc1441
a13c220565 Fixed countdown via negative count value 2023-08-12 21:43:37 +02:00
Nic Limper
3989ecc3a3 bugfix date display 2023-08-12 21:17:08 +02:00
Nic Limper
cb0f029900 Update build-test.yml
don't build all small variations. Just the minor platforms, the rest will work.
2023-08-12 21:11:33 +02:00
Nic Limper
443714e9dc build fixes 2023-08-12 20:58:25 +02:00
Nic Limper
f3f163fa00 Revert "Ziped web files"
This reverts commit 8848cfc0f8.
2023-08-12 20:19:01 +02:00
Bot
8848cfc0f8 Ziped web files 2023-08-12 17:16:45 +00:00
Moritz Wirger
6c91c78aa1 Refactor contentmanager (#112)
* Start contentmanager cleanup

- Make destination constant
- Remove unneeded asignments
- Improve loops
- Move printHeap function into util

* Refactor contentmanager::drawNew

* Optimize contentManager::replaceVariables

* Fix missing const in prepareCancelPending

* Refactor drawDate

* Refactor drawWeather, drawForecast & getLocation

- Generalize http get json function

* Add util function for printing largest free block

* Reuse weather icons for both drawWeather & drawForecast

* Make httpGetJson timeout const

* Reafctor more functions

* Add few more const

* Fix spelling mistake

* Add util for debugging streams

- Add util for checking if strings are empty or contain null
- Fix file and string checks

* Remove leftover debug print
2023-08-12 16:57:42 +02:00
Nic Limper
98baa020ff bugfix ap info screen 2023-08-12 16:17:06 +02:00
Nic Limper
56e1e9e6b6 small fixes
- build in led on esp32-s2 active low
- floyd steinberg dithering improved
- add tokyo time zone
2023-08-12 13:18:22 +02:00
jjwbruijn
2817aa7e38 Added 7.5 OTA img 2023-08-12 09:17:55 +02:00
jjwbruijn
2292aeaf7e another beta of the 88mz100 7.5 fw 2023-08-12 02:26:33 +02:00
Nic Limper
3472b5d4b6 drop image files to upload 2023-08-12 01:11:25 +02:00
Moritz Wirger
19f6a093d3 Cleanup ota files (#111)
- Constify everything
- Remove duplicate code
- Fix warnings in js
- Reduces bin size from 1283453 to 1283273 bytes
2023-08-12 00:37:26 +02:00
Nic Limper
d6734a7f79 bugfix database backup button 2023-08-11 22:42:02 +02:00
Nic Limper
da487fbc5f gzipped files in /www are now stored deterministic, without timestamp 2023-08-11 19:46:22 +02:00
Moritz Wirger
3b7fd7d1f6 Fix a few js warnings in main.js (#108)
* Fix indentation of content_cards json
* Fix multiple warnings in main.js
2023-08-11 19:39:20 +02:00
Nic Limper
f4273630ee rework of apinfo screen + variables in jsontemplate
- AP info screen content card. Can run on any tag.
- now, you can use {variables} in the 'text' entries in a json template. You can set variables via a http call. If you update a variable, all tags with a json template containing that variable get updated.
- font name in json template is more flexible. You can just use 'filename.ttf' or 'filename.vlw'. A full path is still possible.
- colors in the json template can now be set using #rrggbb color values, and using 'black', 'white' or 'red'.
- added direct output for the TFT display for the yellow esp32-s3. No file writes needed.
- added POST variable 'ttl' to json template upload and image upload, to set the next checkin time
- added /variables-demo.html to demonstrate the variables.
- json templates received from jsonupload are now saved in /current, and reused.
- known issue: 'backup db' button doesn't work due to some browser policy change. Fixing.
thanks to @steinwedel for the inspiration on the variables and some other fixes.
2023-08-11 18:46:46 +02:00
Jelmer
0cbb9e770e esp32 deep sleep support 2023-08-10 23:22:24 +02:00
jjwbruijn
9dfb37b376 Merge branch 'master' of github.com:jjwbruijn/OpenEPaperLink 2023-08-10 22:38:07 +02:00
jjwbruijn
e457475ea7 zbs243 tag FW 2.0 - added deepsleep 2023-08-10 22:26:50 +02:00
Jonas Niesner
806b2dc9e0 Merge pull request #107 from enwi/symlinks
Add batch for generating symlinks on windows
2023-08-10 22:18:48 +02:00
Jonas Niesner
2b7fc93043 Update release.yml 2023-08-10 22:16:27 +02:00
Moritz Wirger
6a711c99eb Add batch for generating symlinks 2023-08-10 21:49:55 +02:00
Nic Limper
ffd0acff72 tft driver for yellow board 2023-08-09 23:40:39 +02:00
Jelmer
a9c9812525 Merge pull request #104 from AndreKR/3dp-shelf-holder
Add 3D-printed shelf holder
2023-08-09 22:44:12 +02:00
André Hänsel
03ce036083 Accessories: Image of the shelf holder 2023-08-09 22:39:28 +02:00
André Hänsel
a98ad537ea Accessories: Source file for the shelf holder 2023-08-09 22:39:19 +02:00
André Hänsel
2726b4d2fe Accessories: Add a shelf holder
This adds a shelf holder for shelves with a thickness of 2 cm.
2023-08-09 22:38:03 +02:00
Jonas Niesner
fd5adb40f8 Typo fix 2023-08-09 21:32:45 +02:00
Jonas Niesner
89346b5d77 Update and rename esp32-build-test.yml to build-test.yml 2023-08-09 18:03:29 +02:00
Nic Limper
7ac57577df prelimary tagtype def for EL029H3WRA (M3 2.9")
I will finetune the content positions later
2023-08-08 17:31:30 +02:00
Nic Limper
09f7466f6f new flexible tagtype definition
- new: tagtypes are be defined via json in /tagtypes instead of hardcoded
- content template is moved to the tagtype definition
- optimalisation of spr2buffer (also uses psram now, if available)
- bugfixes in spiffseditor
- size fix in painter screen for large screens
2023-08-08 16:31:20 +02:00
atc1441
55e50b1920 Merge branch 'master' of https://github.com/jjwbruijn/OpenEPaperLink 2023-08-08 16:00:25 +02:00
atc1441
7cb5e13a7f Added compiled version of 7.4" 2023-08-08 16:00:05 +02:00
Jonas Niesner
6f08af2c67 Create 32MB_partition table.csv 2023-08-07 17:30:07 +02:00
Jonas Niesner
e185ddd99b Add OutdoorAP 2023-08-07 16:59:47 +02:00
atc1441
3079101c48 Tag DB Size was only 8bit now 32bit, need to be fixed in further UDP usage later as well 2023-08-07 11:53:28 +02:00
atc1441
0b66a23ce4 Added Yellow AP basic parts, for now using Arduino GFX for simplicity 2023-08-06 23:35:30 +02:00
Nic Limper
41c7cb843f cleanup non-.gz files in www folder 2023-08-05 22:51:38 +02:00
Nic Limper
c43e71288d delete files carefully to not brick the thing if update fails 2023-08-05 22:11:45 +02:00
Nic Limper
66cc62339f fix aligning U8G2 fonts / improv protocol fix 2023-08-05 22:05:33 +02:00
atc1441
84bfb18261 Update cc2531_OEPL.c 2023-08-05 15:21:13 +02:00
Nic Limper
ab3cef8dda Update readme.md 2023-08-04 11:30:01 +02:00
Nic Limper
c831f07b6e group/sort/filter tag list 2023-08-03 23:15:05 +02:00
atc1441
ba39f60e69 Added Sonoff ZB Bridge-P as Board 2023-08-03 23:09:21 +02:00
atc1441
f409f493ec Added CC2531 EOPL Port plus the modded python station by foorschtbar 2023-08-03 18:53:30 +02:00
Nic Limper
df783c6f8f ability to mirror tags
mirrored tags don't take file system space (f they are local to the AP), and don't take time to generate. They share their buffer with the source tag.
2023-08-03 12:37:29 +02:00
Nic Limper
f0e4d25d36 use barcode scanner to select a tag 2023-08-02 20:04:55 +02:00
Nic Limper
b4bf060a51 json template is now streaming (both file and url)
'unlimited' size
2023-07-31 22:35:00 +02:00
Nic Limper
e3407468ea weather icons via truetype
Don't forget to update the file system: added .ttf font, deleted some .vlw fonts.
Saves about 144kB.
2023-07-31 20:25:31 +02:00
Nic Limper
8daff632ba truetype: more floats -> better rendering 2023-07-31 20:22:50 +02:00
Nic Limper
21a52e9b17 truetype fixes
- fixed curves using intermediate points
- now uses ascender to find baseline
- now uses unitsPerEm for font size calculations
rendering is not perfect yet, probably mainly due to rounding issues
2023-07-31 19:02:05 +02:00
Nic Limper
f9b4d163bc cleanup and gzip web files
- clean up unnecessary files
- fix ota update, maybe preventing timeouts
- new 'wwwroot' folder for the web source files, and python script to gzip the files to the /data/www folder
- run gzip_wwwfiles.py to compress the files in wwwroot into /data/www
2023-07-29 20:47:12 +02:00
Nic Limper
a78f2e3af5 added truetype fonts 2023-07-29 14:47:01 +02:00
Nic Limper
6b6eda401f notification on webpage on filesystem full 2023-07-29 11:14:52 +02:00
Nic Limper
26af93dd67 bugfixes
- replaced symlink to firmware pack binary by real file
- bugfix using jsontemplate with google apps script
2023-07-29 10:34:56 +02:00
Nic Limper
3ccf0f931d small bugfixes
- don't display '01-01' in google calendar when start=0
- bigger buffer for json template
- hold generating new content if free space in file system is too low
- tiny bug on failing to color lines red in google calendar for current appointments
2023-07-27 17:40:18 +02:00
Nic Limper
9300301dcb small bugfixes
- small layout fix current weather on 4.2"
- qr code content enabled again
- turned off temperature on esp32
- http 409 on http POST during OTA
- finetuning buitenradar scale and refresh time
- follow redirects on jsontemplate http call
2023-07-26 21:50:58 +02:00
atc1441
22cf435db7 Added CC1352 / CC2652 AP Firmware Code 2023-07-26 21:00:40 +02:00
atc1441
475c40e7e6 Added CC1352 CC2652 Board 2023-07-26 17:54:22 +02:00
Jelmer
768d278ef8 added M2 generation tags to types 2023-07-24 13:23:41 +02:00
Jelmer
30bb5ade9e started adding HAL, should probably delete 'core' 2023-07-24 01:02:42 +02:00
Jelmer
ad44203f29 New M3 tag types 2023-07-23 15:02:55 +02:00
Jelmer
b836d30395 Merge pull request #90 from jjwbruijn/New_Flasher
New flasher
2023-07-23 12:12:53 +02:00
Jelmer
4bcc825f69 Update tag_types.h
Added Newton M3 tag types
2023-07-23 12:12:09 +02:00
Jelmer
666b79e14d No longer compatible with the AP/Flasher board
Please use the flasher script in the AP/Flasher-directory
2023-07-23 12:01:13 +02:00
Jelmer
0f9ea7ee26 fixed flasher python script 2023-07-22 08:44:01 +02:00
Jelmer
d53c89c672 Merge pull request #88 from slimline33/master
.stl files for 3D printer for the SoluM Tags
2023-07-22 00:15:04 +02:00
Jelmer
9ce9abd59e new flasher, support for nRF 2023-07-22 00:02:33 +02:00
Bimmi
b389feb30e Delete 4-2_Solum_Stand_20-degree.3MF 2023-07-21 22:15:42 +02:00
Bimmi
3bb8152512 Update readme.md 2023-07-21 22:14:14 +02:00
Bimmi
fbe5e54a71 Add files via upload 2023-07-21 21:51:52 +02:00
Bimmi
20ae9280f6 Merge branch 'jjwbruijn:master' into master 2023-07-21 21:50:55 +02:00
seeers
7f92e34556 Button for WiFi config on index.html (#89)
added WiFi config button  on 'AP config' page
2023-07-20 21:05:47 +02:00
Bimmi
5fefaf5490 3D Printed JIG for resin
just for resin printers like anycubic photon
2023-07-20 18:17:42 +02:00
Bimmi
551e326f1d Update readme.md 2023-07-20 18:06:27 +02:00
Bimmi
c3f1cf683e Update readme.md 2023-07-20 17:59:37 +02:00
Bimmi
fdebe540a9 Delete SoluM_2-9_Powerstrip.stl 2023-07-20 17:58:23 +02:00
Bimmi
e583a52b95 Delete SoluM_1-54_Powerstrip.stl 2023-07-20 17:58:17 +02:00
Bimmi
2791532e69 Delete SoluM-2_9_EPD-Holder.stl 2023-07-20 17:58:08 +02:00
Bimmi
9cc6801ce2 Delete SoluM-1_54_EPD-Holder.stl 2023-07-20 17:58:00 +02:00
Bimmi
3fc7b43084 Create readme.md 2023-07-20 17:57:34 +02:00
Bimmi
24d08e52ba Add files via upload 2023-07-20 17:57:03 +02:00
atc1441
6ee27e9522 88MZ100 OTA update added, continous block download added 2023-07-20 15:21:21 +02:00
atc1441
3cabb4e3b9 Merge branch 'master' of https://github.com/jjwbruijn/OpenEPaperLink 2023-07-20 02:27:05 +02:00
atc1441
cf8d589add Added 88MZ100 Beta for 640x384 7.4" Display 2023-07-20 02:26:52 +02:00
Nic Limper
4eb89e9596 added improv protocol for wifi provisioning 2023-07-19 17:27:00 +02:00
atc1441
5ba982cb47 Unconfigured Wifi text added to AP image 2023-07-19 16:16:39 +02:00
Nic Limper
f611f0cd80 typo 2023-07-19 15:13:20 +02:00
Nic Limper
6db2f7f9bc replacing wifimanager
This one saves a lot of flash space.
Now, wifimanager is replaced with our own method for managing the wifi connections.
Also, the whole thing will run now even if there is no wifi. If wifi disappears, it automatically tries to reconnect in the background every few minutes.
Wifi settings now available at all times at /setup
If it cannot connect, an access point 'OpenEPaperLink' is created where you can set the wifi credentials (http://192.168.4.1/setup).
2023-07-19 15:00:52 +02:00
atc1441
d6529cfdb3 Added 7.4" 800x480 nRF52811 BETA fw 2023-07-18 15:53:59 +02:00
atc1441
ecdadf8c47 Added Display Access Point Infos on Boot on AP Display 2023-07-17 12:43:31 +02:00
Jelmer
53a3a8de29 uploaded correct files >_< 2023-07-16 01:48:10 +02:00
Jelmer
72ee6d26a7 whoops 2023-07-16 01:43:29 +02:00
Jelmer
1844aa18e6 added M3 Newton 2.9 mini jig 2023-07-16 01:40:44 +02:00
atc1441
f4e7ddb26d Added nRF52811 Firmware working beta 2023-07-14 22:35:55 +02:00
Nic Limper
95711647a3 json template push, and some clean up 2023-07-12 01:42:33 +02:00
Nic Limper
5f48acc6f2 json template 2023-07-11 23:24:05 +02:00
Nic Limper
128fcb0aee fixed sntp blocking on no internet connection 2023-07-11 20:39:08 +02:00
Nic Limper
b178994bd6 apconfig option to turn off preview images
- option to turn preview images off in apconfig
- better browser cache of preview images
- bit of memory optimization on the contentmanager
2023-07-11 13:58:03 +02:00
Nic Limper
9ef2737bc3 fixes issue #80 on painter 2023-07-10 20:33:50 +02:00
Jelmer
dd14fd2074 Delete fw_dumps directory 2023-07-09 22:50:29 +02:00
Nic Limper
112a467cff added wifi power and time zone to APconfig
- added wifi transmit power option
- added time zone config option
- small fixes
2023-07-09 00:56:48 +02:00
Mimoja
aff20e272c Add updateRemote.sh script to update the contentFs on multiple APs at once
As flashing a new LittleFS in case of e.g. a changed main.js is taking time and
the provided web interface is not the fastest to navigate we are introducing a
small script to upload the whole data folder to the esp.
It can also be sourced into a shell allowing for manual file uploads to the esp.

In addition we are also adding a "push_ota.sh" script designed to show its use as
well as uploading the recenty build firmware to the esp where future commits will
allow of SDCard based updates.

Signed-off-by: Mimoja <git@mimoja.de>
2023-07-08 01:21:29 +02:00
Mimoja
8078b4aeed Refactor build flags
So far the platform-io build-flags config option was a copy&paste
situation from one board to the next.
With the recently introduced new supported board these build-flags
are redundant and difficult to oversee.
Longterm they should ideally be partially generated to ensure a good
customizability but for now we are moving the common ones into the
base env where they can be imported by all the boards.

Signed-off-by: Mimoja <git@mimoja.de>
2023-07-08 01:21:29 +02:00
Mimoja
fd22bc0378 Fix: Properly calculate db size for SystemInfo
So far the calculated size for the tagDB in the frontend was
purely based on the size of each of its static entries.
However the data pointer as well as the json based config string
can occupy additional memory which is not accounted for.

We are therefore introducing a helper function to properly
calculate the DBs size.

Signed-off-by: Mimoja <git@mimoja.de>
2023-07-08 01:21:29 +02:00
atc1441
63463435cd Updated NanoAp 3D Printed case to a new version 2023-07-05 22:56:58 +02:00
Jelmer
3dd4f23880 Update README.md
added license
2023-07-04 22:22:18 +02:00
Jelmer
9891d23db1 Create LICENSE
Added CC-BY-NC-SA
2023-07-04 22:04:03 +02:00
Jelmer
4ed9d2e2e9 Merge pull request #77 from Mimoja/powerPins
ESP: Fix Powermanagement for non-configured POWER

Sensible changes, thank you!
2023-07-04 20:42:33 +02:00
Mimoja
a60bc91205 ESP: Fix Powermanagement for non-configured POWER
We currently have two ways of undefining the PowerPin in software for the ESP32
For once we can set POWER_NO_SOFT_POWER which will lead to some helpful screen
messages _but_ will still require the definition of the FLASHER_AP_POWER pin.

The second way (which was replaced with POWER_NO_SOFT_POWER) allowed to set the
powerPin array to {-1} to indicate that the pin is undefined. This would then be
handled in pretty far down the call stack right before toggeling the pin in powerControl:

```
 void powerControl(bool powerState, uint8_t* pin, uint8_t pincount) {
    if (pin[0] == -1) return;
```

This however is leading to an error: pin is n pointer (here an array with additional length)
to an uint8_t which can never be -1. Therefore the check wont ever be reached and an invalid
gpio number is passed to the gpio hal.
This caused the error:
```
  E (XXXX) gpio: gpio_set_level(226): GPIO output gpio_num error
```
to show up in the logs.
We are now proposing three seperate changes to mitigate this behaviour:
1) We are addng the POWER_NO_SOFT_POWER to the Wemos and the M5Stack boards default configs
for new users to find.
2) We are replacing the pin[0] check in powerControl with a check on the pincount and a
nullptr check as the zbs_interface->begin() allows for no powerPin to be passed in which
case we are dereferencing a nullptr.
3) ZBS_interface->begin() is losing its powerPin related default configurations and
sanity checks are put in place before every calling.

We have opted to do 3) in this way and not adding the checked into the ZBS_interface->begin()
function which is also passed an uint8_t pointer to keep the API of the class stable
for reuse in other projects. Changing the interface however would be ideal here

Signed-off-by: Mimoja <git@mimoja.de>
2023-07-03 21:39:41 +02:00
Jonas Niesner
9f86c9ef2c Update main.js
fix
2023-07-02 08:40:37 +02:00
Jonas Niesner
f7078363a4 Update main.js
added ap temp
2023-07-02 08:39:22 +02:00
Jonas Niesner
e0fd1e0f86 Update index.html
added ap temp
2023-07-02 08:38:07 +02:00
Jonas Niesner
057cf14298 Added additional system info to websocket 2023-07-01 11:51:20 +02:00
Nic Limper
51da22b0d4 small fix 2023-06-28 13:52:30 +02:00
Nic Limper
42a3651075 channel id, tag fw version and tag commands integrated in webinterface 2023-06-28 13:11:33 +02:00
Nic Limper
56dfd0c2f0 fix Weemos typo in automatic builds 2023-06-28 11:34:09 +02:00
Nic Limper
716d9823db various small fixes
- cleanup font in flash. Don't forget to update content_template.json in the file system after updating fw.
- fix layout issue in update window
- better error handling + auto retry during fw update
- fixed spelling 'weemos' -> 'wemos_d1_mini32' in build name
2023-06-28 11:01:08 +02:00
Jelmer
da6d783e3b added new larger availdatareq struct for esp32 2023-06-27 23:17:01 +02:00
jjwbruijn
306e5aaf00 bigger availdatareq struct with version 2023-06-27 23:00:11 +02:00
Nic Limper
5376f2540e layout bugfix
fixes issue #74
2023-06-27 14:14:52 +02:00
Jonas Niesner
a251ed10e7 Cleaned up release.yml and added 2 new platforms 2023-06-26 09:51:21 +02:00
Jonas Niesner
65410e3e8d Improve push/pr test pipeline 2023-06-26 09:46:57 +02:00
Jonas Niesner
b2174c2980 cleaned up platformio.ini 2023-06-26 09:44:30 +02:00
Jelmer
7db482a6ba Delete AP_force_flash.bin 2023-06-26 09:02:53 +02:00
Jelmer
bac7cf7ab5 Merge pull request #71 from Mimoja/misc
Misc changes to for low-effort setups
2023-06-25 15:17:52 +02:00
Jelmer
a3e739b8da Merge pull request #72 from slimline33/master
Thank you for your contribution!
2023-06-25 15:16:47 +02:00
Mimoja
cc1dcd9d29 ESP: split esp2buffer into two calls
Sprite rendering is the most heap hungry operation in during
content generation. This can lead to ESP panics as the exception
for the failing "new" is not handled.
To further half the required the memory we are doing it in two passes
for black and red independant. While this add a few ms to the rendering
the main time of the rendering is writing to the FS anyways so the overhead
neglectable after all.

Signed-off-by: Mimoja <git@mimoja.de>
2023-06-25 13:12:56 +02:00
Mimoja
10468313e1 Print free disk space in human readable numbers
Signed-off-by: Mimoja <git@mimoja.de>
2023-06-25 13:12:56 +02:00
Mimoja
2e55c49a92 main: Print free heap in parallel to web interface
Signed-off-by: Mimoja <git@mimoja.de>
2023-06-25 13:12:56 +02:00
Mimoja
e45845e00e Add SPIFFSEditor header to match imported source file
The SPIFFSEditor.h header is being imported from the .platformio folder
while the corresponding .cpp is actually stored with the project.
To ensure we can not accidentally edit the wrong file in the future import
the header as well

Signed-off-by: Mimoja <git@mimoja.de>
2023-06-25 13:12:56 +02:00
Mimoja
940795d05d Dont attack the ledc to the LED pin if no LED is available
Signed-off-by: Mimoja <git@mimoja.de>
2023-06-25 13:12:56 +02:00
Mimoja
a3fc1da6d2 Add Flash Timeout parameter
Signed-off-by: Mimoja <git@mimoja.de>
2023-06-25 13:12:56 +02:00
Bimmi
d778aab553 Add favicon.ico
upload favicon.ico
2023-06-25 08:45:00 +02:00
Bimmi
f460046c51 Update index.html
added code for favicon.ico
2023-06-25 08:44:07 +02:00
Jelmer
e5ddba02ff Merge pull request #70 from Mimoja/SDCard
Add Support for an SDCard and SoftSPI
2023-06-24 23:29:24 +02:00
Jonas Niesner
7ba80f57c9 Merge branch 'master' into SDCard 2023-06-21 21:41:08 +02:00
Jonas Niesner
d6feb5a8ca Update platformio.ini
Added M5 core build config
2023-06-20 21:24:46 +02:00
Jonas Niesner
1e034c83fa Merge pull request #68 from Mimoja/weemos
Add Weemos D1 mini 32 as target
2023-06-20 21:20:43 +02:00
Mimoja
1e93a24b53 Allow the usage of SoftSPI for AP flashing
The AP-Tags are not very fast at flashing. SoftSPI is fast enough for the
rare flashing.
This gives us the ability to move the AP connection to arbitrary pins.

Signed-off-by: Mimoja <git@mimoja.de>
2023-06-20 17:55:41 +02:00
Mimoja
dbf76e2176 Expose flasher speed to config via define
Signed-off-by: Mimoja <git@mimoja.de>
2023-06-20 17:51:10 +02:00
Mimoja
93639ff8ac Disconnect SDCard if it shares the pins with the flasher
Signed-off-by: Mimoja <git@mimoja.de>
2023-06-20 17:51:10 +02:00
Mimoja
48b2925b9f Reset flasher if it shared the pins with the SDCard
If the flasher and the SDCard share pins the ESP will need to be reset
to bring VSPI and HSPI back into sane states. Trying to reinit them
without a reset will lead to heap corruptions.
Better safe than sorry.

Signed-off-by: Mimoja <git@mimoja.de>
2023-06-20 17:51:10 +02:00
Mimoja
9c83d8b5a5 Use SDCard usage where available
When an SD Card is available it is the more interesing
metric in terms of space usage. We are therefore using
it here.

Signed-off-by: Mimoja <git@mimoja.de>
2023-06-20 17:51:10 +02:00
Mimoja
f487092f7f Add SDCard support
To be able to store more images and never worry about running
out of storage again we are adding support of SDCards.

We are faced with two options:
1) Remove the LittleFS code
2) Allow for both FSs but increase the app partition as we run
out of space.

We have opted for 2 for two reasons:
1) Unformated SDCards can be initialized from the littleFS
2) If the SDCard and the flasher share the same SPI pins
the SDCard needs to be completely disconnected so there needs
to be a FS in that rare case.

Performance wise the SDCard is not slowing the system down.
Writing the AP db with 70 APs takes 2.5 seconds, on the SD
only 800ms. This however is SD and setup depending.

By default the SDCard is expected on pins 18,19,23 however this
is configurable via preprocessor defines.

Globally we replace LittleFS with a new pointer to the currently
used FS allowing for hotswapping where the FS pointer is not saved.
One case which is therefore not working is the SPIFSEditor which
copies the FS interally.

Signed-off-by: Mimoja <git@mimoja.de>
2023-06-20 17:51:10 +02:00
Mimoja
eae7c3a159 ESP: Delete files after transfer where requested
Beyond around 20 APs the littleFs will no longer provide enough
space to add .pending files. The original .raw files are premarily
held to be able to send them to the web interface.
In those rare cases where this is not strictly needed we can
allow specific setups to auto-delete them.

Signed-off-by: Mimoja <git@mimoja.de>
2023-06-20 17:51:10 +02:00
Mimoja
4d78df09cc Add M5stack (original core) config
The M5stack board offers three interesting features for use with
OpenEPaperLink:
- LCD
- SDCard slot
- Modules including a batters

Which means it can easily be used to walk around with an AP for testing
purposes.
The LCD is currely not used as the M5Stack library is so old that it collides
with newer versions of eTFT which we are importing already.

Signed-off-by: Mimoja <git@mimoja.de>
2023-06-20 17:51:09 +02:00
Mimoja
e8740b2022 Add Weemos D1 mini 32 as target
The original weemos D1 mini was one of the most popular
ESP8266 boards. To this day many designs are designed around its
formfactor.
The successor is the here added D1 mini 32. It brings the same
"core" header with 8 GPIO but also additional io.

We are adding a default config which is workable with the old
pinconfig as those are usually the only ones exposed on the
breakout boards.
2023-06-20 17:24:53 +02:00
atc1441
6c4e254db0 Update NanoAP_Case.jpg 2023-06-19 22:43:48 +02:00
atc1441
5ccbcb4719 Nano AP Infos and Files added 2023-06-19 22:42:24 +02:00
atc1441
617b49eb86 Yep, Pinout of NanoAP fixed... 2023-06-19 11:47:46 +02:00
Jelmer
5868abf189 Merge pull request #64 from jjwbruijn/customLUTTest
Tag-side config options with binaries
2023-06-15 14:35:14 +02:00
Jelmer
94be1ea3aa Added possibility to xfer tag-side config options 2023-06-15 13:18:12 +02:00
jjwbruijn
5190327d5a optimized i2c, disabled for 4.2 2023-06-15 11:42:15 +02:00
jjwbruijn
6ecf6410ee moved some defaults, fixed typo 2023-06-14 22:11:30 +02:00
jjwbruijn
e72e89d85e Added settings/config for tags 2023-06-14 21:45:36 +02:00
Jonas Niesner
054146677f Fixed release description overwrite 2023-06-13 18:22:46 +02:00
Jonas Niesner
58d9fe2217 Split json file list 2023-06-13 18:21:33 +02:00
Nic Limper
205dfa0ce2 logging reboots 2023-06-11 13:29:49 +02:00
Jelmer
5c7b53b740 update in power management (multiple pins) 2023-06-10 14:24:50 +02:00
jjwbruijn
5196c1b212 76 bytes custom OTA Lut and changes location of the init 2023-06-09 14:59:00 +02:00
Nic Limper
e7fbaffbab added advanced tag options
- added advanced tag options: image rotation / always use default lut / force refresh / cancel pending
- fixed rx/tx swap in documentation
2023-06-09 12:56:58 +02:00
Nic Limper
c68b582be7 overhaul of contentmanager, 4.2" layouts, bugfixes
- added Swedish å Å to Bahnschrift20 and 30
- option to turn dither on/off in 'static image'
- major overhaul of contentmanager.cpp, content is now generated from json template.
- fallback to 1bpp for 4.2" when no psram
- added 4.2" content layouts
- fixed small apconfig bug
- pause content generation for 60 seconds after crash, to prevent uncontrollable boot loop
2023-06-08 15:41:15 +02:00
Nic Limper
9d07df27f0 fix font characters <32 2023-06-07 12:32:11 +02:00
atc1441
064bd4258c Nano AP fully power Control support
The idea to switch to an array based power Control was discarded for now
2023-06-07 01:00:40 +02:00
Jonas Niesner
8e31a1b8eb Update README.md
Added new badges
2023-06-06 20:24:12 +02:00
Jonas Niesner
9598bea315 Merge pull request #57 from seeers/master
Update links to wiki pages README.md
2023-06-06 20:13:06 +02:00
seeers
6d2ed6915b Update links to wiki pages README.md 2023-06-06 20:10:06 +02:00
Jonas Niesner
6ffe967577 Update release.yml
Add builds for Nano_AP
2023-06-06 20:03:47 +02:00
Nic Limper
e169dbab6e added äöüßÄÖÜ to fonts + small updates
- fonts re-rendered: added äöüßÄÖÜ.
- shuffled a bit with fonts to optimize disk usage
- ability to delete files during OTA
- prettify tagDB.json
- error handling in get_DB
- small cosmetic changes

* Due to new ability to delete files: After firmware update via OTA, please perform an OTA update of the filesystem again to perform the deletion of unneeded fonts.
* If updating via platform.io: don't forget to update the filesystem image.
2023-06-06 16:04:18 +02:00
atc1441
b9d3289852 Added NanoAP 2023-06-03 17:21:35 +02:00
atc1441
b0971bd111 Pogo pin size typo fix in ATC1441 Jig 2023-06-03 08:39:12 +02:00
Jelmer
11193a1fbf low power during ap/associate, for S2 boards 2023-06-02 13:24:03 +02:00
Nic Limper
db88de1f75 minor bug fixes
-
2023-06-01 21:42:09 +02:00
Jelmer
e9a554a2bf improved timings for reset/bringing AP online 2023-05-31 20:34:36 +02:00
1875 changed files with 438078 additions and 186313 deletions

34
.github/actions/setup-pio/action.yml vendored Normal file
View File

@@ -0,0 +1,34 @@
name: Setup PlatformIO
description: 'Installs PlatformIO and necessary dependencies.'
inputs:
python-version:
description: 'Set Python version (optional)'
required: false
default: '3.9'
runs:
using: "composite"
steps:
- name: Cache pip
id: cache-pip
uses: actions/cache@v3
with:
path: |
~/.cache/pip
~/.platformio/.cache
key: ${{ runner.os }}-${{ inputs.python-version }}-pio
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: ${{ inputs.python-version }}
- name: Install PlatformIO Core
shell: bash
run: pip install --upgrade platformio
- name: Install intelhex
shell: bash
run: pip install --upgrade intelhex

19
.github/path-filters.yml vendored Normal file
View File

@@ -0,0 +1,19 @@
arm-tag_common: &arm-tag_common
- 'ARM_Tag_FW/common/**'
arm-tag_88MZ100:
- '*arm-tag_common'
- 'ARM_Tag_FW/88MZ100/**'
arm-tag_newton-m3-nrf52811:
- '*arm-tag_common'
- 'ARM_Tag_FW/Newton_M3_nRF52811/**'
arm-tag_nrf-bootloader:
- 'ARM_Tag_FW/nRF_Bootloader/**'
arm-tag_nrf52811-pio-ap:
- 'ARM_Tag_FW/nrf52811_Platformio_AP/**'
esp32-ap:
- 'ESP32_AP-Flasher/**'

View File

@@ -1,51 +0,0 @@
name: ESP32 build
on: [push,pull_request]
jobs:
build:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v3
- uses: actions/cache@v3
with:
path: |
~/.cache/pip
~/.platformio/.cache
key: ${{ runner.os }}-pio
- uses: actions/setup-python@v4
with:
python-version: '3.9'
- name: Install PlatformIO Core
run: pip install --upgrade platformio
- name: Build firmware for ESP32
run: |
cd ESP32_AP-Flasher
pio run --environment Simple_AP
- name: Build filesystem for ESP32
run: |
cd ESP32_AP-Flasher
pio run --target buildfs --environment Simple_AP
- name: Build firmware for ESP32-S2
run: |
cd ESP32_AP-Flasher
pio run --environment OpenEPaperLink_Mini_AP
- name: Build filesystem for ESP32-S2
run: |
cd ESP32_AP-Flasher
pio run --target buildfs --environment OpenEPaperLink_Mini_AP
- name: Build firmware for ESP32-S3
run: |
cd ESP32_AP-Flasher
pio run --environment OpenEPaperLink_AP_and_Flasher
- name: Build filesystem for ESP32-S3
run: |
cd ESP32_AP-Flasher
pio run --target buildfs --environment OpenEPaperLink_AP_and_Flasher

View File

@@ -0,0 +1,91 @@
name: FW Build / Test
on: [push, pull_request]
jobs:
determine-builds:
name: Evaluate Required Builds
runs-on: ubuntu-latest
timeout-minutes: 1
# Map a step output to job output
outputs:
arm-tag_newton-m3-nrf52811: ${{ steps.filter.outputs.arm-tag_newton-m3-nrf52811 }}
arm-tag_nrf-bootloader: ${{ steps.filter.outputs.arm-tag_nrf-bootloader }}
arm-tag_nrf52811-pio-ap: ${{ steps.filter.outputs.arm-tag_nrf52811-pio-ap }}
arm-tag_88MZ100: ${{ steps.filter.outputs.arm-tag_88MZ100 }}
esp32-ap: ${{ steps.filter.outputs.esp32-ap }}
steps:
- uses: actions/checkout@v4
- uses: dorny/paths-filter@v3
id: filter
with:
# TODO: work around issue with paths-filter (https://github.com/dorny/paths-filter/issues/227)
token: ''
filters: .github/path-filters.yml
tag-build:
name: Build Tag FW
needs: [determine-builds]
runs-on: ubuntu-latest
steps:
- name: Checkout Code (with submodules)
uses: actions/checkout@v4
with:
submodules: 'recursive'
- uses: ./.github/actions/setup-pio
- name: ARM_Tag_FW/nRF_Bootloader
if: ${{ needs.determine-builds.outputs.arm-tag_nrf-bootloader == 'true' }}
run: |
cd ARM_Tag_FW/nRF_Bootloader
pio run --environment nRFBootload
- name: ARM_Tag_FW/Newton_M3_nRF52811
if: ${{ needs.determine-builds.outputs.arm-tag_newton-m3-nrf52811 == 'true' }}
run: |
pio --version
cd ARM_Tag_FW/Newton_M3_nRF52811
pio run --environment Newton_M3_Universal
- name: ARM_Tag_FW/nrf52811_Platformio_AP
if: ${{ needs.determine-builds.outputs.arm-tag_nrf52811-pio-ap == 'true' }}
run: |
cd ARM_Tag_FW/nrf52811_Platformio_AP
pio run --environment nrf52811_OEPL_AP
- name: ARM_Tag_FW/88MZ100_OpenEpaperLink_7.4
if: ${{ needs.determine-builds.outputs.arm-tag_88MZ100 == 'true' }}
# TODO: Implement build for 88MZ100
run: |
echo "Note: build for 88MZ100 has not been implementted yet."
ap-build:
name: Build AP FW
needs: [determine-builds]
if: ${{ needs.determine-builds.outputs.esp32-ap == 'true' }}
strategy:
matrix:
environment:
#- OpenEPaperLink_Mini_AP
#- OpenEPaperLink_AP_and_Flasher
- ESP32_S3_16_8_YELLOW_AP
- OpenEPaperLink_Mini_AP_v4
- OpenEPaperLink_ESP32-PoE-ISO_AP
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v4
- uses: ./.github/actions/setup-pio
- name: Build ${{ matrix.environment }} binary
run: |
cd ESP32_AP-Flasher
pio run --environment ${{ matrix.environment }}
- name: Build ${{ matrix.environment }} filesystem
if: ${{ matrix.environment != 'OpenEPaperLink_ESP32-PoE-ISO_AP' }}
run: |
cd ESP32_AP-Flasher
pio run --target buildfs --environment ${{ matrix.environment }}

View File

@@ -5,6 +5,12 @@ on:
tags:
- '*'
env:
INCLUDE_C6_H2: true
INCLUDE_MINI_AP: false
INCLUDE_Nano_AP: false
INCLUDE_S2_Tag_Flasher: false
jobs:
build:
runs-on: ubuntu-22.04
@@ -20,127 +26,340 @@ jobs:
- uses: actions/setup-python@v4
with:
python-version: '3.9'
# - name: Commit zipped files
# run: |
# git config --global user.name 'Bot'
# git config --global user.email "bot@openepaperlink.de"
# git commit -am "Zipped web files"
# git push origin HEAD:master
- name: Install PlatformIO Core
run: pip install --upgrade platformio
- name: Install intelhex
run: pip install --upgrade intelhex
- name: Install esptool
run: pip install esptool
# - name: Add www folder to release
# uses: svenstaro/upload-release-action@v2
# with:
# repo_token: ${{ secrets.GITHUB_TOKEN }}
# file: ESP32_AP-Flasher/data/www/*
# tag: ${{ github.ref }}
# file_glob: true
# - name: Add fonts folder to release
# uses: svenstaro/upload-release-action@v2
# with:
# repo_token: ${{ secrets.GITHUB_TOKEN }}
# file: ESP32_AP-Flasher/data/fonts/*
# tag: ${{ github.ref }}
# file_glob: true
# - name: Add data folder to release
# uses: svenstaro/upload-release-action@v2
# with:
# repo_token: ${{ secrets.GITHUB_TOKEN }}
# file: ESP32_AP-Flasher/data/*
# tag: ${{ github.ref }}
# file_glob: true
- name: Build firmware for ESP32
- name: create folders
run: |
cd ESP32_AP-Flasher
export PLATFORMIO_BUILD_FLAGS="-D BUILD_VERSION=${{ github.ref_name }} -D SHA=$GITHUB_SHA"
pio run --environment Simple_AP
mkdir /home/runner/work/OpenEPaperLink/OpenEPaperLink/esp32fw
cp ~/.platformio/packages/framework-arduinoespressif32/tools/partitions/boot_app0.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/esp32fw/boot_app0.bin
cp .pio/build/Simple_AP/firmware.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/esp32fw/firmware.bin
cp .pio/build/Simple_AP/bootloader.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/esp32fw/bootloader.bin
cp .pio/build/Simple_AP/partitions.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/esp32fw/partitions.bin
- name: Build filesystem for ESP32
mkdir espbinaries
- name: build ESP32-C6 firmware
if: ${{ env.INCLUDE_C6_H2 == 'true' }}
uses: espressif/esp-idf-ci-action@v1
with:
esp_idf_version: latest
target: esp32c6
path: 'ARM_Tag_FW/OpenEPaperLink_esp32_C6_AP/'
- name: Add C6 files to release
if: ${{ env.INCLUDE_C6_H2 == 'true' }}
run: |
cd ESP32_AP-Flasher
pio run --target buildfs --environment Simple_AP
cp .pio/build/Simple_AP/littlefs.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/esp32fw/littlefs.bin
- name: Combine binaries for ESP32
cp /home/runner/work/OpenEPaperLink/OpenEPaperLink/ARM_Tag_FW/OpenEPaperLink_esp32_C6_AP/build/OpenEPaperLink_esp32_C6.bin espbinaries/OpenEPaperLink_esp32_C6.bin
cp /home/runner/work/OpenEPaperLink/OpenEPaperLink/ARM_Tag_FW/OpenEPaperLink_esp32_C6_AP/build/bootloader/bootloader.bin espbinaries/bootloader_C6.bin
cp /home/runner/work/OpenEPaperLink/OpenEPaperLink/ARM_Tag_FW/OpenEPaperLink_esp32_C6_AP/build/partition_table/partition-table.bin espbinaries/partition-table_C6.bin
cp /home/runner/work/OpenEPaperLink/OpenEPaperLink//binaries/ESP32-C6/firmware_C6.json espbinaries
- name: build ESP32-H2 firmware
if: ${{ env.INCLUDE_C6_H2 == 'true' }}
uses: espressif/esp-idf-ci-action@v1
with:
esp_idf_version: latest
target: esp32h2
path: 'ARM_Tag_FW/OpenEPaperLink_esp32_H2_AP/'
- name: Add H2 files to release
if: ${{ env.INCLUDE_C6_H2 == 'true' }}
run: |
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink/esp32fw
esptool.py --chip esp32 merge_bin -o merged-firmware.bin --flash_mode dio --flash_freq 40m --flash_size 4MB 0x1000 bootloader.bin 0x8000 partitions.bin 0xe000 boot_app0.bin 0x10000 firmware.bin
- name: Build firmware for ESP32-S2
cp /home/runner/work/OpenEPaperLink/OpenEPaperLink/ARM_Tag_FW/OpenEPaperLink_esp32_H2_AP/build/OpenEPaperLink_esp32_H2.bin espbinaries/OpenEPaperLink_esp32_H2.bin
cp /home/runner/work/OpenEPaperLink/OpenEPaperLink/ARM_Tag_FW/OpenEPaperLink_esp32_H2_AP/build/bootloader/bootloader.bin espbinaries/bootloader_H2.bin
cp /home/runner/work/OpenEPaperLink/OpenEPaperLink/ARM_Tag_FW/OpenEPaperLink_esp32_H2_AP/build/partition_table/partition-table.bin espbinaries/partition-table_H2.bin
cp /home/runner/work/OpenEPaperLink/OpenEPaperLink//binaries/ESP32-H2/firmware_H2.json espbinaries
# - name: Zip web files
# run: |
# cd /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_AP-Flasher
# python gzip_wwwfiles.py
- name: Build firmware for OpenEPaperLink_Mini_AP
if: ${{ env.INCLUDE_MINI_AP == 'true' }}
run: |
cd ESP32_AP-Flasher
export PLATFORMIO_BUILD_FLAGS="-D BUILD_VERSION=${{ github.ref_name }} -D SHA=$GITHUB_SHA"
pio run --environment OpenEPaperLink_Mini_AP
mkdir /home/runner/work/OpenEPaperLink/OpenEPaperLink/esp32s2fw
cp ~/.platformio/packages/framework-arduinoespressif32/tools/partitions/boot_app0.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/esp32s2fw/boot_app0.bin
cp .pio/build/OpenEPaperLink_Mini_AP/firmware.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/esp32s2fw/firmware.bin
cp .pio/build/OpenEPaperLink_Mini_AP/bootloader.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/esp32s2fw/bootloader.bin
cp .pio/build/OpenEPaperLink_Mini_AP/partitions.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/esp32s2fw/partitions.bin
- name: Build filesystem for ESP32-S2
pio run --target buildfs --environment OpenEPaperLink_Mini_AP
mkdir /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_Mini_AP
cp ~/.platformio/packages/framework-arduinoespressif32/tools/partitions/boot_app0.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_Mini_AP/boot_app0.bin
cp .pio/build/OpenEPaperLink_Mini_AP/firmware.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_Mini_AP/firmware.bin
cp .pio/build/OpenEPaperLink_Mini_AP/bootloader.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_Mini_AP/bootloader.bin
cp .pio/build/OpenEPaperLink_Mini_AP/partitions.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_Mini_AP/partitions.bin
cp .pio/build/OpenEPaperLink_Mini_AP/littlefs.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_Mini_AP/littlefs.bin
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_Mini_AP
esptool.py --chip esp32-s2 merge_bin -o merged-firmware.bin --flash_mode dio --flash_freq 80m --flash_size 4MB 0x1000 bootloader.bin 0x8000 partitions.bin 0xe000 boot_app0.bin 0x10000 firmware.bin 0x290000 littlefs.bin
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink
cp OpenEPaperLink_Mini_AP/firmware.bin espbinaries/OpenEPaperLink_Mini_AP.bin
cp OpenEPaperLink_Mini_AP/merged-firmware.bin espbinaries/OpenEPaperLink_Mini_AP_full.bin
- name: Build firmware for OpenEPaperLink_Nano_AP
if: ${{ env.INCLUDE_Nano_AP == 'true' }}
run: |
cd ESP32_AP-Flasher
pio run --target buildfs --environment OpenEPaperLink_Mini_AP
cp .pio/build/OpenEPaperLink_Mini_AP/littlefs.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/esp32s2fw/littlefs.bin
- name: Combine binaries for ESP32-S2
run: |
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink/esp32s2fw
export PLATFORMIO_BUILD_FLAGS="-D BUILD_VERSION=${{ github.ref_name }} -D SHA=$GITHUB_SHA"
pio run --environment OpenEPaperLink_Nano_AP
pio run --target buildfs --environment OpenEPaperLink_Nano_AP
mkdir /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_Nano_AP
cp ~/.platformio/packages/framework-arduinoespressif32/tools/partitions/boot_app0.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_Nano_AP/boot_app0.bin
cp .pio/build/OpenEPaperLink_Nano_AP/firmware.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_Nano_AP/firmware.bin
cp .pio/build/OpenEPaperLink_Nano_AP/bootloader.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_Nano_AP/bootloader.bin
cp .pio/build/OpenEPaperLink_Nano_AP/partitions.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_Nano_AP/partitions.bin
cp .pio/build/OpenEPaperLink_Nano_AP/littlefs.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_Nano_AP/littlefs.bin
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_Nano_AP
esptool.py --chip esp32-s2 merge_bin -o merged-firmware.bin --flash_mode dio --flash_freq 80m --flash_size 4MB 0x1000 bootloader.bin 0x8000 partitions.bin 0xe000 boot_app0.bin 0x10000 firmware.bin 0x290000 littlefs.bin
- name: Build firmware for ESP32-S3
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink
cp OpenEPaperLink_Nano_AP/firmware.bin espbinaries/OpenEPaperLink_Nano_AP.bin
cp OpenEPaperLink_Nano_AP/merged-firmware.bin espbinaries/OpenEPaperLink_Nano_AP_full.bin
# - name: move files for big APs
# run: |
# cp -a binaries/ESP32-C6/. ESP32_AP-Flasher/data/
- name: Build firmware for OpenEPaperLink_AP_and_Flasher
run: |
cd ESP32_AP-Flasher
export PLATFORMIO_BUILD_FLAGS="-D BUILD_VERSION=${{ github.ref_name }} -D SHA=$GITHUB_SHA"
pio run --environment OpenEPaperLink_AP_and_Flasher
mkdir /home/runner/work/OpenEPaperLink/OpenEPaperLink/esp32s3fw
cp ~/.platformio/packages/framework-arduinoespressif32/tools/partitions/boot_app0.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/esp32s3fw/boot_app0.bin
cp .pio/build/OpenEPaperLink_AP_and_Flasher/firmware.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/esp32s3fw/firmware.bin
cp .pio/build/OpenEPaperLink_AP_and_Flasher/bootloader.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/esp32s3fw/bootloader.bin
cp .pio/build/OpenEPaperLink_AP_and_Flasher/partitions.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/esp32s3fw/partitions.bin
- name: Build filesystem for ESP32-S3
pio run --target buildfs --environment OpenEPaperLink_AP_and_Flasher
mkdir /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_AP_and_Flasher
cp ~/.platformio/packages/framework-arduinoespressif32/tools/partitions/boot_app0.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_AP_and_Flasher/boot_app0.bin
cp .pio/build/OpenEPaperLink_AP_and_Flasher/firmware.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_AP_and_Flasher/firmware.bin
cp .pio/build/OpenEPaperLink_AP_and_Flasher/bootloader.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_AP_and_Flasher/bootloader.bin
cp .pio/build/OpenEPaperLink_AP_and_Flasher/partitions.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_AP_and_Flasher/partitions.bin
cp .pio/build/OpenEPaperLink_AP_and_Flasher/littlefs.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_AP_and_Flasher/littlefs.bin
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_AP_and_Flasher
esptool.py --chip esp32-s3 merge_bin -o merged-firmware.bin --flash_mode dio --flash_freq 80m --flash_size 16MB 0x0000 bootloader.bin 0x8000 partitions.bin 0xe000 boot_app0.bin 0x10000 firmware.bin 0x00c90000 littlefs.bin
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink
cp OpenEPaperLink_AP_and_Flasher/firmware.bin espbinaries/OpenEPaperLink_AP_and_Flasher.bin
cp OpenEPaperLink_AP_and_Flasher/merged-firmware.bin espbinaries/OpenEPaperLink_AP_and_Flasher_full.bin
- name: Build firmware for ESP32_S3_16_8_YELLOW_AP
run: |
cd ESP32_AP-Flasher
pio run --target buildfs --environment OpenEPaperLink_AP_and_Flasher
cp .pio/build/OpenEPaperLink_AP_and_Flasher/littlefs.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/esp32s3fw/littlefs.bin
- name: Combine binaries for ESP32-S3
export PLATFORMIO_BUILD_FLAGS="-D BUILD_VERSION=${{ github.ref_name }} -D SHA=$GITHUB_SHA"
pio run --environment ESP32_S3_16_8_YELLOW_AP
pio run --target buildfs --environment ESP32_S3_16_8_YELLOW_AP
mkdir /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_S3_16_8_YELLOW_AP
cp ~/.platformio/packages/framework-arduinoespressif32/tools/partitions/boot_app0.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_S3_16_8_YELLOW_AP/boot_app0.bin
cp .pio/build/ESP32_S3_16_8_YELLOW_AP/firmware.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_S3_16_8_YELLOW_AP/firmware.bin
cp .pio/build/ESP32_S3_16_8_YELLOW_AP/bootloader.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_S3_16_8_YELLOW_AP/bootloader.bin
cp .pio/build/ESP32_S3_16_8_YELLOW_AP/partitions.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_S3_16_8_YELLOW_AP/partitions.bin
cp .pio/build/ESP32_S3_16_8_YELLOW_AP/littlefs.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_S3_16_8_YELLOW_AP/littlefs.bin
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_S3_16_8_YELLOW_AP
esptool.py --chip esp32-s3 merge_bin -o merged-firmware.bin --flash_mode dio --flash_freq 80m --flash_size 16MB 0x0000 bootloader.bin 0x8000 partitions.bin 0xe000 boot_app0.bin 0x10000 firmware.bin 0x00910000 littlefs.bin
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink
cp ESP32_S3_16_8_YELLOW_AP/firmware.bin espbinaries/ESP32_S3_16_8_YELLOW_AP.bin
cp ESP32_S3_16_8_YELLOW_AP/merged-firmware.bin espbinaries/ESP32_S3_16_8_YELLOW_AP_full.bin
- name: Build firmware for ESP32_S3_C6_NANO_AP
run: |
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink/esp32s3fw
esptool.py --chip esp32-s3 merge_bin -o merged-firmware.bin --flash_mode dio --flash_freq 80m --flash_size 16MB 0x0000 bootloader.bin 0x8000 partitions.bin 0xe000 boot_app0.bin 0x10000 firmware.bin 0x00c90000 littlefs.bin
- name: move binaries
cd ESP32_AP-Flasher
export PLATFORMIO_BUILD_FLAGS="-D BUILD_VERSION=${{ github.ref_name }} -D SHA=$GITHUB_SHA"
pio run --environment ESP32_S3_C6_NANO_AP
pio run --target buildfs --environment ESP32_S3_C6_NANO_AP
mkdir /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_S3_C6_NANO_AP
cp ~/.platformio/packages/framework-arduinoespressif32/tools/partitions/boot_app0.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_S3_C6_NANO_AP/boot_app0.bin
cp .pio/build/ESP32_S3_C6_NANO_AP/firmware.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_S3_C6_NANO_AP/firmware.bin
cp .pio/build/ESP32_S3_C6_NANO_AP/bootloader.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_S3_C6_NANO_AP/bootloader.bin
cp .pio/build/ESP32_S3_C6_NANO_AP/partitions.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_S3_C6_NANO_AP/partitions.bin
cp .pio/build/ESP32_S3_C6_NANO_AP/littlefs.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_S3_C6_NANO_AP/littlefs.bin
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_S3_C6_NANO_AP
esptool.py --chip esp32-s3 merge_bin -o merged-firmware.bin --flash_mode dio --flash_freq 80m --flash_size 16MB 0x0000 bootloader.bin 0x8000 partitions.bin 0xe000 boot_app0.bin 0x10000 firmware.bin 0x00910000 littlefs.bin
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink
cp ESP32_S3_C6_NANO_AP/firmware.bin espbinaries/ESP32_S3_C6_NANO_AP.bin
cp ESP32_S3_C6_NANO_AP/merged-firmware.bin espbinaries/ESP32_S3_C6_NANO_AP_full.bin
- name: Build firmware for ESP32_S3_16_8_LILYGO_AP
run: |
mkdir espbinaries
cp esp32fw/firmware.bin espbinaries/Simple_AP.bin
cp esp32s2fw/firmware.bin espbinaries/OpenEPaperLink_Mini_AP.bin
cp esp32s3fw/firmware.bin espbinaries/OpenEPaperLink_AP_and_Flasher.bin
cp esp32fw/merged-firmware.bin espbinaries/Simple_AP_full.bin
cp esp32s2fw/merged-firmware.bin espbinaries/OpenEPaperLink_Mini_AP_full.bin
cp esp32s3fw/merged-firmware.bin espbinaries/OpenEPaperLink_AP_and_Flasher_full.bin
cd ESP32_AP-Flasher
export PLATFORMIO_BUILD_FLAGS="-D BUILD_VERSION=${{ github.ref_name }} -D SHA=$GITHUB_SHA"
pio run --environment ESP32_S3_16_8_LILYGO_AP
pio run --target buildfs --environment ESP32_S3_16_8_LILYGO_AP
mkdir /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_S3_16_8_LILYGO_AP
cp ~/.platformio/packages/framework-arduinoespressif32/tools/partitions/boot_app0.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_S3_16_8_LILYGO_AP/boot_app0.bin
cp .pio/build/ESP32_S3_16_8_LILYGO_AP/firmware.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_S3_16_8_LILYGO_AP/firmware.bin
cp .pio/build/ESP32_S3_16_8_LILYGO_AP/bootloader.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_S3_16_8_LILYGO_AP/bootloader.bin
cp .pio/build/ESP32_S3_16_8_LILYGO_AP/partitions.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_S3_16_8_LILYGO_AP/partitions.bin
cp .pio/build/ESP32_S3_16_8_LILYGO_AP/littlefs.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_S3_16_8_LILYGO_AP/littlefs.bin
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_S3_16_8_LILYGO_AP
esptool.py --chip esp32-s3 merge_bin -o merged-firmware.bin --flash_mode dio --flash_freq 80m --flash_size 16MB 0x0000 bootloader.bin 0x8000 partitions.bin 0xe000 boot_app0.bin 0x10000 firmware.bin 0x00910000 littlefs.bin
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink
cp ESP32_S3_16_8_LILYGO_AP/firmware.bin espbinaries/ESP32_S3_16_8_LILYGO_AP.bin
cp ESP32_S3_16_8_LILYGO_AP/merged-firmware.bin espbinaries/ESP32_S3_16_8_LILYGO_AP_full.bin
- name: Build firmware for OpenEPaperLink_Nano_TLSR
run: |
cd ESP32_AP-Flasher
export PLATFORMIO_BUILD_FLAGS="-D BUILD_VERSION=${{ github.ref_name }} -D SHA=$GITHUB_SHA"
pio run --environment OpenEPaperLink_Nano_TLSR
pio run --target buildfs --environment OpenEPaperLink_Nano_TLSR
mkdir /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_Nano_TLSR
cp ~/.platformio/packages/framework-arduinoespressif32/tools/partitions/boot_app0.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_Nano_TLSR/boot_app0.bin
cp .pio/build/OpenEPaperLink_Nano_TLSR/firmware.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_Nano_TLSR/firmware.bin
cp .pio/build/OpenEPaperLink_Nano_TLSR/bootloader.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_Nano_TLSR/bootloader.bin
cp .pio/build/OpenEPaperLink_Nano_TLSR/partitions.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_Nano_TLSR/partitions.bin
cp .pio/build/OpenEPaperLink_Nano_TLSR/littlefs.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_Nano_TLSR/littlefs.bin
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_Nano_TLSR
esptool.py --chip esp32-s3 merge_bin -o merged-firmware.bin --flash_mode dio --flash_freq 80m --flash_size 16MB 0x0000 bootloader.bin 0x8000 partitions.bin 0xe000 boot_app0.bin 0x10000 firmware.bin 0x00910000 littlefs.bin
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink
cp OpenEPaperLink_Nano_TLSR/firmware.bin espbinaries/OpenEPaperLink_Nano_TLSR.bin
cp OpenEPaperLink_Nano_TLSR/merged-firmware.bin espbinaries/OpenEPaperLink_Nano_TLSR_full.bin
- name: Build firmware for OpenEPaperLink_PoE_AP
run: |
cd ESP32_AP-Flasher
export PLATFORMIO_BUILD_FLAGS="-D BUILD_VERSION=${{ github.ref_name }} -D SHA=$GITHUB_SHA"
pio run --environment OpenEPaperLink_PoE_AP
pio run --target buildfs --environment OpenEPaperLink_PoE_AP
mkdir /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_PoE_AP
cp ~/.platformio/packages/framework-arduinoespressif32/tools/partitions/boot_app0.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_PoE_AP/boot_app0.bin
cp .pio/build/OpenEPaperLink_PoE_AP/firmware.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_PoE_AP/firmware.bin
cp .pio/build/OpenEPaperLink_PoE_AP/bootloader.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_PoE_AP/bootloader.bin
cp .pio/build/OpenEPaperLink_PoE_AP/partitions.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_PoE_AP/partitions.bin
cp .pio/build/OpenEPaperLink_PoE_AP/littlefs.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_PoE_AP/littlefs.bin
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_PoE_AP
esptool.py --chip esp32 merge_bin -o merged-firmware.bin --flash_mode qio --flash_freq 80m --flash_size 16MB 0x0000 bootloader.bin 0x8000 partitions.bin 0xD000 boot_app0.bin 0x10000 firmware.bin 0x410000 littlefs.bin
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink
cp OpenEPaperLink_PoE_AP/firmware.bin espbinaries/OpenEPaperLink_PoE_AP.bin
cp OpenEPaperLink_PoE_AP/merged-firmware.bin espbinaries/OpenEPaperLink_PoE_AP_full.bin
- name: Build firmware for OpenEPaperLink_Mini_AP_v4
run: |
cd ESP32_AP-Flasher
export PLATFORMIO_BUILD_FLAGS="-D BUILD_VERSION=${{ github.ref_name }} -D SHA=$GITHUB_SHA"
pio run --environment OpenEPaperLink_Mini_AP_v4
pio run --target buildfs --environment OpenEPaperLink_Mini_AP_v4
mkdir /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_Mini_AP_v4
cp ~/.platformio/packages/framework-arduinoespressif32/tools/partitions/boot_app0.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_Mini_AP_v4/boot_app0.bin
cp .pio/build/OpenEPaperLink_Mini_AP_v4/firmware.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_Mini_AP_v4/firmware.bin
cp .pio/build/OpenEPaperLink_Mini_AP_v4/bootloader.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_Mini_AP_v4/bootloader.bin
cp .pio/build/OpenEPaperLink_Mini_AP_v4/partitions.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_Mini_AP_v4/partitions.bin
cp .pio/build/OpenEPaperLink_Mini_AP_v4/littlefs.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_Mini_AP_v4/littlefs.bin
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_Mini_AP_v4
esptool.py --chip esp32-s3 merge_bin -o merged-firmware.bin --flash_mode dio --flash_freq 80m --flash_size 16MB 0x0000 bootloader.bin 0x8000 partitions.bin 0xe000 boot_app0.bin 0x10000 firmware.bin 0x00910000 littlefs.bin
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink
cp OpenEPaperLink_Mini_AP_v4/firmware.bin espbinaries/OpenEPaperLink_Mini_AP_v4.bin
cp OpenEPaperLink_Mini_AP_v4/merged-firmware.bin espbinaries/OpenEPaperLink_Mini_AP_v4_full.bin
- name: Build firmware for BLE_ONLY_AP
run: |
cd ESP32_AP-Flasher
export PLATFORMIO_BUILD_FLAGS="-D BUILD_VERSION=${{ github.ref_name }} -D SHA=$GITHUB_SHA"
pio run --environment BLE_ONLY_AP
pio run --target buildfs --environment BLE_ONLY_AP
mkdir /home/runner/work/OpenEPaperLink/OpenEPaperLink/BLE_ONLY_AP
cp ~/.platformio/packages/framework-arduinoespressif32/tools/partitions/boot_app0.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/BLE_ONLY_AP/boot_app0.bin
cp .pio/build/BLE_ONLY_AP/firmware.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/BLE_ONLY_AP/firmware.bin
cp .pio/build/BLE_ONLY_AP/bootloader.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/BLE_ONLY_AP/bootloader.bin
cp .pio/build/BLE_ONLY_AP/partitions.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/BLE_ONLY_AP/partitions.bin
cp .pio/build/BLE_ONLY_AP/littlefs.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/BLE_ONLY_AP/littlefs.bin
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink/BLE_ONLY_AP
esptool.py --chip esp32-s3 merge_bin -o merged-firmware.bin --flash_mode dio --flash_freq 80m --flash_size 16MB 0x0000 bootloader.bin 0x8000 partitions.bin 0xe000 boot_app0.bin 0x10000 firmware.bin 0x00910000 littlefs.bin
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink
cp BLE_ONLY_AP/firmware.bin espbinaries/BLE_ONLY_AP.bin
cp BLE_ONLY_AP/merged-firmware.bin espbinaries/BLE_ONLY_AP_full.bin
- name: Build firmware for OpenEPaperLink_Nano_TLSR_C6
run: |
cd ESP32_AP-Flasher
export PLATFORMIO_BUILD_FLAGS="-D BUILD_VERSION=${{ github.ref_name }} -D SHA=$GITHUB_SHA"
pio run --environment OpenEPaperLink_Nano_TLSR_C6
pio run --target buildfs --environment OpenEPaperLink_Nano_TLSR_C6
mkdir /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_Nano_TLSR_C6
cp ~/.platformio/packages/framework-arduinoespressif32/tools/partitions/boot_app0.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_Nano_TLSR_C6/boot_app0.bin
cp .pio/build/OpenEPaperLink_Nano_TLSR_C6/firmware.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_Nano_TLSR_C6/firmware.bin
cp .pio/build/OpenEPaperLink_Nano_TLSR_C6/bootloader.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_Nano_TLSR_C6/bootloader.bin
cp .pio/build/OpenEPaperLink_Nano_TLSR_C6/partitions.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_Nano_TLSR_C6/partitions.bin
cp .pio/build/OpenEPaperLink_Nano_TLSR_C6/littlefs.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_Nano_TLSR_C6/littlefs.bin
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_Nano_TLSR_C6
esptool.py --chip esp32-s3 merge_bin -o merged-firmware.bin --flash_mode dio --flash_freq 80m --flash_size 16MB 0x0000 bootloader.bin 0x8000 partitions.bin 0xe000 boot_app0.bin 0x10000 firmware.bin 0x00910000 littlefs.bin
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink
cp OpenEPaperLink_Nano_TLSR_C6/firmware.bin espbinaries/OpenEPaperLink_Nano_TLSR_C6.bin
cp OpenEPaperLink_Nano_TLSR_C6/merged-firmware.bin espbinaries/OpenEPaperLink_Nano_TLSR_C6_full.bin
- name: Build firmware for ESP32_S3_16_8_4inch_AP
run: |
cd ESP32_AP-Flasher
export PLATFORMIO_BUILD_FLAGS="-D BUILD_VERSION=${{ github.ref_name }} -D SHA=$GITHUB_SHA"
pio run --environment ESP32_S3_16_8_4inch_AP
pio run --target buildfs --environment ESP32_S3_16_8_4inch_AP
mkdir /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_S3_16_8_4inch_AP
cp ~/.platformio/packages/framework-arduinoespressif32/tools/partitions/boot_app0.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_S3_16_8_4inch_AP/boot_app0.bin
cp .pio/build/ESP32_S3_16_8_4inch_AP/firmware.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_S3_16_8_4inch_AP/firmware.bin
cp .pio/build/ESP32_S3_16_8_4inch_AP/bootloader.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_S3_16_8_4inch_AP/bootloader.bin
cp .pio/build/ESP32_S3_16_8_4inch_AP/partitions.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_S3_16_8_4inch_AP/partitions.bin
cp .pio/build/ESP32_S3_16_8_4inch_AP/littlefs.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_S3_16_8_4inch_AP/littlefs.bin
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_S3_16_8_4inch_AP
esptool.py --chip esp32-s3 merge_bin -o merged-firmware.bin --flash_mode dio --flash_freq 80m --flash_size 16MB 0x0000 bootloader.bin 0x8000 partitions.bin 0xe000 boot_app0.bin 0x10000 firmware.bin 0x00910000 littlefs.bin
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink
cp ESP32_S3_16_8_4inch_AP/firmware.bin espbinaries/ESP32_S3_16_8_4inch_AP.bin
cp ESP32_S3_16_8_4inch_AP/merged-firmware.bin espbinaries/ESP32_S3_16_8_4inch_AP_full.bin
- name: Build firmware for OpenEPaperLink_ESP32-PoE-ISO_AP
run: |
cd ESP32_AP-Flasher
export PLATFORMIO_BUILD_FLAGS="-D BUILD_VERSION=${{ github.ref_name }} -D SHA=$GITHUB_SHA"
pio run --environment OpenEPaperLink_ESP32-PoE-ISO_AP
mv data data.bak
mkdir data
pio run --target buildfs --environment OpenEPaperLink_ESP32-PoE-ISO_AP
rmdir data
mv data.bak data
mkdir /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_ESP32-PoE-ISO_AP
cp ~/.platformio/packages/framework-arduinoespressif32/tools/partitions/boot_app0.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_ESP32-PoE-ISO_AP/boot_app0.bin
cp .pio/build/OpenEPaperLink_ESP32-PoE-ISO_AP/firmware.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_ESP32-PoE-ISO_AP/firmware.bin
cp .pio/build/OpenEPaperLink_ESP32-PoE-ISO_AP/bootloader.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_ESP32-PoE-ISO_AP/bootloader.bin
cp .pio/build/OpenEPaperLink_ESP32-PoE-ISO_AP/partitions.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_ESP32-PoE-ISO_AP/partitions.bin
cp .pio/build/OpenEPaperLink_ESP32-PoE-ISO_AP/littlefs.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_ESP32-PoE-ISO_AP/littlefs.bin
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink/OpenEPaperLink_ESP32-PoE-ISO_AP
esptool.py --chip esp32 merge_bin -o merged-firmware.bin --flash_mode qio --flash_freq 80m --flash_size 4MB 0x0000 bootloader.bin 0x8000 partitions.bin 0xD000 boot_app0.bin 0x10000 firmware.bin 0x3D0000 littlefs.bin
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink
cp OpenEPaperLink_ESP32-PoE-ISO_AP/firmware.bin espbinaries/OpenEPaperLink_ESP32-PoE-ISO_AP.bin
cp OpenEPaperLink_ESP32-PoE-ISO_AP/merged-firmware.bin espbinaries/OpenEPaperLink_ESP32-PoE-ISO_AP_full.bin
- name: generate release json file
run: |
mkdir jsonfiles
python genfilelist.py ${{ github.ref_name }} $GITHUB_REPOSITORY $GITHUB_SHA
- name: Add file list to release
- name: Add file lists to release
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: /home/runner/work/OpenEPaperLink/OpenEPaperLink/files.json
asset_name: files.json
file: jsonfiles/*
tag: ${{ github.ref }}
file_glob: true
overwrite: true
body: "file list"
# this is down here intentionally to be able to modify the binary folder before adding it to the Tag_Flasher later (ota binaries can be removed)
- name: Build firmware for Tag_Flasher
if: ${{ env.INCLUDE_S2_Tag_Flasher == 'true' }}
run: |
cd Tag_Flasher/ESP32_Flasher
export PLATFORMIO_BUILD_FLAGS="-D BUILD_VERSION=${{ github.ref_name }} -D SHA=$GITHUB_SHA"
pio run --environment S2_Tag_Flasher
pio run --target buildfs --environment S2_Tag_Flasher
mkdir /home/runner/work/OpenEPaperLink/OpenEPaperLink/S2_Tag_Flasher
cp ~/.platformio/packages/framework-arduinoespressif32/tools/partitions/boot_app0.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/S2_Tag_Flasher/boot_app0.bin
cp .pio/build/S2_Tag_Flasher/firmware.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/S2_Tag_Flasher/firmware.bin
cp .pio/build/S2_Tag_Flasher/bootloader.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/S2_Tag_Flasher/bootloader.bin
cp .pio/build/S2_Tag_Flasher/partitions.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/S2_Tag_Flasher/partitions.bin
cp .pio/build/S2_Tag_Flasher/littlefs.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/S2_Tag_Flasher/littlefs.bin
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink/S2_Tag_Flasher
esptool.py --chip esp32-s2 merge_bin -o merged-firmware.bin --flash_mode dio --flash_freq 80m --flash_size 4MB 0x1000 bootloader.bin 0x8000 partitions.bin 0xe000 boot_app0.bin 0x10000 firmware.bin 0x290000 littlefs.bin
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink
cp S2_Tag_Flasher/firmware.bin espbinaries/S2_Tag_Flasher.bin
cp S2_Tag_Flasher/merged-firmware.bin espbinaries/S2_Tag_Flasher_full.bin
- name: Add esp bins to release
uses: svenstaro/upload-release-action@v2
with:
@@ -149,12 +368,3 @@ jobs:
tag: ${{ github.ref }}
file_glob: true
overwrite: true
- name: Add tag bins to release
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: binaries/*
tag: ${{ github.ref }}
file_glob: true
overwrite: true

11
.gitignore vendored
View File

@@ -23,3 +23,14 @@
*.bin
*.lk
*.o
sdcc/sdcc
ESP32_AP-Flasher/.vscode/extensions.json
# ignore any $PROJECT_DIR directories (from incorrect interpolation variables)
$PROJECT_DIR/
# OS generated files
.DS_Store
# Jetbrains IDE
.idea/

6
.gitmodules vendored Normal file
View File

@@ -0,0 +1,6 @@
[submodule "ARM_Tag_FW/common/uzlib"]
path = ARM_Tag_FW/common/uzlib
url = https://github.com/pfalcon/uzlib.git
[submodule "ARM_Tag_FW/common/QRCode"]
path = ARM_Tag_FW/common/QRCode
url = https://github.com/ricmoo/QRCode

View File

@@ -0,0 +1,807 @@
// Ported to ESP32-C6 Arduino By ATC1441(ATCnetz.de) for OpenEPaperLink at ~01.2024
#include "led.h"
#include "proto.h"
#include "radio.h"
#include "subGhz.h"
#include "driver/gpio.h"
#include "driver/uart.h"
#include "esp_log.h"
#include "esp_err.h"
#include "esp_event.h"
#include "esp_ieee802154.h"
#include "esp_phy_init.h"
#include "esp_timer.h"
#include "freertos/FreeRTOS.h"
#include "freertos/queue.h"
#include "freertos/task.h"
#include "sdkconfig.h"
#include "second_uart.h"
#include "soc/lp_uart_reg.h"
#include "soc/uart_struct.h"
#include <esp_mac.h>
#include <math.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
static const char *TAG = "MAIN";
const uint8_t channelList[6] = { 11, 15, 20, 25, 26, 27 };
#define DATATYPE_NOUPDATE 0
#define HW_TYPE 0xC6
#define MAX_PENDING_MACS 250
#define HOUSEKEEPING_INTERVAL 60UL
struct pendingData pendingDataArr[MAX_PENDING_MACS];
// VERSION GOES HERE!
uint16_t version = 0x001A;
#define RAW_PKT_PADDING 2
uint8_t radiotxbuffer[135];
uint8_t radiorxbuffer[135];
static uint32_t housekeepingTimer;
struct blockRequest requestedData = { 0 }; // holds which data was requested by the tag
uint8_t dstMac[8]; // target for the block transfer
uint16_t dstPan; //
static uint32_t blockStartTimer = 0; // reference that holds when the AP sends the next block
uint32_t nextBlockAttempt = 0; // reference time for when the AP can request a new block from the ESP32
uint8_t seq = 0; // holds current sequence number for transmission
uint8_t blockbuffer[BLOCK_XFER_BUFFER_SIZE + 5]; // block transfer buffer
uint8_t lastAckMac[8] = { 0 };
// these variables hold the current mac were talking to
#define CONCURRENT_REQUEST_DELAY 1200UL
uint32_t lastBlockRequest = 0;
uint8_t lastBlockMac[8];
uint8_t lastTagReturn[8];
uint8_t curChannel = 25;
uint8_t curPower = 10;
uint8_t curPendingData = 0;
uint8_t curNoUpdate = 0;
bool highspeedSerial = false;
void sendXferCompleteAck(uint8_t *dst, bool isSubGHz);
void sendCancelXfer(uint8_t *dst, bool isSubGHz);
void espNotifyAPInfo();
// tools
void addCRC(void *p, uint8_t len) {
uint8_t total = 0;
for (uint8_t c = 1; c < len; c++) {
total += ((uint8_t *)p)[c];
}
((uint8_t *)p)[0] = total;
}
bool checkCRC(void *p, uint8_t len) {
uint8_t total = 0;
for (uint8_t c = 1; c < len; c++) {
total += ((uint8_t *)p)[c];
}
return ((uint8_t *)p)[0] == total;
}
uint8_t getPacketType(void *buffer) {
struct MacFcs *fcs = (MacFcs *)buffer;
if ((fcs->frameType == 1) && (fcs->destAddrType == 2) && (fcs->srcAddrType == 3) && (fcs->panIdCompressed == 0)) {
// broadcast frame
uint8_t type = ((uint8_t *)buffer)[sizeof(struct MacFrameBcast)];
return type;
} else if ((fcs->frameType == 1) && (fcs->destAddrType == 3) && (fcs->srcAddrType == 3) && (fcs->panIdCompressed == 1)) {
// normal frame
uint8_t type = ((uint8_t *)buffer)[sizeof(struct MacFrameNormal)];
return type;
}
return 0;
}
uint8_t getBlockDataLength() {
uint8_t partNo = 0;
for (uint8_t c = 0; c < BLOCK_MAX_PARTS; c++) {
if (requestedData.requestedParts[c / 8] & (1 << (c % 8))) {
partNo++;
}
}
return partNo;
}
// pendingdata slot stuff
int8_t findSlotForMac(const uint8_t *mac) {
for (uint8_t c = 0; c < MAX_PENDING_MACS; c++) {
if (memcmp(mac, ((uint8_t *) & (pendingDataArr[c].targetMac)), 8) == 0) {
if (pendingDataArr[c].attemptsLeft != 0) {
return c;
}
}
}
return -1;
}
int8_t findFreeSlot() {
for (uint8_t c = 0; c < MAX_PENDING_MACS; c++) {
if (pendingDataArr[c].attemptsLeft == 0) {
return c;
}
}
return -1;
}
int8_t findSlotForVer(const uint8_t *ver) {
for (uint8_t c = 0; c < MAX_PENDING_MACS; c++) {
if (memcmp(ver, ((uint8_t *) & (pendingDataArr[c].availdatainfo.dataVer)), 8) == 0) {
if (pendingDataArr[c].attemptsLeft != 0) return c;
}
}
return -1;
}
void deleteAllPendingDataForVer(const uint8_t *ver) {
int8_t slot = -1;
do {
slot = findSlotForVer(ver);
if (slot != -1) pendingDataArr[slot].attemptsLeft = 0;
} while (slot != -1);
}
void deleteAllPendingDataForMac(const uint8_t *mac) {
int8_t slot = -1;
do {
slot = findSlotForMac(mac);
if (slot != -1) pendingDataArr[slot].attemptsLeft = 0;
} while (slot != -1);
}
void countSlots() {
curPendingData = 0;
curNoUpdate = 0;
for (uint8_t c = 0; c < MAX_PENDING_MACS; c++) {
if (pendingDataArr[c].attemptsLeft != 0) {
if (pendingDataArr[c].availdatainfo.dataType != 0) {
curPendingData++;
} else {
curNoUpdate++;
}
}
}
}
// processing serial data
#define ZBS_RX_WAIT_HEADER 0
#define ZBS_RX_WAIT_SDA 1 // send data avail
#define ZBS_RX_WAIT_CANCEL 2 // cancel traffic for mac
#define ZBS_RX_WAIT_SCP 3 // set channel power
#define ZBS_RX_WAIT_BLOCKDATA 4
bool isSame(uint8_t *in1, char *in2, int len) {
bool flag = 1;
for (int i = 0; i < len; i++) {
if (in1[i] != in2[i]) flag = 0;
}
return flag;
}
int blockPosition = 0;
void processSerial(uint8_t lastchar) {
static uint8_t cmdbuffer[4];
static uint8_t RXState = 0;
static uint8_t serialbuffer[48];
static uint8_t *serialbufferp;
static uint8_t bytesRemain = 0;
static uint32_t lastSerial = 0;
static uint32_t blockStartTime = 0;
if ((RXState != ZBS_RX_WAIT_HEADER) && ((millis() - lastSerial) > 1000)) {
RXState = ZBS_RX_WAIT_HEADER;
ESP_LOGI(TAG, "UART Timeout");
}
lastSerial = millis();
switch (RXState) {
case ZBS_RX_WAIT_HEADER:
// shift characters in
for (uint8_t c = 0; c < 3; c++) {
cmdbuffer[c] = cmdbuffer[c + 1];
}
cmdbuffer[3] = lastchar;
if (isSame(cmdbuffer + 1, ">D>", 3)) {
pr("ACK>");
blockStartTime = millis();
ESP_LOGI(TAG, "Starting BlkData, %lu ms after request", blockStartTime - nextBlockAttempt );
blockPosition = 0;
RXState = ZBS_RX_WAIT_BLOCKDATA;
}
if (isSame(cmdbuffer, "SDA>", 4)) {
ESP_LOGI(TAG, "SDA In");
RXState = ZBS_RX_WAIT_SDA;
bytesRemain = sizeof(struct pendingData);
serialbufferp = serialbuffer;
break;
}
if (isSame(cmdbuffer, "CXD>", 4)) {
ESP_LOGI(TAG, "CXD In");
RXState = ZBS_RX_WAIT_CANCEL;
bytesRemain = sizeof(struct pendingData);
serialbufferp = serialbuffer;
break;
}
if (isSame(cmdbuffer, "SCP>", 4)) {
ESP_LOGI(TAG, "SCP In");
RXState = ZBS_RX_WAIT_SCP;
bytesRemain = sizeof(struct espSetChannelPower);
serialbufferp = serialbuffer;
break;
}
if (isSame(cmdbuffer, "NFO?", 4)) {
pr("ACK>");
ESP_LOGI(TAG, "NFO? In");
espNotifyAPInfo();
RXState = ZBS_RX_WAIT_HEADER;
}
if (isSame(cmdbuffer, "RDY?", 4)) {
pr("ACK>");
ESP_LOGI(TAG, "RDY? In");
RXState = ZBS_RX_WAIT_HEADER;
}
if (isSame(cmdbuffer, "RSET", 4)) {
pr("ACK>");
ESP_LOGI(TAG, "RSET In");
delay(100);
// TODO RESET US HERE
RXState = ZBS_RX_WAIT_HEADER;
}
if (isSame(cmdbuffer, "HSPD", 4)) {
pr("ACK>");
ESP_LOGI(TAG, "HSPD In, switching to 2000000");
delay(100);
uart_switch_speed(2000000);
delay(100);
highspeedSerial = true;
pr("ACK>");
RXState = ZBS_RX_WAIT_HEADER;
}
break;
case ZBS_RX_WAIT_BLOCKDATA:
blockbuffer[blockPosition++] = 0xAA ^ lastchar;
if (blockPosition >= 4100) {
ESP_LOGI(TAG, "Blockdata fully received in %lu ms, %lu ms after the request", millis() - blockStartTime, millis() - nextBlockAttempt);
RXState = ZBS_RX_WAIT_HEADER;
}
break;
case ZBS_RX_WAIT_SDA:
*serialbufferp = lastchar;
serialbufferp++;
bytesRemain--;
if (bytesRemain == 0) {
if (checkCRC(serialbuffer, sizeof(struct pendingData))) {
struct pendingData *pd = (struct pendingData *)serialbuffer;
int8_t slot = findSlotForMac(pd->targetMac);
if (slot == -1) slot = findFreeSlot();
if (slot != -1) {
memcpy(&(pendingDataArr[slot]), serialbuffer, sizeof(struct pendingData));
pr("ACK>");
} else {
pr("NOQ>");
}
} else {
pr("NOK>");
}
RXState = ZBS_RX_WAIT_HEADER;
}
break;
case ZBS_RX_WAIT_CANCEL:
*serialbufferp = lastchar;
serialbufferp++;
bytesRemain--;
if (bytesRemain == 0) {
if (checkCRC(serialbuffer, sizeof(struct pendingData))) {
struct pendingData *pd = (struct pendingData *)serialbuffer;
deleteAllPendingDataForMac((uint8_t *)&pd->targetMac);
pr("ACK>");
} else {
pr("NOK>");
}
RXState = ZBS_RX_WAIT_HEADER;
}
break;
case ZBS_RX_WAIT_SCP:
*serialbufferp = lastchar;
serialbufferp++;
bytesRemain--;
if (bytesRemain == 0) {
if (checkCRC(serialbuffer, sizeof(struct espSetChannelPower))) {
struct espSetChannelPower *scp = (struct espSetChannelPower *)serialbuffer;
for (uint8_t c = 0; c < sizeof(channelList); c++) {
if (channelList[c] == scp->channel) goto SCPchannelFound;
}
goto SCPfailed;
SCPchannelFound:
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);
} else {
SCPfailed:
pr("NOK>");
}
RXState = ZBS_RX_WAIT_HEADER;
}
break;
}
}
// sending data to the ESP
void espBlockRequest(const struct blockRequest *br, uint8_t *src) {
struct espBlockRequest *ebr = (struct espBlockRequest *)blockbuffer;
uartTx('R');
uartTx('Q');
uartTx('B');
uartTx('>');
memcpy(&(ebr->ver), &(br->ver), 8);
memcpy(&(ebr->src), src, 8);
ebr->blockId = br->blockId;
addCRC(ebr, sizeof(struct espBlockRequest));
for (uint8_t c = 0; c < sizeof(struct espBlockRequest); c++) {
uartTx(((uint8_t *)ebr)[c]);
}
}
void espNotifyAvailDataReq(const struct AvailDataReq *adr, const uint8_t *src) {
uartTx('A');
uartTx('D');
uartTx('R');
uartTx('>');
struct espAvailDataReq eadr = { 0 };
memcpy((void *)eadr.src, (void *)src, 8);
memcpy((void *)&eadr.adr, (void *)adr, sizeof(struct AvailDataReq));
addCRC(&eadr, sizeof(struct espAvailDataReq));
for (uint8_t c = 0; c < sizeof(struct espAvailDataReq); c++) {
uartTx(((uint8_t *)&eadr)[c]);
}
}
void espNotifyXferComplete(const uint8_t *src) {
struct espXferComplete exfc;
memcpy(&exfc.src, src, 8);
uartTx('X');
uartTx('F');
uartTx('C');
uartTx('>');
addCRC(&exfc, sizeof(exfc));
for (uint8_t c = 0; c < sizeof(exfc); c++) {
uartTx(((uint8_t *)&exfc)[c]);
}
}
void espNotifyTimeOut(const uint8_t *src) {
struct espXferComplete exfc;
memcpy(&exfc.src, src, 8);
uartTx('X');
uartTx('T');
uartTx('O');
uartTx('>');
addCRC(&exfc, sizeof(exfc));
for (uint8_t c = 0; c < sizeof(exfc); c++) {
uartTx(((uint8_t *)&exfc)[c]);
}
}
void espNotifyAPInfo() {
pr("TYP>%02X", HW_TYPE);
pr("VER>%04X", version);
pr("MAC>%02X%02X", mSelfMac[0], mSelfMac[1]);
pr("%02X%02X", mSelfMac[2], mSelfMac[3]);
pr("%02X%02X", mSelfMac[4], mSelfMac[5]);
pr("%02X%02X", mSelfMac[6], mSelfMac[7]);
pr("ZCH>%02X", curChannel);
pr("ZPW>%02X", curPower);
countSlots();
pr("PEN>%02X", curPendingData);
pr("NOP>%02X", curNoUpdate);
}
void espNotifyTagReturnData(uint8_t *src, uint8_t len) {
struct tagReturnData *trd = (struct tagReturnData *)(radiorxbuffer + sizeof(struct MacFrameBcast) + 1); // oh how I'd love to pass this as an argument, but sdcc won't let me
struct espTagReturnData *etrd = (struct espTagReturnData *)radiotxbuffer;
if (memcmp((void *)&trd->dataVer, lastTagReturn, 8) == 0) {
return;
} else {
memcpy(lastTagReturn, &trd->dataVer, 8);
}
memcpy(etrd->src, src, 8);
etrd->len = len;
memcpy(&etrd->returnData, trd, len);
addCRC(etrd, len + 10);
uartTx('T');
uartTx('R');
uartTx('D');
uartTx('>');
for (uint8_t c = 0; c < len + 10; c++) {
uartTx(((uint8_t *)etrd)[c]);
}
}
// process data from tag
void processBlockRequest(const uint8_t *buffer, uint8_t forceBlockDownload, bool isSubGHz) {
struct MacFrameNormal *rxHeader = (struct MacFrameNormal *)buffer;
struct blockRequest *blockReq = (struct blockRequest *)(buffer + sizeof(struct MacFrameNormal) + 1);
if (!checkCRC(blockReq, sizeof(struct blockRequest))) return;
// check if we're already talking to this mac
if (memcmp(rxHeader->src, lastBlockMac, 8) == 0) {
lastBlockRequest = millis();
} else {
// we weren't talking to this mac, see if there was a transfer in progress from another mac, recently
if ((millis() - lastBlockRequest) > CONCURRENT_REQUEST_DELAY) {
// mark this mac as the new current mac we're talking to
memcpy((void *)lastBlockMac, (void *)rxHeader->src, 8);
lastBlockRequest = millis();
} else {
// we're talking to another mac, let this mac know we can't accomodate another request right now
pr("BUSY!\n");
sendCancelXfer(rxHeader->src, isSubGHz);
return;
}
}
// check if we have data for this mac
if (findSlotForMac(rxHeader->src) == -1) {
// no data for this mac, politely tell it to fuck off
sendCancelXfer(rxHeader->src, isSubGHz);
return;
}
bool requestDataDownload = false;
if ((blockReq->blockId != requestedData.blockId) || (blockReq->ver != requestedData.ver)) {
// requested block isn't already in the buffer
requestDataDownload = true;
} else {
// requested block is already in the buffer
if (forceBlockDownload) {
if ((millis() - nextBlockAttempt) > 380) {
requestDataDownload = true;
pr("FORCED\n");
} else {
pr("IGNORED\n");
}
}
}
// copy blockrequest into requested data
memcpy(&requestedData, blockReq, sizeof(struct blockRequest));
struct MacFrameNormal *txHeader = (struct MacFrameNormal *)(radiotxbuffer + 1);
struct blockRequestAck *blockRequestAck = (struct blockRequestAck *)(radiotxbuffer + sizeof(struct MacFrameNormal) + 2);
radiotxbuffer[0] = sizeof(struct MacFrameNormal) + 1 + sizeof(struct blockRequestAck) + RAW_PKT_PADDING;
radiotxbuffer[sizeof(struct MacFrameNormal) + 1] = PKT_BLOCK_REQUEST_ACK;
if (blockStartTimer == 0) {
if (requestDataDownload) {
if (highspeedSerial == true) {
blockRequestAck->pleaseWaitMs = 140;
} else {
blockRequestAck->pleaseWaitMs = 550;
}
} else {
// block is already in buffer
blockRequestAck->pleaseWaitMs = 30;
}
} else {
blockRequestAck->pleaseWaitMs = 30;
}
blockStartTimer = millis() + blockRequestAck->pleaseWaitMs;
memcpy(txHeader->src, mSelfMac, 8);
memcpy(txHeader->dst, rxHeader->src, 8);
txHeader->pan = rxHeader->pan;
txHeader->fcs.frameType = 1;
txHeader->fcs.panIdCompressed = 1;
txHeader->fcs.destAddrType = 3;
txHeader->fcs.srcAddrType = 3;
txHeader->seq = seq++;
addCRC((void *)blockRequestAck, sizeof(struct blockRequestAck));
radioTx(radiotxbuffer, isSubGHz);
// save the target for the blockdata
memcpy(dstMac, rxHeader->src, 8);
dstPan = rxHeader->pan;
if (requestDataDownload) {
blockPosition = 0;
espBlockRequest(&requestedData, rxHeader->src);
nextBlockAttempt = millis();
}
}
void processAvailDataReq(uint8_t *buffer, bool isSubGHz) {
struct MacFrameBcast *rxHeader = (struct MacFrameBcast *)buffer;
struct AvailDataReq *availDataReq = (struct AvailDataReq *)(buffer + sizeof(struct MacFrameBcast) + 1);
if (!checkCRC(availDataReq, sizeof(struct AvailDataReq))) return;
// prepare tx buffer to send a response
memset(radiotxbuffer, 0, sizeof(struct MacFrameNormal) + sizeof(struct AvailDataInfo) + 2); // 120);
struct MacFrameNormal *txHeader = (struct MacFrameNormal *)(radiotxbuffer + 1);
struct AvailDataInfo *availDataInfo = (struct AvailDataInfo *)(radiotxbuffer + sizeof(struct MacFrameNormal) + 2);
radiotxbuffer[0] = sizeof(struct MacFrameNormal) + 1 + sizeof(struct AvailDataInfo) + RAW_PKT_PADDING;
radiotxbuffer[sizeof(struct MacFrameNormal) + 1] = PKT_AVAIL_DATA_INFO;
// check to see if we have data available for this mac
bool haveData = false;
for (uint8_t c = 0; c < MAX_PENDING_MACS; c++) {
if (pendingDataArr[c].attemptsLeft) {
if (memcmp(pendingDataArr[c].targetMac, rxHeader->src, 8) == 0) {
haveData = true;
memcpy((void *)availDataInfo, &(pendingDataArr[c].availdatainfo), sizeof(struct AvailDataInfo));
break;
}
}
}
// couldn't find data for this mac
if (!haveData) availDataInfo->dataType = DATATYPE_NOUPDATE;
memcpy(txHeader->src, mSelfMac, 8);
memcpy(txHeader->dst, rxHeader->src, 8);
txHeader->pan = rxHeader->dstPan;
txHeader->fcs.frameType = 1;
txHeader->fcs.panIdCompressed = 1;
txHeader->fcs.destAddrType = 3;
txHeader->fcs.srcAddrType = 3;
txHeader->seq = seq++;
addCRC(availDataInfo, sizeof(struct AvailDataInfo));
radioTx(radiotxbuffer, isSubGHz);
memset(lastAckMac, 0, 8); // reset lastAckMac, so we can record if we've received exactly one ack packet
espNotifyAvailDataReq(availDataReq, rxHeader->src);
}
void processXferComplete(uint8_t *buffer, bool isSubGHz) {
struct MacFrameNormal *rxHeader = (struct MacFrameNormal *)buffer;
sendXferCompleteAck(rxHeader->src, isSubGHz);
if (memcmp(lastAckMac, rxHeader->src, 8) != 0) {
memcpy((void *)lastAckMac, (void *)rxHeader->src, 8);
espNotifyXferComplete(rxHeader->src);
int8_t slot = findSlotForMac(rxHeader->src);
if (slot != -1) pendingDataArr[slot].attemptsLeft = 0;
}
}
void processTagReturnData(uint8_t *buffer, uint8_t len, bool isSubGHz) {
struct MacFrameBcast *rxframe = (struct MacFrameBcast *)buffer;
struct MacFrameNormal *frameHeader = (struct MacFrameNormal *)(radiotxbuffer + 1);
if (!checkCRC((buffer + sizeof(struct MacFrameBcast) + 1), len - (sizeof(struct MacFrameBcast) + 1))) {
return;
}
radiotxbuffer[sizeof(struct MacFrameNormal) + 1] = PKT_TAG_RETURN_DATA_ACK;
radiotxbuffer[0] = sizeof(struct MacFrameNormal) + 1 + RAW_PKT_PADDING;
memcpy(frameHeader->src, mSelfMac, 8);
memcpy(frameHeader->dst, rxframe->src, 8);
radiotxbuffer[1] = 0x41; // fast way to set the appropriate bits
radiotxbuffer[2] = 0xCC; // normal frame
frameHeader->seq = seq++;
frameHeader->pan = rxframe->srcPan;
radioTx(radiotxbuffer, isSubGHz);
espNotifyTagReturnData(rxframe->src, len - (sizeof(struct MacFrameBcast) + 1));
}
// send block data to the tag
void sendPart(uint8_t partNo, bool isSubGHz) {
struct MacFrameNormal *frameHeader = (struct MacFrameNormal *)(radiotxbuffer + 1);
struct blockPart *blockPart = (struct blockPart *)(radiotxbuffer + sizeof(struct MacFrameNormal) + 2);
memset(radiotxbuffer + 1, 0, sizeof(struct blockPart) + sizeof(struct MacFrameNormal));
radiotxbuffer[sizeof(struct MacFrameNormal) + 1] = PKT_BLOCK_PART;
radiotxbuffer[0] = sizeof(struct MacFrameNormal) + sizeof(struct blockPart) + BLOCK_PART_DATA_SIZE + 1 + RAW_PKT_PADDING;
memcpy(frameHeader->src, mSelfMac, 8);
memcpy(frameHeader->dst, dstMac, 8);
blockPart->blockId = requestedData.blockId;
blockPart->blockPart = partNo;
memcpy(&(blockPart->data), blockbuffer + (partNo * BLOCK_PART_DATA_SIZE), BLOCK_PART_DATA_SIZE);
addCRC(blockPart, sizeof(struct blockPart) + BLOCK_PART_DATA_SIZE);
frameHeader->fcs.frameType = 1;
frameHeader->fcs.panIdCompressed = 1;
frameHeader->fcs.destAddrType = 3;
frameHeader->fcs.srcAddrType = 3;
frameHeader->seq = seq++;
frameHeader->pan = dstPan;
radioTx(radiotxbuffer, isSubGHz);
}
void sendBlockData(bool isSubGHz) {
if (getBlockDataLength() == 0) {
pr("Invalid block request received, 0 parts..\n");
requestedData.requestedParts[0] |= 0x01;
}
pr("Sending parts:");
for (uint8_t c = 0; (c < BLOCK_MAX_PARTS); c++) {
if (c % 10 == 0) pr(" ");
if (requestedData.requestedParts[c / 8] & (1 << (c % 8))) {
pr("X");
} else {
pr(".");
}
}
pr("\n");
uint8_t partNo = 0;
while (partNo < BLOCK_MAX_PARTS) {
for (uint8_t c = 0; (c < BLOCK_MAX_PARTS) && (partNo < BLOCK_MAX_PARTS); c++) {
if (requestedData.requestedParts[c / 8] & (1 << (c % 8))) {
sendPart(c, isSubGHz);
partNo++;
}
}
}
}
void sendXferCompleteAck(uint8_t *dst, bool isSubGHz) {
struct MacFrameNormal *frameHeader = (struct MacFrameNormal *)(radiotxbuffer + 1);
memset(radiotxbuffer + 1, 0, sizeof(struct blockPart) + sizeof(struct MacFrameNormal));
radiotxbuffer[sizeof(struct MacFrameNormal) + 1] = PKT_XFER_COMPLETE_ACK;
radiotxbuffer[0] = sizeof(struct MacFrameNormal) + 1 + RAW_PKT_PADDING;
memcpy(frameHeader->src, mSelfMac, 8);
memcpy(frameHeader->dst, dst, 8);
frameHeader->fcs.frameType = 1;
frameHeader->fcs.panIdCompressed = 1;
frameHeader->fcs.destAddrType = 3;
frameHeader->fcs.srcAddrType = 3;
frameHeader->seq = seq++;
frameHeader->pan = dstPan;
radioTx(radiotxbuffer, isSubGHz);
}
void sendCancelXfer(uint8_t *dst, bool isSubGHz) {
struct MacFrameNormal *frameHeader = (struct MacFrameNormal *)(radiotxbuffer + 1);
memset(radiotxbuffer + 1, 0, sizeof(struct blockPart) + sizeof(struct MacFrameNormal));
radiotxbuffer[sizeof(struct MacFrameNormal) + 1] = PKT_CANCEL_XFER;
radiotxbuffer[0] = sizeof(struct MacFrameNormal) + 1 + RAW_PKT_PADDING;
memcpy(frameHeader->src, mSelfMac, 8);
memcpy(frameHeader->dst, dst, 8);
frameHeader->fcs.frameType = 1;
frameHeader->fcs.panIdCompressed = 1;
frameHeader->fcs.destAddrType = 3;
frameHeader->fcs.srcAddrType = 3;
frameHeader->seq = seq++;
frameHeader->pan = dstPan;
radioTx(radiotxbuffer, isSubGHz);
}
void sendPong(void *buf, bool isSubGHz) {
struct MacFrameBcast *rxframe = (struct MacFrameBcast *)buf;
struct MacFrameNormal *frameHeader = (struct MacFrameNormal *)(radiotxbuffer + 1);
radiotxbuffer[sizeof(struct MacFrameNormal) + 1] = PKT_PONG;
radiotxbuffer[sizeof(struct MacFrameNormal) + 2] = curChannel;
radiotxbuffer[0] = sizeof(struct MacFrameNormal) + 1 + 1 + RAW_PKT_PADDING;
memcpy(frameHeader->src, mSelfMac, 8);
memcpy(frameHeader->dst, rxframe->src, 8);
radiotxbuffer[1] = 0x41; // fast way to set the appropriate bits
radiotxbuffer[2] = 0xCC; // normal frame
frameHeader->seq = seq++;
frameHeader->pan = rxframe->srcPan;
radioTx(radiotxbuffer, isSubGHz);
}
extern uint8_t mSelfMac[8];
void setup() {
//Serial.begin(115200);
init_led();
init_second_uart();
requestedData.blockId = 0xFF;
// clear the array with pending information
memset(pendingDataArr, 0, sizeof(pendingDataArr));
radio_init(curChannel);
radioSetTxPower(10);
pr("RES>");
pr("RDY>");
ESP_LOGI(TAG, "C6 ready!");
housekeepingTimer = millis();
}
bool isSubGhzRx = false;
void loop() {
while ((millis() - housekeepingTimer) < ((1000 * HOUSEKEEPING_INTERVAL) - 100)) {
int8_t ret = commsRxUnencrypted(radiorxbuffer, &isSubGhzRx);
if (ret > 1) {
if (0)
{
Serial.printf("RXed packet len %u :", ret);
for (int t = 0; t < ret; t++) {
Serial.printf(" %02x", radiorxbuffer[t]);
}
Serial.printf("\n");
}
if (isSubGhzRx) {
ESP_LOGD(TAG, "RXed packet %s len %u", isSubGhzRx ? "subGhz" : "2.4Ghz", ret);
ESP_LOGD(TAG, "First bytes: %02X %02X %02X %02X %02X", radiorxbuffer[0], radiorxbuffer[1], radiorxbuffer[2], radiorxbuffer[3], radiorxbuffer[4]);
}
led_flash(0);
// received a packet, lets see what it is
switch (getPacketType(radiorxbuffer)) {
case PKT_AVAIL_DATA_REQ:
if (ret == 28) {
// old version of the AvailDataReq struct, set all the new fields to zero, so it will pass the CRC
memset(radiorxbuffer + 1 + sizeof(struct MacFrameBcast) + sizeof(struct oldAvailDataReq), 0,
sizeof(struct AvailDataReq) - sizeof(struct oldAvailDataReq) + 2);
processAvailDataReq(radiorxbuffer, isSubGhzRx);
} else if (ret == 40) {
// new version of the AvailDataReq struct
processAvailDataReq(radiorxbuffer, isSubGhzRx);
}
break;
case PKT_BLOCK_REQUEST:
processBlockRequest(radiorxbuffer, 1, isSubGhzRx);
break;
case PKT_BLOCK_PARTIAL_REQUEST:
processBlockRequest(radiorxbuffer, 0, isSubGhzRx);
break;
case PKT_XFER_COMPLETE:
processXferComplete(radiorxbuffer, isSubGhzRx);
break;
case PKT_PING:
sendPong(radiorxbuffer, isSubGhzRx);
break;
case PKT_AVAIL_DATA_SHORTREQ:
// a short AvailDataReq is basically a very short (1 byte payload) packet that requires little preparation on the tx side, for optimal
// battery use bytes of the struct are set 0, so it passes the checksum test, and the ESP32 can detect that no interesting payload is
// sent
if (ret == 18) {
memset(radiorxbuffer + 1 + sizeof(struct MacFrameBcast), 0, sizeof(struct AvailDataReq) + 2);
processAvailDataReq(radiorxbuffer, isSubGhzRx);
}
break;
case PKT_TAG_RETURN_DATA:
processTagReturnData(radiorxbuffer, ret, isSubGhzRx);
break;
default:
ESP_LOGI(TAG, "t=%02X" , getPacketType(radiorxbuffer));
break;
}
} else if (blockStartTimer == 0) {
delay(10);
}
uint8_t curr_char;
while (getRxCharSecond(&curr_char)) processSerial(curr_char);
if (blockStartTimer) {
if (millis() > blockStartTimer) {
sendBlockData(isSubGhzRx);
blockStartTimer = 0;
}
}
}
radio_housekeeping();
memset(&lastTagReturn, 0, 8);
for (uint8_t cCount = 0; cCount < MAX_PENDING_MACS; cCount++) {
if (pendingDataArr[cCount].attemptsLeft == 1) {
if (pendingDataArr[cCount].availdatainfo.dataType != DATATYPE_NOUPDATE) {
espNotifyTimeOut(pendingDataArr[cCount].targetMac);
}
pendingDataArr[cCount].attemptsLeft = 0;
} else if (pendingDataArr[cCount].attemptsLeft > 1) {
pendingDataArr[cCount].attemptsLeft--;
if (pendingDataArr[cCount].availdatainfo.nextCheckIn) pendingDataArr[cCount].availdatainfo.nextCheckIn--;
}
}
housekeepingTimer = millis();
}

View File

@@ -0,0 +1,44 @@
#include "led.h"
#include "driver/gpio.h"
#include "freertos/FreeRTOS.h"
#include "freertos/queue.h"
#include "freertos/task.h"
#include "freertos/timers.h"
#include "proto.h"
#include <Arduino.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NUM_LEDS 2
const uint8_t led_pins[NUM_LEDS] = { LED1, LED2 };
TimerHandle_t led_timers[NUM_LEDS] = { 0 };
void led_timer_callback(TimerHandle_t xTimer) {
int led_index = (int)pvTimerGetTimerID(xTimer);
if (led_index >= 0 && led_index < NUM_LEDS) {
digitalWrite(led_pins[led_index], 0);
}
}
void init_led() {
pinMode(LED1,OUTPUT);
pinMode(LED2,OUTPUT);
for (int i = 0; i < NUM_LEDS; i++) {
led_timers[i] = xTimerCreate("led_timer", pdMS_TO_TICKS(50), pdFALSE, (void *)i, led_timer_callback);
}
}
void led_flash(int nr) {
digitalWrite(led_pins[nr], 1);
if (nr >= 0 && nr < NUM_LEDS) {
xTimerStart(led_timers[nr], 0);
}
}
void led_set(int nr, bool state) {
digitalWrite(nr, state);
}

View File

@@ -0,0 +1,6 @@
#pragma once
#include <stdbool.h>
void init_led();
void led_set(int nr, bool state);
void led_flash(int nr);

View File

@@ -0,0 +1,190 @@
#ifndef _PROTO_H_
#define _PROTO_H_
#include <stdint.h>
#define LED1 22
#define LED2 23
#define PROTO_PAN_ID (0x4447) // PAN ID compression shall be used
#define RADIO_MAX_PACKET_LEN (125) // useful payload, not including the crc
#define ADDR_MODE_NONE (0)
#define ADDR_MODE_SHORT (2)
#define ADDR_MODE_LONG (3)
#define FRAME_TYPE_BEACON (0)
#define FRAME_TYPE_DATA (1)
#define FRAME_TYPE_ACK (2)
#define FRAME_TYPE_MAC_CMD (3)
#define SHORT_MAC_UNUSED (0x10000000UL) // for radioRxFilterCfg's myShortMac
struct MacFcs {
uint8_t frameType : 3;
uint8_t secure : 1;
uint8_t framePending : 1;
uint8_t ackReqd : 1;
uint8_t panIdCompressed : 1;
uint8_t rfu1 : 1;
uint8_t rfu2 : 2;
uint8_t destAddrType : 2;
uint8_t frameVer : 2;
uint8_t srcAddrType : 2;
} __attribute__((packed, aligned(1)));
struct MacFrameFromMaster {
struct MacFcs fcs;
uint8_t seq;
uint16_t pan;
uint8_t dst[8];
uint16_t from;
} __attribute__((packed, aligned(1)));
struct MacFrameNormal {
struct MacFcs fcs;
uint8_t seq;
uint16_t pan;
uint8_t dst[8];
uint8_t src[8];
} __attribute__((packed, aligned(1)));
struct MacFrameBcast {
struct MacFcs fcs;
uint8_t seq;
uint16_t dstPan;
uint16_t dstAddr;
uint16_t srcPan;
uint8_t src[8];
} __attribute__((packed, aligned(1)));
#define PKT_TAG_RETURN_DATA 0xE1
#define PKT_TAG_RETURN_DATA_ACK 0xE2
#define PKT_AVAIL_DATA_SHORTREQ 0xE3
#define PKT_AVAIL_DATA_REQ 0xE5
#define PKT_AVAIL_DATA_INFO 0xE6
#define PKT_BLOCK_PARTIAL_REQUEST 0xE7
#define PKT_BLOCK_REQUEST_ACK 0xE9
#define PKT_BLOCK_REQUEST 0xE4
#define PKT_BLOCK_PART 0xE8
#define PKT_XFER_COMPLETE 0xEA
#define PKT_XFER_COMPLETE_ACK 0xEB
#define PKT_CANCEL_XFER 0xEC
#define PKT_PING 0xED
#define PKT_PONG 0xEE
struct AvailDataReq {
uint8_t checksum;
uint8_t lastPacketLQI;
int8_t lastPacketRSSI;
int8_t temperature;
uint16_t batteryMv;
uint8_t hwType;
uint8_t wakeupReason;
uint8_t capabilities;
uint16_t tagSoftwareVersion;
uint8_t currentChannel;
uint8_t customMode;
uint8_t reserved[8];
} __attribute__((packed, aligned(1)));
struct oldAvailDataReq {
uint8_t checksum;
uint8_t lastPacketLQI;
int8_t lastPacketRSSI;
int8_t temperature;
uint16_t batteryMv;
uint8_t hwType;
uint8_t wakeupReason;
uint8_t capabilities;
} __attribute__((packed, aligned(1)));
struct AvailDataInfo {
uint8_t checksum;
uint64_t dataVer; // MD5 of potential traffic
uint32_t dataSize;
uint8_t dataType;
uint8_t dataTypeArgument; // extra specification or instruction for the tag (LUT to be used for drawing image)
uint16_t nextCheckIn; // when should the tag check-in again? Measured in minutes
} __attribute__((packed, aligned(1)));
struct pendingData {
struct AvailDataInfo availdatainfo;
uint16_t attemptsLeft;
uint8_t targetMac[8];
} __attribute__((packed, aligned(1)));
struct blockPart {
uint8_t checksum;
uint8_t blockId;
uint8_t blockPart;
uint8_t data[];
} __attribute__((packed, aligned(1)));
struct blockData {
uint16_t size;
uint16_t checksum;
uint8_t data[];
} __attribute__((packed, aligned(1)));
#define TAG_RETURN_DATA_SIZE 90
struct tagReturnData {
uint8_t checksum;
uint8_t partId;
uint64_t dataVer;
uint8_t dataType;
uint8_t data[TAG_RETURN_DATA_SIZE];
} __attribute__((packed, aligned(1)));
#define BLOCK_PART_DATA_SIZE 99
#define BLOCK_MAX_PARTS 42
#define BLOCK_DATA_SIZE 4096UL
#define BLOCK_XFER_BUFFER_SIZE BLOCK_DATA_SIZE + sizeof(struct blockData)
#define BLOCK_REQ_PARTS_BYTES 6
struct blockRequest {
uint8_t checksum;
uint64_t ver;
uint8_t blockId;
uint8_t type;
uint8_t requestedParts[BLOCK_REQ_PARTS_BYTES];
} __attribute__((packed, aligned(1)));
struct blockRequestAck {
uint8_t checksum;
uint16_t pleaseWaitMs;
} __attribute__((packed, aligned(1)));
struct espBlockRequest {
uint8_t checksum;
uint64_t ver;
uint8_t blockId;
uint8_t src[8];
} __attribute__((packed, aligned(1)));
struct espXferComplete {
uint8_t checksum;
uint8_t src[8];
} __attribute__((packed, aligned(1)));
struct espAvailDataReq {
uint8_t checksum;
uint8_t src[8];
struct AvailDataReq adr;
} __attribute__((packed, aligned(1)));
struct espSetChannelPower {
uint8_t checksum;
uint8_t channel;
uint8_t power;
} __attribute__((packed, aligned(1)));
struct espTagReturnData {
uint8_t checksum;
uint8_t src[8];
uint8_t len;
struct tagReturnData returnData;
} __attribute__((packed, aligned(1)));
#endif

View File

@@ -0,0 +1,170 @@
#include "radio.h"
#include "driver/gpio.h"
#include "driver/uart.h"
#include "esp_log.h"
#include "esp_err.h"
#include "esp_event.h"
#include "esp_ieee802154.h"
#include "esp_phy_init.h"
#include "esp_timer.h"
#include "freertos/FreeRTOS.h"
#include "freertos/queue.h"
#include "freertos/task.h"
#include "led.h"
#include "subGhz.h"
#include "proto.h"
#include "sdkconfig.h"
// if you get an error about soc/lp_uart_reg.h not being found,
// you didn't choose the right build target. :-)
#include "soc/lp_uart_reg.h"
#include "soc/uart_struct.h"
#include <esp_mac.h>
#include <math.h>
#include <stdarg.h>
#include <string.h>
#include <Arduino.h>
static const char *TAG = "RADIO";
bool has_sub_ghz = false;
uint8_t mSelfMac[8];
volatile uint8_t isInTransmit = 0;
QueueHandle_t packet_buffer = NULL;
void esp_ieee802154_receive_done(uint8_t *frame, esp_ieee802154_frame_info_t *frame_info) {
ESP_LOGI(TAG, "RX %d", frame[0]);
BaseType_t xHigherPriorityTaskWoken;
static uint8_t inner_rxPKT[130];
memcpy(inner_rxPKT, &frame[0], frame[0] + 1);
xQueueSendFromISR(packet_buffer, (void *)&inner_rxPKT, &xHigherPriorityTaskWoken);
portYIELD_FROM_ISR_ARG(xHigherPriorityTaskWoken);
}
void esp_ieee802154_transmit_failed(const uint8_t *frame, esp_ieee802154_tx_error_t error) {
isInTransmit = 0;
ESP_LOGE(TAG, "TX Err: %d", error);
}
void esp_ieee802154_transmit_done(const uint8_t *frame, const uint8_t *ack, esp_ieee802154_frame_info_t *ack_frame_info) {
isInTransmit = 0;
ESP_LOGI(TAG, "TX %d", frame[0]);
}
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_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);
delay(100);
led_flash(0);
delay(100);
led_flash(1);
delay(100);
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());
if (has_sub_ghz) {// If radio is already working why activate it again^^
if (!tiRadioSetChannel(ch))
ESP_LOGI(TAG, "SubGHz radio channel fail");
} else {
// Lets here take care of the SubGhz Init
if (!init_subGhz())
ESP_LOGI(TAG, "Sub-GHz radio init failed");
else if (!tiRadioSetChannel(ch))
ESP_LOGI(TAG, "SubGHz radio channel fail");
else
has_sub_ghz = true;
ESP_LOGI(TAG, "SubGhz %s", has_sub_ghz ? "Active" : "Not Found");
if (has_sub_ghz) {
tiRadioRxFilterCfg(mSelfMac, SHORT_MAC_UNUSED, PROTO_PAN_ID, false);
tiRadioRxEnable(true, false);
}
}
}
// uint32_t lastZbTx = 0;
bool radioTx(uint8_t *packet, bool subGhz) {
led_flash(1);
if (has_sub_ghz && subGhz) {
tiRadioTxLL(packet);
} else {
static uint8_t txPKT[130];
while (isInTransmit) {
}
// while (millis() - lastZbTx < 6) {
// }
// lastZbTx = millis();
memcpy(txPKT, packet, packet[0]);
isInTransmit = 1;
esp_ieee802154_transmit(txPKT, false);
return true;
}
}
void radio_housekeeping()
{
if (has_sub_ghz) {
tiRadioRxEnable(false, false);
delayMicroseconds(500);
tiRadioRxEnable(true, false);
delayMicroseconds(500);
}
}
void radioSetChannel(uint8_t ch) {
radio_init(ch);
}
void radioSetTxPower(uint8_t power) {}
int8_t commsRxUnencrypted(uint8_t *data, bool *subGhzRx) {
int8_t rssi_sub_rx = 0;
uint8_t lqi_sub_rx = 0;
static uint8_t inner_rxPKT_out[135];
if (xQueueReceive(packet_buffer, (void *)&inner_rxPKT_out, pdMS_TO_TICKS(100)) == pdTRUE) {
memcpy(data, &inner_rxPKT_out[1], inner_rxPKT_out[0] + 1);
*subGhzRx = false; // This is Normal data
return inner_rxPKT_out[0] - 2;
}
if (has_sub_ghz) {
int32_t ret_sub_rx_len = tiRadioRxDequeuePkt(inner_rxPKT_out, sizeof(inner_rxPKT_out), &rssi_sub_rx, &lqi_sub_rx);
if (ret_sub_rx_len > 0)
{
ESP_LOGD(TAG, "Got Sub Ghz Len %i data: %i %u", ret_sub_rx_len, rssi_sub_rx, lqi_sub_rx);
memcpy(data, inner_rxPKT_out, ret_sub_rx_len);
*subGhzRx = true; // This is SubGHz data
return ret_sub_rx_len;
}
}
return 0;
}

View File

@@ -0,0 +1,12 @@
#pragma once
#include <stdbool.h>
#include <stdint.h>
extern uint8_t mSelfMac[8];
void radio_init(uint8_t ch);
void radio_housekeeping();
bool radioTx(uint8_t *packet, bool subGhz);
void radioSetChannel(uint8_t ch);
void radioSetTxPower(uint8_t power);
int8_t commsRxUnencrypted(uint8_t *data, bool *subGhzRx);

View File

@@ -0,0 +1,128 @@
#include <esp_mac.h>
#include <math.h>
#include <stdarg.h>
#include <string.h>
#include <Arduino.h>
#include "driver/gpio.h"
#include "driver/uart.h"
#include "esp_log.h"
#include "esp_err.h"
#include "esp_event.h"
#include "esp_ieee802154.h"
#include "esp_phy_init.h"
#include "esp_timer.h"
#include "freertos/FreeRTOS.h"
#include "freertos/queue.h"
#include "freertos/task.h"
#include "nvs.h"
#include "nvs_flash.h"
#include "proto.h"
#include "sdkconfig.h"
#include "soc/uart_struct.h"
#include "soc/lp_uart_reg.h"
#include "second_uart.h"
static const char *TAG = "SECOND_UART";
#if defined(CONFIG_OEPL_HARDWARE_PROFILE_POE_AP)
#define CONFIG_OEPL_HARDWARE_UART_TX 5
#define CONFIG_OEPL_HARDWARE_UART_RX 18
#else
#if !defined(CONFIG_OEPL_HARDWARE_UART_TX) || !defined(CONFIG_OEPL_HARDWARE_UART_RX)
#define CONFIG_OEPL_HARDWARE_UART_TX 3
#define CONFIG_OEPL_HARDWARE_UART_RX 2
#endif
#endif
#define BUF_SIZE (1024)
#define RD_BUF_SIZE (BUF_SIZE)
static QueueHandle_t uart0_queue;
#define MAX_BUFF_POS 8000
volatile int curr_buff_pos = 0;
volatile int worked_buff_pos = 0;
volatile uint8_t buff_pos[MAX_BUFF_POS + 5];
static void uart_event_task(void *pvParameters);
void init_second_uart() {
uart_config_t uart_config = {
.baud_rate = 115200,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
.source_clk = UART_SCLK_DEFAULT,
};
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, CONFIG_OEPL_HARDWARE_UART_TX, CONFIG_OEPL_HARDWARE_UART_RX, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE));
xTaskCreate(uart_event_task, "uart_event_task", 16384, NULL, 12, NULL);
}
void uart_switch_speed(int baudrate) {
uart_config_t uart_config = {
.baud_rate = baudrate,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
.source_clk = UART_SCLK_DEFAULT,
};
ESP_ERROR_CHECK(uart_param_config(1, &uart_config));
}
void uartTx(uint8_t data) {
uart_write_bytes(1, (const char *)&data, 1);
}
bool getRxCharSecond(uint8_t *newChar) {
if (curr_buff_pos != worked_buff_pos) {
*newChar = buff_pos[worked_buff_pos];
worked_buff_pos++;
worked_buff_pos %= MAX_BUFF_POS;
return true;
}
return false;
}
static void uart_event_task(void *pvParameters) {
uart_event_t event;
uint8_t *dtmp = (uint8_t *)malloc(RD_BUF_SIZE);
for (;;) {
if (xQueueReceive(uart0_queue, (void *)&event, (TickType_t)portMAX_DELAY)) {
bzero(dtmp, RD_BUF_SIZE);
switch (event.type) {
case UART_DATA:
uart_read_bytes(1, dtmp, event.size, portMAX_DELAY);
for (int i = 0; i < event.size; i++) {
buff_pos[curr_buff_pos] = dtmp[i];
curr_buff_pos++;
curr_buff_pos %= MAX_BUFF_POS;
}
break;
default:
// ESP_LOGI(TAG, "uart event type: %d", event.type);
break;
}
}
}
free(dtmp);
dtmp = NULL;
vTaskDelete(NULL);
}
void uart_printf(const char *format, ...) {
va_list args;
va_start(args, format);
char buffer[128];
int len = vsnprintf(buffer, sizeof(buffer), format, args);
va_end(args);
if (len > 0) {
uart_write_bytes(1, buffer, len);
}
}

View File

@@ -0,0 +1,13 @@
#pragma once
#include <inttypes.h>
void init_second_uart();
void uart_switch_speed(int baudrate);
void uartTx(uint8_t data);
bool getRxCharSecond(uint8_t *newChar);
void uart_printf(const char *format, ...);
#define pr uart_printf

View File

@@ -0,0 +1,613 @@
// This code is heavily depending on Dmitrys wonderful Work !
// https://dmitry.gr/?r=05.Projects&proj=29.%20eInk%20Price%20Tags
// Ported and modified to fit the OpenEPaperLink Project by ATC1441 (ATCnetz.de) ~01.2024
#include "subGhz.h"
#include "driver/gpio.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/queue.h"
#include "freertos/task.h"
#include "freertos/timers.h"
#include "proto.h"
#include <Arduino.h>
#include <SPI.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static const char *TAG = "subGHz";
#define SUB_GHZ_CH_OFST 11
#define SUB_GHZ_NUM_CHANNELS 27
/*
//we configure GDO_2 is for TX.has_fifo_space
//we configure GDO_0 is for RX.has_data
WIRING:
*/
#define sub_CS 4
#define sub_GD0 5
#define sub_GD2 6
#define sub_MISO 7
#define sub_CLK 0
#define sub_MOSI 1
#define CMD_SRES 0x30
#define CMD_SFSTXON 0x31
#define CMD_SXOFF 0x32
#define CMD_SCAL 0x33
#define CMD_SRX 0x34
#define CMD_STX 0x35
#define CMD_SIDLE 0x36
#define CMD_SWOR 0x38
#define CMD_SPWD 0x39
#define CMD_SFRX 0x3a
#define CMD_SFTX 0x3b
#define CMD_SWORRST 0x3c
#define CMD_SNOP 0x3d
#define REG_IOCFG2 0x00
#define REG_IOCFG1 0x01
#define REG_IOCFG0 0x02
#define REG_FIFOTHR 0x03
#define REG_SYNC1 0x04
#define REG_SYNC0 0x05
#define REG_PKTLEN 0x06
#define REG_PKTCTRL1 0x07
#define REG_PKTCTRL0 0x08
#define REG_ADDR 0x09
#define REG_CHANNR 0x0a
#define REG_FSCTRL1 0x0b
#define REG_FSCTRL0 0x0c
#define REG_FREQ2 0x0d
#define REG_FREQ1 0x0e
#define REG_FREQ0 0x0f
#define REG_MDMCFG4 0x10
#define REG_MDMCFG3 0x11
#define REG_MDMCFG2 0x12
#define REG_MDMCFG1 0x13
#define REG_MDMCFG0 0x14
#define REG_DEVIATN 0x15
#define REG_MCSM2 0x16
#define REG_MCSM1 0x17
#define REG_MCSM0 0x18
#define REG_FOCCFG 0x19
#define REG_BSCFG 0x1a
#define REG_AGCTRL2 0x1b
#define REG_AGCTRL1 0x1c
#define REG_AGCTRL0 0x1d
#define REG_WOREVT1 0x1e
#define REG_WOREVT0 0x1f
#define REG_WORCTRL 0x20
#define REG_FREND1 0x21
#define REG_FREND0 0x22
#define REG_FSCAL3 0x23
#define REG_FSCAL2 0x24
#define REG_FSCAL1 0x25
#define REG_FSCAL0 0x26
#define REG_RCCTRL1 0x27
#define REG_RCCTRL0 0x28
#define REG_FSTEST 0x29
#define REG_PTEST 0x2a
#define REG_AGCTEST 0x2b
#define REG_TEST2 0x2c
#define REG_TEST1 0x2d
#define REG_TEST0 0x2e
#define REG_PATABLE 0x3e
#define REG_FIFO 0x3f
#define REG_PARTNUM 0xf0
#define REG_VERSION 0xf1
#define REG_FREQEST 0xf2
#define REG_LQI 0xf3
#define REG_RSSI 0xf4
#define REG_MARCSTATE 0xf5
#define REG_WORTIME1 0xf6
#define REG_WORTIME0 0xf7
#define REG_PKTSTATUS 0xf8
#define REG_VCO_VC_DAC 0xf9
#define REG_TXBYTES 0xfa
#define REG_RXBYTES 0xfb
#define REG_RCCTRL1_STA 0xfc
#define REG_RCCTRL0_STA 0xfd
#define MAX_RX_PKTS 80
static volatile uint8_t mRxBufs[MAX_RX_PKTS][RADIO_MAX_PACKET_LEN + 1 /* length */ + 2 /* RSSI, LQI/STA */];
static volatile uint8_t mRxNextWrite, mRxNextRead, mRxNumFree, mRxNumGot;
static uint8_t mRxFilterLongMac[8];
static uint32_t mRxFilterShortMac;
static bool mRxEnabled, mAutoAck, mPromisc;
static uint16_t mRxFilterPan;
static volatile int16_t mLastAck;
struct MacHeaderGenericAddr {
struct MacFcs fixed;
uint8_t seq;
} __attribute__((packed));
struct MacHeaderShortAddr {
struct MacFcs fixed;
uint8_t seq;
uint16_t pan;
uint16_t shortDstAddr;
} __attribute__((packed));
struct MacHeaderLongAddr {
struct MacFcs fixed;
uint8_t seq;
uint16_t pan;
uint8_t longDstAddr[8];
} __attribute__((packed));
void tiRadioRxFilterCfg(const uint8_t *myMac, uint32_t myShortMac, uint16_t myPan, bool promisc) {
mPromisc = promisc;
mRxFilterShortMac = myShortMac;
mRxFilterPan = myPan;
memcpy(mRxFilterLongMac, myMac, sizeof(mRxFilterLongMac));
}
static bool tiRadioPrvSelect(void) {
digitalWrite(sub_CS, LOW);
SPI.beginTransaction(SPISettings(6000000, MSBFIRST, SPI_MODE0));
asm volatile("nop \n nop \n nop \n");
return true;
}
static void tiRadioPrvDeselect(void) {
asm volatile("nop \n nop \n nop \n");
SPI.endTransaction();
digitalWrite(sub_CS, HIGH);
asm volatile("nop \n nop \n nop \n");
}
static void read_multiple(uint8_t *dst, uint_fast8_t rxLen) {
for (int i = 0; i < rxLen; i++) {
dst[i] = SPI.transfer(0xff);
}
}
static int_fast16_t tiRadioPrvStrobe(uint8_t cmd) //negative on error
{
if (!tiRadioPrvSelect())
return -1;
cmd = SPI.transfer(cmd);
tiRadioPrvDeselect();
return (uint_fast16_t)cmd;
}
static bool tiRadioPrvRegWrite(uint_fast8_t reg, uint_fast8_t val) {
if (!tiRadioPrvSelect())
return false;
SPI.transfer(reg);
SPI.transfer(val);
tiRadioPrvDeselect();
return true;
}
static int_fast16_t tiRadioPrvRegRead(uint_fast8_t reg) {
uint8_t read_data = 0x00;
if (!tiRadioPrvSelect())
return -1;
SPI.transfer(reg | 0x80);
read_data = SPI.transfer(0xff);
tiRadioPrvDeselect();
return (uint_fast16_t)read_data;
}
static bool tiRadioPrvRegWriteLong(uint8_t reg, const uint8_t *valP, uint8_t len) {
if (!tiRadioPrvSelect())
return false;
SPI.transfer(reg | 0x40);
for (int i = 0; i < len; i++) {
SPI.transfer(valP[i]);
}
tiRadioPrvDeselect();
return true;
}
bool tiRadioRxEnable(bool on, bool autoAck) {
bool ret = false;
if (on) {
mAutoAck = autoAck;
if (mRxEnabled) {
ret = true;
goto out;
}
if (!tiRadioPrvStrobe(CMD_SRX))
goto out;
mRxEnabled = true;
} else if (mRxEnabled) {
if (!tiRadioPrvStrobe(CMD_SIDLE))
goto out;
mRxEnabled = false;
}
ret = true;
out:
return ret;
}
static bool radioPrvMacsEqual(const uint8_t *macA, const uint8_t *macB) {
const uint32_t *a = (const uint32_t *)(const char *)macA;
const uint32_t *b = (const uint32_t *)(const char *)macB;
return a[0] == b[0] && a[1] == b[1];
}
static uint_fast8_t tiRadioPrvGetState(void) {
uint_fast8_t state;
do {
state = tiRadioPrvRegRead(REG_MARCSTATE);
} while (tiRadioPrvRegRead(REG_MARCSTATE) != state);
return state;
}
static void tiRadioPrvPacketRx(void) {
uint8_t *rxedPkt = (uint8_t *)mRxBufs[mRxNextWrite];
const struct MacHeaderShortAddr *withShortDst = (const struct MacHeaderShortAddr *)(rxedPkt + 1);
const struct MacHeaderGenericAddr *generic = (const struct MacHeaderGenericAddr *)(rxedPkt + 1);
const struct MacHeaderLongAddr *withLongDst = (const struct MacHeaderLongAddr *)(rxedPkt + 1);
bool crcOk, acceptPacket, sendAck = false;
int32_t t, lenNoCrc, lenNoMacFixed;
uint32_t nWaitCycles = 10000;
uint_fast8_t spiLen, now;
t = tiRadioPrvRegRead(REG_FIFO);
if (t < 0)
goto fail;
if (!mRxNumFree)
goto fail;
spiLen = t;
if (spiLen > RADIO_MAX_PACKET_LEN)
goto fail;
t = 0;
rxedPkt[t++] = lenNoCrc = spiLen;
now = 31; //we just read one so 31 left for sure in the FIFO
spiLen += 2; //we expect 2 more bytes
while (spiLen) {
uint8_t reg;
if (!tiRadioPrvSelect()) {
tiRadioPrvDeselect();
goto fail;
}
reg = 0xc0 | REG_FIFO; //burst read
reg = SPI.transfer(reg);
now = reg & 0x0f;
if (now > spiLen)
now = spiLen;
if (!now && !--nWaitCycles) {
tiRadioPrvDeselect();
ESP_LOGE(TAG, " !!! RX timeout !!! ");
goto fail;
}
read_multiple(rxedPkt + t, now);
t += now;
spiLen -= now;
tiRadioPrvDeselect();
}
rxedPkt++; //skip len;
crcOk = !!(rxedPkt[lenNoCrc + 1] & 0x80);
lenNoMacFixed = lenNoCrc - sizeof(struct MacFcs) - sizeof(uint8_t);
if (mPromisc)
acceptPacket = true;
//otherwise, we need a valid crc
else if (!crcOk) {
acceptPacket = false;
}
//packet should be big enough to contain a header
else if (lenNoMacFixed < 0)
acceptPacket = false;
else switch (generic->fixed.frameType) {
case FRAME_TYPE_ACK:
mLastAck = (uint16_t)generic->seq;
acceptPacket = false; //no need to save it as a packet
break;
case FRAME_TYPE_DATA: //we are not the coordinator, so we demand to see our address as destination...
switch (generic->fixed.destAddrType) {
case ADDR_MODE_SHORT:
acceptPacket = (withShortDst->pan == 0xffff && withShortDst->shortDstAddr == 0xffff) || (withShortDst->pan == mRxFilterPan && (withShortDst->shortDstAddr == 0xffff || ((uint32_t)withShortDst->shortDstAddr) == mRxFilterShortMac));
break;
case ADDR_MODE_LONG:
acceptPacket = withLongDst->pan == mRxFilterPan && radioPrvMacsEqual(withLongDst->longDstAddr, mRxFilterLongMac);
break;
default:
acceptPacket = false;
break;
}
sendAck = generic->fixed.ackReqd && mAutoAck;
break;
default:
//no riff-raff please
acceptPacket = false;
break;
}
if (acceptPacket) { //other checks here too plz
if (sendAck) {
static struct {
uint8_t len;
struct MacFcs mac;
uint8_t seq;
} __attribute__((packed)) ack = {
.len = sizeof(ack) + sizeof(uint16_t) - sizeof(ack.len),
.mac = {
.frameType = FRAME_TYPE_ACK,
},
};
ack.seq = generic->seq;
tiRadioTxLL(&ack);
}
mRxNumFree--;
if (++mRxNextWrite == MAX_RX_PKTS)
mRxNextWrite = 0;
mRxNumGot++;
}
out:
if (mRxEnabled && !sendAck) { //if ack is being TXed, TX irq will restart rx later
uint32_t maxWait = 100000;
uint8_t state;
(void)tiRadioPrvStrobe(CMD_SRX);
do {
state = tiRadioPrvGetState();
if (!--maxWait) {
//ESP_LOGE(TAG, "too long wait for rx state. state is %d", state);
break;
}
} while (state != 13 && state != 14 && state != 15);
}
return;
fail:
(void)tiRadioPrvStrobe(CMD_SFRX);
goto out;
}
void tiRadioRxAckReset(void) {
mLastAck = -1;
}
int16_t tiRadioRxAckGetLast(void) {
return mLastAck;
}
int32_t tiRadioRxDequeuePkt(void *dstBuf, uint32_t maxLen, int8_t *rssiP, uint8_t *lqiP) {
uint32_t len, copyLen = maxLen;
if (!mRxNumGot)
return -1;
len = mRxBufs[mRxNextRead][0];
if (copyLen > len)
copyLen = len;
memcpy(dstBuf, (const void *)(mRxBufs[mRxNextRead] + 1), copyLen);
if (lqiP) {
uint32_t lqi = 296 - ((mRxBufs[mRxNextRead][len + 2] & 0x7f) * 2);
//LQI: lower is better. 48 is very good (no lower value seen), 127 is very bad (max value possible)
//we want LQI 0..255 so we scale as SATURATE(296 - 2 * val)
if (lqi > 255)
lqi = 255;
*lqiP = lqi;
}
if (rssiP)
*rssiP = ((int8_t)mRxBufs[mRxNextRead][len + 1]) / 2 - 77;
if (++mRxNextRead == MAX_RX_PKTS)
mRxNextRead = 0;
noInterrupts();
mRxNumFree++;
mRxNumGot--;
interrupts();
//ti radio never stalls RX state machine so nothing to do even if we just freed up a buffer
return len;
}
void data_input_interrupt(void) {
while (digitalRead(sub_GD0)) //while there is data (packets)
tiRadioPrvPacketRx();
}
static void tiRadioPrvIfInit(void) {
//configure pins
pinMode(sub_CS, OUTPUT);
pinMode(sub_GD0, INPUT_PULLUP);
pinMode(sub_GD2, INPUT_PULLUP);
SPI.begin(sub_CLK, sub_MISO, sub_MOSI);
tiRadioPrvDeselect();
mRxNumFree = MAX_RX_PKTS;
}
bool tiRadioSetChannel(uint_fast8_t channel) {
channel -= SUB_GHZ_CH_OFST;
if (channel >= SUB_GHZ_NUM_CHANNELS) {
ESP_LOGI(TAG, "CH not set: %i", channel);
return false;
}
ESP_LOGI(TAG, "CH: %i", channel);
delayMicroseconds(1000);
return tiRadioPrvRegWrite(REG_CHANNR, channel * 3);
}
bool tiRadioTxLL(const void *pkt) {
const uint8_t *data = (const uint8_t *)pkt;
uint32_t len = 1 + *data, now;
bool ret = false;
ESP_LOGD(TAG, "TX packet len %u", len);
ESP_LOGD(TAG, "First bytes: %02X %02X %02X %02X %02X", data[1], data[2], data[3], data[4], data[5]);
if (tiRadioPrvStrobe(CMD_SIDLE) < 0)
goto out;
if (tiRadioPrvStrobe(CMD_SFTX) < 0)
goto out;
now = (len > 64 ? 64 : len);
if (!tiRadioPrvRegWriteLong(REG_FIFO, data, now))
goto out;
len -= now;
data += now;
if (tiRadioPrvStrobe(CMD_STX) < 0)
goto out;
while (len) {
now = 8;
if (now > len)
now = len;
while (digitalRead(sub_GD2))
; //wait till there is space
if (!tiRadioPrvRegWriteLong(REG_FIFO, data, now))
goto out;
data += now;
len -= now;
}
while (tiRadioPrvGetState() != 1)
;
if (!tiRadioPrvStrobe(mRxEnabled ? CMD_SRX : CMD_SIDLE))
goto out;
ret = true;
out:
return ret;
}
bool interrupt_attached = false;
bool init_subGhz(void) {
uint8_t regsCfg[] = {
/* 0x00 */ 0x02, 0x2e, 0x01, 0x07, 0xd3, 0x91, 0x7f, 0x04,
/* 0x08 */ 0x45, 0x22, 0x00, 0x0e, 0x00, 0x22, 0xbb, 0x13,
/* 0x10 */ 0x1d, 0x3b, 0x13, 0x43, 0xa4, 0x65, 0x07, 0x30,
/* 0x18 */ 0x1d, 0x1e, 0x1c, 0xc7, 0x00, 0xb0, 0x87, 0x6b,
/* 0x20 */ 0xfb, 0xb6, 0x10, 0xea, 0x2a, 0x00, 0x1f, 0x41,
/* 0x28 */ 0x00,
};
uint8_t paTab[] = { 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0 };
if (interrupt_attached)
detachInterrupt(sub_GD0);
tiRadioPrvIfInit();
if (tiRadioPrvRegRead(REG_PARTNUM) != 0x00) {
ESP_LOGE(TAG, "partnum is wrong");
return false;
}
delayMicroseconds(300);
if (tiRadioPrvStrobe(CMD_SRES) < 0) {
ESP_LOGE(TAG, "res reply");
return false;
}
delayMicroseconds(300);
if (tiRadioPrvStrobe(CMD_SIDLE) != 0x0f) {
ESP_LOGE(TAG, "idle reply");
return false;
}
delayMicroseconds(300);
if (!tiRadioPrvRegWriteLong(0, regsCfg, sizeof(regsCfg))) {
ESP_LOGE(TAG, "config issue");
return false;
}
delayMicroseconds(300);
if (!tiRadioPrvRegWriteLong(REG_PATABLE, paTab, sizeof(paTab))) {
ESP_LOGE(TAG, "PAtable issue");
return false;
}
attachInterrupt(sub_GD0, data_input_interrupt, RISING);
interrupt_attached = true;
ESP_LOGI(TAG, "Sub-GHz radio inited");
tiRadioRxEnable(true, false);
delayMicroseconds(1000);
ESP_LOGI(TAG, "Sub-GHz rx is on");
return true;
}

View File

@@ -0,0 +1,31 @@
// This code is heavily depending on Dmitrys wonderful Work !
// https://dmitry.gr/?r=05.Projects&proj=29.%20eInk%20Price%20Tags
// Ported and modified to fit the OpenEPaperLink Project by ATC1441 (ATCnetz.de) ~01.2024
#pragma once
#include <Arduino.h>
#include <stdbool.h>
void tiRadioRxFilterCfg(const uint8_t *myMac, uint32_t myShortMac, uint16_t myPan, bool promisc);
static bool tiRadioPrvSelect(void);
static void tiRadioPrvDeselect(void);
static void read_multiple(uint8_t *dst, uint_fast8_t rxLen);
static int_fast16_t tiRadioPrvStrobe(uint8_t cmd);
static bool tiRadioPrvRegWrite(uint_fast8_t reg, uint_fast8_t val);
static int_fast16_t tiRadioPrvRegRead(uint_fast8_t reg);
static bool tiRadioPrvRegWriteLong(uint8_t reg, const uint8_t *valP, uint8_t len);
bool tiRadioRxEnable(bool on, bool autoAck);
static bool radioPrvMacsEqual(const uint8_t *macA, const uint8_t *macB);
static uint_fast8_t tiRadioPrvGetState(void);
static void tiRadioPrvPacketRx(void);
void tiRadioRxAckReset(void);
int16_t tiRadioRxAckGetLast(void);
int32_t tiRadioRxDequeuePkt(void* dstBuf, uint32_t maxLen, int8_t *rssiP, uint8_t *lqiP);
void data_input_interrupt(void);
static void tiRadioPrvIfInit(void);
static void tiRadioPrvIrqInit(void);
bool tiRadioSetChannel(uint_fast8_t channel);
bool tiRadioTxLL(const void* pkt);
bool init_subGhz(void);

View File

@@ -0,0 +1,786 @@
// Ported to ESP32-C6 Arduino By ATC1441(ATCnetz.de) for OpenEPaperLink at ~03.2024
#include "led.h"
#include "proto.h"
#include "radio.h"
#include "driver/gpio.h"
#include "driver/uart.h"
#include "esp_err.h"
#include "esp_event.h"
#include "esp_ieee802154.h"
#include "esp_phy_init.h"
#include "esp_timer.h"
#include "freertos/FreeRTOS.h"
#include "freertos/queue.h"
#include "freertos/task.h"
#include "sdkconfig.h"
#include "second_uart.h"
#include "soc/uart_struct.h"
#include <esp_mac.h>
#include <math.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
const uint8_t channelList[6] = { 11, 15, 20, 25, 26, 27 };
#define DATATYPE_NOUPDATE 0
#define HW_TYPE 0xC2
#define MAX_PENDING_MACS 250
#define HOUSEKEEPING_INTERVAL 60UL
struct pendingData pendingDataArr[MAX_PENDING_MACS];
// VERSION GOES HERE!
uint16_t version = 0x0019;
#define RAW_PKT_PADDING 2
uint8_t radiotxbuffer[128];
uint8_t radiorxbuffer[128];
static uint32_t housekeepingTimer;
struct blockRequest requestedData = { 0 }; // holds which data was requested by the tag
uint8_t dstMac[8]; // target for the block transfer
uint16_t dstPan; //
static uint32_t blockStartTimer = 0; // reference that holds when the AP sends the next block
uint32_t nextBlockAttempt = 0; // reference time for when the AP can request a new block from the ESP32
uint8_t seq = 0; // holds current sequence number for transmission
uint8_t blockbuffer[BLOCK_XFER_BUFFER_SIZE + 5]; // block transfer buffer
uint8_t lastAckMac[8] = { 0 };
// these variables hold the current mac were talking to
#define CONCURRENT_REQUEST_DELAY 1200UL
uint32_t lastBlockRequest = 0;
uint8_t lastBlockMac[8];
uint8_t lastTagReturn[8];
uint8_t curChannel = 25;
uint8_t curPower = 10;
uint8_t curPendingData = 0;
uint8_t curNoUpdate = 0;
bool highspeedSerial = false;
void sendXferCompleteAck(uint8_t *dst);
void sendCancelXfer(uint8_t *dst);
void espNotifyAPInfo();
// tools
void addCRC(void *p, uint8_t len) {
uint8_t total = 0;
for (uint8_t c = 1; c < len; c++) {
total += ((uint8_t *)p)[c];
}
((uint8_t *)p)[0] = total;
}
bool checkCRC(void *p, uint8_t len) {
uint8_t total = 0;
for (uint8_t c = 1; c < len; c++) {
total += ((uint8_t *)p)[c];
}
return ((uint8_t *)p)[0] == total;
}
uint8_t getPacketType(void *buffer) {
struct MacFcs *fcs = (MacFcs *)buffer;
if ((fcs->frameType == 1) && (fcs->destAddrType == 2) && (fcs->srcAddrType == 3) && (fcs->panIdCompressed == 0)) {
// broadcast frame
uint8_t type = ((uint8_t *)buffer)[sizeof(struct MacFrameBcast)];
return type;
} else if ((fcs->frameType == 1) && (fcs->destAddrType == 3) && (fcs->srcAddrType == 3) && (fcs->panIdCompressed == 1)) {
// normal frame
uint8_t type = ((uint8_t *)buffer)[sizeof(struct MacFrameNormal)];
return type;
}
return 0;
}
uint8_t getBlockDataLength() {
uint8_t partNo = 0;
for (uint8_t c = 0; c < BLOCK_MAX_PARTS; c++) {
if (requestedData.requestedParts[c / 8] & (1 << (c % 8))) {
partNo++;
}
}
return partNo;
}
// pendingdata slot stuff
int8_t findSlotForMac(const uint8_t *mac) {
for (uint8_t c = 0; c < MAX_PENDING_MACS; c++) {
if (memcmp(mac, ((uint8_t *)&(pendingDataArr[c].targetMac)), 8) == 0) {
if (pendingDataArr[c].attemptsLeft != 0) {
return c;
}
}
}
return -1;
}
int8_t findFreeSlot() {
for (uint8_t c = 0; c < MAX_PENDING_MACS; c++) {
if (pendingDataArr[c].attemptsLeft == 0) {
return c;
}
}
return -1;
}
int8_t findSlotForVer(const uint8_t *ver) {
for (uint8_t c = 0; c < MAX_PENDING_MACS; c++) {
if (memcmp(ver, ((uint8_t *)&(pendingDataArr[c].availdatainfo.dataVer)), 8) == 0) {
if (pendingDataArr[c].attemptsLeft != 0) return c;
}
}
return -1;
}
void deleteAllPendingDataForVer(const uint8_t *ver) {
int8_t slot = -1;
do {
slot = findSlotForVer(ver);
if (slot != -1) pendingDataArr[slot].attemptsLeft = 0;
} while (slot != -1);
}
void deleteAllPendingDataForMac(const uint8_t *mac) {
int8_t slot = -1;
do {
slot = findSlotForMac(mac);
if (slot != -1) pendingDataArr[slot].attemptsLeft = 0;
} while (slot != -1);
}
void countSlots() {
curPendingData = 0;
curNoUpdate = 0;
for (uint8_t c = 0; c < MAX_PENDING_MACS; c++) {
if (pendingDataArr[c].attemptsLeft != 0) {
if (pendingDataArr[c].availdatainfo.dataType != 0) {
curPendingData++;
} else {
curNoUpdate++;
}
}
}
}
// processing serial data
#define ZBS_RX_WAIT_HEADER 0
#define ZBS_RX_WAIT_SDA 1 // send data avail
#define ZBS_RX_WAIT_CANCEL 2 // cancel traffic for mac
#define ZBS_RX_WAIT_SCP 3 // set channel power
#define ZBS_RX_WAIT_BLOCKDATA 4
bool isSame(uint8_t *in1, char *in2, int len) {
bool flag = 1;
for (int i = 0; i < len; i++) {
if (in1[i] != in2[i]) flag = 0;
}
return flag;
}
int blockPosition = 0;
void processSerial(uint8_t lastchar) {
static uint8_t cmdbuffer[4];
static uint8_t RXState = 0;
static uint8_t serialbuffer[48];
static uint8_t *serialbufferp;
static uint8_t bytesRemain = 0;
static uint32_t lastSerial = 0;
static uint32_t blockStartTime = 0;
if ((RXState != ZBS_RX_WAIT_HEADER) && ((millis() - lastSerial) > 1000)) {
RXState = ZBS_RX_WAIT_HEADER;
Serial.printf("UART Timeout\r\n");
}
lastSerial = millis();
switch (RXState) {
case ZBS_RX_WAIT_HEADER:
// shift characters in
for (uint8_t c = 0; c < 3; c++) {
cmdbuffer[c] = cmdbuffer[c + 1];
}
cmdbuffer[3] = lastchar;
if (isSame(cmdbuffer + 1, ">D>", 3)) {
pr("ACK>");
blockStartTime = millis();
Serial.printf("Starting BlkData, %lu ms after request\r\n", blockStartTime - nextBlockAttempt);
blockPosition = 0;
RXState = ZBS_RX_WAIT_BLOCKDATA;
}
if (isSame(cmdbuffer, "SDA>", 4)) {
Serial.printf("SDA In\r\n");
RXState = ZBS_RX_WAIT_SDA;
bytesRemain = sizeof(struct pendingData);
serialbufferp = serialbuffer;
break;
}
if (isSame(cmdbuffer, "CXD>", 4)) {
Serial.printf("CXD In\r\n");
RXState = ZBS_RX_WAIT_CANCEL;
bytesRemain = sizeof(struct pendingData);
serialbufferp = serialbuffer;
break;
}
if (isSame(cmdbuffer, "SCP>", 4)) {
Serial.printf("SCP In\r\n");
RXState = ZBS_RX_WAIT_SCP;
bytesRemain = sizeof(struct espSetChannelPower);
serialbufferp = serialbuffer;
break;
}
if (isSame(cmdbuffer, "NFO?", 4)) {
pr("ACK>");
Serial.printf("NFO? In\r\n");
espNotifyAPInfo();
RXState = ZBS_RX_WAIT_HEADER;
}
if (isSame(cmdbuffer, "RDY?", 4)) {
pr("ACK>");
Serial.printf("RDY? In\r\n");
RXState = ZBS_RX_WAIT_HEADER;
}
if (isSame(cmdbuffer, "RSET", 4)) {
pr("ACK>");
Serial.printf("RSET In\r\n");
delay(100);
// TODO RESET US HERE
RXState = ZBS_RX_WAIT_HEADER;
}
if (isSame(cmdbuffer, "HSPD", 4)) {
pr("ACK>");
Serial.printf("HSPD In, switching to 2000000\r\n");
delay(100);
uart_switch_speed(2000000);
delay(100);
highspeedSerial = true;
pr("ACK>");
RXState = ZBS_RX_WAIT_HEADER;
}
break;
case ZBS_RX_WAIT_BLOCKDATA:
blockbuffer[blockPosition++] = 0xAA ^ lastchar;
if (blockPosition >= 4100) {
Serial.printf("Blockdata fully received in %lu ms, %lu ms after the request\r\n", millis() - blockStartTime, millis() - nextBlockAttempt);
RXState = ZBS_RX_WAIT_HEADER;
}
break;
case ZBS_RX_WAIT_SDA:
*serialbufferp = lastchar;
serialbufferp++;
bytesRemain--;
if (bytesRemain == 0) {
if (checkCRC(serialbuffer, sizeof(struct pendingData))) {
struct pendingData *pd = (struct pendingData *)serialbuffer;
int8_t slot = findSlotForMac(pd->targetMac);
if (slot == -1) slot = findFreeSlot();
if (slot != -1) {
memcpy(&(pendingDataArr[slot]), serialbuffer, sizeof(struct pendingData));
pr("ACK>");
} else {
pr("NOQ>");
}
} else {
pr("NOK>");
}
RXState = ZBS_RX_WAIT_HEADER;
}
break;
case ZBS_RX_WAIT_CANCEL:
*serialbufferp = lastchar;
serialbufferp++;
bytesRemain--;
if (bytesRemain == 0) {
if (checkCRC(serialbuffer, sizeof(struct pendingData))) {
struct pendingData *pd = (struct pendingData *)serialbuffer;
deleteAllPendingDataForMac((uint8_t *)&pd->targetMac);
pr("ACK>");
} else {
pr("NOK>");
}
RXState = ZBS_RX_WAIT_HEADER;
}
break;
case ZBS_RX_WAIT_SCP:
*serialbufferp = lastchar;
serialbufferp++;
bytesRemain--;
if (bytesRemain == 0) {
if (checkCRC(serialbuffer, sizeof(struct espSetChannelPower))) {
struct espSetChannelPower *scp = (struct espSetChannelPower *)serialbuffer;
for (uint8_t c = 0; c < sizeof(channelList); c++) {
if (channelList[c] == scp->channel) goto SCPchannelFound;
}
goto SCPfailed;
SCPchannelFound:
pr("ACK>");
if (curChannel != scp->channel) {
radioSetChannel(scp->channel);
curChannel = scp->channel;
}
curPower = scp->power;
radioSetTxPower(scp->power);
Serial.printf("Set channel: %d power: %d\r\n", curChannel, curPower);
} else {
SCPfailed:
pr("NOK>");
}
RXState = ZBS_RX_WAIT_HEADER;
}
break;
}
}
// sending data to the ESP
void espBlockRequest(const struct blockRequest *br, uint8_t *src) {
struct espBlockRequest *ebr = (struct espBlockRequest *)blockbuffer;
uartTx('R');
uartTx('Q');
uartTx('B');
uartTx('>');
memcpy(&(ebr->ver), &(br->ver), 8);
memcpy(&(ebr->src), src, 8);
ebr->blockId = br->blockId;
addCRC(ebr, sizeof(struct espBlockRequest));
for (uint8_t c = 0; c < sizeof(struct espBlockRequest); c++) {
uartTx(((uint8_t *)ebr)[c]);
}
}
void espNotifyAvailDataReq(const struct AvailDataReq *adr, const uint8_t *src) {
uartTx('A');
uartTx('D');
uartTx('R');
uartTx('>');
struct espAvailDataReq eadr = { 0 };
memcpy((void *)eadr.src, (void *)src, 8);
memcpy((void *)&eadr.adr, (void *)adr, sizeof(struct AvailDataReq));
addCRC(&eadr, sizeof(struct espAvailDataReq));
for (uint8_t c = 0; c < sizeof(struct espAvailDataReq); c++) {
uartTx(((uint8_t *)&eadr)[c]);
}
}
void espNotifyXferComplete(const uint8_t *src) {
struct espXferComplete exfc;
memcpy(&exfc.src, src, 8);
uartTx('X');
uartTx('F');
uartTx('C');
uartTx('>');
addCRC(&exfc, sizeof(exfc));
for (uint8_t c = 0; c < sizeof(exfc); c++) {
uartTx(((uint8_t *)&exfc)[c]);
}
}
void espNotifyTimeOut(const uint8_t *src) {
struct espXferComplete exfc;
memcpy(&exfc.src, src, 8);
uartTx('X');
uartTx('T');
uartTx('O');
uartTx('>');
addCRC(&exfc, sizeof(exfc));
for (uint8_t c = 0; c < sizeof(exfc); c++) {
uartTx(((uint8_t *)&exfc)[c]);
}
}
void espNotifyAPInfo() {
pr("TYP>%02X", HW_TYPE);
pr("VER>%04X", version);
pr("MAC>%02X%02X", mSelfMac[0], mSelfMac[1]);
pr("%02X%02X", mSelfMac[2], mSelfMac[3]);
pr("%02X%02X", mSelfMac[4], mSelfMac[5]);
pr("%02X%02X", mSelfMac[6], mSelfMac[7]);
pr("ZCH>%02X", curChannel);
pr("ZPW>%02X", curPower);
countSlots();
pr("PEN>%02X", curPendingData);
pr("NOP>%02X", curNoUpdate);
}
void espNotifyTagReturnData(uint8_t *src, uint8_t len) {
struct tagReturnData *trd = (struct tagReturnData *)(radiorxbuffer + sizeof(struct MacFrameBcast) + 1); // oh how I'd love to pass this as an argument, but sdcc won't let me
struct espTagReturnData *etrd = (struct espTagReturnData *)radiotxbuffer;
if (memcmp((void *)&trd->dataVer, lastTagReturn, 8) == 0) {
return;
} else {
memcpy(lastTagReturn, &trd->dataVer, 8);
}
memcpy(etrd->src, src, 8);
etrd->len = len;
memcpy(&etrd->returnData, trd, len);
addCRC(etrd, len + 10);
uartTx('T');
uartTx('R');
uartTx('D');
uartTx('>');
for (uint8_t c = 0; c < len + 10; c++) {
uartTx(((uint8_t *)etrd)[c]);
}
}
// process data from tag
void processBlockRequest(const uint8_t *buffer, uint8_t forceBlockDownload) {
struct MacFrameNormal *rxHeader = (struct MacFrameNormal *)buffer;
struct blockRequest *blockReq = (struct blockRequest *)(buffer + sizeof(struct MacFrameNormal) + 1);
if (!checkCRC(blockReq, sizeof(struct blockRequest))) return;
// check if we're already talking to this mac
if (memcmp(rxHeader->src, lastBlockMac, 8) == 0) {
lastBlockRequest = millis();
} else {
// we weren't talking to this mac, see if there was a transfer in progress from another mac, recently
if ((millis() - lastBlockRequest) > CONCURRENT_REQUEST_DELAY) {
// mark this mac as the new current mac we're talking to
memcpy((void *)lastBlockMac, (void *)rxHeader->src, 8);
lastBlockRequest = millis();
} else {
// we're talking to another mac, let this mac know we can't accomodate another request right now
pr("BUSY!\n");
sendCancelXfer(rxHeader->src);
return;
}
}
// check if we have data for this mac
if (findSlotForMac(rxHeader->src) == -1) {
// no data for this mac, politely tell it to fuck off
sendCancelXfer(rxHeader->src);
return;
}
bool requestDataDownload = false;
if ((blockReq->blockId != requestedData.blockId) || (blockReq->ver != requestedData.ver)) {
// requested block isn't already in the buffer
requestDataDownload = true;
} else {
// requested block is already in the buffer
if (forceBlockDownload) {
if ((millis() - nextBlockAttempt) > 380) {
requestDataDownload = true;
pr("FORCED\n");
} else {
pr("IGNORED\n");
}
}
}
// copy blockrequest into requested data
memcpy(&requestedData, blockReq, sizeof(struct blockRequest));
struct MacFrameNormal *txHeader = (struct MacFrameNormal *)(radiotxbuffer + 1);
struct blockRequestAck *blockRequestAck = (struct blockRequestAck *)(radiotxbuffer + sizeof(struct MacFrameNormal) + 2);
radiotxbuffer[0] = sizeof(struct MacFrameNormal) + 1 + sizeof(struct blockRequestAck) + RAW_PKT_PADDING;
radiotxbuffer[sizeof(struct MacFrameNormal) + 1] = PKT_BLOCK_REQUEST_ACK;
if (blockStartTimer == 0) {
if (requestDataDownload) {
if (highspeedSerial == true) {
blockRequestAck->pleaseWaitMs = 140;
} else {
blockRequestAck->pleaseWaitMs = 550;
}
} else {
// block is already in buffer
blockRequestAck->pleaseWaitMs = 30;
}
} else {
blockRequestAck->pleaseWaitMs = 30;
}
blockStartTimer = millis() + blockRequestAck->pleaseWaitMs;
memcpy(txHeader->src, mSelfMac, 8);
memcpy(txHeader->dst, rxHeader->src, 8);
txHeader->pan = rxHeader->pan;
txHeader->fcs.frameType = 1;
txHeader->fcs.panIdCompressed = 1;
txHeader->fcs.destAddrType = 3;
txHeader->fcs.srcAddrType = 3;
txHeader->seq = seq++;
addCRC((void *)blockRequestAck, sizeof(struct blockRequestAck));
radioTx(radiotxbuffer);
// save the target for the blockdata
memcpy(dstMac, rxHeader->src, 8);
dstPan = rxHeader->pan;
if (requestDataDownload) {
blockPosition = 0;
espBlockRequest(&requestedData, rxHeader->src);
nextBlockAttempt = millis();
}
}
void processAvailDataReq(uint8_t *buffer) {
struct MacFrameBcast *rxHeader = (struct MacFrameBcast *)buffer;
struct AvailDataReq *availDataReq = (struct AvailDataReq *)(buffer + sizeof(struct MacFrameBcast) + 1);
if (!checkCRC(availDataReq, sizeof(struct AvailDataReq))) return;
// prepare tx buffer to send a response
memset(radiotxbuffer, 0, sizeof(struct MacFrameNormal) + sizeof(struct AvailDataInfo) + 2); // 120);
struct MacFrameNormal *txHeader = (struct MacFrameNormal *)(radiotxbuffer + 1);
struct AvailDataInfo *availDataInfo = (struct AvailDataInfo *)(radiotxbuffer + sizeof(struct MacFrameNormal) + 2);
radiotxbuffer[0] = sizeof(struct MacFrameNormal) + 1 + sizeof(struct AvailDataInfo) + RAW_PKT_PADDING;
radiotxbuffer[sizeof(struct MacFrameNormal) + 1] = PKT_AVAIL_DATA_INFO;
// check to see if we have data available for this mac
bool haveData = false;
for (uint8_t c = 0; c < MAX_PENDING_MACS; c++) {
if (pendingDataArr[c].attemptsLeft) {
if (memcmp(pendingDataArr[c].targetMac, rxHeader->src, 8) == 0) {
haveData = true;
memcpy((void *)availDataInfo, &(pendingDataArr[c].availdatainfo), sizeof(struct AvailDataInfo));
break;
}
}
}
// couldn't find data for this mac
if (!haveData) availDataInfo->dataType = DATATYPE_NOUPDATE;
memcpy(txHeader->src, mSelfMac, 8);
memcpy(txHeader->dst, rxHeader->src, 8);
txHeader->pan = rxHeader->dstPan;
txHeader->fcs.frameType = 1;
txHeader->fcs.panIdCompressed = 1;
txHeader->fcs.destAddrType = 3;
txHeader->fcs.srcAddrType = 3;
txHeader->seq = seq++;
addCRC(availDataInfo, sizeof(struct AvailDataInfo));
radioTx(radiotxbuffer);
memset(lastAckMac, 0, 8); // reset lastAckMac, so we can record if we've received exactly one ack packet
espNotifyAvailDataReq(availDataReq, rxHeader->src);
}
void processXferComplete(uint8_t *buffer) {
struct MacFrameNormal *rxHeader = (struct MacFrameNormal *)buffer;
sendXferCompleteAck(rxHeader->src);
if (memcmp(lastAckMac, rxHeader->src, 8) != 0) {
memcpy((void *)lastAckMac, (void *)rxHeader->src, 8);
espNotifyXferComplete(rxHeader->src);
int8_t slot = findSlotForMac(rxHeader->src);
if (slot != -1) pendingDataArr[slot].attemptsLeft = 0;
}
}
void processTagReturnData(uint8_t *buffer, uint8_t len) {
struct MacFrameBcast *rxframe = (struct MacFrameBcast *)buffer;
struct MacFrameNormal *frameHeader = (struct MacFrameNormal *)(radiotxbuffer + 1);
if (!checkCRC((buffer + sizeof(struct MacFrameBcast) + 1), len - (sizeof(struct MacFrameBcast) + 1))) {
return;
}
radiotxbuffer[sizeof(struct MacFrameNormal) + 1] = PKT_TAG_RETURN_DATA_ACK;
radiotxbuffer[0] = sizeof(struct MacFrameNormal) + 1 + RAW_PKT_PADDING;
memcpy(frameHeader->src, mSelfMac, 8);
memcpy(frameHeader->dst, rxframe->src, 8);
radiotxbuffer[1] = 0x41; // fast way to set the appropriate bits
radiotxbuffer[2] = 0xCC; // normal frame
frameHeader->seq = seq++;
frameHeader->pan = rxframe->srcPan;
radioTx(radiotxbuffer);
espNotifyTagReturnData(rxframe->src, len - (sizeof(struct MacFrameBcast) + 1));
}
// send block data to the tag
void sendPart(uint8_t partNo) {
struct MacFrameNormal *frameHeader = (struct MacFrameNormal *)(radiotxbuffer + 1);
struct blockPart *blockPart = (struct blockPart *)(radiotxbuffer + sizeof(struct MacFrameNormal) + 2);
memset(radiotxbuffer + 1, 0, sizeof(struct blockPart) + sizeof(struct MacFrameNormal));
radiotxbuffer[sizeof(struct MacFrameNormal) + 1] = PKT_BLOCK_PART;
radiotxbuffer[0] = sizeof(struct MacFrameNormal) + sizeof(struct blockPart) + BLOCK_PART_DATA_SIZE + 1 + RAW_PKT_PADDING;
memcpy(frameHeader->src, mSelfMac, 8);
memcpy(frameHeader->dst, dstMac, 8);
blockPart->blockId = requestedData.blockId;
blockPart->blockPart = partNo;
memcpy(&(blockPart->data), blockbuffer + (partNo * BLOCK_PART_DATA_SIZE), BLOCK_PART_DATA_SIZE);
addCRC(blockPart, sizeof(struct blockPart) + BLOCK_PART_DATA_SIZE);
frameHeader->fcs.frameType = 1;
frameHeader->fcs.panIdCompressed = 1;
frameHeader->fcs.destAddrType = 3;
frameHeader->fcs.srcAddrType = 3;
frameHeader->seq = seq++;
frameHeader->pan = dstPan;
radioTx(radiotxbuffer);
}
void sendBlockData() {
if (getBlockDataLength() == 0) {
pr("Invalid block request received, 0 parts..\n");
requestedData.requestedParts[0] |= 0x01;
}
pr("Sending parts:");
for (uint8_t c = 0; (c < BLOCK_MAX_PARTS); c++) {
if (c % 10 == 0) pr(" ");
if (requestedData.requestedParts[c / 8] & (1 << (c % 8))) {
pr("X");
} else {
pr(".");
}
}
pr("\n");
uint8_t partNo = 0;
while (partNo < BLOCK_MAX_PARTS) {
for (uint8_t c = 0; (c < BLOCK_MAX_PARTS) && (partNo < BLOCK_MAX_PARTS); c++) {
if (requestedData.requestedParts[c / 8] & (1 << (c % 8))) {
sendPart(c);
partNo++;
}
}
}
}
void sendXferCompleteAck(uint8_t *dst) {
struct MacFrameNormal *frameHeader = (struct MacFrameNormal *)(radiotxbuffer + 1);
memset(radiotxbuffer + 1, 0, sizeof(struct blockPart) + sizeof(struct MacFrameNormal));
radiotxbuffer[sizeof(struct MacFrameNormal) + 1] = PKT_XFER_COMPLETE_ACK;
radiotxbuffer[0] = sizeof(struct MacFrameNormal) + 1 + RAW_PKT_PADDING;
memcpy(frameHeader->src, mSelfMac, 8);
memcpy(frameHeader->dst, dst, 8);
frameHeader->fcs.frameType = 1;
frameHeader->fcs.panIdCompressed = 1;
frameHeader->fcs.destAddrType = 3;
frameHeader->fcs.srcAddrType = 3;
frameHeader->seq = seq++;
frameHeader->pan = dstPan;
radioTx(radiotxbuffer);
}
void sendCancelXfer(uint8_t *dst) {
struct MacFrameNormal *frameHeader = (struct MacFrameNormal *)(radiotxbuffer + 1);
memset(radiotxbuffer + 1, 0, sizeof(struct blockPart) + sizeof(struct MacFrameNormal));
radiotxbuffer[sizeof(struct MacFrameNormal) + 1] = PKT_CANCEL_XFER;
radiotxbuffer[0] = sizeof(struct MacFrameNormal) + 1 + RAW_PKT_PADDING;
memcpy(frameHeader->src, mSelfMac, 8);
memcpy(frameHeader->dst, dst, 8);
frameHeader->fcs.frameType = 1;
frameHeader->fcs.panIdCompressed = 1;
frameHeader->fcs.destAddrType = 3;
frameHeader->fcs.srcAddrType = 3;
frameHeader->seq = seq++;
frameHeader->pan = dstPan;
radioTx(radiotxbuffer);
}
void sendPong(void *buf) {
struct MacFrameBcast *rxframe = (struct MacFrameBcast *)buf;
struct MacFrameNormal *frameHeader = (struct MacFrameNormal *)(radiotxbuffer + 1);
radiotxbuffer[sizeof(struct MacFrameNormal) + 1] = PKT_PONG;
radiotxbuffer[sizeof(struct MacFrameNormal) + 2] = curChannel;
radiotxbuffer[0] = sizeof(struct MacFrameNormal) + 1 + 1 + RAW_PKT_PADDING;
memcpy(frameHeader->src, mSelfMac, 8);
memcpy(frameHeader->dst, rxframe->src, 8);
radiotxbuffer[1] = 0x41; // fast way to set the appropriate bits
radiotxbuffer[2] = 0xCC; // normal frame
frameHeader->seq = seq++;
frameHeader->pan = rxframe->srcPan;
radioTx(radiotxbuffer);
}
void setup() {
Serial.begin(115200);
init_led();
init_second_uart();
requestedData.blockId = 0xFF;
// clear the array with pending information
memset(pendingDataArr, 0, sizeof(pendingDataArr));
radio_init(curChannel);
radioSetTxPower(10);
pr("RES>");
pr("RDY>");
Serial.printf("C6 ready!\r\n");
housekeepingTimer = millis();
}
void loop() {
while ((millis() - housekeepingTimer) < ((1000 * HOUSEKEEPING_INTERVAL) - 100)) {
int8_t ret = commsRxUnencrypted(radiorxbuffer);
if (ret > 1) {
led_flash(0);
// received a packet, lets see what it is
switch (getPacketType(radiorxbuffer)) {
case PKT_AVAIL_DATA_REQ:
if (ret == 28) {
// old version of the AvailDataReq struct, set all the new fields to zero, so it will pass the CRC
memset(radiorxbuffer + 1 + sizeof(struct MacFrameBcast) + sizeof(struct oldAvailDataReq), 0,
sizeof(struct AvailDataReq) - sizeof(struct oldAvailDataReq) + 2);
processAvailDataReq(radiorxbuffer);
} else if (ret == 40) {
// new version of the AvailDataReq struct
processAvailDataReq(radiorxbuffer);
}
break;
case PKT_BLOCK_REQUEST:
processBlockRequest(radiorxbuffer, 1);
break;
case PKT_BLOCK_PARTIAL_REQUEST:
processBlockRequest(radiorxbuffer, 0);
break;
case PKT_XFER_COMPLETE:
processXferComplete(radiorxbuffer);
break;
case PKT_PING:
sendPong(radiorxbuffer);
break;
case PKT_AVAIL_DATA_SHORTREQ:
// a short AvailDataReq is basically a very short (1 byte payload) packet that requires little preparation on the tx side, for optimal
// battery use bytes of the struct are set 0, so it passes the checksum test, and the ESP32 can detect that no interesting payload is
// sent
if (ret == 18) {
memset(radiorxbuffer + 1 + sizeof(struct MacFrameBcast), 0, sizeof(struct AvailDataReq) + 2);
processAvailDataReq(radiorxbuffer);
}
break;
case PKT_TAG_RETURN_DATA:
processTagReturnData(radiorxbuffer, ret);
break;
default:
Serial.printf("t=%02X\r\n", getPacketType(radiorxbuffer));
break;
}
} else if (blockStartTimer == 0) {
delay(10);
}
uint8_t curr_char;
while (getRxCharSecond(&curr_char)) processSerial(curr_char);
if (blockStartTimer) {
if (millis() > blockStartTimer) {
sendBlockData();
blockStartTimer = 0;
}
}
}
memset(&lastTagReturn, 0, 8);
for (uint8_t cCount = 0; cCount < MAX_PENDING_MACS; cCount++) {
if (pendingDataArr[cCount].attemptsLeft == 1) {
if (pendingDataArr[cCount].availdatainfo.dataType != DATATYPE_NOUPDATE) {
espNotifyTimeOut(pendingDataArr[cCount].targetMac);
}
pendingDataArr[cCount].attemptsLeft = 0;
} else if (pendingDataArr[cCount].attemptsLeft > 1) {
pendingDataArr[cCount].attemptsLeft--;
if (pendingDataArr[cCount].availdatainfo.nextCheckIn) pendingDataArr[cCount].availdatainfo.nextCheckIn--;
}
}
housekeepingTimer = millis();
}

View File

@@ -0,0 +1,44 @@
#include "led.h"
#include "driver/gpio.h"
#include "freertos/FreeRTOS.h"
#include "freertos/queue.h"
#include "freertos/task.h"
#include "freertos/timers.h"
#include "proto.h"
#include <Arduino.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NUM_LEDS 2
const uint8_t led_pins[NUM_LEDS] = { LED1, LED2 };
TimerHandle_t led_timers[NUM_LEDS] = { 0 };
void led_timer_callback(TimerHandle_t xTimer) {
int led_index = (int)pvTimerGetTimerID(xTimer);
if (led_index >= 0 && led_index < NUM_LEDS) {
digitalWrite(led_pins[led_index], 0);
}
}
void init_led() {
pinMode(LED1,OUTPUT);
pinMode(LED2,OUTPUT);
for (int i = 0; i < NUM_LEDS; i++) {
led_timers[i] = xTimerCreate("led_timer", pdMS_TO_TICKS(50), pdFALSE, (void *)i, led_timer_callback);
}
}
void led_flash(int nr) {
digitalWrite(led_pins[nr], 1);
if (nr >= 0 && nr < NUM_LEDS) {
xTimerStart(led_timers[nr], 0);
}
}
void led_set(int nr, bool state) {
digitalWrite(nr, state);
}

View File

@@ -0,0 +1,6 @@
#pragma once
#include <stdbool.h>
void init_led();
void led_set(int nr, bool state);
void led_flash(int nr);

View File

@@ -0,0 +1,190 @@
#ifndef _PROTO_H_
#define _PROTO_H_
#include <stdint.h>
#define LED1 22
#define LED2 25
#define PROTO_PAN_ID (0x4447) // PAN ID compression shall be used
#define RADIO_MAX_PACKET_LEN (125) // useful payload, not including the crc
#define ADDR_MODE_NONE (0)
#define ADDR_MODE_SHORT (2)
#define ADDR_MODE_LONG (3)
#define FRAME_TYPE_BEACON (0)
#define FRAME_TYPE_DATA (1)
#define FRAME_TYPE_ACK (2)
#define FRAME_TYPE_MAC_CMD (3)
#define SHORT_MAC_UNUSED (0x10000000UL) // for radioRxFilterCfg's myShortMac
struct MacFcs {
uint8_t frameType : 3;
uint8_t secure : 1;
uint8_t framePending : 1;
uint8_t ackReqd : 1;
uint8_t panIdCompressed : 1;
uint8_t rfu1 : 1;
uint8_t rfu2 : 2;
uint8_t destAddrType : 2;
uint8_t frameVer : 2;
uint8_t srcAddrType : 2;
} __attribute__((packed, aligned(1)));
struct MacFrameFromMaster {
struct MacFcs fcs;
uint8_t seq;
uint16_t pan;
uint8_t dst[8];
uint16_t from;
} __attribute__((packed, aligned(1)));
struct MacFrameNormal {
struct MacFcs fcs;
uint8_t seq;
uint16_t pan;
uint8_t dst[8];
uint8_t src[8];
} __attribute__((packed, aligned(1)));
struct MacFrameBcast {
struct MacFcs fcs;
uint8_t seq;
uint16_t dstPan;
uint16_t dstAddr;
uint16_t srcPan;
uint8_t src[8];
} __attribute__((packed, aligned(1)));
#define PKT_TAG_RETURN_DATA 0xE1
#define PKT_TAG_RETURN_DATA_ACK 0xE2
#define PKT_AVAIL_DATA_SHORTREQ 0xE3
#define PKT_AVAIL_DATA_REQ 0xE5
#define PKT_AVAIL_DATA_INFO 0xE6
#define PKT_BLOCK_PARTIAL_REQUEST 0xE7
#define PKT_BLOCK_REQUEST_ACK 0xE9
#define PKT_BLOCK_REQUEST 0xE4
#define PKT_BLOCK_PART 0xE8
#define PKT_XFER_COMPLETE 0xEA
#define PKT_XFER_COMPLETE_ACK 0xEB
#define PKT_CANCEL_XFER 0xEC
#define PKT_PING 0xED
#define PKT_PONG 0xEE
struct AvailDataReq {
uint8_t checksum;
uint8_t lastPacketLQI;
int8_t lastPacketRSSI;
int8_t temperature;
uint16_t batteryMv;
uint8_t hwType;
uint8_t wakeupReason;
uint8_t capabilities;
uint16_t tagSoftwareVersion;
uint8_t currentChannel;
uint8_t customMode;
uint8_t reserved[8];
} __attribute__((packed, aligned(1)));
struct oldAvailDataReq {
uint8_t checksum;
uint8_t lastPacketLQI;
int8_t lastPacketRSSI;
int8_t temperature;
uint16_t batteryMv;
uint8_t hwType;
uint8_t wakeupReason;
uint8_t capabilities;
} __attribute__((packed, aligned(1)));
struct AvailDataInfo {
uint8_t checksum;
uint64_t dataVer; // MD5 of potential traffic
uint32_t dataSize;
uint8_t dataType;
uint8_t dataTypeArgument; // extra specification or instruction for the tag (LUT to be used for drawing image)
uint16_t nextCheckIn; // when should the tag check-in again? Measured in minutes
} __attribute__((packed, aligned(1)));
struct pendingData {
struct AvailDataInfo availdatainfo;
uint16_t attemptsLeft;
uint8_t targetMac[8];
} __attribute__((packed, aligned(1)));
struct blockPart {
uint8_t checksum;
uint8_t blockId;
uint8_t blockPart;
uint8_t data[];
} __attribute__((packed, aligned(1)));
struct blockData {
uint16_t size;
uint16_t checksum;
uint8_t data[];
} __attribute__((packed, aligned(1)));
#define TAG_RETURN_DATA_SIZE 90
struct tagReturnData {
uint8_t checksum;
uint8_t partId;
uint64_t dataVer;
uint8_t dataType;
uint8_t data[TAG_RETURN_DATA_SIZE];
} __attribute__((packed, aligned(1)));
#define BLOCK_PART_DATA_SIZE 99
#define BLOCK_MAX_PARTS 42
#define BLOCK_DATA_SIZE 4096UL
#define BLOCK_XFER_BUFFER_SIZE BLOCK_DATA_SIZE + sizeof(struct blockData)
#define BLOCK_REQ_PARTS_BYTES 6
struct blockRequest {
uint8_t checksum;
uint64_t ver;
uint8_t blockId;
uint8_t type;
uint8_t requestedParts[BLOCK_REQ_PARTS_BYTES];
} __attribute__((packed, aligned(1)));
struct blockRequestAck {
uint8_t checksum;
uint16_t pleaseWaitMs;
} __attribute__((packed, aligned(1)));
struct espBlockRequest {
uint8_t checksum;
uint64_t ver;
uint8_t blockId;
uint8_t src[8];
} __attribute__((packed, aligned(1)));
struct espXferComplete {
uint8_t checksum;
uint8_t src[8];
} __attribute__((packed, aligned(1)));
struct espAvailDataReq {
uint8_t checksum;
uint8_t src[8];
struct AvailDataReq adr;
} __attribute__((packed, aligned(1)));
struct espSetChannelPower {
uint8_t checksum;
uint8_t channel;
uint8_t power;
} __attribute__((packed, aligned(1)));
struct espTagReturnData {
uint8_t checksum;
uint8_t src[8];
uint8_t len;
struct tagReturnData returnData;
} __attribute__((packed, aligned(1)));
#endif

View File

@@ -0,0 +1,113 @@
#include "radio.h"
#include "driver/gpio.h"
#include "driver/uart.h"
#include "esp_err.h"
#include "esp_event.h"
#include "esp_ieee802154.h"
#include "esp_phy_init.h"
#include "esp_timer.h"
#include "freertos/FreeRTOS.h"
#include "freertos/queue.h"
#include "freertos/task.h"
#include "led.h"
#include "proto.h"
#include "sdkconfig.h"
#include "soc/uart_struct.h"
#include <esp_mac.h>
#include <math.h>
#include <stdarg.h>
#include <string.h>
#include <Arduino.h>
uint8_t mSelfMac[8];
volatile uint8_t isInTransmit = 0;
QueueHandle_t packet_buffer = NULL;
void esp_ieee802154_receive_done(uint8_t *frame, esp_ieee802154_frame_info_t *frame_info) {
Serial.printf("RADIO info RX %d\r\n", frame[0]);
BaseType_t xHigherPriorityTaskWoken;
static uint8_t inner_rxPKT[130];
memcpy(inner_rxPKT, &frame[0], frame[0] + 1);
xQueueSendFromISR(packet_buffer, (void *)&inner_rxPKT, &xHigherPriorityTaskWoken);
portYIELD_FROM_ISR_ARG(xHigherPriorityTaskWoken);
}
void esp_ieee802154_transmit_failed(const uint8_t *frame, esp_ieee802154_tx_error_t error) {
isInTransmit = 0;
Serial.printf("RADIO err TX Err: %d\r\n", error);
}
void esp_ieee802154_transmit_done(const uint8_t *frame, const uint8_t *ack, esp_ieee802154_frame_info_t *ack_frame_info) {
isInTransmit = 0;
Serial.printf("RADIO info TX %d\r\n", frame[0]);
}
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_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);
delay(100);
led_flash(0);
delay(100);
led_flash(1);
delay(100);
led_flash(0);
Serial.printf("RADIO Receiver ready, panId=0x%04x, channel=%d, long=%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x, short=%04x\r\n",
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;
bool radioTx(uint8_t *packet) {
static uint8_t txPKT[130];
led_flash(1);
while (isInTransmit) {
}
// while (millis() - lastZbTx < 6) {
// }
// lastZbTx = millis();
memcpy(txPKT, packet, packet[0]);
isInTransmit = 1;
esp_ieee802154_transmit(txPKT, false);
return true;
}
void radioSetChannel(uint8_t ch) {
radio_init(ch);
}
void radioSetTxPower(uint8_t power) {}
int8_t commsRxUnencrypted(uint8_t *data) {
static uint8_t inner_rxPKT_out[130];
if (xQueueReceive(packet_buffer, (void *)&inner_rxPKT_out, pdMS_TO_TICKS(100)) == pdTRUE) {
memcpy(data, &inner_rxPKT_out[1], inner_rxPKT_out[0] + 1);
return inner_rxPKT_out[0] - 2;
}
return 0;
}

View File

@@ -0,0 +1,11 @@
#pragma once
#include <stdbool.h>
#include <stdint.h>
extern uint8_t mSelfMac[8];
void radio_init(uint8_t ch);
bool radioTx(uint8_t *packet);
void radioSetChannel(uint8_t ch);
void radioSetTxPower(uint8_t power);
int8_t commsRxUnencrypted(uint8_t *data);

View File

@@ -0,0 +1,117 @@
#include <esp_mac.h>
#include <math.h>
#include <stdarg.h>
#include <string.h>
#include <Arduino.h>
#include "driver/gpio.h"
#include "driver/uart.h"
#include "esp_err.h"
#include "esp_event.h"
#include "esp_ieee802154.h"
#include "esp_phy_init.h"
#include "esp_timer.h"
#include "freertos/FreeRTOS.h"
#include "freertos/queue.h"
#include "freertos/task.h"
#include "nvs.h"
#include "nvs_flash.h"
#include "proto.h"
#include "sdkconfig.h"
#include "soc/uart_struct.h"
#include "second_uart.h"
#define CONFIG_OEPL_HARDWARE_UART_TX 4
#define CONFIG_OEPL_HARDWARE_UART_RX 5
#define BUF_SIZE (1024)
#define RD_BUF_SIZE (BUF_SIZE)
static QueueHandle_t uart0_queue;
#define MAX_BUFF_POS 8000
volatile int curr_buff_pos = 0;
volatile int worked_buff_pos = 0;
volatile uint8_t buff_pos[MAX_BUFF_POS + 5];
static void uart_event_task(void *pvParameters);
void init_second_uart() {
uart_config_t uart_config = {
.baud_rate = 115200,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
.source_clk = UART_SCLK_DEFAULT,
};
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, CONFIG_OEPL_HARDWARE_UART_TX, CONFIG_OEPL_HARDWARE_UART_RX, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE));
xTaskCreate(uart_event_task, "uart_event_task", 16384, NULL, 12, NULL);
}
void uart_switch_speed(int baudrate) {
uart_config_t uart_config = {
.baud_rate = baudrate,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
.source_clk = UART_SCLK_DEFAULT,
};
ESP_ERROR_CHECK(uart_param_config(1, &uart_config));
}
void uartTx(uint8_t data) {
uart_write_bytes(1, (const char *)&data, 1);
}
bool getRxCharSecond(uint8_t *newChar) {
if (curr_buff_pos != worked_buff_pos) {
*newChar = buff_pos[worked_buff_pos];
worked_buff_pos++;
worked_buff_pos %= MAX_BUFF_POS;
return true;
}
return false;
}
static void uart_event_task(void *pvParameters) {
uart_event_t event;
uint8_t *dtmp = (uint8_t *)malloc(RD_BUF_SIZE);
for (;;) {
if (xQueueReceive(uart0_queue, (void *)&event, (TickType_t)portMAX_DELAY)) {
bzero(dtmp, RD_BUF_SIZE);
switch (event.type) {
case UART_DATA:
uart_read_bytes(1, dtmp, event.size, portMAX_DELAY);
for (int i = 0; i < event.size; i++) {
buff_pos[curr_buff_pos] = dtmp[i];
curr_buff_pos++;
curr_buff_pos %= MAX_BUFF_POS;
}
break;
default:
Serial.printf("Second UART uart event type: %d\r\n", event.type);
break;
}
}
}
free(dtmp);
dtmp = NULL;
vTaskDelete(NULL);
}
void uart_printf(const char *format, ...) {
va_list args;
va_start(args, format);
char buffer[128];
int len = vsnprintf(buffer, sizeof(buffer), format, args);
va_end(args);
if (len > 0) {
uart_write_bytes(1, buffer, len);
}
}

View File

@@ -0,0 +1,13 @@
#pragma once
#include <inttypes.h>
void init_second_uart();
void uart_switch_speed(int baudrate);
void uartTx(uint8_t data);
bool getRxCharSecond(uint8_t *newChar);
void uart_printf(const char *format, ...);
#define pr uart_printf

View File

@@ -0,0 +1,5 @@
.pio
.vscode/.browse.c_cpp.db*
.vscode/c_cpp_properties.json
.vscode/launch.json
.vscode/ipch

View File

@@ -0,0 +1,39 @@
This directory is intended for project header files.
A header file is a file containing C declarations and macro definitions
to be shared between several project source files. You request the use of a
header file in your project source file (C, C++, etc) located in `src` folder
by including it, with the C preprocessing directive `#include'.
```src/main.c
#include "header.h"
int main (void)
{
...
}
```
Including a header file produces the same results as copying the header file
into each source file that needs it. Such copying would be time-consuming
and error-prone. With a header file, the related declarations appear
in only one place. If they need to be changed, they can be changed in one
place, and programs that include the header file will automatically use the
new version when next recompiled. The header file eliminates the labor of
finding and changing all the copies as well as the risk that a failure to
find one copy will result in inconsistencies within a program.
In C, the usual convention is to give header files names that end with `.h'.
It is most portable to use only letters, digits, dashes, and underscores in
header file names, and at most one dot.
Read more about using header files in official GCC documentation:
* Include Syntax
* Include Operation
* Once-Only Headers
* Computed Includes
https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html

View File

@@ -0,0 +1,46 @@
This directory is intended for project specific (private) libraries.
PlatformIO will compile them to static libraries and link into executable file.
The source code of each library should be placed in a an own separate directory
("lib/your_library_name/[here are source files]").
For example, see a structure of the following two libraries `Foo` and `Bar`:
|--lib
| |
| |--Bar
| | |--docs
| | |--examples
| | |--src
| | |- Bar.c
| | |- Bar.h
| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
| |
| |--Foo
| | |- Foo.c
| | |- Foo.h
| |
| |- README --> THIS FILE
|
|- platformio.ini
|--src
|- main.c
and a contents of `src/main.c`:
```
#include <Foo.h>
#include <Bar.h>
int main (void)
{
...
}
```
PlatformIO Library Dependency Finder will find automatically dependent
libraries scanning project source files.
More information about PlatformIO Library Dependency Finder
- https://docs.platformio.org/page/librarymanager/ldf.html

View File

@@ -0,0 +1,47 @@
name: Bug report
description: Report a problem with esp-serial-flasher operation
labels: ['Type: Bug']
body:
- type: markdown
attributes:
value: |
* Please ensure you are using the latest version of `esp-serial-flasher`.
* Try using one of the examples from the `examples` directory and following the example documentation.
* If your board is a custom design, consider using our [free-of-charge schematic and PCB review service](https://www.espressif.com/en/contact-us/circuit-schematic-pcb-design-review).
* If still experiencing issues, please provide as many details as possible below about your hardware and software setup.
- type: input
id: port
attributes:
label: Port
description: Which port are you experiencing the issue with?
placeholder: ex. ESP, STM32
validations:
required: true
- type: input
id: target
attributes:
label: Target chip
description: Which chip are you trying to flash?
placeholder: ex. ESP8266, ESP32, ESP32-C3
validations:
required: true
- type: textarea
id: other-hw
attributes:
label: Hardware Configuration
description: What dev boards/custom PCB are you using, how are the chips connected, which baudrate are you trying to flash with?
validations:
required: true
id: output
- type: textarea
attributes:
label: Log output
description: Enable tracing with SERIAL_FLASHER_DEBUG_TRACE and provide the full log.
render: plain
validations:
required: true
- type: textarea
id: more-info
attributes:
label: More Information
description: Provide any additional information relevant to the issue.

View File

@@ -0,0 +1,34 @@
name: Feature request
description: Suggest an idea for this project
labels: ['Type: Feature Request']
body:
- type: markdown
attributes:
value: |
* We welcome any ideas or feature requests! It's helpful if you can explain exactly why the feature would be useful.
* Please check if the feature has already been suggested in [existing issues](https://github.com/espressif/esp-serial-flasher/issues) or [pull requests](https://github.com/espressif/esp-serial-flasher/pulls).
* Please provide enough context so that the reasoning behind the suggestion can be understood.
- type: textarea
id: problem-related
attributes:
label: Is your feature request related to a problem?
description: Please provide a clear and concise description of what the problem is.
validations:
required: true
- type: textarea
id: solution
attributes:
label: Describe the solution you'd like
description: Please provide a clear and concise description of a solution of the described problem or usecase.
validations:
required: true
- type: textarea
id: alternatives
attributes:
label: Describe alternatives you've considered
description: Please provide a clear and concise description of any alternative solutions or features you've considered.
- type: textarea
id: context
attributes:
label: Additional context
description: Please add any other context here.

View File

@@ -0,0 +1,20 @@
name: Sync issue comments to JIRA
# This workflow will be triggered when new issue comment is created (including PR comments)
on: issue_comment
jobs:
sync_issue_comments_to_jira:
name: Sync Issue Comments to Jira
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
- name: Sync issue comments to JIRA
uses: espressif/github-actions/sync_issues_to_jira@master
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
JIRA_PASS: ${{ secrets.JIRA_PASS }}
JIRA_PROJECT: ESF
JIRA_COMPONENT: GitHub
JIRA_URL: ${{ secrets.JIRA_URL }}
JIRA_USER: ${{ secrets.JIRA_USER }}

View File

@@ -0,0 +1,20 @@
name: Sync issues to Jira
# This workflow will be triggered when a new issue is opened
on: issues
jobs:
sync_issues_to_jira:
name: Sync issues to Jira
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
- name: Sync GitHub issues to Jira project
uses: espressif/github-actions/sync_issues_to_jira@master
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
JIRA_PASS: ${{ secrets.JIRA_PASS }}
JIRA_PROJECT: ESF
JIRA_COMPONENT: GitHub
JIRA_URL: ${{ secrets.JIRA_URL }}
JIRA_USER: ${{ secrets.JIRA_USER }}

View File

@@ -0,0 +1,25 @@
name: Sync remain PRs to Jira
# This workflow will be triggered every hour, to sync remaining PRs (i.e. PRs with zero comment) to Jira project
# Note that, PRs can also get synced when new PR comment is created
on:
schedule:
- cron: "0 * * * *"
jobs:
sync_prs_to_jira:
name: Sync PRs to Jira
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
- name: Sync PRs to Jira project
uses: espressif/github-actions/sync_issues_to_jira@master
with:
cron_job: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
JIRA_PASS: ${{ secrets.JIRA_PASS }}
JIRA_PROJECT: ESF
JIRA_COMPONENT: GitHub
JIRA_URL: ${{ secrets.JIRA_URL }}
JIRA_USER: ${{ secrets.JIRA_USER }}

View File

@@ -0,0 +1,6 @@
build
sdkconfig
sdkconfig.old
empty_file.bin
binaries.c
*.lock

View File

@@ -0,0 +1,139 @@
stages:
- build
- test
- deploy
workflow:
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
- if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS && $CI_PIPELINE_SOURCE == "push"
when: never
- if: "$CI_COMMIT_BRANCH"
variables:
STM32_CUBE_F4_REPO: https://github.com/STMicroelectronics/STM32CubeF4
STM32_CUBE_F4_REPO_TAG: v1.26.2
ARM_TOOLCHAIN_URL: https://developer.arm.com/-/media/Files/downloads/gnu-rm/9-2020q2/gcc-arm-none-eabi-9-2020-q2-update-x86_64-linux.tar.bz2?revision=05382cca-1721-44e1-ae19-1e7c3dc96118&la=en&hash=D7C9D18FCA2DD9F894FD9F3C3DC9228498FA281A
QEMU_PATH: /opt/qemu/bin/qemu-system-xtensa
ZEPHYR_REPO: https://github.com/zephyrproject-rtos/zephyr.git
ZEPHYR_REPO_REV: v3.2.0
ZEPHYR_TOOLCHAIN: https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.15.2/toolchain_linux-x86_64_xtensa-espressif_esp32_zephyr-elf.tar.gz
ZEPHYR_SDK: https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.15.2/zephyr-sdk-0.15.2_linux-aarch64_minimal.tar.gz
.build_idf_template:
stage: build
image: espressif/idf:latest
tags:
- build
- internet
variables:
PEDANTIC_FLAGS: "-Werror=all -Werror=extra"
EXTRA_CFLAGS: "${PEDANTIC_FLAGS}"
EXTRA_CXXFLAGS: "${PEDANTIC_FLAGS}"
script:
- cd $CI_PROJECT_DIR/examples/esp32_example
- idf.py build -DMD5_ENABLED=1
- idf.py build -DMD5_ENABLED=0
- cd $CI_PROJECT_DIR/examples/esp32_load_ram_example
- idf.py build
- cd $CI_PROJECT_DIR/examples/esp32_spi_load_ram_example
- idf.py build
build_idf_v4.2:
extends: .build_idf_template
image: espressif/idf:release-v4.2
build_idf_v4.3:
extends: .build_idf_template
image: espressif/idf:release-v4.3
build_idf_v4.4:
extends: .build_idf_template
image: espressif/idf:release-v4.4
build_idf_v5.0:
extends: .build_idf_template
image: espressif/idf:release-v5.0
build_idf_v5.1:
extends: .build_idf_template
image: espressif/idf:release-v5.1
build_idf_master:
extends: .build_idf_template
image: espressif/idf:latest
build_stm32:
stage: build
# IDF is not necessary for STM32 build, but this image is already used in another job
# and it comes with a recent enough CMake version.
image: espressif/idf:latest
tags:
- build
- internet
script:
- cd $CI_PROJECT_DIR
- git submodule update --init
- git clone --depth=1 -b ${STM32_CUBE_F4_REPO_TAG} ${STM32_CUBE_F4_REPO}
- wget --no-verbose -O gcc-arm-none-eabi.tar.bz2 ${ARM_TOOLCHAIN_URL}
- tar -xjf gcc-arm-none-eabi.tar.bz2
- mv gcc-arm-none-eabi-* gcc-arm-none-eabi
- mkdir $CI_PROJECT_DIR/examples/stm32_example/build
- cd $CI_PROJECT_DIR/examples/stm32_example/build
- cmake -DTOOLCHAIN_PREFIX=$CI_PROJECT_DIR/gcc-arm-none-eabi -DSTM32Cube_DIR=$CI_PROJECT_DIR/STM32CubeF4 -G Ninja ..
- cmake --build .
build_zephyr:
stage: build
image: espressif/idf:latest
tags:
- build
- internet
script:
- mkdir $CI_PROJECT_DIR/zephyrproject-rtos
- cd $CI_PROJECT_DIR/zephyrproject-rtos
- git clone --single-branch --depth=1 -b ${ZEPHYR_REPO_REV} ${ZEPHYR_REPO}
- mkdir $CI_PROJECT_DIR/zephyrproject-rtos/zephyr-sdk
- cd $CI_PROJECT_DIR/zephyrproject-rtos/zephyr-sdk
- wget --no-verbose -O zephyr_sdk.tar.gz ${ZEPHYR_SDK}
- tar xvf zephyr_sdk.tar.gz --strip-components=1
- wget --no-verbose -O esp32_toolchain.tar.gz ${ZEPHYR_TOOLCHAIN}
- tar xvf esp32_toolchain.tar.gz
- export ZEPHYR_SDK_INSTALL_DIR=$(pwd)
- export ZEPHYR_TOOLCHAIN_VARIANT="zephyr"
- cd $CI_PROJECT_DIR/zephyrproject-rtos/zephyr
- export ZEPHYR_BASE=$(pwd)
- pip install -r scripts/requirements.txt
- pip install wheel
- if [[ ! -d "$CI_PROJECT_DIR/zephyrproject-rtos/.west" ]]; then
- west init -l .
- fi
- unset IDF_PATH
- west zephyr-export
- west update hal_espressif
- west build -p -b esp32 $CI_PROJECT_DIR/examples/zephyr_example -DZEPHYR_EXTRA_MODULES=$CI_PROJECT_DIR
run_tests:
stage: test
image: ${CI_DOCKER_REGISTRY}/qemu:esp-develop-20191124
tags:
- build
- internet
script:
- cd $CI_PROJECT_DIR/test
- export QEMU_PATH=/opt/qemu/bin/qemu-system-xtensa
- ./run_test.sh qemu
- ./run_test.sh host
push_to_the_components_registry:
stage: deploy
image: python:3.10-alpine
tags:
- build
- internet
rules:
- if: '$CI_COMMIT_BRANCH == "master"'
- if: '$FORCE_PUSH_COMPONENT == "1"'
script:
- pip install idf-component-manager
- python -m idf_component_manager upload-component --allow-existing --name=esp-serial-flasher --namespace=espressif

View File

@@ -0,0 +1,3 @@
[submodule "submodules/stm32-cmake"]
path = submodules/stm32-cmake
url = https://github.com/ObKo/stm32-cmake.git

View File

@@ -0,0 +1,119 @@
cmake_minimum_required(VERSION 3.5)
set(srcs
src/esp_targets.c
src/md5_hash.c
src/esp_loader.c
src/protocol_common.c
)
if (DEFINED ESP_PLATFORM)
if (${CONFIG_SERIAL_FLASHER_INTERFACE_UART})
list(APPEND srcs
src/protocol_uart.c
src/slip.c
port/esp32_port.c
)
elseif (${CONFIG_SERIAL_FLASHER_INTERFACE_SPI})
list(APPEND srcs
src/protocol_spi.c
port/esp32_spi_port.c
)
endif()
# Register component to esp-idf build system
if ("${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}" VERSION_GREATER "4.0")
# esp_timer component was introduced in v4.2
set(priv_requires driver)
if("${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}" VERSION_GREATER "4.1")
list(APPEND priv_requires esp_timer)
endif()
idf_component_register(SRCS ${srcs}
INCLUDE_DIRS include port
PRIV_INCLUDE_DIRS private_include
PRIV_REQUIRES ${priv_requires})
set(target ${COMPONENT_LIB})
component_compile_options(-Wstrict-prototypes)
else()
# Remove when dropping support for IDF 3.3
set(COMPONENT_SRCS ${srcs})
set(COMPONENT_ADD_INCLUDEDIRS include port)
set(COMPONENT_PRIV_INCLUDEDIRS private_include)
register_component()
set(target ${COMPONENT_TARGET})
endif()
else()
if (NOT DEFINED SERIAL_FLASHER_INTERFACE_UART AND NOT DEFINED SERIAL_FLASHER_INTERFACE_SPI)
set(SERIAL_FLASHER_INTERFACE_UART true)
endif()
if (DEFINED SERIAL_FLASHER_INTERFACE_UART)
list(APPEND srcs
src/protocol_uart.c
src/slip.c
)
elseif (DEFINED SERIAL_FLASHER_INTERFACE_SPI)
list(APPEND srcs src/protocol_spi.c)
endif()
# Create traditional CMake target
add_library(flasher ${srcs})
target_include_directories(flasher PUBLIC include port PRIVATE private_include)
if(PORT STREQUAL "STM32")
target_link_libraries(flasher PUBLIC stm_cube)
target_sources(flasher PRIVATE port/stm32_port.c)
elseif(PORT STREQUAL "RASPBERRY_PI")
find_library(pigpio_LIB pigpio)
target_link_libraries(flasher PUBLIC ${pigpio_LIB})
target_sources(flasher PRIVATE port/raspberry_port.c)
else()
message(FATAL_ERROR "Selected port is not supported")
endif()
set(target flasher)
endif()
if (DEFINED SERIAL_FLASHER_INTERFACE_UART OR CONFIG_SERIAL_FLASHER_INTERFACE_UART STREQUAL "y")
target_compile_definitions(${target}
PUBLIC
SERIAL_FLASHER_INTERFACE_UART
)
if (DEFINED MD5_ENABLED OR CONFIG_SERIAL_FLASHER_MD5_ENABLED)
target_compile_definitions(${target} PUBLIC MD5_ENABLED=1)
endif()
elseif (DEFINED SERIAL_FLASHER_INTERFACE_SPI OR CONFIG_SERIAL_FLASHER_INTERFACE_SPI STREQUAL "y")
target_compile_definitions(${target}
PUBLIC
SERIAL_FLASHER_INTERFACE_SPI
)
endif()
if(DEFINED SERIAL_FLASHER_DEBUG_TRACE OR CONFIG_SERIAL_FLASHER_DEBUG_TRACE)
target_compile_definitions(${target} PUBLIC SERIAL_FLASHER_DEBUG_TRACE)
endif()
if(DEFINED CONFIG_SERIAL_FLASHER_RESET_HOLD_TIME_MS AND DEFINED CONFIG_SERIAL_FLASHER_BOOT_HOLD_TIME_MS)
target_compile_definitions(${target}
PUBLIC
SERIAL_FLASHER_RESET_HOLD_TIME_MS=${CONFIG_SERIAL_FLASHER_RESET_HOLD_TIME_MS}
SERIAL_FLASHER_BOOT_HOLD_TIME_MS=${CONFIG_SERIAL_FLASHER_BOOT_HOLD_TIME_MS}
)
else()
if(NOT DEFINED SERIAL_FLASHER_RESET_HOLD_TIME_MS)
target_compile_definitions(${target}
PUBLIC
SERIAL_FLASHER_RESET_HOLD_TIME_MS=100
)
endif()
if(NOT DEFINED SERIAL_FLASHER_BOOT_HOLD_TIME_MS)
target_compile_definitions(${target}
PUBLIC
SERIAL_FLASHER_BOOT_HOLD_TIME_MS=50
)
endif()
endif()

View File

@@ -0,0 +1,34 @@
menu "ESP serial flasher"
config SERIAL_FLASHER_MD5_ENABLED
bool "Enable MD5 check"
default y
help
Select this option to enable MD5 hashsum check after flashing.
choice SERIAL_FLASHER_INTERFACE
prompt "Hardware interface to use for firmware download"
default SERIAL_FLASHER_INTERFACE_UART
help
esp-serial-flasher can work with UART and SPI interfaces.
config SERIAL_FLASHER_INTERFACE_UART
bool "UART"
config SERIAL_FLASHER_INTERFACE_SPI
bool "SPI (Only supports downloading to RAM, experimental)"
endchoice
config SERIAL_FLASHER_RESET_HOLD_TIME_MS
int "Time for which the reset pin is asserted when doing a hard reset"
default 100
config SERIAL_FLASHER_BOOT_HOLD_TIME_MS
int "Time for which the boot pin is asserted when doing a hard reset"
default 50
config SERIAL_FLASHER_DEBUG_TRACE
bool "Enable debug tracing output (only transfer data tracing is supported at the time)"
default n
endmenu

View File

@@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
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.

View File

@@ -0,0 +1,155 @@
# esp-serial-flasher
`esp-serial-flasher` is a portable C library for flashing or loading apps to RAM of Espressif SoCs from other host microcontrollers.
## Using the library
Espressif SoCs are normally programmed via serial interface (UART). The port layer for the given host microcontroller has to be implemented if not available. Details can be found in section below.
Supported **host** microcontrollers:
- STM32
- Raspberry Pi SBC
- ESP32
- Any MCU running Zephyr OS
Supported **target** microcontrollers:
- ESP32
- ESP8266
- ESP32-S2
- ESP32-S3
- ESP32-C3
- ESP32-C2
- ESP32-H2
- ESP32-C6
Supported hardware interfaces:
- UART
- SPI (only for RAM download, experimental)
For example usage check the `examples` directory.
## Supporting a new host target
In order to support a new target, following functions have to be implemented by user:
- `loader_port_read()`
- `loader_port_write()`
- `loader_port_enter_bootloader()`
- `loader_port_delay_ms()`
- `loader_port_start_timer()`
- `loader_port_remaining_time()`
For the SPI interface ports
- `loader_port_spi_set_cs()`
needs to be implemented as well.
The following functions are part of the [io.h](include/io.h) header for convenience, however, the user does not have to strictly follow function signatures, as there are not called directly from library.
- `loader_port_change_transmission_rate()`
- `loader_port_reset_target()`
- `loader_port_debug_print()`
Prototypes of all functions mentioned above can be found in [io.h](include/io.h).
## Configuration
These are the configuration toggles available to the user:
* `SERIAL_FLASHER_INTERFACE_UART/SERIAL_FLASHER_INTERFACE_SPI`
This defines the hardware interface to use. SPI interface only supports RAM download mode and is in experimental stage and can undergo changes.
Default: SERIAL_FLASHER_INTERFACE_UART
* `MD5_ENABLED`
If enabled, `esp-serial-flasher` is capable of verifying flash integrity after writing to flash.
Default: Enabled
> Warning: As ROM bootloader of the ESP8266 does not support MD5_CHECK, this option has to be disabled!
* `SERIAL_FLASHER_RESET_HOLD_TIME_MS`
This is the time for which the reset pin is asserted when doing a hard reset in milliseconds.
Default: 100
* `SERIAL_FLASHER_BOOT_HOLD_TIME_MS`
This is the time for which the boot pin is asserted when doing a hard reset in milliseconds.
Default: 50
Configuration can be passed to `cmake` via command line:
```
cmake -DMD5_ENABLED=1 .. && cmake --build .
```
### STM32 support
The STM32 port makes use of STM32 HAL libraries, and these do not come with CMake support. In order to compile the project, `stm32-cmake` (a `CMake` support package) has to be pulled as submodule.
```
git clone --recursive https://github.com/espressif/esp-serial-flasher.git
```
If you have cloned this repository without the `--recursive` flag, you can initialize the submodule using the following command:
```
git submodule update --init
```
In addition to configuration parameters mentioned above, following definitions has to be set:
- TOOLCHAIN_PREFIX: path to arm toolchain (i.e /home/user/gcc-arm-none-eabi-9-2019-q4-major)
- STM32Cube_DIR: path to STM32 Cube libraries (i.e /home/user/STM32Cube/Repository/STM32Cube_FW_F4_V1.25.0)
- STM32_CHIP: name of STM32 for which project should be compiled (i.e STM32F407VG)
- PORT: STM32
This can be achieved by passing definitions to the command line, such as:
```
cmake -DTOOLCHAIN_PREFIX="/path_to_toolchain" -DSTM32Cube_DIR="path_to_stm32Cube" -DSTM32_CHIP="STM32F407VG" -DPORT="STM32" .. && cmake --build .
```
Alternatively, those variables can be set in the top level `cmake` directory:
```
set(TOOLCHAIN_PREFIX path_to_toolchain)
set(STM32Cube_DIR path_to_stm32_HAL)
set(STM32_CHIP STM32F407VG)
set(PORT STM32)
```
### Zephyr support
The Zephyr port is ready to be integrated into Zephyr apps as a Zephyr module. In the manifest file (west.yml), add:
```
- name: esp-flasher
url: https://github.com/espressif/esp-serial-flasher
revision: master
path: modules/lib/esp_flasher
```
And add
```
CONFIG_ESP_SERIAL_FLASHER=y
CONFIG_CONSOLE_GETCHAR=y
CONFIG_SERIAL_FLASHER_MD5_ENABLED=y
```
to the project configuration `prj.conf`.
For the C/C++ source code, the example code provided in `examples/zephyr_example` can be used as a starting point.
## Licence
Code is distributed under Apache 2.0 license.
## Known limitations
Size of new binary image has to be known before flashing.

View File

@@ -0,0 +1,15 @@
# The following lines of boilerplate have to be in your project's
# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.16)
# Here we remove all unecessary components from the build to make the binary smaller
set(COMPONENTS main)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(hello_world)
# This generates a binary file from the elf, as the RAM build doesn't do that automatically
add_custom_command(TARGET ${PROJECT_NAME}.elf
POST_BUILD
COMMAND esptool.py --chip ${IDF_TARGET} elf2image --output app.bin ${PROJECT_NAME}.elf
)

View File

@@ -0,0 +1,2 @@
idf_component_register(SRCS "main.c"
INCLUDE_DIRS "")

View File

@@ -0,0 +1,16 @@
/*
* SPDX-FileCopyrightText: 2010-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: CC0-1.0
*/
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
void app_main(void)
{
while (true) {
esp_rom_printf("Hello world!\n");
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
}

View File

@@ -0,0 +1,11 @@
# This file was generated using idf.py save-defconfig. It can be edited manually.
# Espressif IoT Development Framework (ESP-IDF) Project Minimal Configuration
#
CONFIG_APP_BUILD_TYPE_ELF_RAM=y
CONFIG_COMPILER_OPTIMIZATION_SIZE=y
CONFIG_APP_NO_BLOBS=y
CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_DISABLE=y
CONFIG_COMPILER_OPTIMIZATION_CHECKS_SILENT=y
# CONFIG_ESP_ERR_TO_NAME_LOOKUP is not set
CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT=y
CONFIG_LOG_DEFAULT_LEVEL_NONE=y

View File

@@ -0,0 +1,20 @@
# Creates C resources file from files in given directory recursively
function(create_resources dir output)
# Create empty output file
file(WRITE ${output} "#include <stdint.h>\n\n")
# Collect input files
file(GLOB bin_paths ${dir}/ESP*/*)
# Iterate through input files
foreach(bin ${bin_paths})
# Get short filenames, by discarding relative path
file(GLOB name RELATIVE ${dir} ${bin})
# Replace filename spaces & extension separator for C compatibility
string(REGEX REPLACE "[\\./-]" "_" filename ${name})
# Read hex data from file
file(READ ${bin} filedata HEX)
# Convert hex data for C compatibility
string(REGEX REPLACE "([0-9a-f][0-9a-f])" "0x\\1," filedata ${filedata})
# Append data to output file
file(APPEND ${output} "const uint8_t ${filename}[] = {${filedata}};\nconst uint32_t ${filename}_size = sizeof(${filename});\n")
endforeach()
endfunction()

View File

@@ -0,0 +1,7 @@
# The following lines of boilerplate have to be in your project's CMakeLists
# in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.5)
set(EXTRA_COMPONENT_DIRS ../../)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(esp-serial-flasher)

View File

@@ -0,0 +1,78 @@
# Flash multiple partitions example
## Overview
Example demonstrates how to flash ESP32/ESP32-S2/ESP8266 from another (host) MCU using esp_serial_flash component API. In this case, ESP32 is also used as host MCU. Binaries to be flashed from host MCU to another Espressif SoC can be found in `binaries` folder and are converted into C-array during build process.
Following steps are performed in order to re-program target's memory:
1. Filesystem is initialized and mounted.
2. UART1 through which new binary will be transfered is initialized.
3. Host puts slave device into boot mode tries to connect by calling `esp_loader_connect()`.
4. Binary file is opened and its size is acquired, as it has to be known before flashing.
5. Then `esp_loader_flash_start()` is called to enter flashing mode and erase amount of memory to be flashed.
6. `esp_loader_flash_write()` function is called repeatedly until the whole binary image is transfered.
Note: In addition, to steps mentioned above, `esp_loader_change_transmission_rate` is called after connection is established in order to increase flashing speed. This does not apply for ESP8266, as its bootloader does not support this command. However, ESP8266 is capable of detecting baud rate during connection phase, and can be changed before calling `esp_loader_connect`, if necessary.
## SPI pin initialization
In majority of cases `ESP_LOADER_CONNECT_DEFAULT` helper macro is used in order to initialize `loader_connect_args_t` data structure passed to `esp_loader_connect`. Helper macro sets `spi_pin_config` field of the data structure to zero, thus, default SPI pins are used to connect to FLASH memory. In special cases, such as custom design in which FLASH is connected to different pins, `spi_pin_config` field has to be set accordingly. For more detailed information refer to [serial protocol](https://docs.espressif.com/projects/esptool/en/latest/esp32s3/advanced-topics/serial-protocol.html).
## Hardware Required
* Two development boards with ESP32 SoC (e.g., ESP32-DevKitC, ESP-WROVER-KIT, etc.).
* One or two USB cables for power supply and programming.
## Hardware connection
Table below shows connection between two ESP32 devices.
| ESP32 (host) | ESP32 (slave) |
|:------------:|:-------------:|
| IO26 | IO0 |
| IO25 | RESET |
| IO4 | RX0 |
| IO5 | TX0 |
Note: interconnection is the same for all three targets (slaves).
## Build and flash
To run the example, type the following command:
```CMake
idf.py -p PORT flash monitor
```
(To exit the serial monitor, type ``Ctrl-]``.)
See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects.
## Configuration
For details about available configuration option, please refer to top level [README.md](../../README.md).
Compile definitions can be specified on command line when running `idf.py`, for example:
```
idf.py build -DMD5_ENABLED=1
```
Binaries to be flashed are placed in separate folder (binaries.c) for each possible target and converted to C-array. Without explicitly enabling MD5 check, flash integrity verification is disabled by default.
## Example output
Here is the example's console output:
```
...
I (342) example: Initializing SPIFFS
I (482) example: Image size: 144672
I (902) example: Connected to target
I (1732) example: Start programming
I (1832) example: packet: 0 written: 1024 B
I (1932) example: packet: 1 written: 1024 B
...
I (16052) example: packet: 140 written: 1024 B
I (16152) example: packet: 141 written: 288 B
I (16152) example: Finished programming
```

View File

@@ -0,0 +1,22 @@
set(srcs main.c ../../common/example_common.c)
set(include_dirs . ../../common)
if ("${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}" VERSION_GREATER "4.0")
idf_component_register(SRCS ${srcs}
INCLUDE_DIRS ${include_dirs})
set(target ${COMPONENT_LIB})
else()
# remove when dropping IDF 3.3 support
set(COMPONENT_SRCS ${srcs})
set(COMPONENT_ADD_INCLUDEDIRS ${include_dirs})
register_component()
set(target ${COMPONENT_TARGET})
endif()
# Embed binaries into the app.
# In ESP-IDF this can also be done using EMBED_FILES option of idf_component_register.
# Here an external tool is used to make file embedding similar with other ports.
include(${CMAKE_CURRENT_LIST_DIR}/../../common/bin2array.cmake)
create_resources(${CMAKE_CURRENT_LIST_DIR}/../../binaries/Hello-world ${CMAKE_BINARY_DIR}/binaries.c)
set_property(SOURCE ${CMAKE_BINARY_DIR}/binaries.c PROPERTY GENERATED 1)
target_sources(${target} PRIVATE ${CMAKE_BINARY_DIR}/binaries.c)

View File

@@ -0,0 +1,54 @@
/* Flash multiple partitions example
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#include <sys/param.h>
#include <string.h>
#include "esp_err.h"
#include "esp_log.h"
#include "driver/uart.h"
#include "driver/gpio.h"
#include "esp32_port.h"
#include "esp_loader.h"
#include "example_common.h"
static const char *TAG = "serial_flasher";
#define HIGHER_BAUDRATE 230400
void app_main(void)
{
example_binaries_t bin;
const loader_esp32_config_t config = {
.baud_rate = 115200,
.uart_port = UART_NUM_1,
.uart_rx_pin = GPIO_NUM_5,
.uart_tx_pin = GPIO_NUM_4,
.reset_trigger_pin = GPIO_NUM_25,
.gpio0_trigger_pin = GPIO_NUM_26,
};
if (loader_port_esp32_init(&config) != ESP_LOADER_SUCCESS) {
ESP_LOGE(TAG, "serial initialization failed.");
return;
}
if (connect_to_target(HIGHER_BAUDRATE) == ESP_LOADER_SUCCESS) {
get_example_binaries(esp_loader_get_target(), &bin);
ESP_LOGI(TAG, "Loading bootloader...");
flash_binary(bin.boot.data, bin.boot.size, bin.boot.addr);
ESP_LOGI(TAG, "Loading partition table...");
flash_binary(bin.part.data, bin.part.size, bin.part.addr);
ESP_LOGI(TAG, "Loading app...");
flash_binary(bin.app.data, bin.app.size, bin.app.addr);
ESP_LOGI(TAG, "Done!");
}
}

View File

@@ -0,0 +1,4 @@
# Name, Type, SubType, Offset, Size, Flags
nvs, data, nvs, , 0x6000,
phy_init, data, phy, , 0x1000,
factory, app, factory, , 1500K,
1 # Name Type SubType Offset Size Flags
2 nvs data nvs 0x6000
3 phy_init data phy 0x1000
4 factory app factory 1500K

View File

@@ -0,0 +1 @@
CONFIG_PARTITION_TABLE_CUSTOM=y

View File

@@ -0,0 +1,7 @@
# The following lines of boilerplate have to be in your project's CMakeLists
# in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.5)
set(EXTRA_COMPONENT_DIRS ../../)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(esp32-serial-ram-loader)

View File

@@ -0,0 +1,14 @@
set(srcs main.c ../../common/example_common.c)
set(include_dirs . ../../common)
idf_component_register(SRCS ${srcs}
INCLUDE_DIRS ${include_dirs})
set(target ${COMPONENT_LIB})
# Embed binaries into the app.
# In ESP-IDF this can also be done using EMBED_FILES option of idf_component_register.
# Here an external tool is used to make file embedding similar with other ports.
include(${CMAKE_CURRENT_LIST_DIR}/../../common/bin2array.cmake)
create_resources(${CMAKE_CURRENT_LIST_DIR}/../../binaries/RAM_APP ${CMAKE_BINARY_DIR}/binaries.c)
set_property(SOURCE ${CMAKE_BINARY_DIR}/binaries.c PROPERTY GENERATED 1)
target_sources(${target} PRIVATE ${CMAKE_BINARY_DIR}/binaries.c)

View File

@@ -0,0 +1,80 @@
/* Example of loading the program into RAM
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#include <sys/param.h>
#include <string.h>
#include "esp_err.h"
#include "esp_log.h"
#include "esp_task_wdt.h"
#include "driver/uart.h"
#include "driver/gpio.h"
#include "esp32_port.h"
#include "esp_loader.h"
#include "example_common.h"
#include "freertos/FreeRTOS.h"
static const char *TAG = "serial_ram_loader";
// This can be set to a higher baud rate, but because it takes some time to
// switch the uart baud rate in slave_monitor task, the log at slave starup
// time will be lost or garbled.
#define HIGHER_BAUDRATE 115200
// Max line size
#define BUF_LEN 128
static uint8_t buf[BUF_LEN] = {0};
void slave_monitor(void *arg)
{
#if (HIGHER_BAUDRATE != 115200)
uart_flush_input(UART_NUM_1);
uart_flush(UART_NUM_1);
uart_set_baudrate(UART_NUM_1, 115200);
#endif
while (1) {
int rxBytes = uart_read_bytes(UART_NUM_1, buf, BUF_LEN, 100 / portTICK_PERIOD_MS);
buf[rxBytes] = '\0';
printf("%s", buf);
}
}
void app_main(void)
{
example_ram_app_binary_t bin;
const loader_esp32_config_t config = {
.baud_rate = 115200,
.uart_port = UART_NUM_1,
.uart_rx_pin = GPIO_NUM_5,
.uart_tx_pin = GPIO_NUM_4,
.reset_trigger_pin = GPIO_NUM_25,
.gpio0_trigger_pin = GPIO_NUM_26,
};
if (loader_port_esp32_init(&config) != ESP_LOADER_SUCCESS) {
ESP_LOGE(TAG, "serial initialization failed.");
abort();
}
if (connect_to_target(HIGHER_BAUDRATE) == ESP_LOADER_SUCCESS) {
get_example_ram_app_binary(esp_loader_get_target(), &bin);
ESP_LOGI(TAG, "Loading app to RAM ...");
esp_loader_error_t err = load_ram_binary(bin.ram_app.data);
if (err == ESP_LOADER_SUCCESS) {
// Forward slave's serial output
ESP_LOGI(TAG, "********************************************");
ESP_LOGI(TAG, "*** Logs below are print from slave .... ***");
ESP_LOGI(TAG, "********************************************");
xTaskCreate(slave_monitor, "slave_monitor", 2048, NULL, configMAX_PRIORITIES, NULL);
} else {
ESP_LOGE(TAG, "Loading to ram failed ...");
}
}
vTaskDelete(NULL);
}

View File

@@ -0,0 +1,7 @@
# The following lines of boilerplate have to be in your project's CMakeLists
# in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.16)
set(EXTRA_COMPONENT_DIRS ../../)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(esp32-spi-ram-loader)

View File

@@ -0,0 +1,80 @@
# Example of loading the program into RAM through SPI
## Overview
This example demonstrates how to upload an app to RAM of an Espressif MCU with SPI download support from another (host) MCU using the `esp_serial_flash` component API. In this case, another Espressif MCU is used as the host. Binaries to be uploaded to RAM from host MCU to the target MCU can be found in `binaries/RAM_APP` folder and are converted into C-array during build process.
Following steps are performed in order to re-program the target's memory:
1. SPI2 through which the binary will be transfered is initialized.
2. Host puts slave device into SPI download mode tries to connect by calling `esp_loader_connect()`.
3. Then `esp_loader_mem_start()` is called for each segment in RAM.
4. `esp_loader_flash_write()` function is called repeatedly for every segment until the whole binary image is transfered.
5. `esp_loader_mem_finish()` is called with the binary entrypoint, telling the chip to start the uploaded program.
6. UART2 is initialized for the connection to the target
7. Target output is continually read and printed
## Hardware Required
* Two development boards, one with any Espressif MCU (e.g., ESP32-DevKitC, ESP-WROVER-KIT, etc.) and one with an Espressif MCU with SPI download support. Here is a short list of supported MCUs:
1. ESP32-C3
2. ESP32-C2
3. ESP32-S3
4. ESP32-S2
5. ESP32-H2
* One or two USB cables for power supply and programming.
## Hardware connection
Table below shows connection between two Espressif MCUs.
| Host | Slave |
| IO_5 | RESET |
| IO_12 | CLK |
| IO_10 | CS |
| IO_13 | MISO |
| IO_11 | MOSI |
| IO_14 | QUADWP |
| IO_9 | QUADHD |
| IO_13 | STRAP_B0 |
| IO_2 | STRAP_B1 |
| IO_3 | STRAP_B2 |
| IO_4 | STRAP_B3 |
| IO_6 | UART0_RX |
| IO_7 | UART0_TX |
> Note 1: Strapping bit pins are documented in the TRM for each respective chip
> Note 2: For achieving highest speeds, check which pins go through the IO MUX bypassing the GPIO matrix and use those. Pins chosen here are IO MUX pins for ESP32S3 and ESP32S2 chips.
## Build and flash
To run the example, type the following command:
```CMake
idf.py -p PORT flash monitor
```
(To exit the serial monitor, type ``Ctrl-]``.)
See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects.
## Example output
Here is the example's console output:
```
Connected to target
I (682) spi_ram_loader: Loading app to RAM ...
Start loading
Downloading 7840 bytes at 0x3fc96e00...
Downloading 312 bytes at 0x3fca0020...
Downloading 93164 bytes at 0x40380000...
Finished loading
I (802) spi_ram_loader: ********************************************
I (802) spi_ram_loader: *** Logs below are print from slave .... ***
I (812) spi_ram_loader: ********************************************
Hello world!
Hello world!
...
```

View File

@@ -0,0 +1,14 @@
set(srcs main.c ../../common/example_common.c)
set(include_dirs . ../../common)
idf_component_register(SRCS ${srcs}
INCLUDE_DIRS ${include_dirs})
set(target ${COMPONENT_LIB})
# Embed binaries into the app.
# In ESP-IDF this can also be done using EMBED_FILES option of idf_component_register.
# Here an external tool is used to make file embedding similar with other ports.
include(${CMAKE_CURRENT_LIST_DIR}/../../common/bin2array.cmake)
create_resources(${CMAKE_CURRENT_LIST_DIR}/../../binaries/RAM_APP ${CMAKE_BINARY_DIR}/binaries.c)
set_property(SOURCE ${CMAKE_BINARY_DIR}/binaries.c PROPERTY GENERATED 1)
target_sources(${target} PRIVATE ${CMAKE_BINARY_DIR}/binaries.c)

View File

@@ -0,0 +1,97 @@
/* Example of loading the program into RAM through SPI
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#include <sys/param.h>
#include <string.h>
#include "esp_err.h"
#include "esp_log.h"
#include "esp_task_wdt.h"
#include "driver/spi_master.h"
#include "driver/uart.h"
#include "driver/gpio.h"
#include "esp32_spi_port.h"
#include "esp_loader.h"
#include "example_common.h"
#include "freertos/FreeRTOS.h"
static const char *TAG = "spi_ram_loader";
// Max line size
#define BUF_LEN 128
static uint8_t buf[BUF_LEN] = {0};
void slave_monitor(void *arg)
{
// Initialize UART
uart_config_t uart_config = {
.baud_rate = 115200,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
.source_clk = UART_SCLK_DEFAULT,
#endif
};
ESP_ERROR_CHECK(uart_param_config(UART_NUM_2, &uart_config));
ESP_ERROR_CHECK(uart_set_pin(UART_NUM_2, GPIO_NUM_6, GPIO_NUM_7,
UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE));
ESP_ERROR_CHECK(uart_driver_install(UART_NUM_2, BUF_LEN * 4, BUF_LEN * 4, 0, NULL, 0));
while (1) {
int rxBytes = uart_read_bytes(UART_NUM_2, buf, BUF_LEN, 100 / portTICK_PERIOD_MS);
buf[rxBytes] = '\0';
printf("%s", buf);
}
}
void app_main(void)
{
example_ram_app_binary_t bin;
const loader_esp32_spi_config_t config = {
.spi_bus = SPI2_HOST,
.frequency = 20 * 1000000,
.reset_trigger_pin = GPIO_NUM_5,
.spi_clk_pin = GPIO_NUM_12,
.spi_cs_pin = GPIO_NUM_10,
.spi_miso_pin = GPIO_NUM_13,
.spi_mosi_pin = GPIO_NUM_11,
.spi_quadwp_pin = GPIO_NUM_14,
.spi_quadhd_pin = GPIO_NUM_9,
.strap_bit0_pin = GPIO_NUM_13,
.strap_bit1_pin = GPIO_NUM_2,
.strap_bit2_pin = GPIO_NUM_3,
.strap_bit3_pin = GPIO_NUM_4,
};
if (loader_port_esp32_spi_init(&config) != ESP_LOADER_SUCCESS) {
ESP_LOGE(TAG, "SPI initialization failed.");
abort();
}
if (connect_to_target(0) == ESP_LOADER_SUCCESS) {
get_example_ram_app_binary(esp_loader_get_target(), &bin);
ESP_LOGI(TAG, "Loading app to RAM ...");
esp_loader_error_t err = load_ram_binary(bin.ram_app.data);
if (err == ESP_LOADER_SUCCESS) {
// Forward slave's serial output
ESP_LOGI(TAG, "********************************************");
ESP_LOGI(TAG, "*** Logs below are print from slave .... ***");
ESP_LOGI(TAG, "********************************************");
xTaskCreate(slave_monitor, "slave_monitor", 2048, NULL, configMAX_PRIORITIES, NULL);
} else {
ESP_LOGE(TAG, "Loading to RAM failed ...");
}
}
vTaskDelete(NULL);
}

View File

@@ -0,0 +1,4 @@
# This file was generated using idf.py save-defconfig. It can be edited manually.
# Espressif IoT Development Framework (ESP-IDF) Project Minimal Configuration
#
CONFIG_SERIAL_FLASHER_INTERFACE_SPI=y

View File

@@ -0,0 +1,17 @@
cmake_minimum_required(VERSION 3.5)
set(FLASHER_DIR ${CMAKE_CURRENT_LIST_DIR}/../..)
set(PORT RASPBERRY_PI)
project(raspberry_flasher)
add_executable(${CMAKE_PROJECT_NAME} Src/main.c ../common/example_common.c)
target_include_directories(${CMAKE_PROJECT_NAME} PRIVATE ../common/)
add_subdirectory(${FLASHER_DIR} ${CMAKE_BINARY_DIR}/flasher)
target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE flasher)
# This example only supports one target (ESP32) and uses specific binary to be flashed.
target_compile_definitions(${CMAKE_PROJECT_NAME} PRIVATE -DSINGLE_TARGET_SUPPORT=1)

View File

@@ -0,0 +1,76 @@
# Raspberry Pi example
## Overview
Example demonstrates how to flash ESP32 from Raspberry Pi 4 (Model B) using esp_serial_flash component API. AT command firmware to be flashed from Raspberry Pi to ESP32 can be found in `binaries`. USART0 is dedicated for communication with ESP32.
Following steps are performed in order to re-program target's memory:
1. Peripherals are initialized.
2. Host puts slave device into boot mode tries to connect by calling `esp_loader_connect()`.
3. Then `esp_loader_flash_start()` is called to enter flashing mode and erase amount of memory to be flashed.
4. `esp_loader_flash_write()` function is called repeatedly until the whole binary image is transfered.
5. At the end, `loader_port_reset_target()` is called to restart ESP32 and execute updated firmware.
Note: In addition, to steps mentioned above, `esp_loader_change_transmission_rate` is called after connection is established in order to increase flashing speed. Bootloader is also capable of detecting baud rate during connection phase, and can be changed before calling `esp_loader_connect`. However, it is recommended to start at lower speed and then use dedicated command to increase baud rate. This does not apply for ESP8266, as its bootloader does not support this command, therefore, baud rate can only be changed before connection phase in this case.
## Hardware Required
* Raspberry Pi 4 Model B.
* A development board with ESP32 SoC (e.g. ESP-WROVER-KIT, ESP32-DevKitC, etc.).
* USB cable in case ESP32 board is powered from USB. ESP32 can be powered by Raspberry Pi as well.
## Hardware connection
Table below shows connection between Raspberry Pi and ESP32.
| Raspberry Pi (host) | ESP32 (slave) |
|:-------------------:|:-------------------:|
| GPIO3 | IO0 |
| GPIO2 | RST |
| GPIO14 | RX0 |
| GPIO15 | TX0 |
| GND | GND |
Optionally, UART-to-USB bridge can be connected to PD5(RX) and PD6(TX) for debug purposes.
## Installation
### GPIO library
Raspberry Pi makes use of [pigpio](http://abyz.me.uk/rpi/pigpio/) library in order to simplify controlling GPIO pins. Some distributions of 'Raspberry Pi OS' may come with `pigpio` already installed. Presence of the library in the system can checked by running command:
```
pigpiod -v
```
If not present, run following commands to install the library.
```
sudo apt-get update
sudo apt-get install pigpio
```
### Enable UART
On Raspberry Pi 4, primary UART (UART0) is connected to the On-board Bluetooth module by default.
In order to enable serial communication on this UART, run following command in terminal:
```
sudo raspi-config
```
* Navigate to **Interfacing Options -> Serial**.
* Then it will ask for login shell to be accessible over Serial, select **No**.
* After that, it will ask for enabling Hardware Serial port, select **Yes**.
* Reboot the Raspberry Pi.
## Build and run
To compile the example:
Create and navigate to `build` directory:
```
mkdir build && cd build
```
Run cmake, build example and run example:
```
cmake .. && cmake --build . && ./raspberry_flasher
```
For more details regarding to esp_serial_flasher configuration, please refer to top level [README.md](../../README.md).

View File

@@ -0,0 +1,81 @@
/* Flash multiple partitions example
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <sys/param.h>
#include "esp_loader.h"
#include "example_common.h"
#include "raspberry_port.h"
#define TARGET_RST_Pin 2
#define TARGET_IO0_Pin 3
#define DEFAULT_BAUD_RATE 115200
#define HIGHER_BAUD_RATE 460800
#define SERIAL_DEVICE "/dev/ttyS0"
#define BINARY_PATH "../../binaries/ESP32_AT_Firmware/Firmware.bin"
static void upload_file(const char *path, size_t address)
{
char *buffer = NULL;
FILE *image = fopen(path, "r");
if (image == NULL) {
printf("Error:Failed to open file %s\n", path);
return;
}
fseek(image, 0L, SEEK_END);
size_t size = ftell(image);
rewind(image);
printf("File %s opened. Size: %u bytes\n", path, size);
buffer = (char *)malloc(size);
if (buffer == NULL) {
printf("Error: Failed allocate memory\n");
goto cleanup;
}
// copy file content to buffer
size_t bytes_read = fread(buffer, 1, size, image);
if (bytes_read != size) {
printf("Error occurred while reading file");
goto cleanup;
}
flash_binary(buffer, size, address);
cleanup:
fclose(image);
free(buffer);
}
int main(void)
{
const loader_raspberry_config_t config = {
.device = SERIAL_DEVICE,
.baudrate = DEFAULT_BAUD_RATE,
.reset_trigger_pin = TARGET_RST_Pin,
.gpio0_trigger_pin = TARGET_IO0_Pin,
};
loader_port_raspberry_init(&config);
if (connect_to_target(HIGHER_BAUD_RATE) == ESP_LOADER_SUCCESS) {
upload_file(BINARY_PATH, 0);
}
loader_port_reset_target();
}

View File

@@ -0,0 +1,39 @@
cmake_minimum_required(VERSION 3.5)
include(${CMAKE_CURRENT_LIST_DIR}/../common/bin2array.cmake)
set(TOOLCHAIN_PREFIX / CACHE PATH "Path to arm toolchain")
set(STM32Cube_DIR / CACHE PATH "Path to STM32 hal library")
set(FLASHER_DIR ${CMAKE_CURRENT_LIST_DIR}/../..)
set(CMAKE_TOOLCHAIN_FILE ${FLASHER_DIR}/submodules/stm32-cmake/cmake/gcc_stm32.cmake)
set(STM32_CHIP STM32F407VG)
set(PORT STM32)
project(stm32_flasher)
enable_language(ASM)
create_resources(${CMAKE_CURRENT_LIST_DIR}/../binaries/Hello-world Src/binaries.c)
include_directories(${CMAKE_CURRENT_SOURCE_DIR} Inc)
add_executable(${CMAKE_PROJECT_NAME}
../common/example_common.c
Src/main.c
Src/stm32f4xx_hal_msp.c
Src/stm32f4xx_it.c
Src/libc_compat.c
Src/binaries.c)
target_include_directories(${CMAKE_PROJECT_NAME} PRIVATE ../common)
add_subdirectory(${FLASHER_DIR}/submodules ${CMAKE_BINARY_DIR}/submodules)
add_subdirectory(${FLASHER_DIR} ${CMAKE_BINARY_DIR}/flasher)
target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE stm_cube flasher)
STM32_ADD_HEX_BIN_TARGETS(${CMAKE_PROJECT_NAME})
add_custom_target(BuildBinary ALL)
add_dependencies(BuildBinary ${CMAKE_PROJECT_NAME}.bin)

View File

@@ -0,0 +1,50 @@
/**
******************************************************************************
* @file : main.h
* @brief : Header for main.c file.
* This file contains the common defines of the application.
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2020 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
#ifndef __MAIN_H
#define __MAIN_H
#ifdef __cplusplus
extern "C" {
#endif
#include "stm32f4xx_hal.h"
void Error_Handler(void);
#define GREEN_LED_Pin GPIO_PIN_12
#define GREEN_LED_GPIO_Port GPIOD
#define ORANGE_LED_Pin GPIO_PIN_13
#define ORANGE_LED_GPIO_Port GPIOD
#define RED_LED_Pin GPIO_PIN_14
#define RED_LED_GPIO_Port GPIOD
#define BLUE_LED_Pin GPIO_PIN_15
#define BLUE_LED_GPIO_Port GPIOD
#define TARGET_RST_Pin GPIO_PIN_4
#define TARGET_RST_GPIO_Port GPIOB
#define TARGET_IO0_Pin GPIO_PIN_5
#define TARGET_IO0_GPIO_Port GPIOB
#ifdef __cplusplus
}
#endif
#endif /* __MAIN_H */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@@ -0,0 +1,443 @@
/**
******************************************************************************
* @file stm32f4xx_hal_conf_template.h
* @author MCD Application Team
* @brief HAL configuration template file.
* This file should be copied to the application folder and renamed
* to stm32f4xx_hal_conf.h.
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __STM32F4xx_HAL_CONF_H
#define __STM32F4xx_HAL_CONF_H
#ifdef __cplusplus
extern "C" {
#endif
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* ########################## Module Selection ############################## */
/**
* @brief This is the list of modules to be used in the HAL driver
*/
#define HAL_MODULE_ENABLED
/* #define HAL_ADC_MODULE_ENABLED */
/* #define HAL_CRYP_MODULE_ENABLED */
/* #define HAL_CAN_MODULE_ENABLED */
/* #define HAL_CRC_MODULE_ENABLED */
/* #define HAL_CRYP_MODULE_ENABLED */
/* #define HAL_DAC_MODULE_ENABLED */
/* #define HAL_DCMI_MODULE_ENABLED */
/* #define HAL_DMA2D_MODULE_ENABLED */
/* #define HAL_ETH_MODULE_ENABLED */
/* #define HAL_NAND_MODULE_ENABLED */
/* #define HAL_NOR_MODULE_ENABLED */
/* #define HAL_PCCARD_MODULE_ENABLED */
/* #define HAL_SRAM_MODULE_ENABLED */
/* #define HAL_SDRAM_MODULE_ENABLED */
/* #define HAL_HASH_MODULE_ENABLED */
/* #define HAL_I2C_MODULE_ENABLED */
/* #define HAL_I2S_MODULE_ENABLED */
/* #define HAL_IWDG_MODULE_ENABLED */
/* #define HAL_LTDC_MODULE_ENABLED */
/* #define HAL_RNG_MODULE_ENABLED */
/* #define HAL_RTC_MODULE_ENABLED */
/* #define HAL_SAI_MODULE_ENABLED */
/* #define HAL_SD_MODULE_ENABLED */
/* #define HAL_MMC_MODULE_ENABLED */
/* #define HAL_SPI_MODULE_ENABLED */
/* #define HAL_TIM_MODULE_ENABLED */
#define HAL_UART_MODULE_ENABLED
/* #define HAL_USART_MODULE_ENABLED */
/* #define HAL_IRDA_MODULE_ENABLED */
/* #define HAL_SMARTCARD_MODULE_ENABLED */
/* #define HAL_SMBUS_MODULE_ENABLED */
/* #define HAL_WWDG_MODULE_ENABLED */
/* #define HAL_PCD_MODULE_ENABLED */
/* #define HAL_HCD_MODULE_ENABLED */
/* #define HAL_DSI_MODULE_ENABLED */
/* #define HAL_QSPI_MODULE_ENABLED */
/* #define HAL_QSPI_MODULE_ENABLED */
/* #define HAL_CEC_MODULE_ENABLED */
/* #define HAL_FMPI2C_MODULE_ENABLED */
/* #define HAL_SPDIFRX_MODULE_ENABLED */
/* #define HAL_DFSDM_MODULE_ENABLED */
/* #define HAL_LPTIM_MODULE_ENABLED */
#define HAL_GPIO_MODULE_ENABLED
#define HAL_EXTI_MODULE_ENABLED
#define HAL_DMA_MODULE_ENABLED
#define HAL_RCC_MODULE_ENABLED
#define HAL_FLASH_MODULE_ENABLED
#define HAL_PWR_MODULE_ENABLED
#define HAL_CORTEX_MODULE_ENABLED
/* ########################## HSE/HSI Values adaptation ##################### */
/**
* @brief Adjust the value of External High Speed oscillator (HSE) used in your application.
* This value is used by the RCC HAL module to compute the system frequency
* (when HSE is used as system clock source, directly or through the PLL).
*/
#if !defined (HSE_VALUE)
#define HSE_VALUE ((uint32_t)25000000U) /*!< Value of the External oscillator in Hz */
#endif /* HSE_VALUE */
#if !defined (HSE_STARTUP_TIMEOUT)
#define HSE_STARTUP_TIMEOUT ((uint32_t)100U) /*!< Time out for HSE start up, in ms */
#endif /* HSE_STARTUP_TIMEOUT */
/**
* @brief Internal High Speed oscillator (HSI) value.
* This value is used by the RCC HAL module to compute the system frequency
* (when HSI is used as system clock source, directly or through the PLL).
*/
#if !defined (HSI_VALUE)
#define HSI_VALUE ((uint32_t)16000000U) /*!< Value of the Internal oscillator in Hz*/
#endif /* HSI_VALUE */
/**
* @brief Internal Low Speed oscillator (LSI) value.
*/
#if !defined (LSI_VALUE)
#define LSI_VALUE ((uint32_t)32000U) /*!< LSI Typical Value in Hz*/
#endif /* LSI_VALUE */ /*!< Value of the Internal Low Speed oscillator in Hz
The real value may vary depending on the variations
in voltage and temperature.*/
/**
* @brief External Low Speed oscillator (LSE) value.
*/
#if !defined (LSE_VALUE)
#define LSE_VALUE ((uint32_t)32768U) /*!< Value of the External Low Speed oscillator in Hz */
#endif /* LSE_VALUE */
#if !defined (LSE_STARTUP_TIMEOUT)
#define LSE_STARTUP_TIMEOUT ((uint32_t)5000U) /*!< Time out for LSE start up, in ms */
#endif /* LSE_STARTUP_TIMEOUT */
/**
* @brief External clock source for I2S peripheral
* This value is used by the I2S HAL module to compute the I2S clock source
* frequency, this source is inserted directly through I2S_CKIN pad.
*/
#if !defined (EXTERNAL_CLOCK_VALUE)
#define EXTERNAL_CLOCK_VALUE ((uint32_t)12288000U) /*!< Value of the External audio frequency in Hz*/
#endif /* EXTERNAL_CLOCK_VALUE */
/* Tip: To avoid modifying this file each time you need to use different HSE,
=== you can define the HSE value in your toolchain compiler preprocessor. */
/* ########################### System Configuration ######################### */
/**
* @brief This is the HAL system configuration section
*/
#define VDD_VALUE ((uint32_t)3300U) /*!< Value of VDD in mv */
#define TICK_INT_PRIORITY ((uint32_t)0U) /*!< tick interrupt priority */
#define USE_RTOS 0U
#define PREFETCH_ENABLE 1U
#define INSTRUCTION_CACHE_ENABLE 1U
#define DATA_CACHE_ENABLE 1U
/* ########################## Assert Selection ############################## */
/**
* @brief Uncomment the line below to expanse the "assert_param" macro in the
* HAL drivers code
*/
/* #define USE_FULL_ASSERT 1U */
/* ################## Ethernet peripheral configuration ##################### */
/* Section 1 : Ethernet peripheral configuration */
/* MAC ADDRESS: MAC_ADDR0:MAC_ADDR1:MAC_ADDR2:MAC_ADDR3:MAC_ADDR4:MAC_ADDR5 */
#define MAC_ADDR0 2U
#define MAC_ADDR1 0U
#define MAC_ADDR2 0U
#define MAC_ADDR3 0U
#define MAC_ADDR4 0U
#define MAC_ADDR5 0U
/* Definition of the Ethernet driver buffers size and count */
#define ETH_RX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for receive */
#define ETH_TX_BUF_SIZE ETH_MAX_PACKET_SIZE /* buffer size for transmit */
#define ETH_RXBUFNB ((uint32_t)4U) /* 4 Rx buffers of size ETH_RX_BUF_SIZE */
#define ETH_TXBUFNB ((uint32_t)4U) /* 4 Tx buffers of size ETH_TX_BUF_SIZE */
/* Section 2: PHY configuration section */
/* DP83848_PHY_ADDRESS Address*/
#define DP83848_PHY_ADDRESS 0x01U
/* PHY Reset delay these values are based on a 1 ms Systick interrupt*/
#define PHY_RESET_DELAY ((uint32_t)0x000000FFU)
/* PHY Configuration delay */
#define PHY_CONFIG_DELAY ((uint32_t)0x00000FFFU)
#define PHY_READ_TO ((uint32_t)0x0000FFFFU)
#define PHY_WRITE_TO ((uint32_t)0x0000FFFFU)
/* Section 3: Common PHY Registers */
#define PHY_BCR ((uint16_t)0x0000U) /*!< Transceiver Basic Control Register */
#define PHY_BSR ((uint16_t)0x0001U) /*!< Transceiver Basic Status Register */
#define PHY_RESET ((uint16_t)0x8000U) /*!< PHY Reset */
#define PHY_LOOPBACK ((uint16_t)0x4000U) /*!< Select loop-back mode */
#define PHY_FULLDUPLEX_100M ((uint16_t)0x2100U) /*!< Set the full-duplex mode at 100 Mb/s */
#define PHY_HALFDUPLEX_100M ((uint16_t)0x2000U) /*!< Set the half-duplex mode at 100 Mb/s */
#define PHY_FULLDUPLEX_10M ((uint16_t)0x0100U) /*!< Set the full-duplex mode at 10 Mb/s */
#define PHY_HALFDUPLEX_10M ((uint16_t)0x0000U) /*!< Set the half-duplex mode at 10 Mb/s */
#define PHY_AUTONEGOTIATION ((uint16_t)0x1000U) /*!< Enable auto-negotiation function */
#define PHY_RESTART_AUTONEGOTIATION ((uint16_t)0x0200U) /*!< Restart auto-negotiation function */
#define PHY_POWERDOWN ((uint16_t)0x0800U) /*!< Select the power down mode */
#define PHY_ISOLATE ((uint16_t)0x0400U) /*!< Isolate PHY from MII */
#define PHY_AUTONEGO_COMPLETE ((uint16_t)0x0020U) /*!< Auto-Negotiation process completed */
#define PHY_LINKED_STATUS ((uint16_t)0x0004U) /*!< Valid link established */
#define PHY_JABBER_DETECTION ((uint16_t)0x0002U) /*!< Jabber condition detected */
/* Section 4: Extended PHY Registers */
#define PHY_SR ((uint16_t)0x10U) /*!< PHY status register Offset */
#define PHY_SPEED_STATUS ((uint16_t)0x0002U) /*!< PHY Speed mask */
#define PHY_DUPLEX_STATUS ((uint16_t)0x0004U) /*!< PHY Duplex mask */
/* ################## SPI peripheral configuration ########################## */
/* CRC FEATURE: Use to activate CRC feature inside HAL SPI Driver
* Activated: CRC code is present inside driver
* Deactivated: CRC code cleaned from driver
*/
#define USE_SPI_CRC 0U
/* Includes ------------------------------------------------------------------*/
/**
* @brief Include module's header file
*/
#ifdef HAL_RCC_MODULE_ENABLED
#include "stm32f4xx_hal_rcc.h"
#endif /* HAL_RCC_MODULE_ENABLED */
#ifdef HAL_EXTI_MODULE_ENABLED
#include "stm32f4xx_hal_exti.h"
#endif /* HAL_EXTI_MODULE_ENABLED */
#ifdef HAL_GPIO_MODULE_ENABLED
#include "stm32f4xx_hal_gpio.h"
#endif /* HAL_GPIO_MODULE_ENABLED */
#ifdef HAL_DMA_MODULE_ENABLED
#include "stm32f4xx_hal_dma.h"
#endif /* HAL_DMA_MODULE_ENABLED */
#ifdef HAL_CORTEX_MODULE_ENABLED
#include "stm32f4xx_hal_cortex.h"
#endif /* HAL_CORTEX_MODULE_ENABLED */
#ifdef HAL_ADC_MODULE_ENABLED
#include "stm32f4xx_hal_adc.h"
#endif /* HAL_ADC_MODULE_ENABLED */
#ifdef HAL_CAN_MODULE_ENABLED
#include "stm32f4xx_hal_can.h"
#endif /* HAL_CAN_MODULE_ENABLED */
#ifdef HAL_CRC_MODULE_ENABLED
#include "stm32f4xx_hal_crc.h"
#endif /* HAL_CRC_MODULE_ENABLED */
#ifdef HAL_CRYP_MODULE_ENABLED
#include "stm32f4xx_hal_cryp.h"
#endif /* HAL_CRYP_MODULE_ENABLED */
#ifdef HAL_SMBUS_MODULE_ENABLED
#include "stm32f4xx_hal_smbus.h"
#endif /* HAL_SMBUS_MODULE_ENABLED */
#ifdef HAL_DMA2D_MODULE_ENABLED
#include "stm32f4xx_hal_dma2d.h"
#endif /* HAL_DMA2D_MODULE_ENABLED */
#ifdef HAL_DAC_MODULE_ENABLED
#include "stm32f4xx_hal_dac.h"
#endif /* HAL_DAC_MODULE_ENABLED */
#ifdef HAL_DCMI_MODULE_ENABLED
#include "stm32f4xx_hal_dcmi.h"
#endif /* HAL_DCMI_MODULE_ENABLED */
#ifdef HAL_ETH_MODULE_ENABLED
#include "stm32f4xx_hal_eth.h"
#endif /* HAL_ETH_MODULE_ENABLED */
#ifdef HAL_FLASH_MODULE_ENABLED
#include "stm32f4xx_hal_flash.h"
#endif /* HAL_FLASH_MODULE_ENABLED */
#ifdef HAL_SRAM_MODULE_ENABLED
#include "stm32f4xx_hal_sram.h"
#endif /* HAL_SRAM_MODULE_ENABLED */
#ifdef HAL_NOR_MODULE_ENABLED
#include "stm32f4xx_hal_nor.h"
#endif /* HAL_NOR_MODULE_ENABLED */
#ifdef HAL_NAND_MODULE_ENABLED
#include "stm32f4xx_hal_nand.h"
#endif /* HAL_NAND_MODULE_ENABLED */
#ifdef HAL_PCCARD_MODULE_ENABLED
#include "stm32f4xx_hal_pccard.h"
#endif /* HAL_PCCARD_MODULE_ENABLED */
#ifdef HAL_SDRAM_MODULE_ENABLED
#include "stm32f4xx_hal_sdram.h"
#endif /* HAL_SDRAM_MODULE_ENABLED */
#ifdef HAL_HASH_MODULE_ENABLED
#include "stm32f4xx_hal_hash.h"
#endif /* HAL_HASH_MODULE_ENABLED */
#ifdef HAL_I2C_MODULE_ENABLED
#include "stm32f4xx_hal_i2c.h"
#endif /* HAL_I2C_MODULE_ENABLED */
#ifdef HAL_I2S_MODULE_ENABLED
#include "stm32f4xx_hal_i2s.h"
#endif /* HAL_I2S_MODULE_ENABLED */
#ifdef HAL_IWDG_MODULE_ENABLED
#include "stm32f4xx_hal_iwdg.h"
#endif /* HAL_IWDG_MODULE_ENABLED */
#ifdef HAL_LTDC_MODULE_ENABLED
#include "stm32f4xx_hal_ltdc.h"
#endif /* HAL_LTDC_MODULE_ENABLED */
#ifdef HAL_PWR_MODULE_ENABLED
#include "stm32f4xx_hal_pwr.h"
#endif /* HAL_PWR_MODULE_ENABLED */
#ifdef HAL_RNG_MODULE_ENABLED
#include "stm32f4xx_hal_rng.h"
#endif /* HAL_RNG_MODULE_ENABLED */
#ifdef HAL_RTC_MODULE_ENABLED
#include "stm32f4xx_hal_rtc.h"
#endif /* HAL_RTC_MODULE_ENABLED */
#ifdef HAL_SAI_MODULE_ENABLED
#include "stm32f4xx_hal_sai.h"
#endif /* HAL_SAI_MODULE_ENABLED */
#ifdef HAL_SD_MODULE_ENABLED
#include "stm32f4xx_hal_sd.h"
#endif /* HAL_SD_MODULE_ENABLED */
#ifdef HAL_MMC_MODULE_ENABLED
#include "stm32f4xx_hal_mmc.h"
#endif /* HAL_MMC_MODULE_ENABLED */
#ifdef HAL_SPI_MODULE_ENABLED
#include "stm32f4xx_hal_spi.h"
#endif /* HAL_SPI_MODULE_ENABLED */
#ifdef HAL_TIM_MODULE_ENABLED
#include "stm32f4xx_hal_tim.h"
#endif /* HAL_TIM_MODULE_ENABLED */
#ifdef HAL_UART_MODULE_ENABLED
#include "stm32f4xx_hal_uart.h"
#endif /* HAL_UART_MODULE_ENABLED */
#ifdef HAL_USART_MODULE_ENABLED
#include "stm32f4xx_hal_usart.h"
#endif /* HAL_USART_MODULE_ENABLED */
#ifdef HAL_IRDA_MODULE_ENABLED
#include "stm32f4xx_hal_irda.h"
#endif /* HAL_IRDA_MODULE_ENABLED */
#ifdef HAL_SMARTCARD_MODULE_ENABLED
#include "stm32f4xx_hal_smartcard.h"
#endif /* HAL_SMARTCARD_MODULE_ENABLED */
#ifdef HAL_WWDG_MODULE_ENABLED
#include "stm32f4xx_hal_wwdg.h"
#endif /* HAL_WWDG_MODULE_ENABLED */
#ifdef HAL_PCD_MODULE_ENABLED
#include "stm32f4xx_hal_pcd.h"
#endif /* HAL_PCD_MODULE_ENABLED */
#ifdef HAL_HCD_MODULE_ENABLED
#include "stm32f4xx_hal_hcd.h"
#endif /* HAL_HCD_MODULE_ENABLED */
#ifdef HAL_DSI_MODULE_ENABLED
#include "stm32f4xx_hal_dsi.h"
#endif /* HAL_DSI_MODULE_ENABLED */
#ifdef HAL_QSPI_MODULE_ENABLED
#include "stm32f4xx_hal_qspi.h"
#endif /* HAL_QSPI_MODULE_ENABLED */
#ifdef HAL_CEC_MODULE_ENABLED
#include "stm32f4xx_hal_cec.h"
#endif /* HAL_CEC_MODULE_ENABLED */
#ifdef HAL_FMPI2C_MODULE_ENABLED
#include "stm32f4xx_hal_fmpi2c.h"
#endif /* HAL_FMPI2C_MODULE_ENABLED */
#ifdef HAL_SPDIFRX_MODULE_ENABLED
#include "stm32f4xx_hal_spdifrx.h"
#endif /* HAL_SPDIFRX_MODULE_ENABLED */
#ifdef HAL_DFSDM_MODULE_ENABLED
#include "stm32f4xx_hal_dfsdm.h"
#endif /* HAL_DFSDM_MODULE_ENABLED */
#ifdef HAL_LPTIM_MODULE_ENABLED
#include "stm32f4xx_hal_lptim.h"
#endif /* HAL_LPTIM_MODULE_ENABLED */
/* Exported macro ------------------------------------------------------------*/
#ifdef USE_FULL_ASSERT
/**
* @brief The assert_param macro is used for function's parameters check.
* @param expr: If expr is false, it calls assert_failed function
* which reports the name of the source file and the source
* line number of the call that failed.
* If expr is true, it returns no value.
* @retval None
*/
#define assert_param(expr) ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__))
/* Exported functions ------------------------------------------------------- */
void assert_failed(uint8_t* file, uint32_t line);
#else
#define assert_param(expr) ((void)0U)
#endif /* USE_FULL_ASSERT */
#ifdef __cplusplus
}
#endif
#endif /* __STM32F4xx_HAL_CONF_H */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@@ -0,0 +1,42 @@
/**
******************************************************************************
* @file stm32f4xx_it.h
* @brief This file contains the headers of the interrupt handlers.
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2020 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
#ifndef __STM32F4xx_IT_H
#define __STM32F4xx_IT_H
#ifdef __cplusplus
extern "C" {
#endif
void NMI_Handler(void);
void HardFault_Handler(void);
void MemManage_Handler(void);
void BusFault_Handler(void);
void UsageFault_Handler(void);
void SVC_Handler(void);
void DebugMon_Handler(void);
void PendSV_Handler(void);
void SysTick_Handler(void);
#ifdef __cplusplus
}
#endif
#endif /* __STM32F4xx_IT_H */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@@ -0,0 +1,59 @@
# STM32 example
## Overview
Example demonstrates how to flash ESP32 from another STM32 (host MCU) using esp_serial_flash component API. STM32F4-Discovery board is used in this example, as STM32F407VG has FLASH memory large enough to fit the whole hello-world example of ESP32. Binaries to be flashed from host MCU to ESP32 can be found in `binaries` directory and converted into C-arrays during build process. USART1 is dedicated for communication with ESP32, whereas, USART2 can be used for debug purposes by attaching UART-to-USB bridge.
Following steps are performed in order to re-program target's memory:
1. Peripherals are initialized.
2. Host puts slave device into boot mode tries to connect by calling `esp_loader_connect()`.
3. Then `esp_loader_flash_start()` is called to enter flashing mode and erase amount of memory to be flashed.
4. `esp_loader_flash_write()` function is called repeatedly until the whole binary image is transfered.
Note: In addition, to steps mentioned above, `esp_loader_change_transmission_rate` is called after connection is established in order to increase flashing speed. Bootloader is also capable of detecting baud rate during connection phase, and can be changed before calling `esp_loader_connect`. However, it is recommended to start at lower speed and then use dedicated command to increase baud rate. This does not apply for ESP8266, as its bootloader does not support this command, therefore, baud rate can only be changed before connection phase in this case.
## Hardware Required
* STM32F4-Discovery board.
* A development board with ESP32 SoC (e.g. ESP-WROVER-KIT, ESP32-DevKitC, etc.).
* One or two USB cables for power supply and programming.
## Hardware connection
Table below shows connection between STM32 and ESP32.
| STM32 (host) | ESP32 (slave) |
|:------------:|:-------------:|
| PB5 | IO0 |
| PB4 | RST |
| PB6 | RX0 |
| PB7 | TX0 |
Optionally, UART-to-USB bridge can be connected to PD5(RX) and PD6(TX) for debug purposes.
## Build and flash
To compile the example:
Create and navigate to `build` directory:
```
mkdir build && cd build
```
Run cmake (with appropriate parameters) and build:
```
cmake -DTOOLCHAIN_PREFIX="/path_to_toolchain" -DSTM32Cube_DIR="path_to_stm32Cube" -DSTM32_CHIP="STM32F407VG" -DPORT="STM32" .. && cmake --build .
```
Binaries to be flashed are placed in separate folder (binaries.c) for each possible target and converted to C-array. Without explicitly enabling MD5 check, flash integrity verification is disabled by default.
For more details regarding to esp_serial_flasher configuration and STM32 support, please refer to top level [README.md](../../README.md).
Note: CMake 3.13 or later is required.
## STM32CubeMx configuration
Following configuration was used to generate STM32 `cmake` based project:
* Project tab: Toolchain/IDE - Other toolchain (GPDSC)
* Code Generator tab: Add necessary files as reference in the toolchain project configuration file

View File

@@ -0,0 +1,183 @@
/* libc_compat
This code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#include <errno.h>
#include <sys/stat.h>
#include <sys/times.h>
#include <sys/unistd.h>
#include <sys/time.h>
#if defined STM32F1
# include <stm32f1xx_hal.h>
#elif defined STM32F2
# include <stm32f2xx_hal.h>
#elif defined STM32F4
# include <stm32f4xx_hal.h>
#elif defined STM32G0
# include <stm32g0xx_hal.h>
#endif
extern uint32_t __get_MSP(void);
extern UART_HandleTypeDef huart2;
extern uint64_t virtualTimer;
#undef errno
extern int errno;
char *__env[1] = { 0 };
char **environ = __env;
int _write(int file, char *ptr, int len);
void _exit(int status)
{
while (1);
}
int _close(int file)
{
return -1;
}
int _execve(char *name, char **argv, char **env)
{
errno = ENOMEM;
return -1;
}
int _fork()
{
errno = EAGAIN;
return -1;
}
int _fstat(int file, struct stat *st)
{
st->st_mode = S_IFCHR;
return 0;
}
int _getpid()
{
return 1;
}
int _gettimeofday(struct timeval *tv, struct timezone *tz)
{
tv->tv_sec = HAL_GetTick() / 1000;
tv->tv_usec = (HAL_GetTick() % 1000) * 1000;
return 0;
}
int _isatty(int file)
{
switch (file)
{
case STDOUT_FILENO:
case STDERR_FILENO:
case STDIN_FILENO:
return 1;
default:
//errno = ENOTTY;
errno = EBADF;
return 0;
}
}
int _kill(int pid, int sig)
{
errno = EINVAL;
return (-1);
}
int _link(char *old, char *new)
{
errno = EMLINK;
return -1;
}
int _lseek(int file, int ptr, int dir)
{
return 0;
}
caddr_t _sbrk(int incr)
{
extern char _ebss;
static char *heap_end= &_ebss;
char *prev_heap_end;
prev_heap_end = heap_end;
char * stack = (char*) __get_MSP();
if (heap_end + incr > stack)
{
_write(STDERR_FILENO, "Heap and stack collision\n", 25);
errno = ENOMEM;
return (caddr_t) - 1;
//abort ();
}
heap_end += incr;
return (caddr_t) prev_heap_end;
}
int _read(int file, char *ptr, int len)
{
switch (file)
{
case STDIN_FILENO:
HAL_UART_Receive(&huart2, (uint8_t *)ptr, 1, HAL_MAX_DELAY);
return 1;
default:
errno = EBADF;
return -1;
}
}
int _stat(const char *filepath, struct stat *st)
{
st->st_mode = S_IFCHR;
return 0;
}
clock_t _times(struct tms *buf)
{
return -1;
}
int _unlink(char *name)
{
errno = ENOENT;
return -1;
}
int _wait(int *status)
{
errno = ECHILD;
return -1;
}
int _write(int file, char *ptr, int len)
{
switch (file)
{
case STDOUT_FILENO: /*stdout*/
HAL_UART_Transmit(&huart2, (uint8_t*)ptr, len, HAL_MAX_DELAY);
break;
case STDERR_FILENO: /* stderr */
HAL_UART_Transmit(&huart2, (uint8_t*)ptr, len, HAL_MAX_DELAY);
break;
default:
errno = EBADF;
return -1;
}
return len;
}

View File

@@ -0,0 +1,189 @@
/**
******************************************************************************
* @file : main.c
* @brief : Main program body
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2020 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
#include "main.h"
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <sys/param.h>
#include "stm32_port.h"
#include "esp_loader.h"
#include "example_common.h"
UART_HandleTypeDef huart1;
UART_HandleTypeDef huart2;
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_USART1_UART_Init(void);
static void MX_USART2_UART_Init(void);
#define HIGHER_BAUDRATE 230400
int main(void)
{
example_binaries_t bin;
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_USART1_UART_Init();
MX_USART2_UART_Init();
loader_stm32_config_t config = {
.huart = &huart1,
.port_io0 = GPIOB,
.pin_num_io0 = TARGET_IO0_Pin,
.port_rst = GPIOB,
.pin_num_rst = TARGET_RST_Pin,
};
loader_port_stm32_init(&config);
if (connect_to_target(HIGHER_BAUDRATE) == ESP_LOADER_SUCCESS) {
get_example_binaries(esp_loader_get_target(), &bin);
flash_binary(bin.boot.data, bin.boot.size, bin.boot.addr);
flash_binary(bin.part.data, bin.part.size, bin.part.addr);
flash_binary(bin.app.data, bin.app.size, bin.app.addr);
}
while (1) { }
}
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
/** Configure the main internal regulator output voltage
*/
__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
/** Initializes the CPU, AHB and APB busses clocks
*/
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
Error_Handler();
}
/** Initializes the CPU, AHB and APB busses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK
| RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK) {
Error_Handler();
}
}
static void MX_USART1_UART_Init(void)
{
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart1) != HAL_OK) {
Error_Handler();
}
}
static void MX_USART2_UART_Init(void)
{
huart2.Instance = USART2;
huart2.Init.BaudRate = 115200;
huart2.Init.WordLength = UART_WORDLENGTH_8B;
huart2.Init.StopBits = UART_STOPBITS_1;
huart2.Init.Parity = UART_PARITY_NONE;
huart2.Init.Mode = UART_MODE_TX_RX;
huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart2.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart2) != HAL_OK) {
Error_Handler();
}
}
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOD_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOD, GREEN_LED_Pin | ORANGE_LED_Pin | RED_LED_Pin | BLUE_LED_Pin, GPIO_PIN_RESET);
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOB, TARGET_RST_Pin | TARGET_IO0_Pin, GPIO_PIN_RESET);
/*Configure GPIO pins : GREEN_LED_Pin ORANGE_LED_Pin RED_LED_Pin BLUE_LED_Pin */
GPIO_InitStruct.Pin = GREEN_LED_Pin | ORANGE_LED_Pin | RED_LED_Pin | BLUE_LED_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
/*Configure GPIO pins : PB4 PB5 */
GPIO_InitStruct.Pin = TARGET_RST_Pin | TARGET_IO0_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void)
{
/* User can add his own implementation to report the HAL error return state */
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* User can add his own implementation to report the file name and line number,
tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
}
#endif /* USE_FULL_ASSERT */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@@ -0,0 +1,109 @@
/**
******************************************************************************
* File Name : stm32f4xx_hal_msp.c
* Description : This file provides code for the MSP Initialization
* and de-Initialization codes.
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2020 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
#include "main.h"
void HAL_MspInit(void)
{
__HAL_RCC_SYSCFG_CLK_ENABLE();
__HAL_RCC_PWR_CLK_ENABLE();
}
/**
* @brief UART MSP Initialization
* This function configures the hardware resources used in this example
* @param huart: UART handle pointer
* @retval None
*/
void HAL_UART_MspInit(UART_HandleTypeDef* huart)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(huart->Instance==USART1)
{
/* Peripheral clock enable */
__HAL_RCC_USART1_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/**USART1 GPIO Configuration
PB6 ------> USART1_TX
PB7 ------> USART1_RX
*/
GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}
else if(huart->Instance==USART2)
{
/* Peripheral clock enable */
__HAL_RCC_USART2_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
/**USART2 GPIO Configuration
PD5 ------> USART2_TX
PD6 ------> USART2_RX
*/
GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_6;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF7_USART2;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
}
}
/**
* @brief UART MSP De-Initialization
* This function freeze the hardware resources used in this example
* @param huart: UART handle pointer
* @retval None
*/
void HAL_UART_MspDeInit(UART_HandleTypeDef* huart)
{
if(huart->Instance==USART1)
{
/* Peripheral clock disable */
__HAL_RCC_USART1_CLK_DISABLE();
/**USART1 GPIO Configuration
PB6 ------> USART1_TX
PB7 ------> USART1_RX
*/
HAL_GPIO_DeInit(GPIOB, GPIO_PIN_6|GPIO_PIN_7);
}
else if(huart->Instance==USART2)
{
/* Peripheral clock disable */
__HAL_RCC_USART2_CLK_DISABLE();
/**USART2 GPIO Configuration
PD5 ------> USART2_TX
PD6 ------> USART2_RX
*/
HAL_GPIO_DeInit(GPIOD, GPIO_PIN_5|GPIO_PIN_6);
}
}
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@@ -0,0 +1,204 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file stm32f4xx_it.c
* @brief Interrupt Service Routines.
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2020 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "stm32f4xx_it.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <stdio.h>
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN TD */
/* USER CODE END TD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/* External variables --------------------------------------------------------*/
/* USER CODE BEGIN EV */
/* USER CODE END EV */
/******************************************************************************/
/* Cortex-M4 Processor Interruption and Exception Handlers */
/******************************************************************************/
/**
* @brief This function handles Non maskable interrupt.
*/
void NMI_Handler(void)
{
/* USER CODE BEGIN NonMaskableInt_IRQn 0 */
/* USER CODE END NonMaskableInt_IRQn 0 */
/* USER CODE BEGIN NonMaskableInt_IRQn 1 */
/* USER CODE END NonMaskableInt_IRQn 1 */
}
/**
* @brief This function handles Hard fault interrupt.
*/
void HardFault_Handler(void)
{
/* USER CODE BEGIN HardFault_IRQn 0 */
/* USER CODE END HardFault_IRQn 0 */
while (1)
{
/* USER CODE BEGIN W1_HardFault_IRQn 0 */
/* USER CODE END W1_HardFault_IRQn 0 */
}
}
/**
* @brief This function handles Memory management fault.
*/
void MemManage_Handler(void)
{
/* USER CODE BEGIN MemoryManagement_IRQn 0 */
/* USER CODE END MemoryManagement_IRQn 0 */
while (1)
{
/* USER CODE BEGIN W1_MemoryManagement_IRQn 0 */
/* USER CODE END W1_MemoryManagement_IRQn 0 */
}
}
/**
* @brief This function handles Pre-fetch fault, memory access fault.
*/
void BusFault_Handler(void)
{
/* USER CODE BEGIN BusFault_IRQn 0 */
/* USER CODE END BusFault_IRQn 0 */
while (1)
{
/* USER CODE BEGIN W1_BusFault_IRQn 0 */
/* USER CODE END W1_BusFault_IRQn 0 */
}
}
/**
* @brief This function handles Undefined instruction or illegal state.
*/
void UsageFault_Handler(void)
{
/* USER CODE BEGIN UsageFault_IRQn 0 */
/* USER CODE END UsageFault_IRQn 0 */
while (1)
{
/* USER CODE BEGIN W1_UsageFault_IRQn 0 */
/* USER CODE END W1_UsageFault_IRQn 0 */
}
}
/**
* @brief This function handles System service call via SWI instruction.
*/
void SVC_Handler(void)
{
/* USER CODE BEGIN SVCall_IRQn 0 */
/* USER CODE END SVCall_IRQn 0 */
/* USER CODE BEGIN SVCall_IRQn 1 */
/* USER CODE END SVCall_IRQn 1 */
}
/**
* @brief This function handles Debug monitor.
*/
void DebugMon_Handler(void)
{
/* USER CODE BEGIN DebugMonitor_IRQn 0 */
/* USER CODE END DebugMonitor_IRQn 0 */
/* USER CODE BEGIN DebugMonitor_IRQn 1 */
/* USER CODE END DebugMonitor_IRQn 1 */
}
/**
* @brief This function handles Pendable request for system service.
*/
void PendSV_Handler(void)
{
/* USER CODE BEGIN PendSV_IRQn 0 */
/* USER CODE END PendSV_IRQn 0 */
/* USER CODE BEGIN PendSV_IRQn 1 */
/* USER CODE END PendSV_IRQn 1 */
}
/**
* @brief This function handles System tick timer.
*/
void SysTick_Handler(void)
{
/* USER CODE BEGIN SysTick_IRQn 0 */
/* USER CODE END SysTick_IRQn 0 */
HAL_IncTick();
/* USER CODE BEGIN SysTick_IRQn 1 */
/* USER CODE END SysTick_IRQn 1 */
}
/******************************************************************************/
/* STM32F4xx Peripheral Interrupt Handlers */
/* Add here the Interrupt Handlers for the used peripherals. */
/* For the available peripheral interrupt handler names, */
/* please refer to the startup file (startup_stm32f4xx.s). */
/******************************************************************************/
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@@ -0,0 +1,727 @@
/**
******************************************************************************
* @file system_stm32f4xx.c
* @author MCD Application Team
* @brief CMSIS Cortex-M4 Device Peripheral Access Layer System Source File.
*
* This file provides two functions and one global variable to be called from
* user application:
* - SystemInit(): This function is called at startup just after reset and
* before branch to main program. This call is made inside
* the "startup_stm32f4xx.s" file.
*
* - SystemCoreClock variable: Contains the core clock (HCLK), it can be used
* by the user application to setup the SysTick
* timer or configure other parameters.
*
* - SystemCoreClockUpdate(): Updates the variable SystemCoreClock and must
* be called whenever the core clock is changed
* during program execution.
*
*
******************************************************************************
* @attention
*
* <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
* All rights reserved.</center></h2>
*
* This software component is licensed by ST under BSD 3-Clause license,
* the "License"; You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*
******************************************************************************
*/
/** @addtogroup CMSIS
* @{
*/
/** @addtogroup stm32f4xx_system
* @{
*/
/** @addtogroup STM32F4xx_System_Private_Includes
* @{
*/
#include "stm32f4xx.h"
#if !defined (HSE_VALUE)
#define HSE_VALUE ((uint32_t)25000000) /*!< Default value of the External oscillator in Hz */
#endif /* HSE_VALUE */
#if !defined (HSI_VALUE)
#define HSI_VALUE ((uint32_t)16000000) /*!< Value of the Internal oscillator in Hz*/
#endif /* HSI_VALUE */
/**
* @}
*/
/** @addtogroup STM32F4xx_System_Private_TypesDefinitions
* @{
*/
/**
* @}
*/
/** @addtogroup STM32F4xx_System_Private_Defines
* @{
*/
/************************* Miscellaneous Configuration ************************/
/*!< Uncomment the following line if you need to use external SRAM or SDRAM as data memory */
#if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx) || defined(STM32F417xx)\
|| defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\
|| defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F412Zx) || defined(STM32F412Vx)
/* #define DATA_IN_ExtSRAM */
#endif /* STM32F40xxx || STM32F41xxx || STM32F42xxx || STM32F43xxx || STM32F469xx || STM32F479xx ||\
STM32F412Zx || STM32F412Vx */
#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\
|| defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx)
/* #define DATA_IN_ExtSDRAM */
#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F446xx || STM32F469xx ||\
STM32F479xx */
/*!< Uncomment the following line if you need to relocate your vector Table in
Internal SRAM. */
/* #define VECT_TAB_SRAM */
#define VECT_TAB_OFFSET 0x00 /*!< Vector Table base offset field.
This value must be a multiple of 0x200. */
/******************************************************************************/
/**
* @}
*/
/** @addtogroup STM32F4xx_System_Private_Macros
* @{
*/
/**
* @}
*/
/** @addtogroup STM32F4xx_System_Private_Variables
* @{
*/
/* This variable is updated in three ways:
1) by calling CMSIS function SystemCoreClockUpdate()
2) by calling HAL API function HAL_RCC_GetHCLKFreq()
3) each time HAL_RCC_ClockConfig() is called to configure the system clock frequency
Note: If you use this function to configure the system clock; then there
is no need to call the 2 first functions listed above, since SystemCoreClock
variable is updated automatically.
*/
uint32_t SystemCoreClock = 16000000;
const uint8_t AHBPrescTable[16] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 6, 7, 8, 9};
const uint8_t APBPrescTable[8] = {0, 0, 0, 0, 1, 2, 3, 4};
/**
* @}
*/
/** @addtogroup STM32F4xx_System_Private_FunctionPrototypes
* @{
*/
#if defined (DATA_IN_ExtSRAM) || defined (DATA_IN_ExtSDRAM)
static void SystemInit_ExtMemCtl(void);
#endif /* DATA_IN_ExtSRAM || DATA_IN_ExtSDRAM */
/**
* @}
*/
/** @addtogroup STM32F4xx_System_Private_Functions
* @{
*/
/**
* @brief Setup the microcontroller system
* Initialize the FPU setting, vector table location and External memory
* configuration.
* @param None
* @retval None
*/
void SystemInit(void)
{
/* FPU settings ------------------------------------------------------------*/
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11 Full Access */
#endif
#if defined (DATA_IN_ExtSRAM) || defined (DATA_IN_ExtSDRAM)
SystemInit_ExtMemCtl();
#endif /* DATA_IN_ExtSRAM || DATA_IN_ExtSDRAM */
/* Configure the Vector Table location add offset address ------------------*/
#ifdef VECT_TAB_SRAM
SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */
#else
SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */
#endif
}
/**
* @brief Update SystemCoreClock variable according to Clock Register Values.
* The SystemCoreClock variable contains the core clock (HCLK), it can
* be used by the user application to setup the SysTick timer or configure
* other parameters.
*
* @note Each time the core clock (HCLK) changes, this function must be called
* to update SystemCoreClock variable value. Otherwise, any configuration
* based on this variable will be incorrect.
*
* @note - The system frequency computed by this function is not the real
* frequency in the chip. It is calculated based on the predefined
* constant and the selected clock source:
*
* - If SYSCLK source is HSI, SystemCoreClock will contain the HSI_VALUE(*)
*
* - If SYSCLK source is HSE, SystemCoreClock will contain the HSE_VALUE(**)
*
* - If SYSCLK source is PLL, SystemCoreClock will contain the HSE_VALUE(**)
* or HSI_VALUE(*) multiplied/divided by the PLL factors.
*
* (*) HSI_VALUE is a constant defined in stm32f4xx_hal_conf.h file (default value
* 16 MHz) but the real value may vary depending on the variations
* in voltage and temperature.
*
* (**) HSE_VALUE is a constant defined in stm32f4xx_hal_conf.h file (its value
* depends on the application requirements), user has to ensure that HSE_VALUE
* is same as the real frequency of the crystal used. Otherwise, this function
* may have wrong result.
*
* - The result of this function could be not correct when using fractional
* value for HSE crystal.
*
* @param None
* @retval None
*/
void SystemCoreClockUpdate(void)
{
uint32_t tmp = 0, pllvco = 0, pllp = 2, pllsource = 0, pllm = 2;
/* Get SYSCLK source -------------------------------------------------------*/
tmp = RCC->CFGR & RCC_CFGR_SWS;
switch (tmp)
{
case 0x00: /* HSI used as system clock source */
SystemCoreClock = HSI_VALUE;
break;
case 0x04: /* HSE used as system clock source */
SystemCoreClock = HSE_VALUE;
break;
case 0x08: /* PLL used as system clock source */
/* PLL_VCO = (HSE_VALUE or HSI_VALUE / PLL_M) * PLL_N
SYSCLK = PLL_VCO / PLL_P
*/
pllsource = (RCC->PLLCFGR & RCC_PLLCFGR_PLLSRC) >> 22;
pllm = RCC->PLLCFGR & RCC_PLLCFGR_PLLM;
if (pllsource != 0)
{
/* HSE used as PLL clock source */
pllvco = (HSE_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6);
}
else
{
/* HSI used as PLL clock source */
pllvco = (HSI_VALUE / pllm) * ((RCC->PLLCFGR & RCC_PLLCFGR_PLLN) >> 6);
}
pllp = (((RCC->PLLCFGR & RCC_PLLCFGR_PLLP) >>16) + 1 ) *2;
SystemCoreClock = pllvco/pllp;
break;
default:
SystemCoreClock = HSI_VALUE;
break;
}
/* Compute HCLK frequency --------------------------------------------------*/
/* Get HCLK prescaler */
tmp = AHBPrescTable[((RCC->CFGR & RCC_CFGR_HPRE) >> 4)];
/* HCLK frequency */
SystemCoreClock >>= tmp;
}
#if defined (DATA_IN_ExtSRAM) && defined (DATA_IN_ExtSDRAM)
#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\
|| defined(STM32F469xx) || defined(STM32F479xx)
/**
* @brief Setup the external memory controller.
* Called in startup_stm32f4xx.s before jump to main.
* This function configures the external memories (SRAM/SDRAM)
* This SRAM/SDRAM will be used as program data memory (including heap and stack).
* @param None
* @retval None
*/
void SystemInit_ExtMemCtl(void)
{
__IO uint32_t tmp = 0x00;
register uint32_t tmpreg = 0, timeout = 0xFFFF;
register __IO uint32_t index;
/* Enable GPIOC, GPIOD, GPIOE, GPIOF, GPIOG, GPIOH and GPIOI interface clock */
RCC->AHB1ENR |= 0x000001F8;
/* Delay after an RCC peripheral clock enabling */
tmp = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOCEN);
/* Connect PDx pins to FMC Alternate function */
GPIOD->AFR[0] = 0x00CCC0CC;
GPIOD->AFR[1] = 0xCCCCCCCC;
/* Configure PDx pins in Alternate function mode */
GPIOD->MODER = 0xAAAA0A8A;
/* Configure PDx pins speed to 100 MHz */
GPIOD->OSPEEDR = 0xFFFF0FCF;
/* Configure PDx pins Output type to push-pull */
GPIOD->OTYPER = 0x00000000;
/* No pull-up, pull-down for PDx pins */
GPIOD->PUPDR = 0x00000000;
/* Connect PEx pins to FMC Alternate function */
GPIOE->AFR[0] = 0xC00CC0CC;
GPIOE->AFR[1] = 0xCCCCCCCC;
/* Configure PEx pins in Alternate function mode */
GPIOE->MODER = 0xAAAA828A;
/* Configure PEx pins speed to 100 MHz */
GPIOE->OSPEEDR = 0xFFFFC3CF;
/* Configure PEx pins Output type to push-pull */
GPIOE->OTYPER = 0x00000000;
/* No pull-up, pull-down for PEx pins */
GPIOE->PUPDR = 0x00000000;
/* Connect PFx pins to FMC Alternate function */
GPIOF->AFR[0] = 0xCCCCCCCC;
GPIOF->AFR[1] = 0xCCCCCCCC;
/* Configure PFx pins in Alternate function mode */
GPIOF->MODER = 0xAA800AAA;
/* Configure PFx pins speed to 50 MHz */
GPIOF->OSPEEDR = 0xAA800AAA;
/* Configure PFx pins Output type to push-pull */
GPIOF->OTYPER = 0x00000000;
/* No pull-up, pull-down for PFx pins */
GPIOF->PUPDR = 0x00000000;
/* Connect PGx pins to FMC Alternate function */
GPIOG->AFR[0] = 0xCCCCCCCC;
GPIOG->AFR[1] = 0xCCCCCCCC;
/* Configure PGx pins in Alternate function mode */
GPIOG->MODER = 0xAAAAAAAA;
/* Configure PGx pins speed to 50 MHz */
GPIOG->OSPEEDR = 0xAAAAAAAA;
/* Configure PGx pins Output type to push-pull */
GPIOG->OTYPER = 0x00000000;
/* No pull-up, pull-down for PGx pins */
GPIOG->PUPDR = 0x00000000;
/* Connect PHx pins to FMC Alternate function */
GPIOH->AFR[0] = 0x00C0CC00;
GPIOH->AFR[1] = 0xCCCCCCCC;
/* Configure PHx pins in Alternate function mode */
GPIOH->MODER = 0xAAAA08A0;
/* Configure PHx pins speed to 50 MHz */
GPIOH->OSPEEDR = 0xAAAA08A0;
/* Configure PHx pins Output type to push-pull */
GPIOH->OTYPER = 0x00000000;
/* No pull-up, pull-down for PHx pins */
GPIOH->PUPDR = 0x00000000;
/* Connect PIx pins to FMC Alternate function */
GPIOI->AFR[0] = 0xCCCCCCCC;
GPIOI->AFR[1] = 0x00000CC0;
/* Configure PIx pins in Alternate function mode */
GPIOI->MODER = 0x0028AAAA;
/* Configure PIx pins speed to 50 MHz */
GPIOI->OSPEEDR = 0x0028AAAA;
/* Configure PIx pins Output type to push-pull */
GPIOI->OTYPER = 0x00000000;
/* No pull-up, pull-down for PIx pins */
GPIOI->PUPDR = 0x00000000;
/*-- FMC Configuration -------------------------------------------------------*/
/* Enable the FMC interface clock */
RCC->AHB3ENR |= 0x00000001;
/* Delay after an RCC peripheral clock enabling */
tmp = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FMCEN);
FMC_Bank5_6->SDCR[0] = 0x000019E4;
FMC_Bank5_6->SDTR[0] = 0x01115351;
/* SDRAM initialization sequence */
/* Clock enable command */
FMC_Bank5_6->SDCMR = 0x00000011;
tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
while((tmpreg != 0) && (timeout-- > 0))
{
tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
}
/* Delay */
for (index = 0; index<1000; index++);
/* PALL command */
FMC_Bank5_6->SDCMR = 0x00000012;
timeout = 0xFFFF;
while((tmpreg != 0) && (timeout-- > 0))
{
tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
}
/* Auto refresh command */
FMC_Bank5_6->SDCMR = 0x00000073;
timeout = 0xFFFF;
while((tmpreg != 0) && (timeout-- > 0))
{
tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
}
/* MRD register program */
FMC_Bank5_6->SDCMR = 0x00046014;
timeout = 0xFFFF;
while((tmpreg != 0) && (timeout-- > 0))
{
tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
}
/* Set refresh count */
tmpreg = FMC_Bank5_6->SDRTR;
FMC_Bank5_6->SDRTR = (tmpreg | (0x0000027C<<1));
/* Disable write protection */
tmpreg = FMC_Bank5_6->SDCR[0];
FMC_Bank5_6->SDCR[0] = (tmpreg & 0xFFFFFDFF);
#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)
/* Configure and enable Bank1_SRAM2 */
FMC_Bank1->BTCR[2] = 0x00001011;
FMC_Bank1->BTCR[3] = 0x00000201;
FMC_Bank1E->BWTR[2] = 0x0fffffff;
#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx */
#if defined(STM32F469xx) || defined(STM32F479xx)
/* Configure and enable Bank1_SRAM2 */
FMC_Bank1->BTCR[2] = 0x00001091;
FMC_Bank1->BTCR[3] = 0x00110212;
FMC_Bank1E->BWTR[2] = 0x0fffffff;
#endif /* STM32F469xx || STM32F479xx */
(void)(tmp);
}
#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F469xx || STM32F479xx */
#elif defined (DATA_IN_ExtSRAM) || defined (DATA_IN_ExtSDRAM)
/**
* @brief Setup the external memory controller.
* Called in startup_stm32f4xx.s before jump to main.
* This function configures the external memories (SRAM/SDRAM)
* This SRAM/SDRAM will be used as program data memory (including heap and stack).
* @param None
* @retval None
*/
void SystemInit_ExtMemCtl(void)
{
__IO uint32_t tmp = 0x00;
#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\
|| defined(STM32F446xx) || defined(STM32F469xx) || defined(STM32F479xx)
#if defined (DATA_IN_ExtSDRAM)
register uint32_t tmpreg = 0, timeout = 0xFFFF;
register __IO uint32_t index;
#if defined(STM32F446xx)
/* Enable GPIOA, GPIOC, GPIOD, GPIOE, GPIOF, GPIOG interface
clock */
RCC->AHB1ENR |= 0x0000007D;
#else
/* Enable GPIOC, GPIOD, GPIOE, GPIOF, GPIOG, GPIOH and GPIOI interface
clock */
RCC->AHB1ENR |= 0x000001F8;
#endif /* STM32F446xx */
/* Delay after an RCC peripheral clock enabling */
tmp = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIOCEN);
#if defined(STM32F446xx)
/* Connect PAx pins to FMC Alternate function */
GPIOA->AFR[0] |= 0xC0000000;
GPIOA->AFR[1] |= 0x00000000;
/* Configure PDx pins in Alternate function mode */
GPIOA->MODER |= 0x00008000;
/* Configure PDx pins speed to 50 MHz */
GPIOA->OSPEEDR |= 0x00008000;
/* Configure PDx pins Output type to push-pull */
GPIOA->OTYPER |= 0x00000000;
/* No pull-up, pull-down for PDx pins */
GPIOA->PUPDR |= 0x00000000;
/* Connect PCx pins to FMC Alternate function */
GPIOC->AFR[0] |= 0x00CC0000;
GPIOC->AFR[1] |= 0x00000000;
/* Configure PDx pins in Alternate function mode */
GPIOC->MODER |= 0x00000A00;
/* Configure PDx pins speed to 50 MHz */
GPIOC->OSPEEDR |= 0x00000A00;
/* Configure PDx pins Output type to push-pull */
GPIOC->OTYPER |= 0x00000000;
/* No pull-up, pull-down for PDx pins */
GPIOC->PUPDR |= 0x00000000;
#endif /* STM32F446xx */
/* Connect PDx pins to FMC Alternate function */
GPIOD->AFR[0] = 0x000000CC;
GPIOD->AFR[1] = 0xCC000CCC;
/* Configure PDx pins in Alternate function mode */
GPIOD->MODER = 0xA02A000A;
/* Configure PDx pins speed to 50 MHz */
GPIOD->OSPEEDR = 0xA02A000A;
/* Configure PDx pins Output type to push-pull */
GPIOD->OTYPER = 0x00000000;
/* No pull-up, pull-down for PDx pins */
GPIOD->PUPDR = 0x00000000;
/* Connect PEx pins to FMC Alternate function */
GPIOE->AFR[0] = 0xC00000CC;
GPIOE->AFR[1] = 0xCCCCCCCC;
/* Configure PEx pins in Alternate function mode */
GPIOE->MODER = 0xAAAA800A;
/* Configure PEx pins speed to 50 MHz */
GPIOE->OSPEEDR = 0xAAAA800A;
/* Configure PEx pins Output type to push-pull */
GPIOE->OTYPER = 0x00000000;
/* No pull-up, pull-down for PEx pins */
GPIOE->PUPDR = 0x00000000;
/* Connect PFx pins to FMC Alternate function */
GPIOF->AFR[0] = 0xCCCCCCCC;
GPIOF->AFR[1] = 0xCCCCCCCC;
/* Configure PFx pins in Alternate function mode */
GPIOF->MODER = 0xAA800AAA;
/* Configure PFx pins speed to 50 MHz */
GPIOF->OSPEEDR = 0xAA800AAA;
/* Configure PFx pins Output type to push-pull */
GPIOF->OTYPER = 0x00000000;
/* No pull-up, pull-down for PFx pins */
GPIOF->PUPDR = 0x00000000;
/* Connect PGx pins to FMC Alternate function */
GPIOG->AFR[0] = 0xCCCCCCCC;
GPIOG->AFR[1] = 0xCCCCCCCC;
/* Configure PGx pins in Alternate function mode */
GPIOG->MODER = 0xAAAAAAAA;
/* Configure PGx pins speed to 50 MHz */
GPIOG->OSPEEDR = 0xAAAAAAAA;
/* Configure PGx pins Output type to push-pull */
GPIOG->OTYPER = 0x00000000;
/* No pull-up, pull-down for PGx pins */
GPIOG->PUPDR = 0x00000000;
#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\
|| defined(STM32F469xx) || defined(STM32F479xx)
/* Connect PHx pins to FMC Alternate function */
GPIOH->AFR[0] = 0x00C0CC00;
GPIOH->AFR[1] = 0xCCCCCCCC;
/* Configure PHx pins in Alternate function mode */
GPIOH->MODER = 0xAAAA08A0;
/* Configure PHx pins speed to 50 MHz */
GPIOH->OSPEEDR = 0xAAAA08A0;
/* Configure PHx pins Output type to push-pull */
GPIOH->OTYPER = 0x00000000;
/* No pull-up, pull-down for PHx pins */
GPIOH->PUPDR = 0x00000000;
/* Connect PIx pins to FMC Alternate function */
GPIOI->AFR[0] = 0xCCCCCCCC;
GPIOI->AFR[1] = 0x00000CC0;
/* Configure PIx pins in Alternate function mode */
GPIOI->MODER = 0x0028AAAA;
/* Configure PIx pins speed to 50 MHz */
GPIOI->OSPEEDR = 0x0028AAAA;
/* Configure PIx pins Output type to push-pull */
GPIOI->OTYPER = 0x00000000;
/* No pull-up, pull-down for PIx pins */
GPIOI->PUPDR = 0x00000000;
#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F469xx || STM32F479xx */
/*-- FMC Configuration -------------------------------------------------------*/
/* Enable the FMC interface clock */
RCC->AHB3ENR |= 0x00000001;
/* Delay after an RCC peripheral clock enabling */
tmp = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FMCEN);
/* Configure and enable SDRAM bank1 */
#if defined(STM32F446xx)
FMC_Bank5_6->SDCR[0] = 0x00001954;
#else
FMC_Bank5_6->SDCR[0] = 0x000019E4;
#endif /* STM32F446xx */
FMC_Bank5_6->SDTR[0] = 0x01115351;
/* SDRAM initialization sequence */
/* Clock enable command */
FMC_Bank5_6->SDCMR = 0x00000011;
tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
while((tmpreg != 0) && (timeout-- > 0))
{
tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
}
/* Delay */
for (index = 0; index<1000; index++);
/* PALL command */
FMC_Bank5_6->SDCMR = 0x00000012;
timeout = 0xFFFF;
while((tmpreg != 0) && (timeout-- > 0))
{
tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
}
/* Auto refresh command */
#if defined(STM32F446xx)
FMC_Bank5_6->SDCMR = 0x000000F3;
#else
FMC_Bank5_6->SDCMR = 0x00000073;
#endif /* STM32F446xx */
timeout = 0xFFFF;
while((tmpreg != 0) && (timeout-- > 0))
{
tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
}
/* MRD register program */
#if defined(STM32F446xx)
FMC_Bank5_6->SDCMR = 0x00044014;
#else
FMC_Bank5_6->SDCMR = 0x00046014;
#endif /* STM32F446xx */
timeout = 0xFFFF;
while((tmpreg != 0) && (timeout-- > 0))
{
tmpreg = FMC_Bank5_6->SDSR & 0x00000020;
}
/* Set refresh count */
tmpreg = FMC_Bank5_6->SDRTR;
#if defined(STM32F446xx)
FMC_Bank5_6->SDRTR = (tmpreg | (0x0000050C<<1));
#else
FMC_Bank5_6->SDRTR = (tmpreg | (0x0000027C<<1));
#endif /* STM32F446xx */
/* Disable write protection */
tmpreg = FMC_Bank5_6->SDCR[0];
FMC_Bank5_6->SDCR[0] = (tmpreg & 0xFFFFFDFF);
#endif /* DATA_IN_ExtSDRAM */
#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx || STM32F446xx || STM32F469xx || STM32F479xx */
#if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx) || defined(STM32F417xx)\
|| defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)\
|| defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F412Zx) || defined(STM32F412Vx)
#if defined(DATA_IN_ExtSRAM)
/*-- GPIOs Configuration -----------------------------------------------------*/
/* Enable GPIOD, GPIOE, GPIOF and GPIOG interface clock */
RCC->AHB1ENR |= 0x00000078;
/* Delay after an RCC peripheral clock enabling */
tmp = READ_BIT(RCC->AHB1ENR, RCC_AHB1ENR_GPIODEN);
/* Connect PDx pins to FMC Alternate function */
GPIOD->AFR[0] = 0x00CCC0CC;
GPIOD->AFR[1] = 0xCCCCCCCC;
/* Configure PDx pins in Alternate function mode */
GPIOD->MODER = 0xAAAA0A8A;
/* Configure PDx pins speed to 100 MHz */
GPIOD->OSPEEDR = 0xFFFF0FCF;
/* Configure PDx pins Output type to push-pull */
GPIOD->OTYPER = 0x00000000;
/* No pull-up, pull-down for PDx pins */
GPIOD->PUPDR = 0x00000000;
/* Connect PEx pins to FMC Alternate function */
GPIOE->AFR[0] = 0xC00CC0CC;
GPIOE->AFR[1] = 0xCCCCCCCC;
/* Configure PEx pins in Alternate function mode */
GPIOE->MODER = 0xAAAA828A;
/* Configure PEx pins speed to 100 MHz */
GPIOE->OSPEEDR = 0xFFFFC3CF;
/* Configure PEx pins Output type to push-pull */
GPIOE->OTYPER = 0x00000000;
/* No pull-up, pull-down for PEx pins */
GPIOE->PUPDR = 0x00000000;
/* Connect PFx pins to FMC Alternate function */
GPIOF->AFR[0] = 0x00CCCCCC;
GPIOF->AFR[1] = 0xCCCC0000;
/* Configure PFx pins in Alternate function mode */
GPIOF->MODER = 0xAA000AAA;
/* Configure PFx pins speed to 100 MHz */
GPIOF->OSPEEDR = 0xFF000FFF;
/* Configure PFx pins Output type to push-pull */
GPIOF->OTYPER = 0x00000000;
/* No pull-up, pull-down for PFx pins */
GPIOF->PUPDR = 0x00000000;
/* Connect PGx pins to FMC Alternate function */
GPIOG->AFR[0] = 0x00CCCCCC;
GPIOG->AFR[1] = 0x000000C0;
/* Configure PGx pins in Alternate function mode */
GPIOG->MODER = 0x00085AAA;
/* Configure PGx pins speed to 100 MHz */
GPIOG->OSPEEDR = 0x000CAFFF;
/* Configure PGx pins Output type to push-pull */
GPIOG->OTYPER = 0x00000000;
/* No pull-up, pull-down for PGx pins */
GPIOG->PUPDR = 0x00000000;
/*-- FMC/FSMC Configuration --------------------------------------------------*/
/* Enable the FMC/FSMC interface clock */
RCC->AHB3ENR |= 0x00000001;
#if defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx)
/* Delay after an RCC peripheral clock enabling */
tmp = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FMCEN);
/* Configure and enable Bank1_SRAM2 */
FMC_Bank1->BTCR[2] = 0x00001011;
FMC_Bank1->BTCR[3] = 0x00000201;
FMC_Bank1E->BWTR[2] = 0x0fffffff;
#endif /* STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx */
#if defined(STM32F469xx) || defined(STM32F479xx)
/* Delay after an RCC peripheral clock enabling */
tmp = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FMCEN);
/* Configure and enable Bank1_SRAM2 */
FMC_Bank1->BTCR[2] = 0x00001091;
FMC_Bank1->BTCR[3] = 0x00110212;
FMC_Bank1E->BWTR[2] = 0x0fffffff;
#endif /* STM32F469xx || STM32F479xx */
#if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx)|| defined(STM32F417xx)\
|| defined(STM32F412Zx) || defined(STM32F412Vx)
/* Delay after an RCC peripheral clock enabling */
tmp = READ_BIT(RCC->AHB3ENR, RCC_AHB3ENR_FSMCEN);
/* Configure and enable Bank1_SRAM2 */
FSMC_Bank1->BTCR[2] = 0x00001011;
FSMC_Bank1->BTCR[3] = 0x00000201;
FSMC_Bank1E->BWTR[2] = 0x0FFFFFFF;
#endif /* STM32F405xx || STM32F415xx || STM32F407xx || STM32F417xx || STM32F412Zx || STM32F412Vx */
#endif /* DATA_IN_ExtSRAM */
#endif /* STM32F405xx || STM32F415xx || STM32F407xx || STM32F417xx || STM32F427xx || STM32F437xx ||\
STM32F429xx || STM32F439xx || STM32F469xx || STM32F479xx || STM32F412Zx || STM32F412Vx */
(void)(tmp);
}
#endif /* DATA_IN_ExtSRAM && DATA_IN_ExtSDRAM */
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/

View File

@@ -0,0 +1,27 @@
# SPDX-License-Identifier: Apache-2.0
cmake_minimum_required(VERSION 3.20.0)
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(zephyr_flasher)
zephyr_compile_definitions_ifdef(CONFIG_SERIAL_FLASHER_MD5_ENABLED MD5_ENABLED)
zephyr_library_sources(
../common/example_common.c
)
zephyr_library_include_directories(
../common
../binaries
)
# Needed for example_common
add_compile_definitions(SERIAL_FLASHER_INTERFACE_UART)
# Embed binaries into the app.
include(${CMAKE_CURRENT_LIST_DIR}/../common/bin2array.cmake)
create_resources(${CMAKE_CURRENT_LIST_DIR}/../binaries/Hello-world ${CMAKE_BINARY_DIR}/binaries.c)
set_property(SOURCE ${CMAKE_BINARY_DIR}/binaries.c PROPERTY GENERATED 1)
target_sources(app PRIVATE src/main.c ${CMAKE_BINARY_DIR}/binaries.c)

View File

@@ -0,0 +1,84 @@
# ESP32 Zephyr example
## Overview
This sample code demonstrates how to flash ESP32/ESP32-S2/ESP8266 from another (host) MCU using
esp_serial_flash component API. In this case, ESP32 is also used as host MCU.
Binaries to be flashed from host MCU to another Espressif SoC can be found in `binaries` folder
and are converted into C-array during build process.
Following steps are performed in order to re-program target's memory:
1. Peripherals are initialized (GPIO for BOOT and EN pins and UART).
2. UART1 (can be changed) through which new binary will be transfered is initialized.
3. Host puts slave device into boot mode tries to connect by calling `esp_loader_connect()`.
4. Binary file is opened and its size is acquired, as it has to be known before flashing.
5. Then `esp_loader_flash_start()` is called to enter flashing mode and erase amount of memory to be flashed.
6. `esp_loader_flash_write()` function is called repeatedly until the whole binary image is transfered.
Note: In addition, to steps mentioned above, `esp_loader_change_transmission_rate` is called after connection
is established in order to increase flashing speed. This does not apply for ESP8266, as its bootloader
does not support this command. However, ESP8266 is capable of detecting baud rate during connection
phase, and can be changed before calling `esp_loader_connect`, if necessary.
## Hardware Required
* Two development boards with ESP32 SoC (e.g., ESP32-DevKitC, ESP-WROVER-KIT, etc.).
* One or two USB cables for power supply and programming.
## Hardware connection
Table below shows connection between two ESP32 devices.
| ESP32 (host) | ESP32 (slave) |
|:------------:|:-------------:|
| IO4 | IO0 |
| IO2 | RESET |
| IO9 | TX0 |
| IO10 | RX0 |
Note: interconnection is the same for all three targets (slaves).
## Build and flash
To run the example, type the following command:
```c
west build -p -b esp32
west flash
west espressif monitor
```
(To exit the serial monitor, type ``ctrl-c``.)
For more information, check [Zephyr's Getting Started](https://docs.zephyrproject.org/latest/develop/getting_started/index.html)
## Configuration
For details about available configuration option, please refer to top level [README.md](../../README.md).
Compile definitions can be specified in `prj.conf` file.
Binaries to be flashed are placed in separate folder (binaries.c) for each possible target and converted to C-array. Without explicitly enabling MD5 check, flash integrity verification is disabled by default.
## Example output
Here is the example's console output:
```
*** Booting Zephyr OS build zephyr-v3.2.0-3548-ga1bb9c9d1736 ***
Running ESP Flasher from Zephyr
Connected to target
Baudrate changed
Erasing flash (this may take a while)...
Start programming
Progress: 100 %
Finished programming
Erasing flash (this may take a while)...
Start programming
Progress: 100 %
Finished programming
Erasing flash (this may take a while)...
Start programming
Progress: 100 %
Finished programming
```

View File

@@ -0,0 +1,34 @@
/*
* Copyright (c) 2022 Espressif Systems (Shanghai) Co., Ltd.
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/dt-bindings/pinctrl/esp-pinctrl-common.h>
#include <dt-bindings/pinctrl/esp32-pinctrl.h>
#include <zephyr/dt-bindings/pinctrl/esp32-gpio-sigmap.h>
/ {
aliases {
en = &en_button;
boot = &boot_button;
uart1 = &uart1;
};
gpio_keys {
compatible = "gpio-keys";
en_button: en_button {
gpios = <&gpio0 2 (GPIO_PULL_UP | GPIO_ACTIVE_HIGH)>;
};
boot_button: boot_button {
gpios = <&gpio0 4 (GPIO_PULL_UP | GPIO_ACTIVE_HIGH)>;
};
};
};
&uart1 {
status = "okay";
current-speed = <115200>;
pinctrl-0 = <&uart1_default>;
pinctrl-names = "default";
};

View File

@@ -0,0 +1,4 @@
# nothing here
CONFIG_CONSOLE=y
CONFIG_CONSOLE_GETCHAR=y
CONFIG_NEWLIB_LIBC=y

View File

@@ -0,0 +1,7 @@
sample:
description: ESP Serial Flasher sample code
name: zephyr_flasher
tests:
sample.esp_flasher.zephyr_example:
platform_allow: esp32
tags: esp32

View File

@@ -0,0 +1,81 @@
/*
* ESP Flasher Library Example for Zephyr
* Written in 2022 by KT-Elektronik, Klaucke und Partner GmbH
* This example code is in the Public Domain (or CC0 licensed, at your option.)
* Unless required by applicable law or agreed to in writing, this
* software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied.
*
* Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd.
*/
#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/devicetree.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/sys/util.h>
#include <stdio.h>
#include <string.h>
#include <zephyr_port.h>
#include <esp_loader.h>
#include "example_common.h"
#define HIGHER_BAUDRATE 230400
#define DEFAULT_BAUDRATE 115200
/* Get UART DTS entry used as flash interface */
static const struct device *esp_uart_dev = DEVICE_DT_GET(DT_ALIAS(uart1));
/* Get GPIO pin connected to the ESP's enable pin. */
static const struct gpio_dt_spec esp_enable_spec = GPIO_DT_SPEC_GET(DT_ALIAS(en), gpios);
/* Get GPIO pin connected to the ESP's boot pin. */
static const struct gpio_dt_spec esp_boot_spec = GPIO_DT_SPEC_GET(DT_ALIAS(boot), gpios);
void main(void)
{
example_binaries_t bin;
const loader_zephyr_config_t config = {
.uart_dev = esp_uart_dev,
.enable_spec = esp_enable_spec,
.boot_spec = esp_boot_spec
};
printk("Running ESP Flasher from Zephyr\r\n");
if (!device_is_ready(esp_uart_dev)) {
printk("ESP UART not ready");
return;
}
if (!device_is_ready(esp_boot_spec.port)) {
printk("ESP boot GPIO not ready");
return;
}
if (!device_is_ready(esp_enable_spec.port)) {
printk("Bluetooth Enable GPIO not ready");
return;
}
gpio_pin_configure_dt(&esp_boot_spec, GPIO_OUTPUT_ACTIVE);
gpio_pin_configure_dt(&esp_enable_spec, GPIO_OUTPUT_INACTIVE);
if (loader_port_zephyr_init(&config) != ESP_LOADER_SUCCESS) {
printk("ESP loader init failed");
return;
}
if (connect_to_target(HIGHER_BAUDRATE) == ESP_LOADER_SUCCESS) {
get_example_binaries(esp_loader_get_target(), &bin);
flash_binary(bin.boot.data, bin.boot.size, bin.boot.addr);
flash_binary(bin.part.data, bin.part.size, bin.part.addr);
flash_binary(bin.app.data, bin.app.size, bin.app.addr);
}
loader_port_change_transmission_rate(DEFAULT_BAUDRATE);
loader_port_reset_target();
}

View File

@@ -0,0 +1,3 @@
version: "0.3.1"
description: Serial flasher component provides portable library for flashing or loading ram loadble app to Espressif SoCs from other host microcontroller
url: https://github.com/espressif/esp-serial-flasher

View File

@@ -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

View File

@@ -0,0 +1,299 @@
/* 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 <stdint.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
/* Used for backwards compatibility with the previous API */
#define esp_loader_change_baudrate esp_loader_change_transmission_rate
/**
* Macro which can be used to check the error code,
* and return in case the code is not ESP_LOADER_SUCCESS.
*/
#define RETURN_ON_ERROR(x) do { \
esp_loader_error_t _err_ = (x); \
if (_err_ != ESP_LOADER_SUCCESS) { \
return _err_; \
} \
} while(0)
/**
* @brief Error codes
*/
typedef enum {
ESP_LOADER_SUCCESS, /*!< Success */
ESP_LOADER_ERROR_FAIL, /*!< Unspecified error */
ESP_LOADER_ERROR_TIMEOUT, /*!< Timeout elapsed */
ESP_LOADER_ERROR_IMAGE_SIZE, /*!< Image size to flash is larger than flash size */
ESP_LOADER_ERROR_INVALID_MD5, /*!< Computed and received MD5 does not match */
ESP_LOADER_ERROR_INVALID_PARAM, /*!< Invalid parameter passed to function */
ESP_LOADER_ERROR_INVALID_TARGET, /*!< Connected target is invalid */
ESP_LOADER_ERROR_UNSUPPORTED_CHIP, /*!< Attached chip is not supported */
ESP_LOADER_ERROR_UNSUPPORTED_FUNC, /*!< Function is not supported on attached target */
ESP_LOADER_ERROR_INVALID_RESPONSE /*!< Internal error */
} esp_loader_error_t;
/**
* @brief Supported targets
*/
typedef enum {
ESP8266_CHIP = 0,
ESP32_CHIP = 1,
ESP32S2_CHIP = 2,
ESP32C3_CHIP = 3,
ESP32S3_CHIP = 4,
ESP32C2_CHIP = 5,
ESP32H4_CHIP = 6,
ESP32H2_CHIP = 7,
ESP32C6_CHIP = 8,
ESP_MAX_CHIP = 9,
ESP_UNKNOWN_CHIP = 9
} target_chip_t;
/**
* @brief Application binary header
*/
typedef struct {
uint8_t magic;
uint8_t segments;
uint8_t flash_mode;
uint8_t flash_size_freq;
uint32_t entrypoint;
} esp_loader_bin_header_t;
/**
* @brief Segment binary header
*/
typedef struct {
uint32_t addr;
uint32_t size;
uint8_t *data;
} esp_loader_bin_segment_t;
/**
* @brief Connection arguments
*/
typedef struct {
uint32_t sync_timeout; /*!< Maximum time to wait for response from serial interface. */
int32_t trials; /*!< Number of trials to connect to target. If greater than 1,
100 millisecond delay is inserted after each try. */
} esp_loader_connect_args_t;
#define ESP_LOADER_CONNECT_DEFAULT() { \
.sync_timeout = 100, \
.trials = 10, \
}
/**
* @brief Connects to the target
*
* @param connect_args[in] Timing parameters to be used for connecting to target.
*
* @return
* - ESP_LOADER_SUCCESS Success
* - ESP_LOADER_ERROR_TIMEOUT Timeout
* - ESP_LOADER_ERROR_INVALID_RESPONSE Internal error
*/
esp_loader_error_t esp_loader_connect(esp_loader_connect_args_t *connect_args);
/**
* @brief Returns attached target chip.
*
* @warning This function can only be called after connection with target
* has been successfully established by calling esp_loader_connect().
*
* @return One of target_chip_t
*/
target_chip_t esp_loader_get_target(void);
#ifdef SERIAL_FLASHER_INTERFACE_UART
/**
* @brief Initiates flash operation
*
* @param offset[in] Address from which flash operation will be performed.
* @param image_size[in] Size of the whole binary to be loaded into flash.
* @param block_size[in] Size of buffer used in subsequent calls to esp_loader_flash_write.
*
* @note image_size is size of the whole image, whereas, block_size is chunk of data sent
* to the target, each time esp_loader_flash_write function is called.
*
* @return
* - ESP_LOADER_SUCCESS Success
* - ESP_LOADER_ERROR_TIMEOUT Timeout
* - ESP_LOADER_ERROR_INVALID_RESPONSE Internal error
*/
esp_loader_error_t esp_loader_flash_start(uint32_t offset, uint32_t image_size, uint32_t block_size);
/**
* @brief Writes supplied data to target's flash memory.
*
* @param payload[in] Data to be flashed into target's memory.
* @param size[in] Size of payload in bytes.
*
* @note size must not be greater that block_size supplied to previously called
* esp_loader_flash_start function. If size is less than block_size,
* remaining bytes of payload buffer will be padded with 0xff.
* Therefore, size of payload buffer has to be equal or greater than block_size.
*
* @return
* - ESP_LOADER_SUCCESS Success
* - ESP_LOADER_ERROR_TIMEOUT Timeout
* - ESP_LOADER_ERROR_INVALID_RESPONSE Internal error
*/
esp_loader_error_t esp_loader_flash_write(void *payload, uint32_t size);
/**
* @brief Ends flash operation.
*
* @param reboot[in] reboot the target if true.
*
* @return
* - ESP_LOADER_SUCCESS Success
* - ESP_LOADER_ERROR_TIMEOUT Timeout
* - ESP_LOADER_ERROR_INVALID_RESPONSE Internal error
*/
esp_loader_error_t esp_loader_flash_finish(bool reboot);
#endif /* SERIAL_FLASHER_INTERFACE_UART */
/**
* @brief Initiates mem operation, initiates loading for program into target RAM
*
* @param offset[in] Address from which mem operation will be performed.
* @param size[in] Size of the whole binary to be loaded into mem.
* @param block_size[in] Size of buffer used in subsequent calls to esp_loader_mem_write.
*
* @note image_size is size of the whole image, whereas, block_size is chunk of data sent
* to the target, each time esp_mem_flash_write function is called.
*
* @return
* - ESP_LOADER_SUCCESS Success
* - ESP_LOADER_ERROR_TIMEOUT Timeout
* - ESP_LOADER_ERROR_INVALID_RESPONSE Internal error
*/
esp_loader_error_t esp_loader_mem_start(uint32_t offset, uint32_t size, uint32_t block_size);
/**
* @brief Writes supplied data to target's mem memory.
*
* @param payload[in] Data to be loaded into target's memory.
* @param size[in] Size of data in bytes.
*
* @note size must not be greater that block_size supplied to previously called
* esp_loader_mem_start function.
* Therefore, size of data buffer has to be equal or greater than block_size.
*
* @return
* - ESP_LOADER_SUCCESS Success
* - ESP_LOADER_ERROR_TIMEOUT Timeout
* - ESP_LOADER_ERROR_INVALID_RESPONSE Internal error
*/
esp_loader_error_t esp_loader_mem_write(const void *payload, uint32_t size);
/**
* @brief Ends mem operation, finish loading for program into target RAM
* and send the entrypoint of ram_loadable app
*
* @param entrypoint[in] entrypoint of ram program.
*
* @return
* - ESP_LOADER_SUCCESS Success
* - ESP_LOADER_ERROR_TIMEOUT Timeout
* - ESP_LOADER_ERROR_INVALID_RESPONSE Internal error
*/
esp_loader_error_t esp_loader_mem_finish(uint32_t entrypoint);
/**
* @brief Writes register.
*
* @param address[in] Address of register.
* @param reg_value[in] New register value.
*
* @return
* - ESP_LOADER_SUCCESS Success
* - ESP_LOADER_ERROR_TIMEOUT Timeout
* - ESP_LOADER_ERROR_INVALID_RESPONSE Internal error
*/
esp_loader_error_t esp_loader_write_register(uint32_t address, uint32_t reg_value);
/**
* @brief Reads register.
*
* @param address[in] Address of register.
* @param reg_value[out] Register value.
*
* @return
* - ESP_LOADER_SUCCESS Success
* - ESP_LOADER_ERROR_TIMEOUT Timeout
* - ESP_LOADER_ERROR_INVALID_RESPONSE Internal error
*/
esp_loader_error_t esp_loader_read_register(uint32_t address, uint32_t *reg_value);
/**
* @brief Change baud rate.
*
* @note Baud rate has to be also adjusted accordingly on host MCU, as
* target's baud rate is changed upon return from this function.
*
* @param transmission_rate[in] new baud rate to be set.
*
* @return
* - ESP_LOADER_SUCCESS Success
* - ESP_LOADER_ERROR_TIMEOUT Timeout
* - ESP_LOADER_ERROR_INVALID_RESPONSE Internal error
* - ESP_LOADER_ERROR_UNSUPPORTED_FUNC Unsupported on the target
*/
esp_loader_error_t esp_loader_change_transmission_rate(uint32_t transmission_rate);
/**
* @brief Verify target's flash integrity by checking MD5.
* MD5 checksum is computed from data pushed to target's memory by calling
* esp_loader_flash_write() function and compared against target's MD5.
* Target computes checksum based on offset and image_size passed to
* esp_loader_flash_start() function.
*
* @note This function is only available if MD5_ENABLED is set.
*
* @return
* - ESP_LOADER_SUCCESS Success
* - ESP_LOADER_ERROR_INVALID_MD5 MD5 does not match
* - ESP_LOADER_ERROR_TIMEOUT Timeout
* - ESP_LOADER_ERROR_INVALID_RESPONSE Internal error
* - ESP_LOADER_ERROR_UNSUPPORTED_FUNC Unsupported on the target
*/
#if MD5_ENABLED
esp_loader_error_t esp_loader_flash_verify(void);
#endif
/**
* @brief Toggles reset pin.
*/
void esp_loader_reset_target(void);
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,112 @@
/* 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 <stdint.h>
#include "esp_loader.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Changes the transmission rate of the used peripheral.
*/
esp_loader_error_t loader_port_change_transmission_rate(uint32_t transmission_rate);
/**
* @brief Writes data over the io interface.
*
* @param data[in] Buffer with data to be written.
* @param size[in] Size of data in bytes.
* @param timeout[in] Timeout in milliseconds.
*
* @return
* - ESP_LOADER_SUCCESS Success
* - ESP_LOADER_ERROR_TIMEOUT Timeout elapsed
*/
esp_loader_error_t loader_port_write(const uint8_t *data, uint16_t size, uint32_t timeout);
/**
* @brief Reads data from the io interface.
*
* @param data[out] Buffer into which received data will be written.
* @param size[in] Number of bytes to read.
* @param timeout[in] Timeout in milliseconds.
*
* @return
* - ESP_LOADER_SUCCESS Success
* - ESP_LOADER_ERROR_TIMEOUT Timeout elapsed
*/
esp_loader_error_t loader_port_read(uint8_t *data, uint16_t size, uint32_t timeout);
/**
* @brief Delay in milliseconds.
*
* @param ms[in] Number of milliseconds.
*
*/
void loader_port_delay_ms(uint32_t ms);
/**
* @brief Starts timeout timer.
*
* @param ms[in] Number of milliseconds.
*
*/
void loader_port_start_timer(uint32_t ms);
/**
* @brief Returns remaining time since timer was started by calling esp_loader_start_timer.
* 0 if timer has elapsed.
*
* @return Number of milliseconds.
*
*/
uint32_t loader_port_remaining_time(void);
/**
* @brief Asserts bootstrap pins to enter boot mode and toggles reset pin.
*
* @note Reset pin should stay asserted for at least 20 milliseconds.
*/
void loader_port_enter_bootloader(void);
/**
* @brief Toggles reset pin.
*
* @note Reset pin should stay asserted for at least 20 milliseconds.
*/
void loader_port_reset_target(void);
/**
* @brief Function can be defined by user to print debug message.
*
* @note Empty weak function is used, otherwise.
*
*/
void loader_port_debug_print(const char *str);
#ifdef SERIAL_FLASHER_INTERFACE_SPI
/**
* @brief Sets the chip select to a defined level
*/
void loader_port_spi_set_cs(uint32_t level);
#endif /* SERIAL_FLASHER_INTERFACE_SPI */
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,33 @@
/* Copyright 2020 Espressif Systems (Shanghai) PTE 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 <stdint.h>
#include "esp_loader.h"
typedef struct {
uint32_t cmd;
uint32_t usr;
uint32_t usr1;
uint32_t usr2;
uint32_t w0;
uint32_t mosi_dlen;
uint32_t miso_dlen;
} target_registers_t;
esp_loader_error_t loader_detect_chip(target_chip_t *target, const target_registers_t **regs);
esp_loader_error_t loader_read_spi_config(target_chip_t target_chip, uint32_t *spi_config);
bool encryption_in_begin_flash_cmd(target_chip_t target);

View File

@@ -0,0 +1,63 @@
/* 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
#define BIN_FIRST_SEGMENT_OFFSET 0x18
// Maximum block sized for RAM and Flash writes, respectively.
#define ESP_RAM_BLOCK 0x1800
typedef struct {
const uint8_t *data;
uint32_t size;
uint32_t addr;
} partition_attr_t;
typedef struct {
partition_attr_t boot;
partition_attr_t part;
partition_attr_t app;
} example_binaries_t;
typedef struct {
partition_attr_t ram_app;
} example_ram_app_binary_t;
/**
* @brief esptool portable bin header format
*/
typedef struct example_bin_header {
uint8_t magic;
uint8_t segments;
uint8_t flash_mode;
uint8_t flash_size_freq;
uint32_t entrypoint;
} example_bin_header_t;
/**
* @brief esptool portable bin segment format
*/
typedef struct example_bin_segment {
uint32_t addr;
uint32_t size;
uint8_t *data;
} example_bin_segment_t;
void get_example_binaries(target_chip_t target, example_binaries_t *binaries);
void get_example_ram_app_binary(target_chip_t target, example_ram_app_binary_t *bin);
esp_loader_error_t connect_to_target(uint32_t higher_transmission_rate);
esp_loader_error_t flash_binary(const uint8_t *bin, size_t size, size_t address);
esp_loader_error_t load_ram_binary(const uint8_t *bin);

View File

@@ -0,0 +1,28 @@
/*
* MD5 hash implementation and interface functions
* Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#pragma once
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
struct MD5Context {
uint32_t buf[4];
uint32_t bits[2];
uint8_t in[64];
};
void MD5Init(struct MD5Context *context);
void MD5Update(struct MD5Context *context, unsigned char const *buf, unsigned len);
void MD5Final(unsigned char digest[16], struct MD5Context *context);
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,236 @@
/* 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 <stdint.h>
#include <stdbool.h>
#include "esp_loader.h"
#ifdef __cplusplus
extern "C" {
#endif
#define STATUS_FAILURE 1
#define STATUS_SUCCESS 0
#define READ_DIRECTION 1
#define WRITE_DIRECTION 0
#define MD5_SIZE 32
typedef enum __attribute__((packed))
{
FLASH_BEGIN = 0x02,
FLASH_DATA = 0x03,
FLASH_END = 0x04,
MEM_BEGIN = 0x05,
MEM_END = 0x06,
MEM_DATA = 0x07,
SYNC = 0x08,
WRITE_REG = 0x09,
READ_REG = 0x0a,
SPI_SET_PARAMS = 0x0b,
SPI_ATTACH = 0x0d,
CHANGE_BAUDRATE = 0x0f,
FLASH_DEFL_BEGIN = 0x10,
FLASH_DEFL_DATA = 0x11,
FLASH_DEFL_END = 0x12,
SPI_FLASH_MD5 = 0x13,
} command_t;
typedef enum __attribute__((packed))
{
RESPONSE_OK = 0x00,
INVALID_COMMAND = 0x05, // parameters or length field is invalid
COMMAND_FAILED = 0x06, // Failed to act on received message
INVALID_CRC = 0x07, // Invalid CRC in message
FLASH_WRITE_ERR = 0x08, // After writing a block of data to flash, the ROM loader reads the value back and the 8-bit CRC is compared to the data read from flash. If they don't match, this error is returned.
FLASH_READ_ERR = 0x09, // SPI read failed
READ_LENGTH_ERR = 0x0a, // SPI read request length is too long
DEFLATE_ERROR = 0x0b, // ESP32 compressed uploads only
} error_code_t;
typedef struct __attribute__((packed))
{
uint8_t direction;
uint8_t command; // One of command_t
uint16_t size;
uint32_t checksum;
} command_common_t;
typedef struct __attribute__((packed))
{
command_common_t common;
uint32_t erase_size;
uint32_t packet_count;
uint32_t packet_size;
uint32_t offset;
uint32_t encrypted;
} flash_begin_command_t;
typedef struct __attribute__((packed))
{
command_common_t common;
uint32_t data_size;
uint32_t sequence_number;
uint32_t zero_0;
uint32_t zero_1;
} data_command_t;
typedef struct __attribute__((packed))
{
command_common_t common;
uint32_t stay_in_loader;
} flash_end_command_t;
typedef struct __attribute__((packed))
{
command_common_t common;
uint32_t total_size;
uint32_t blocks;
uint32_t block_size;
uint32_t offset;
} mem_begin_command_t;
typedef struct __attribute__((packed))
{
command_common_t common;
uint32_t stay_in_loader;
uint32_t entry_point_address;
} mem_end_command_t;
typedef struct __attribute__((packed))
{
command_common_t common;
uint8_t sync_sequence[36];
} sync_command_t;
typedef struct __attribute__((packed))
{
command_common_t common;
uint32_t address;
uint32_t value;
uint32_t mask;
uint32_t delay_us;
} write_reg_command_t;
typedef struct __attribute__((packed))
{
command_common_t common;
uint32_t address;
} read_reg_command_t;
typedef struct __attribute__((packed))
{
command_common_t common;
uint32_t configuration;
uint32_t zero; // ESP32 ROM only
} spi_attach_command_t;
typedef struct __attribute__((packed))
{
command_common_t common;
uint32_t new_baudrate;
uint32_t old_baudrate;
} change_baudrate_command_t;
typedef struct __attribute__((packed))
{
command_common_t common;
uint32_t address;
uint32_t size;
uint32_t reserved_0;
uint32_t reserved_1;
} spi_flash_md5_command_t;
typedef struct __attribute__((packed))
{
uint8_t direction;
uint8_t command; // One of command_t
uint16_t size;
uint32_t value;
} common_response_t;
typedef struct __attribute__((packed))
{
uint8_t failed;
uint8_t error;
} response_status_t;
typedef struct __attribute__((packed))
{
common_response_t common;
response_status_t status;
} response_t;
typedef struct __attribute__((packed))
{
common_response_t common;
uint8_t md5[MD5_SIZE]; // ROM only
response_status_t status;
} rom_md5_response_t;
typedef struct __attribute__((packed))
{
command_common_t common;
uint32_t id;
uint32_t total_size;
uint32_t block_size;
uint32_t sector_size;
uint32_t page_size;
uint32_t status_mask;
} write_spi_command_t;
esp_loader_error_t loader_initialize_conn(esp_loader_connect_args_t *connect_args);
#ifdef SERIAL_FLASHER_INTERFACE_UART
esp_loader_error_t loader_flash_begin_cmd(uint32_t offset, uint32_t erase_size, uint32_t block_size, uint32_t blocks_to_write, bool encryption);
esp_loader_error_t loader_flash_data_cmd(const uint8_t *data, uint32_t size);
esp_loader_error_t loader_flash_end_cmd(bool stay_in_loader);
esp_loader_error_t loader_sync_cmd(void);
esp_loader_error_t loader_spi_attach_cmd(uint32_t config);
esp_loader_error_t loader_md5_cmd(uint32_t address, uint32_t size, uint8_t *md5_out);
esp_loader_error_t loader_spi_parameters(uint32_t total_size);
#endif /* SERIAL_FLASHER_INTERFACE_UART */
esp_loader_error_t loader_mem_begin_cmd(uint32_t offset, uint32_t size, uint32_t blocks_to_write, uint32_t block_size);
esp_loader_error_t loader_mem_data_cmd(const uint8_t *data, uint32_t size);
esp_loader_error_t loader_mem_end_cmd(uint32_t entrypoint);
esp_loader_error_t loader_mem_begin_cmd(uint32_t offset, uint32_t size, uint32_t blocks_to_write, uint32_t block_size);
esp_loader_error_t loader_mem_data_cmd(const uint8_t *data, uint32_t size);
esp_loader_error_t loader_mem_end_cmd(uint32_t entrypoint);
esp_loader_error_t loader_write_reg_cmd(uint32_t address, uint32_t value, uint32_t mask, uint32_t delay_us);
esp_loader_error_t loader_read_reg_cmd(uint32_t address, uint32_t *reg);
esp_loader_error_t loader_change_baudrate_cmd(uint32_t baudrate);
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,31 @@
/* 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 <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include "esp_loader.h"
#include "protocol.h"
void log_loader_internal_error(error_code_t error);
esp_loader_error_t send_cmd(const void *cmd_data, uint32_t size, uint32_t *reg_value);
esp_loader_error_t send_cmd_with_data(const void *cmd_data, size_t cmd_size,
const void *data, size_t data_size);
esp_loader_error_t send_cmd_md5(const void *cmd_data, size_t cmd_size, uint8_t md5_out[MD5_SIZE]);

View File

@@ -0,0 +1,24 @@
/* 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.
*/
#warning Please replace serial_io.h with esp_loader_io.h and change the function names \
to match the new API
/* Defines used to avoid breaking existing ports */
#define loader_port_change_baudrate loader_port_change_transmission_rate
#define loader_port_serial_write loader_port_write
#define loader_port_serial_read loader_port_read
#include "esp_loader_io.h"

View File

@@ -0,0 +1,28 @@
/* 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.h"
#include <stdint.h>
#include <stdlib.h>
esp_loader_error_t SLIP_receive_data(uint8_t *buff, size_t size);
esp_loader_error_t SLIP_receive_packet(uint8_t *buff, size_t size);
esp_loader_error_t SLIP_send(const uint8_t *data, size_t size);
esp_loader_error_t SLIP_send_delimiter(void);

View File

@@ -0,0 +1,181 @@
/* 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.
*/
#include "esp32_port.h"
#include "driver/uart.h"
#include "driver/gpio.h"
#include "esp_timer.h"
#include "esp_log.h"
#include "esp_idf_version.h"
#include <unistd.h>
#ifdef SERIAL_FLASHER_DEBUG_TRACE
static void transfer_debug_print(const uint8_t *data, uint16_t size, bool write)
{
static bool write_prev = false;
if (write_prev != write) {
write_prev = write;
printf("\n--- %s ---\n", write ? "WRITE" : "READ");
}
for (uint32_t i = 0; i < size; i++) {
printf("%02x ", data[i]);
}
}
#endif
static int64_t s_time_end;
static int32_t s_uart_port;
static int32_t s_reset_trigger_pin;
static int32_t s_gpio0_trigger_pin;
esp_loader_error_t loader_port_esp32_init(const loader_esp32_config_t *config)
{
s_uart_port = config->uart_port;
s_reset_trigger_pin = config->reset_trigger_pin;
s_gpio0_trigger_pin = config->gpio0_trigger_pin;
// Initialize UART
uart_config_t uart_config = {
.baud_rate = config->baud_rate,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)
.source_clk = UART_SCLK_DEFAULT,
#endif
};
int rx_buffer_size = config->rx_buffer_size ? config->rx_buffer_size : 400;
int tx_buffer_size = config->tx_buffer_size ? config->tx_buffer_size : 400;
QueueHandle_t *uart_queue = config->uart_queue ? config->uart_queue : NULL;
int queue_size = config->queue_size ? config->queue_size : 0;
if ( uart_param_config(s_uart_port, &uart_config) != ESP_OK ) {
return ESP_LOADER_ERROR_FAIL;
}
if ( uart_set_pin(s_uart_port, config->uart_tx_pin, config->uart_rx_pin, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE) != ESP_OK ) {
return ESP_LOADER_ERROR_FAIL;
}
if ( uart_driver_install(s_uart_port, rx_buffer_size, tx_buffer_size, queue_size, uart_queue, 0) != ESP_OK ) {
return ESP_LOADER_ERROR_FAIL;
}
// Initialize boot pin selection pins
gpio_reset_pin(s_reset_trigger_pin);
gpio_set_pull_mode(s_reset_trigger_pin, GPIO_PULLUP_ONLY);
gpio_set_direction(s_reset_trigger_pin, GPIO_MODE_OUTPUT);
gpio_reset_pin(s_gpio0_trigger_pin);
gpio_set_pull_mode(s_gpio0_trigger_pin, GPIO_PULLUP_ONLY);
gpio_set_direction(s_gpio0_trigger_pin, GPIO_MODE_OUTPUT);
return ESP_LOADER_SUCCESS;
}
void loader_port_esp32_deinit(void)
{
uart_driver_delete(s_uart_port);
}
esp_loader_error_t loader_port_write(const uint8_t *data, uint16_t size, uint32_t timeout)
{
uart_write_bytes(s_uart_port, (const char *)data, size);
esp_err_t err = uart_wait_tx_done(s_uart_port, pdMS_TO_TICKS(timeout));
if (err == ESP_OK) {
#ifdef SERIAL_FLASHER_DEBUG_TRACE
transfer_debug_print(data, size, true);
#endif
return ESP_LOADER_SUCCESS;
} else if (err == ESP_ERR_TIMEOUT) {
return ESP_LOADER_ERROR_TIMEOUT;
} else {
return ESP_LOADER_ERROR_FAIL;
}
}
esp_loader_error_t loader_port_read(uint8_t *data, uint16_t size, uint32_t timeout)
{
int read = uart_read_bytes(s_uart_port, data, size, pdMS_TO_TICKS(timeout));
if (read < 0) {
return ESP_LOADER_ERROR_FAIL;
} else if (read < size) {
#ifdef SERIAL_FLASHER_DEBUG_TRACE
transfer_debug_print(data, read, false);
#endif
return ESP_LOADER_ERROR_TIMEOUT;
} else {
#ifdef SERIAL_FLASHER_DEBUG_TRACE
transfer_debug_print(data, read, false);
#endif
return ESP_LOADER_SUCCESS;
}
}
// Set GPIO0 LOW, then
// assert reset pin for 50 milliseconds.
void loader_port_enter_bootloader(void)
{
gpio_set_level(s_gpio0_trigger_pin, 0);
loader_port_reset_target();
loader_port_delay_ms(SERIAL_FLASHER_BOOT_HOLD_TIME_MS);
gpio_set_level(s_gpio0_trigger_pin, 1);
}
void loader_port_reset_target(void)
{
gpio_set_level(s_reset_trigger_pin, 0);
loader_port_delay_ms(SERIAL_FLASHER_RESET_HOLD_TIME_MS);
gpio_set_level(s_reset_trigger_pin, 1);
}
void loader_port_delay_ms(uint32_t ms)
{
usleep(ms * 1000);
}
void loader_port_start_timer(uint32_t ms)
{
s_time_end = esp_timer_get_time() + ms * 1000;
}
uint32_t loader_port_remaining_time(void)
{
int64_t remaining = (s_time_end - esp_timer_get_time()) / 1000;
return (remaining > 0) ? (uint32_t)remaining : 0;
}
void loader_port_debug_print(const char *str)
{
printf("DEBUG: %s\n", str);
}
esp_loader_error_t loader_port_change_transmission_rate(uint32_t baudrate)
{
esp_err_t err = uart_set_baudrate(s_uart_port, baudrate);
return (err == ESP_OK) ? ESP_LOADER_SUCCESS : ESP_LOADER_ERROR_FAIL;
}

View File

@@ -0,0 +1,415 @@
/* 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.
*/
#include "protocol.h"
#include "esp_loader_io.h"
#include "esp_loader.h"
#include "esp_targets.h"
#include "md5_hash.h"
#include <string.h>
#include <assert.h>
#ifndef MAX
#define MAX(a, b) ((a) > (b)) ? (a) : (b)
#endif
#ifndef MIN
#define MIN(a, b) ((a) < (b)) ? (a) : (b)
#endif
#ifndef ROUNDUP
#define ROUNDUP(a, b) (((int)a + (int)b - 1) / (int)b)
#endif
static const uint32_t DEFAULT_TIMEOUT = 1000;
static const uint32_t DEFAULT_FLASH_TIMEOUT = 3000; // timeout for most flash operations
static const uint32_t LOAD_RAM_TIMEOUT_PER_MB = 2000000; // timeout (per megabyte) for erasing a region
typedef enum {
SPI_FLASH_READ_ID = 0x9F
} spi_flash_cmd_t;
static const target_registers_t *s_reg = NULL;
static target_chip_t s_target = ESP_UNKNOWN_CHIP;
#if MD5_ENABLED
static const uint32_t MD5_TIMEOUT_PER_MB = 800;
static struct MD5Context s_md5_context;
static uint32_t s_start_address;
static uint32_t s_image_size;
static inline void init_md5(uint32_t address, uint32_t size)
{
s_start_address = address;
s_image_size = size;
MD5Init(&s_md5_context);
}
static inline void md5_update(const uint8_t *data, uint32_t size)
{
MD5Update(&s_md5_context, data, size);
}
static inline void md5_final(uint8_t digets[16])
{
MD5Final(digets, &s_md5_context);
}
#else
static inline void init_md5(uint32_t address, uint32_t size) { }
static inline void md5_update(const uint8_t *data, uint32_t size) { }
static inline void md5_final(uint8_t digets[16]) { }
#endif
static uint32_t timeout_per_mb(uint32_t size_bytes, uint32_t time_per_mb)
{
uint32_t timeout = time_per_mb * (size_bytes / 1e6);
return MAX(timeout, DEFAULT_FLASH_TIMEOUT);
}
esp_loader_error_t esp_loader_connect(esp_loader_connect_args_t *connect_args)
{
loader_port_enter_bootloader();
RETURN_ON_ERROR(loader_initialize_conn(connect_args));
RETURN_ON_ERROR(loader_detect_chip(&s_target, &s_reg));
#ifdef SERIAL_FLASHER_INTERFACE_UART
esp_loader_error_t err;
uint32_t spi_config;
if (s_target == ESP8266_CHIP) {
err = loader_flash_begin_cmd(0, 0, 0, 0, s_target);
} else {
RETURN_ON_ERROR( loader_read_spi_config(s_target, &spi_config) );
loader_port_start_timer(DEFAULT_TIMEOUT);
err = loader_spi_attach_cmd(spi_config);
}
return err;
#endif /* SERIAL_FLASHER_INTERFACE_UART */
return ESP_LOADER_SUCCESS;
}
target_chip_t esp_loader_get_target(void)
{
return s_target;
}
#ifdef SERIAL_FLASHER_INTERFACE_UART
static uint32_t s_flash_write_size = 0;
static esp_loader_error_t spi_set_data_lengths(size_t mosi_bits, size_t miso_bits)
{
if (mosi_bits > 0) {
RETURN_ON_ERROR( esp_loader_write_register(s_reg->mosi_dlen, mosi_bits - 1) );
}
if (miso_bits > 0) {
RETURN_ON_ERROR( esp_loader_write_register(s_reg->miso_dlen, miso_bits - 1) );
}
return ESP_LOADER_SUCCESS;
}
static esp_loader_error_t spi_set_data_lengths_8266(size_t mosi_bits, size_t miso_bits)
{
uint32_t mosi_mask = (mosi_bits == 0) ? 0 : mosi_bits - 1;
uint32_t miso_mask = (miso_bits == 0) ? 0 : miso_bits - 1;
return esp_loader_write_register(s_reg->usr1, (miso_mask << 8) | (mosi_mask << 17));
}
static esp_loader_error_t spi_flash_command(spi_flash_cmd_t cmd, void *data_tx, size_t tx_size, void *data_rx, size_t rx_size)
{
assert(rx_size <= 32); // Reading more than 32 bits back from a SPI flash operation is unsupported
assert(tx_size <= 64); // Writing more than 64 bytes of data with one SPI command is unsupported
uint32_t SPI_USR_CMD = (1 << 31);
uint32_t SPI_USR_MISO = (1 << 28);
uint32_t SPI_USR_MOSI = (1 << 27);
uint32_t SPI_CMD_USR = (1 << 18);
uint32_t CMD_LEN_SHIFT = 28;
// Save SPI configuration
uint32_t old_spi_usr;
uint32_t old_spi_usr2;
RETURN_ON_ERROR( esp_loader_read_register(s_reg->usr, &old_spi_usr) );
RETURN_ON_ERROR( esp_loader_read_register(s_reg->usr2, &old_spi_usr2) );
if (s_target == ESP8266_CHIP) {
RETURN_ON_ERROR( spi_set_data_lengths_8266(tx_size, rx_size) );
} else {
RETURN_ON_ERROR( spi_set_data_lengths(tx_size, rx_size) );
}
uint32_t usr_reg_2 = (7 << CMD_LEN_SHIFT) | cmd;
uint32_t usr_reg = SPI_USR_CMD;
if (rx_size > 0) {
usr_reg |= SPI_USR_MISO;
}
if (tx_size > 0) {
usr_reg |= SPI_USR_MOSI;
}
RETURN_ON_ERROR( esp_loader_write_register(s_reg->usr, usr_reg) );
RETURN_ON_ERROR( esp_loader_write_register(s_reg->usr2, usr_reg_2 ) );
if (tx_size == 0) {
// clear data register before we read it
RETURN_ON_ERROR( esp_loader_write_register(s_reg->w0, 0) );
} else {
uint32_t *data = (uint32_t *)data_tx;
uint32_t words_to_write = (tx_size + 31) / (8 * 4);
uint32_t data_reg_addr = s_reg->w0;
while (words_to_write--) {
uint32_t word = *data++;
RETURN_ON_ERROR( esp_loader_write_register(data_reg_addr, word) );
data_reg_addr += 4;
}
}
RETURN_ON_ERROR( esp_loader_write_register(s_reg->cmd, SPI_CMD_USR) );
uint32_t trials = 10;
while (trials--) {
uint32_t cmd_reg;
RETURN_ON_ERROR( esp_loader_read_register(s_reg->cmd, &cmd_reg) );
if ((cmd_reg & SPI_CMD_USR) == 0) {
break;
}
}
if (trials == 0) {
return ESP_LOADER_ERROR_TIMEOUT;
}
RETURN_ON_ERROR( esp_loader_read_register(s_reg->w0, data_rx) );
// Restore SPI configuration
RETURN_ON_ERROR( esp_loader_write_register(s_reg->usr, old_spi_usr) );
RETURN_ON_ERROR( esp_loader_write_register(s_reg->usr2, old_spi_usr2) );
return ESP_LOADER_SUCCESS;
}
static esp_loader_error_t detect_flash_size(size_t *flash_size)
{
uint32_t flash_id = 0;
RETURN_ON_ERROR( spi_flash_command(SPI_FLASH_READ_ID, NULL, 0, &flash_id, 24) );
uint32_t size_id = flash_id >> 16;
if (size_id < 0x12 || size_id > 0x18) {
return ESP_LOADER_ERROR_UNSUPPORTED_CHIP;
}
*flash_size = 1 << size_id;
return ESP_LOADER_SUCCESS;
}
static uint32_t calc_erase_size(const target_chip_t target, const uint32_t offset,
const uint32_t image_size)
{
if (target != ESP8266_CHIP) {
return image_size;
} else {
/* Needed to fix a bug in the ESP8266 ROM */
const uint32_t sectors_per_block = 16U;
const uint32_t sector_size = 4096U;
const uint32_t num_sectors = (image_size + sector_size - 1) / sector_size;
const uint32_t start_sector = offset / sector_size;
uint32_t head_sectors = sectors_per_block - (start_sector % sectors_per_block);
/* The ROM bug deletes extra num_sectors if we don't cross the block boundary
and extra head_sectors if we do */
if (num_sectors <= head_sectors) {
return ((num_sectors + 1) / 2) * sector_size;
} else {
return (num_sectors - head_sectors) * sector_size;
}
}
}
esp_loader_error_t esp_loader_flash_start(uint32_t offset, uint32_t image_size, uint32_t block_size)
{
s_flash_write_size = block_size;
size_t flash_size = 0;
if (detect_flash_size(&flash_size) == ESP_LOADER_SUCCESS) {
if (image_size > flash_size) {
return ESP_LOADER_ERROR_IMAGE_SIZE;
}
loader_port_start_timer(DEFAULT_TIMEOUT);
RETURN_ON_ERROR( loader_spi_parameters(flash_size) );
} else {
loader_port_debug_print("Flash size detection failed, falling back to default");
}
init_md5(offset, image_size);
bool encryption_in_cmd = encryption_in_begin_flash_cmd(s_target);
const uint32_t erase_size = calc_erase_size(esp_loader_get_target(), offset, image_size);
const uint32_t blocks_to_write = (image_size + block_size - 1) / block_size;
const uint32_t erase_region_timeout_per_mb = 10000;
loader_port_start_timer(timeout_per_mb(erase_size, erase_region_timeout_per_mb));
return loader_flash_begin_cmd(offset, erase_size, block_size, blocks_to_write, encryption_in_cmd);
}
esp_loader_error_t esp_loader_flash_write(void *payload, uint32_t size)
{
uint32_t padding_bytes = s_flash_write_size - size;
uint8_t *data = (uint8_t *)payload;
uint32_t padding_index = size;
if (size > s_flash_write_size) {
return ESP_LOADER_ERROR_INVALID_PARAM;
}
const uint8_t padding_pattern = 0xFF;
while (padding_bytes--) {
data[padding_index++] = padding_pattern;
}
md5_update(payload, (size + 3) & ~3);
loader_port_start_timer(DEFAULT_TIMEOUT);
return loader_flash_data_cmd(data, s_flash_write_size);
}
esp_loader_error_t esp_loader_flash_finish(bool reboot)
{
loader_port_start_timer(DEFAULT_TIMEOUT);
return loader_flash_end_cmd(!reboot);
}
#endif /* SERIAL_FLASHER_INTERFACE_UART */
esp_loader_error_t esp_loader_mem_start(uint32_t offset, uint32_t size, uint32_t block_size)
{
uint32_t blocks_to_write = ROUNDUP(size, block_size);
loader_port_start_timer(timeout_per_mb(size, LOAD_RAM_TIMEOUT_PER_MB));
return loader_mem_begin_cmd(offset, size, blocks_to_write, block_size);
}
esp_loader_error_t esp_loader_mem_write(const void *payload, uint32_t size)
{
const uint8_t *data = (const uint8_t *)payload;
loader_port_start_timer(timeout_per_mb(size, LOAD_RAM_TIMEOUT_PER_MB));
return loader_mem_data_cmd(data, size);
}
esp_loader_error_t esp_loader_mem_finish(uint32_t entrypoint)
{
loader_port_start_timer(DEFAULT_TIMEOUT);
return loader_mem_end_cmd(entrypoint);
}
esp_loader_error_t esp_loader_read_register(uint32_t address, uint32_t *reg_value)
{
loader_port_start_timer(DEFAULT_TIMEOUT);
return loader_read_reg_cmd(address, reg_value);
}
esp_loader_error_t esp_loader_write_register(uint32_t address, uint32_t reg_value)
{
loader_port_start_timer(DEFAULT_TIMEOUT);
return loader_write_reg_cmd(address, reg_value, 0xFFFFFFFF, 0);
}
esp_loader_error_t esp_loader_change_transmission_rate(uint32_t transmission_rate)
{
if (s_target == ESP8266_CHIP) {
return ESP_LOADER_ERROR_UNSUPPORTED_FUNC;
}
loader_port_start_timer(DEFAULT_TIMEOUT);
return loader_change_baudrate_cmd(transmission_rate);
}
#if MD5_ENABLED
static void hexify(const uint8_t raw_md5[16], uint8_t hex_md5_out[32])
{
static const uint8_t dec_to_hex[] = {
'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
};
for (int i = 0; i < 16; i++) {
*hex_md5_out++ = dec_to_hex[raw_md5[i] >> 4];
*hex_md5_out++ = dec_to_hex[raw_md5[i] & 0xF];
}
}
esp_loader_error_t esp_loader_flash_verify(void)
{
if (s_target == ESP8266_CHIP) {
return ESP_LOADER_ERROR_UNSUPPORTED_FUNC;
}
uint8_t raw_md5[16] = {0};
/* Zero termination and new line character require 2 bytes */
uint8_t hex_md5[MD5_SIZE + 2] = {0};
uint8_t received_md5[MD5_SIZE + 2] = {0};
md5_final(raw_md5);
hexify(raw_md5, hex_md5);
loader_port_start_timer(timeout_per_mb(s_image_size, MD5_TIMEOUT_PER_MB));
RETURN_ON_ERROR( loader_md5_cmd(s_start_address, s_image_size, received_md5) );
bool md5_match = memcmp(hex_md5, received_md5, MD5_SIZE) == 0;
if (!md5_match) {
hex_md5[MD5_SIZE] = '\n';
received_md5[MD5_SIZE] = '\n';
loader_port_debug_print("Error: MD5 checksum does not match:\n");
loader_port_debug_print("Expected:\n");
loader_port_debug_print((char *)received_md5);
loader_port_debug_print("Actual:\n");
loader_port_debug_print((char *)hex_md5);
return ESP_LOADER_ERROR_INVALID_MD5;
}
return ESP_LOADER_SUCCESS;
}
#endif
void esp_loader_reset_target(void)
{
loader_port_reset_target();
}

View File

@@ -0,0 +1,296 @@
/* Copyright 2020 Espressif Systems (Shanghai) PTE 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.
*/
#include "esp_targets.h"
#include <stddef.h>
#define MAX_MAGIC_VALUES 2
typedef esp_loader_error_t (*read_spi_config_t)(uint32_t efuse_base, uint32_t *spi_config);
typedef struct {
target_registers_t regs;
uint32_t efuse_base;
uint32_t chip_magic_value[MAX_MAGIC_VALUES];
read_spi_config_t read_spi_config;
bool encryption_in_begin_flash_cmd;
} esp_target_t;
// This ROM address has a different value on each chip model
#define CHIP_DETECT_MAGIC_REG_ADDR 0x40001000
#define ESP8266_SPI_REG_BASE 0x60000200
#define ESP32S2_SPI_REG_BASE 0x3f402000
#define ESP32C6_SPI_REG_BASE 0x60003000
#define ESP32xx_SPI_REG_BASE 0x60002000
#define ESP32_SPI_REG_BASE 0x3ff42000
static esp_loader_error_t spi_config_esp32(uint32_t efuse_base, uint32_t *spi_config);
static esp_loader_error_t spi_config_esp32xx(uint32_t efuse_base, uint32_t *spi_config);
static const esp_target_t esp_target[ESP_MAX_CHIP] = {
// ESP8266
{
.regs = {
.cmd = ESP8266_SPI_REG_BASE + 0x00,
.usr = ESP8266_SPI_REG_BASE + 0x1c,
.usr1 = ESP8266_SPI_REG_BASE + 0x20,
.usr2 = ESP8266_SPI_REG_BASE + 0x24,
.w0 = ESP8266_SPI_REG_BASE + 0x40,
.mosi_dlen = 0,
.miso_dlen = 0,
},
.efuse_base = 0, // Not used
.chip_magic_value = { 0xfff0c101, 0 },
.read_spi_config = NULL, // Not used
.encryption_in_begin_flash_cmd = false,
},
// ESP32
{
.regs = {
.cmd = ESP32_SPI_REG_BASE + 0x00,
.usr = ESP32_SPI_REG_BASE + 0x1c,
.usr1 = ESP32_SPI_REG_BASE + 0x20,
.usr2 = ESP32_SPI_REG_BASE + 0x24,
.w0 = ESP32_SPI_REG_BASE + 0x80,
.mosi_dlen = ESP32_SPI_REG_BASE + 0x28,
.miso_dlen = ESP32_SPI_REG_BASE + 0x2c,
},
.efuse_base = 0x3ff5A000,
.chip_magic_value = { 0x00f01d83, 0 },
.read_spi_config = spi_config_esp32,
.encryption_in_begin_flash_cmd = false,
},
// ESP32S2
{
.regs = {
.cmd = ESP32S2_SPI_REG_BASE + 0x00,
.usr = ESP32S2_SPI_REG_BASE + 0x18,
.usr1 = ESP32S2_SPI_REG_BASE + 0x1c,
.usr2 = ESP32S2_SPI_REG_BASE + 0x20,
.w0 = ESP32S2_SPI_REG_BASE + 0x58,
.mosi_dlen = ESP32S2_SPI_REG_BASE + 0x24,
.miso_dlen = ESP32S2_SPI_REG_BASE + 0x28,
},
.efuse_base = 0x3f41A000,
.chip_magic_value = { 0x000007c6, 0 },
.read_spi_config = spi_config_esp32xx,
.encryption_in_begin_flash_cmd = true,
},
// ESP32C3
{
.regs = {
.cmd = ESP32xx_SPI_REG_BASE + 0x00,
.usr = ESP32xx_SPI_REG_BASE + 0x18,
.usr1 = ESP32xx_SPI_REG_BASE + 0x1c,
.usr2 = ESP32xx_SPI_REG_BASE + 0x20,
.w0 = ESP32xx_SPI_REG_BASE + 0x58,
.mosi_dlen = ESP32xx_SPI_REG_BASE + 0x24,
.miso_dlen = ESP32xx_SPI_REG_BASE + 0x28,
},
.efuse_base = 0x60008800,
.chip_magic_value = { 0x6921506f, 0x1b31506f },
.read_spi_config = spi_config_esp32xx,
.encryption_in_begin_flash_cmd = true,
},
// ESP32S3
{
.regs = {
.cmd = ESP32xx_SPI_REG_BASE + 0x00,
.usr = ESP32xx_SPI_REG_BASE + 0x18,
.usr1 = ESP32xx_SPI_REG_BASE + 0x1c,
.usr2 = ESP32xx_SPI_REG_BASE + 0x20,
.w0 = ESP32xx_SPI_REG_BASE + 0x58,
.mosi_dlen = ESP32xx_SPI_REG_BASE + 0x24,
.miso_dlen = ESP32xx_SPI_REG_BASE + 0x28,
},
.efuse_base = 0x60007000,
.chip_magic_value = { 0x00000009, 0 },
.read_spi_config = spi_config_esp32xx,
.encryption_in_begin_flash_cmd = true,
},
// ESP32C2
{
.regs = {
.cmd = ESP32xx_SPI_REG_BASE + 0x00,
.usr = ESP32xx_SPI_REG_BASE + 0x18,
.usr1 = ESP32xx_SPI_REG_BASE + 0x1c,
.usr2 = ESP32xx_SPI_REG_BASE + 0x20,
.w0 = ESP32xx_SPI_REG_BASE + 0x58,
.mosi_dlen = ESP32xx_SPI_REG_BASE + 0x24,
.miso_dlen = ESP32xx_SPI_REG_BASE + 0x28,
},
.efuse_base = 0x60008800,
.chip_magic_value = { 0x6f51306f, 0x7c41a06f },
.read_spi_config = spi_config_esp32xx,
.encryption_in_begin_flash_cmd = true,
},
// ESP32H4
{
.regs = {
.cmd = ESP32xx_SPI_REG_BASE + 0x00,
.usr = ESP32xx_SPI_REG_BASE + 0x18,
.usr1 = ESP32xx_SPI_REG_BASE + 0x1c,
.usr2 = ESP32xx_SPI_REG_BASE + 0x20,
.w0 = ESP32xx_SPI_REG_BASE + 0x58,
.mosi_dlen = ESP32xx_SPI_REG_BASE + 0x24,
.miso_dlen = ESP32xx_SPI_REG_BASE + 0x28,
},
.efuse_base = 0x6001A000,
.chip_magic_value = {0xca26cc22, 0x6881b06f}, // ESP32H4-BETA1, ESP32H4-BETA2
.read_spi_config = spi_config_esp32xx,
.encryption_in_begin_flash_cmd = true,
},
// ESP32H2
{
.regs = {
.cmd = ESP32xx_SPI_REG_BASE + 0x00,
.usr = ESP32xx_SPI_REG_BASE + 0x18,
.usr1 = ESP32xx_SPI_REG_BASE + 0x1c,
.usr2 = ESP32xx_SPI_REG_BASE + 0x20,
.w0 = ESP32xx_SPI_REG_BASE + 0x58,
.mosi_dlen = ESP32xx_SPI_REG_BASE + 0x24,
.miso_dlen = ESP32xx_SPI_REG_BASE + 0x28,
},
.efuse_base = 0x6001A000,
.chip_magic_value = {0xd7b73e80, 0},
.read_spi_config = spi_config_esp32xx,
.encryption_in_begin_flash_cmd = true,
},
// ESP32C6
{
.regs = {
.cmd = ESP32C6_SPI_REG_BASE + 0x00,
.usr = ESP32C6_SPI_REG_BASE + 0x18,
.usr1 = ESP32C6_SPI_REG_BASE + 0x1c,
.usr2 = ESP32C6_SPI_REG_BASE + 0x20,
.w0 = ESP32C6_SPI_REG_BASE + 0x58,
.mosi_dlen = ESP32C6_SPI_REG_BASE + 0x24,
.miso_dlen = ESP32C6_SPI_REG_BASE + 0x28,
},
.efuse_base = 0x600B0800,
.chip_magic_value = { 0x2CE0806F, 0 },
.read_spi_config = spi_config_esp32xx,
.encryption_in_begin_flash_cmd = true,
},
};
const target_registers_t *get_esp_target_data(target_chip_t chip)
{
return (const target_registers_t *)&esp_target[chip];
}
esp_loader_error_t loader_detect_chip(target_chip_t *target_chip, const target_registers_t **target_data)
{
uint32_t magic_value;
RETURN_ON_ERROR( esp_loader_read_register(CHIP_DETECT_MAGIC_REG_ADDR, &magic_value) );
for (int chip = 0; chip < ESP_MAX_CHIP; chip++) {
for(int index = 0; index < MAX_MAGIC_VALUES; index++) {
if (magic_value == esp_target[chip].chip_magic_value[index]) {
*target_chip = (target_chip_t)chip;
*target_data = (target_registers_t *)&esp_target[chip];
return ESP_LOADER_SUCCESS;
}
}
}
return ESP_LOADER_ERROR_INVALID_TARGET;
}
esp_loader_error_t loader_read_spi_config(target_chip_t target_chip, uint32_t *spi_config)
{
const esp_target_t *target = &esp_target[target_chip];
return target->read_spi_config(target->efuse_base, spi_config);
}
static inline uint32_t efuse_word_addr(uint32_t efuse_base, uint32_t n)
{
return efuse_base + (n * 4);
}
// 30->GPIO32 | 31->GPIO33
static inline uint8_t adjust_pin_number(uint8_t num)
{
return (num >= 30) ? num + 2 : num;
}
static esp_loader_error_t spi_config_esp32(uint32_t efuse_base, uint32_t *spi_config)
{
*spi_config = 0;
uint32_t reg5, reg3;
RETURN_ON_ERROR( esp_loader_read_register(efuse_word_addr(efuse_base, 5), &reg5) );
RETURN_ON_ERROR( esp_loader_read_register(efuse_word_addr(efuse_base, 3), &reg3) );
uint32_t pins = reg5 & 0xfffff;
if (pins == 0 || pins == 0xfffff) {
return ESP_LOADER_SUCCESS;
}
uint8_t clk = adjust_pin_number( (pins >> 0) & 0x1f );
uint8_t q = adjust_pin_number( (pins >> 5) & 0x1f );
uint8_t d = adjust_pin_number( (pins >> 10) & 0x1f );
uint8_t cs = adjust_pin_number( (pins >> 15) & 0x1f );
uint8_t hd = adjust_pin_number( (reg3 >> 4) & 0x1f );
if (clk == cs || clk == d || clk == q || q == cs || q == d || q == d) {
return ESP_LOADER_SUCCESS;
}
*spi_config = (hd << 24) | (cs << 18) | (d << 12) | (q << 6) | clk;
return ESP_LOADER_SUCCESS;
}
// Applies for esp32s2, esp32c3 and esp32c3
static esp_loader_error_t spi_config_esp32xx(uint32_t efuse_base, uint32_t *spi_config)
{
*spi_config = 0;
// *** FIXME
// There seems to be a bug here.
// For ESP32-C6, esptool reads registers 0x600b0844 and 0x600b0848 (0x11 and 0x12).
// This tools reads registers 0x600b0848 and 0x600b084C (0x12 and 0x13).
// This function is supposted to read non-default SPI pins.
// As mostly they will be connected like default, it's pretty save to just exit.
return ESP_LOADER_SUCCESS;
// *** end FIXME
uint32_t reg1, reg2;
RETURN_ON_ERROR( esp_loader_read_register(efuse_word_addr(efuse_base, 18), &reg1) );
RETURN_ON_ERROR( esp_loader_read_register(efuse_word_addr(efuse_base, 19), &reg2) );
uint32_t pins = ((reg1 >> 16) | ((reg2 & 0xfffff) << 16)) & 0x3fffffff;
if (pins == 0 || pins == 0xffffffff) {
return ESP_LOADER_SUCCESS;
}
*spi_config = pins;
return ESP_LOADER_SUCCESS;
}
bool encryption_in_begin_flash_cmd(const target_chip_t target)
{
return esp_target[target].encryption_in_begin_flash_cmd;
}

View File

@@ -0,0 +1,347 @@
/* 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.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include <sys/param.h>
#include "esp_loader_io.h"
#include "esp_loader.h"
#include "example_common.h"
#ifndef SINGLE_TARGET_SUPPORT
// For esp8266, esp32, esp32s2
#define BOOTLOADER_ADDRESS_V0 0x1000
// For esp32s3 and later chips
#define BOOTLOADER_ADDRESS_V1 0x0
#define PARTITION_ADDRESS 0x8000
#define APPLICATION_ADDRESS 0x10000
extern const uint8_t ESP32_bootloader_bin[];
extern const uint32_t ESP32_bootloader_bin_size;
extern const uint8_t ESP32_hello_world_bin[];
extern const uint32_t ESP32_hello_world_bin_size;
extern const uint8_t ESP32_partition_table_bin[];
extern const uint32_t ESP32_partition_table_bin_size;
extern const uint8_t ESP32_S2_bootloader_bin[];
extern const uint32_t ESP32_S2_bootloader_bin_size;
extern const uint8_t ESP32_S2_hello_world_bin[];
extern const uint32_t ESP32_S2_hello_world_bin_size;
extern const uint8_t ESP32_S2_partition_table_bin[];
extern const uint32_t ESP32_S2_partition_table_bin_size;
extern const uint8_t ESP8266_bootloader_bin[];
extern const uint32_t ESP8266_bootloader_bin_size;
extern const uint8_t ESP8266_hello_world_bin[];
extern const uint32_t ESP8266_hello_world_bin_size;
extern const uint8_t ESP8266_partition_table_bin[];
extern const uint32_t ESP8266_partition_table_bin_size;
extern const uint8_t ESP32_H4_bootloader_bin[];
extern const uint32_t ESP32_H4_bootloader_bin_size;
extern const uint8_t ESP32_H4_hello_world_bin[];
extern const uint32_t ESP32_H4_hello_world_bin_size;
extern const uint8_t ESP32_H4_partition_table_bin[];
extern const uint32_t ESP32_H4_partition_table_bin_size;
extern const uint8_t ESP32_H2_bootloader_bin[];
extern const uint32_t ESP32_H2_bootloader_bin_size;
extern const uint8_t ESP32_H2_hello_world_bin[];
extern const uint32_t ESP32_H2_hello_world_bin_size;
extern const uint8_t ESP32_H2_partition_table_bin[];
extern const uint32_t ESP32_H2_partition_table_bin_size;
extern const uint8_t ESP32_C6_bootloader_bin[];
extern const uint32_t ESP32_C6_bootloader_bin_size;
extern const uint8_t ESP32_C6_hello_world_bin[];
extern const uint32_t ESP32_C6_hello_world_bin_size;
extern const uint8_t ESP32_C6_partition_table_bin[];
extern const uint32_t ESP32_C6_partition_table_bin_size;
void get_example_binaries(target_chip_t target, example_binaries_t *bins)
{
if (target == ESP8266_CHIP) {
bins->boot.data = ESP8266_bootloader_bin;
bins->boot.size = ESP8266_bootloader_bin_size;
bins->boot.addr = BOOTLOADER_ADDRESS_V0;
bins->part.data = ESP8266_partition_table_bin;
bins->part.size = ESP8266_partition_table_bin_size;
bins->part.addr = PARTITION_ADDRESS;
bins->app.data = ESP8266_hello_world_bin;
bins->app.size = ESP8266_hello_world_bin_size;
bins->app.addr = APPLICATION_ADDRESS;
} else if (target == ESP32_CHIP) {
bins->boot.data = ESP32_bootloader_bin;
bins->boot.size = ESP32_bootloader_bin_size;
bins->boot.addr = BOOTLOADER_ADDRESS_V0;
bins->part.data = ESP32_partition_table_bin;
bins->part.size = ESP32_partition_table_bin_size;
bins->part.addr = PARTITION_ADDRESS;
bins->app.data = ESP32_hello_world_bin;
bins->app.size = ESP32_hello_world_bin_size;
bins->app.addr = APPLICATION_ADDRESS;
} else if (target == ESP32S2_CHIP) {
bins->boot.data = ESP32_S2_bootloader_bin;
bins->boot.size = ESP32_S2_bootloader_bin_size;
bins->boot.addr = BOOTLOADER_ADDRESS_V0;
bins->part.data = ESP32_S2_partition_table_bin;
bins->part.size = ESP32_S2_partition_table_bin_size;
bins->part.addr = PARTITION_ADDRESS;
bins->app.data = ESP32_S2_hello_world_bin;
bins->app.size = ESP32_S2_hello_world_bin_size;
bins->app.addr = APPLICATION_ADDRESS;
} else if (target == ESP32H4_CHIP){
bins->boot.data = ESP32_H4_bootloader_bin;
bins->boot.size = ESP32_H4_bootloader_bin_size;
bins->boot.addr = BOOTLOADER_ADDRESS_V1;
bins->part.data = ESP32_H4_partition_table_bin;
bins->part.size = ESP32_H4_partition_table_bin_size;
bins->part.addr = PARTITION_ADDRESS;
bins->app.data = ESP32_H4_hello_world_bin;
bins->app.size = ESP32_H4_hello_world_bin_size;
bins->app.addr = APPLICATION_ADDRESS;
} else if (target == ESP32H2_CHIP){
bins->boot.data = ESP32_H2_bootloader_bin;
bins->boot.size = ESP32_H2_bootloader_bin_size;
bins->boot.addr = BOOTLOADER_ADDRESS_V1;
bins->part.data = ESP32_H2_partition_table_bin;
bins->part.size = ESP32_H2_partition_table_bin_size;
bins->part.addr = PARTITION_ADDRESS;
bins->app.data = ESP32_H2_hello_world_bin;
bins->app.size = ESP32_H2_hello_world_bin_size;
bins->app.addr = APPLICATION_ADDRESS;
} else if (target == ESP32C6_CHIP){
bins->boot.data = ESP32_C6_bootloader_bin;
bins->boot.size = ESP32_C6_bootloader_bin_size;
bins->boot.addr = BOOTLOADER_ADDRESS_V1;
bins->part.data = ESP32_C6_partition_table_bin;
bins->part.size = ESP32_C6_partition_table_bin_size;
bins->part.addr = PARTITION_ADDRESS;
bins->app.data = ESP32_C6_hello_world_bin;
bins->app.size = ESP32_C6_hello_world_bin_size;
bins->app.addr = APPLICATION_ADDRESS;
} else {
abort();
}
}
extern const uint8_t ESP32_app_bin[];
extern const uint32_t ESP32_app_bin_size;
extern const uint8_t ESP32_C2_app_bin[];
extern const uint32_t ESP32_C2_app_bin_size;
extern const uint8_t ESP32_C3_app_bin[];
extern const uint32_t ESP32_C3_app_bin_size;
extern const uint8_t ESP32_H2_app_bin[];
extern const uint32_t ESP32_H2_app_bin_size;
extern const uint8_t ESP32_H4_app_bin[];
extern const uint32_t ESP32_H4_app_bin_size;
extern const uint8_t ESP32_S3_app_bin[];
extern const uint32_t ESP32_S3_app_bin_size;
extern const uint8_t ESP32_C6_app_bin[];
extern const uint32_t ESP32_C6_app_bin_size;
void get_example_ram_app_binary(target_chip_t target, example_ram_app_binary_t *bin)
{
switch (target) {
case ESP32_CHIP: {
bin->ram_app.data = ESP32_app_bin;
bin->ram_app.size = ESP32_app_bin_size;
break;
}
case ESP32C2_CHIP: {
bin->ram_app.data = ESP32_C2_app_bin;
bin->ram_app.size = ESP32_C2_app_bin_size;
break;
}
case ESP32C3_CHIP: {
bin->ram_app.data = ESP32_C3_app_bin;
bin->ram_app.size = ESP32_C3_app_bin_size;
break;
}
case ESP32H2_CHIP: {
bin->ram_app.data = ESP32_H2_app_bin;
bin->ram_app.size = ESP32_H2_app_bin_size;
break;
}
case ESP32H4_CHIP: {
bin->ram_app.data = ESP32_H4_app_bin;
bin->ram_app.size = ESP32_H4_app_bin_size;
break;
}
case ESP32S3_CHIP: {
bin->ram_app.data = ESP32_S3_app_bin;
bin->ram_app.size = ESP32_S3_app_bin_size;
break;
}
case ESP32C6_CHIP: {
bin->ram_app.data = ESP32_C6_app_bin;
bin->ram_app.size = ESP32_C6_app_bin_size;
break;
}
default: {
abort();
}
}
}
#endif
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");
#ifdef SERIAL_FLASHER_INTERFACE_UART
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 changed\n");
}
}
#endif /* SERIAL_FLASHER_INTERFACE_UART */
return ESP_LOADER_SUCCESS;
}
#ifdef SERIAL_FLASHER_INTERFACE_UART
esp_loader_error_t flash_binary(const uint8_t *bin, size_t size, size_t address)
{
esp_loader_error_t err;
static uint8_t payload[1024];
const uint8_t *bin_addr = bin;
printf("Erasing flash (this may take a while)...\n");
err = esp_loader_flash_start(address, size, sizeof(payload));
if (err != ESP_LOADER_SUCCESS) {
printf("Erasing flash failed with error %d.\n", err);
return err;
}
printf("Start programming\n");
size_t binary_size = size;
size_t written = 0;
while (size > 0) {
size_t to_read = MIN(size, sizeof(payload));
memcpy(payload, bin_addr, to_read);
err = esp_loader_flash_write(payload, to_read);
if (err != ESP_LOADER_SUCCESS) {
printf("\nPacket could not be written! Error %d.\n", err);
return err;
}
size -= to_read;
bin_addr += to_read;
written += to_read;
int progress = (int)(((float)written / binary_size) * 100);
printf("\rProgress: %d %%", progress);
fflush(stdout);
};
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) {
printf("MD5 does not match. err: %d\n", err);
return err;
}
printf("Flash verified\n");
#endif
return ESP_LOADER_SUCCESS;
}
#endif /* SERIAL_FLASHER_INTERFACE_UART */
esp_loader_error_t load_ram_binary(const uint8_t *bin)
{
printf("Start loading\n");
esp_loader_error_t err;
const esp_loader_bin_header_t *header = (const esp_loader_bin_header_t *)bin;
esp_loader_bin_segment_t segments[header->segments];
// Parse segments
uint32_t seg;
uint32_t *cur_seg_pos;
for (seg=0, cur_seg_pos = (uint32_t *)(&bin[BIN_FIRST_SEGMENT_OFFSET]);
seg < header->segments;
seg++) {
segments[seg].addr = *cur_seg_pos++;
segments[seg].size = *cur_seg_pos++;
segments[seg].data = (uint8_t *)cur_seg_pos;
cur_seg_pos += (segments[seg].size) / 4;
}
// Download segments
for (seg=0; seg < header->segments; seg++) {
printf("Downloading %"PRIu32" bytes at 0x%08"PRIx32"...\n", segments[seg].size, segments[seg].addr);
err = esp_loader_mem_start(segments[seg].addr, segments[seg].size, ESP_RAM_BLOCK);
if (err != ESP_LOADER_SUCCESS) {
printf("Loading ram start with error %d.\n", err);
return err;
}
size_t remain_size = segments[seg].size;
uint8_t *data_pos = segments[seg].data;
while(remain_size > 0) {
size_t data_size = MIN(ESP_RAM_BLOCK, remain_size);
err = esp_loader_mem_write(data_pos, data_size);
if (err != ESP_LOADER_SUCCESS) {
printf("\nPacket could not be written! Error %d.\n", err);
return err;
}
data_pos += data_size;
remain_size -= data_size;
}
}
err = esp_loader_mem_finish(header->entrypoint);
if (err != ESP_LOADER_SUCCESS) {
printf("\nLoad ram finish with Error %d.\n", err);
return err;
}
printf("\nFinished loading\n");
return ESP_LOADER_SUCCESS;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,262 @@
/*
* MD5 hash implementation and interface functions
* Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi>
*
* This software may be distributed under the terms of the BSD license.
* See README for more details.
*/
#include "md5_hash.h"
#include <stdlib.h>
#include <string.h>
static void MD5Transform(uint32_t buf[4], uint32_t const in[16]);
/* ===== start - public domain MD5 implementation ===== */
/*
* This code implements the MD5 message-digest algorithm.
* The algorithm is due to Ron Rivest. This code was
* written by Colin Plumb in 1993, no copyright is claimed.
* This code is in the public domain; do with it what you wish.
*
* Equivalent code is available from RSA Data Security, Inc.
* This code has been tested against that, and is equivalent,
* except that you don't need to include two pages of legalese
* with every copy.
*
* To compute the message digest of a chunk of bytes, declare an
* MD5Context structure, pass it to MD5Init, call MD5Update as
* needed on buffers full of bytes, and then call MD5Final, which
* will fill a supplied 16-byte array with the digest.
*/
#ifndef WORDS_BIGENDIAN
#define byteReverse(buf, len) /* Nothing */
#else
/*
* Note: this code is harmless on little-endian machines.
*/
static void byteReverse(unsigned char *buf, unsigned longs)
{
uint32_t t;
do {
t = (uint32_t) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
((unsigned) buf[1] << 8 | buf[0]);
*(uint32_t *) buf = t;
buf += 4;
} while (--longs);
}
#endif
/*
* Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
* initialization constants.
*/
void MD5Init(struct MD5Context *ctx)
{
ctx->buf[0] = 0x67452301;
ctx->buf[1] = 0xefcdab89;
ctx->buf[2] = 0x98badcfe;
ctx->buf[3] = 0x10325476;
ctx->bits[0] = 0;
ctx->bits[1] = 0;
}
/*
* Update context to reflect the concatenation of another buffer full
* of bytes.
*/
void MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len)
{
uint32_t t;
/* Update bitcount */
t = ctx->bits[0];
if ((ctx->bits[0] = t + ((uint32_t) len << 3)) < t) {
ctx->bits[1]++; /* Carry from low to high */
}
ctx->bits[1] += len >> 29;
t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
/* Handle any leading odd-sized chunks */
if (t) {
unsigned char *p = (unsigned char *) ctx->in + t;
t = 64 - t;
if (len < t) {
memcpy(p, buf, len);
return;
}
memcpy(p, buf, t);
byteReverse(ctx->in, 16);
MD5Transform((uint32_t *)ctx->buf, (uint32_t *) ctx->in);
buf += t;
len -= t;
}
/* Process data in 64-byte chunks */
while (len >= 64) {
memcpy(ctx->in, buf, 64);
byteReverse(ctx->in, 16);
MD5Transform((uint32_t *)ctx->buf, (uint32_t *) ctx->in);
buf += 64;
len -= 64;
}
/* Handle any remaining bytes of data. */
memcpy(ctx->in, buf, len);
}
/*
* Final wrapup - pad to 64-byte boundary with the bit pattern
* 1 0* (64-bit count of bits processed, MSB-first)
*/
void MD5Final(unsigned char digest[16], struct MD5Context *ctx)
{
unsigned count;
unsigned char *p;
/* Compute number of bytes mod 64 */
count = (ctx->bits[0] >> 3) & 0x3F;
/* Set the first char of padding to 0x80. This is safe since there is
always at least one byte free */
p = ctx->in + count;
*p++ = 0x80;
/* Bytes of padding needed to make 64 bytes */
count = 64 - 1 - count;
/* Pad out to 56 mod 64 */
if (count < 8) {
/* Two lots of padding: Pad the first block to 64 bytes */
memset(p, 0, count);
byteReverse(ctx->in, 16);
MD5Transform((uint32_t *)ctx->buf, (uint32_t *) ctx->in);
/* Now fill the next block with 56 bytes */
memset(ctx->in, 0, 56);
} else {
/* Pad block to 56 bytes */
memset(p, 0, count - 8);
}
byteReverse(ctx->in, 14);
/* Append length in bits and transform */
((uint32_t *) ctx->in)[14] = ctx->bits[0];
((uint32_t *) ctx->in)[15] = ctx->bits[1];
MD5Transform((uint32_t *)ctx->buf, (uint32_t *) ctx->in);
byteReverse((unsigned char *) ctx->buf, 4);
memcpy(digest, ctx->buf, 16);
memset(ctx, 0, sizeof(struct MD5Context)); /* In case it's sensitive */
}
/* The four core functions - F1 is optimized somewhat */
/* #define F1(x, y, z) (x & y | ~x & z) */
#define F1(x, y, z) (z ^ (x & (y ^ z)))
#define F2(x, y, z) F1(z, x, y)
#define F3(x, y, z) (x ^ y ^ z)
#define F4(x, y, z) (y ^ (x | ~z))
/* This is the central step in the MD5 algorithm. */
#define MD5STEP(f, w, x, y, z, data, s) \
( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
/*
* The core of the MD5 algorithm, this alters an existing MD5 hash to
* reflect the addition of 16 longwords of new data. MD5Update blocks
* the data and converts bytes into longwords for this routine.
*/
static void MD5Transform(uint32_t buf[4], uint32_t const in[16])
{
register uint32_t a, b, c, d;
a = buf[0];
b = buf[1];
c = buf[2];
d = buf[3];
MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
buf[0] += a;
buf[1] += b;
buf[2] += c;
buf[3] += d;
}
/* ===== end - public domain MD5 implementation ===== */

View File

@@ -0,0 +1,301 @@
/* 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.
*/
#include "protocol.h"
#include "protocol_prv.h"
#include "esp_loader_io.h"
#include <stddef.h>
#include <string.h>
#define CMD_SIZE(cmd) ( sizeof(cmd) - sizeof(command_common_t) )
static uint32_t s_sequence_number = 0;
static uint8_t compute_checksum(const uint8_t *data, uint32_t size)
{
uint8_t checksum = 0xEF;
while (size--) {
checksum ^= *data++;
}
return checksum;
}
void log_loader_internal_error(error_code_t error)
{
loader_port_debug_print("Error: ");
switch (error) {
case INVALID_CRC: loader_port_debug_print("INVALID_CRC"); break;
case INVALID_COMMAND: loader_port_debug_print("INVALID_COMMAND"); break;
case COMMAND_FAILED: loader_port_debug_print("COMMAND_FAILED"); break;
case FLASH_WRITE_ERR: loader_port_debug_print("FLASH_WRITE_ERR"); break;
case FLASH_READ_ERR: loader_port_debug_print("FLASH_READ_ERR"); break;
case READ_LENGTH_ERR: loader_port_debug_print("READ_LENGTH_ERR"); break;
case DEFLATE_ERROR: loader_port_debug_print("DEFLATE_ERROR"); break;
default: loader_port_debug_print("UNKNOWN ERROR"); break;
}
loader_port_debug_print("\n");
}
esp_loader_error_t loader_flash_begin_cmd(uint32_t offset,
uint32_t erase_size,
uint32_t block_size,
uint32_t blocks_to_write,
bool encryption)
{
flash_begin_command_t flash_begin_cmd = {
.common = {
.direction = WRITE_DIRECTION,
.command = FLASH_BEGIN,
.size = CMD_SIZE(flash_begin_cmd) - (encryption ? 0 : sizeof(uint32_t)),
.checksum = 0
},
.erase_size = erase_size,
.packet_count = blocks_to_write,
.packet_size = block_size,
.offset = offset,
.encrypted = 0
};
s_sequence_number = 0;
return send_cmd(&flash_begin_cmd,
sizeof(flash_begin_cmd) - (encryption ? 0 : sizeof(uint32_t)),
NULL);
}
esp_loader_error_t loader_flash_data_cmd(const uint8_t *data, uint32_t size)
{
data_command_t data_cmd = {
.common = {
.direction = WRITE_DIRECTION,
.command = FLASH_DATA,
.size = CMD_SIZE(data_cmd) + size,
.checksum = compute_checksum(data, size)
},
.data_size = size,
.sequence_number = s_sequence_number++,
};
return send_cmd_with_data(&data_cmd, sizeof(data_cmd), data, size);
}
esp_loader_error_t loader_flash_end_cmd(bool stay_in_loader)
{
flash_end_command_t end_cmd = {
.common = {
.direction = WRITE_DIRECTION,
.command = FLASH_END,
.size = CMD_SIZE(end_cmd),
.checksum = 0
},
.stay_in_loader = stay_in_loader
};
return send_cmd(&end_cmd, sizeof(end_cmd), NULL);
}
esp_loader_error_t loader_mem_begin_cmd(uint32_t offset, uint32_t size, uint32_t blocks_to_write, uint32_t block_size)
{
mem_begin_command_t mem_begin_cmd = {
.common = {
.direction = WRITE_DIRECTION,
.command = MEM_BEGIN,
.size = CMD_SIZE(mem_begin_cmd),
.checksum = 0
},
.total_size = size,
.blocks = blocks_to_write,
.block_size = block_size,
.offset = offset
};
s_sequence_number = 0;
return send_cmd(&mem_begin_cmd, sizeof(mem_begin_cmd), NULL);
}
esp_loader_error_t loader_mem_data_cmd(const uint8_t *data, uint32_t size)
{
data_command_t data_cmd = {
.common = {
.direction = WRITE_DIRECTION,
.command = MEM_DATA,
.size = CMD_SIZE(data_cmd) + size,
.checksum = compute_checksum(data, size)
},
.data_size = size,
.sequence_number = s_sequence_number++,
};
return send_cmd_with_data(&data_cmd, sizeof(data_cmd), data, size);
}
esp_loader_error_t loader_mem_end_cmd(uint32_t entrypoint)
{
mem_end_command_t end_cmd = {
.common = {
.direction = WRITE_DIRECTION,
.command = MEM_END,
.size = CMD_SIZE(end_cmd),
},
.stay_in_loader = (entrypoint == 0),
.entry_point_address = entrypoint
};
return send_cmd(&end_cmd, sizeof(end_cmd), NULL);
}
esp_loader_error_t loader_sync_cmd(void)
{
sync_command_t sync_cmd = {
.common = {
.direction = WRITE_DIRECTION,
.command = SYNC,
.size = CMD_SIZE(sync_cmd),
.checksum = 0
},
.sync_sequence = {
0x07, 0x07, 0x12, 0x20,
0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
}
};
return send_cmd(&sync_cmd, sizeof(sync_cmd), NULL);
}
esp_loader_error_t loader_write_reg_cmd(uint32_t address, uint32_t value,
uint32_t mask, uint32_t delay_us)
{
write_reg_command_t write_cmd = {
.common = {
.direction = WRITE_DIRECTION,
.command = WRITE_REG,
.size = CMD_SIZE(write_cmd),
.checksum = 0
},
.address = address,
.value = value,
.mask = mask,
.delay_us = delay_us
};
return send_cmd(&write_cmd, sizeof(write_cmd), NULL);
}
esp_loader_error_t loader_read_reg_cmd(uint32_t address, uint32_t *reg)
{
read_reg_command_t read_cmd = {
.common = {
.direction = WRITE_DIRECTION,
.command = READ_REG,
.size = CMD_SIZE(read_cmd),
.checksum = 0
},
.address = address,
};
return send_cmd(&read_cmd, sizeof(read_cmd), reg);
}
esp_loader_error_t loader_spi_attach_cmd(uint32_t config)
{
spi_attach_command_t attach_cmd = {
.common = {
.direction = WRITE_DIRECTION,
.command = SPI_ATTACH,
.size = CMD_SIZE(attach_cmd),
.checksum = 0
},
.configuration = config,
.zero = 0
};
return send_cmd(&attach_cmd, sizeof(attach_cmd), NULL);
}
esp_loader_error_t loader_change_baudrate_cmd(uint32_t baudrate)
{
change_baudrate_command_t baudrate_cmd = {
.common = {
.direction = WRITE_DIRECTION,
.command = CHANGE_BAUDRATE,
.size = CMD_SIZE(baudrate_cmd),
.checksum = 0
},
.new_baudrate = baudrate,
.old_baudrate = 0 // ESP32 ROM only
};
return send_cmd(&baudrate_cmd, sizeof(baudrate_cmd), NULL);
}
esp_loader_error_t loader_md5_cmd(uint32_t address, uint32_t size, uint8_t *md5_out)
{
spi_flash_md5_command_t md5_cmd = {
.common = {
.direction = WRITE_DIRECTION,
.command = SPI_FLASH_MD5,
.size = CMD_SIZE(md5_cmd),
.checksum = 0
},
.address = address,
.size = size,
.reserved_0 = 0,
.reserved_1 = 0
};
return send_cmd_md5(&md5_cmd, sizeof(md5_cmd), md5_out);
}
esp_loader_error_t loader_spi_parameters(uint32_t total_size)
{
write_spi_command_t spi_cmd = {
.common = {
.direction = WRITE_DIRECTION,
.command = SPI_SET_PARAMS,
.size = 24,
.checksum = 0
},
.id = 0,
.total_size = total_size,
.block_size = 64 * 1024,
.sector_size = 4 * 1024,
.page_size = 0x100,
.status_mask = 0xFFFF,
};
return send_cmd(&spi_cmd, sizeof(spi_cmd), NULL);
}
__attribute__ ((weak)) void loader_port_debug_print(const char *str)
{
}

View File

@@ -0,0 +1,114 @@
/* 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.
*/
#include "protocol.h"
#include "protocol_prv.h"
#include "esp_loader_io.h"
#include "slip.h"
#include <stddef.h>
#include <string.h>
static esp_loader_error_t check_response(command_t cmd, uint32_t *reg_value, void* resp, uint32_t resp_size);
esp_loader_error_t loader_initialize_conn(esp_loader_connect_args_t *connect_args) {
esp_loader_error_t err;
int32_t trials = connect_args->trials;
do {
loader_port_start_timer(connect_args->sync_timeout);
err = loader_sync_cmd();
if (err == ESP_LOADER_ERROR_TIMEOUT) {
if (--trials == 0) {
return ESP_LOADER_ERROR_TIMEOUT;
}
loader_port_delay_ms(100);
} else if (err != ESP_LOADER_SUCCESS) {
return err;
}
} while (err != ESP_LOADER_SUCCESS);
return err;
}
esp_loader_error_t send_cmd(const void *cmd_data, uint32_t size, uint32_t *reg_value)
{
response_t response;
command_t command = ((const command_common_t *)cmd_data)->command;
RETURN_ON_ERROR( SLIP_send_delimiter() );
RETURN_ON_ERROR( SLIP_send((const uint8_t *)cmd_data, size) );
RETURN_ON_ERROR( SLIP_send_delimiter() );
return check_response(command, reg_value, &response, sizeof(response));
}
esp_loader_error_t send_cmd_with_data(const void *cmd_data, size_t cmd_size,
const void *data, size_t data_size)
{
response_t response;
command_t command = ((const command_common_t *)cmd_data)->command;
RETURN_ON_ERROR( SLIP_send_delimiter() );
RETURN_ON_ERROR( SLIP_send((const uint8_t *)cmd_data, cmd_size) );
RETURN_ON_ERROR( SLIP_send(data, data_size) );
RETURN_ON_ERROR( SLIP_send_delimiter() );
return check_response(command, NULL, &response, sizeof(response));
}
esp_loader_error_t send_cmd_md5(const void *cmd_data, size_t cmd_size, uint8_t md5_out[MD5_SIZE])
{
rom_md5_response_t response;
command_t command = ((const command_common_t *)cmd_data)->command;
RETURN_ON_ERROR( SLIP_send_delimiter() );
RETURN_ON_ERROR( SLIP_send((const uint8_t *)cmd_data, cmd_size) );
RETURN_ON_ERROR( SLIP_send_delimiter() );
RETURN_ON_ERROR( check_response(command, NULL, &response, sizeof(response)) );
memcpy(md5_out, response.md5, MD5_SIZE);
return ESP_LOADER_SUCCESS;
}
static esp_loader_error_t check_response(command_t cmd, uint32_t *reg_value, void* resp, uint32_t resp_size)
{
esp_loader_error_t err;
common_response_t *response = (common_response_t *)resp;
do {
err = SLIP_receive_packet(resp, resp_size);
if (err != ESP_LOADER_SUCCESS) {
return err;
}
} while ((response->direction != READ_DIRECTION) || (response->command != cmd));
response_status_t *status = (response_status_t *)((uint8_t *)resp + resp_size - sizeof(response_status_t));
if (status->failed) {
log_loader_internal_error(status->error);
return ESP_LOADER_ERROR_INVALID_RESPONSE;
}
if (reg_value != NULL) {
*reg_value = response->value;
}
return ESP_LOADER_SUCCESS;
}

View File

@@ -0,0 +1,125 @@
/* 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.
*/
#include "slip.h"
#include "esp_loader_io.h"
static const uint8_t DELIMITER = 0xC0;
static const uint8_t C0_REPLACEMENT[2] = {0xDB, 0xDC};
static const uint8_t DB_REPLACEMENT[2] = {0xDB, 0xDD};
static inline esp_loader_error_t peripheral_read(uint8_t *buff, const size_t size)
{
return loader_port_read(buff, size, loader_port_remaining_time());
}
static inline esp_loader_error_t peripheral_write(const uint8_t *buff, const size_t size)
{
return loader_port_write(buff, size, loader_port_remaining_time());
}
esp_loader_error_t SLIP_receive_data(uint8_t *buff, const size_t size)
{
uint8_t ch;
for (uint32_t i = 0; i < size; i++) {
RETURN_ON_ERROR( peripheral_read(&ch, 1) );
if (ch == 0xDB) {
RETURN_ON_ERROR( peripheral_read(&ch, 1) );
if (ch == 0xDC) {
buff[i] = 0xC0;
} else if (ch == 0xDD) {
buff[i] = 0xDB;
} else {
return ESP_LOADER_ERROR_INVALID_RESPONSE;
}
} else {
buff[i] = ch;
}
}
return ESP_LOADER_SUCCESS;
}
esp_loader_error_t SLIP_receive_packet(uint8_t *buff, const size_t size)
{
uint8_t ch;
// Wait for delimiter
do {
RETURN_ON_ERROR( peripheral_read(&ch, 1) );
} while (ch != DELIMITER);
// Workaround: bootloader sends two dummy(0xC0) bytes after response when baud rate is changed.
do {
RETURN_ON_ERROR( peripheral_read(&ch, 1) );
} while (ch == DELIMITER);
buff[0] = ch;
RETURN_ON_ERROR( SLIP_receive_data(&buff[1], size - 1) );
// Wait for delimiter
do {
RETURN_ON_ERROR( peripheral_read(&ch, 1) );
} while (ch != DELIMITER);
return ESP_LOADER_SUCCESS;
}
esp_loader_error_t SLIP_send(const uint8_t *data, const size_t size)
{
uint32_t to_write = 0; // Bytes ready to write as they are
uint32_t written = 0; // Bytes already written
for (uint32_t i = 0; i < size; i++) {
if (data[i] != 0xC0 && data[i] != 0xDB) {
to_write++; // Queue this byte for writing
continue;
}
// We have a byte that needs encoding, write the queue first
if (to_write > 0) {
RETURN_ON_ERROR( peripheral_write(&data[written], to_write) );
}
// Write the encoded byte
if (data[i] == 0xC0) {
RETURN_ON_ERROR( peripheral_write(C0_REPLACEMENT, 2) );
} else {
RETURN_ON_ERROR( peripheral_write(DB_REPLACEMENT, 2) );
}
// Update to start again after the encoded byte
written = i + 1;
to_write = 0;
}
// Write the rest of the bytes that didn't need encoding
if (to_write > 0) {
RETURN_ON_ERROR( peripheral_write(&data[written], to_write) );
}
return ESP_LOADER_SUCCESS;
}
esp_loader_error_t SLIP_send_delimiter(void)
{
return peripheral_write(&DELIMITER, 1);
}

View File

@@ -0,0 +1,20 @@
cmake_minimum_required(VERSION 3.13)
set(CMAKE_TOOLCHAIN_FILE ${CMAKE_CURRENT_LIST_DIR}/stm32-cmake/cmake/gcc_stm32.cmake)
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/stm32-cmake/cmake)
find_package(CMSIS REQUIRED)
find_package(STM32HAL COMPONENTS gpio tim uart REQUIRED)
add_library(stm_cube_impl ${CMSIS_SOURCES} ${STM32HAL_SOURCES})
target_include_directories(stm_cube_impl PUBLIC ${CMSIS_INCLUDE_DIRS} ${STM32HAL_INCLUDE_DIR})
stm32_set_target_properties(stm_cube_impl)
# stm_cube target is made to propagate properties of stm_cube_impl, as stm32_set_target_properties
# sets properties privately for given target. This eliminates need to call stm32_set_target_properties
# on every target that links against STM32HAL.
add_library(stm_cube INTERFACE)
target_link_libraries(stm_cube INTERFACE stm_cube_impl)
target_compile_definitions(stm_cube INTERFACE $<TARGET_PROPERTY:stm_cube_impl,COMPILE_DEFINITIONS>)
target_link_options(stm_cube INTERFACE -T${CMAKE_CURRENT_BINARY_DIR}/stm_cube_impl_flash.ld)

View File

@@ -0,0 +1,29 @@
cmake_minimum_required(VERSION 3.5)
project(serial_flasher_test)
add_executable( ${PROJECT_NAME}
test_main.cpp
../src/esp_loader.c
../src/esp_targets.c
../src/md5_hash.c
../src/protocol_common.c
../src/protocol_uart.c
../src/slip.c)
target_include_directories(${PROJECT_NAME} PRIVATE ../include ../private_include ../test ../port)
target_compile_options(${PROJECT_NAME} PRIVATE -Wall -Werror -O3)
set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 14)
if( QEMU_TEST )
target_sources(${PROJECT_NAME} PRIVATE serial_io_tcp.cpp qemu_test.cpp)
else()
target_sources(${PROJECT_NAME} PRIVATE serial_io_mock.cpp test.cpp)
endif()
target_compile_definitions(${PROJECT_NAME} PRIVATE
MD5_ENABLED=1
SERIAL_FLASHER_INTERFACE_UART
SERIAL_FLASHER_DEBUG_TRACE
)

Some files were not shown because too many files have changed in this diff Show More