├── .cproject
├── .gitignore
├── .project
├── .settings
└── language.settings.xml
├── LICENSE
├── Makefile
├── README.md
├── components
├── bootloader
│ ├── Kconfig.projbuild
│ ├── Makefile.projbuild
│ ├── component.mk
│ └── subproject
│ │ ├── .gitignore
│ │ ├── Makefile
│ │ └── main
│ │ ├── Makefile.projbuild
│ │ ├── bootloader_config.h
│ │ ├── bootloader_start.c
│ │ ├── component.mk
│ │ ├── esp32.bootloader.ld
│ │ ├── esp32.bootloader.rom.ld
│ │ ├── flash_qio_mode.c
│ │ └── flash_qio_mode.h
└── cpp_utils
├── main
├── OTAServer.cpp
├── component.mk
├── main.cpp
└── ota_main.cpp
├── ota_app1.aia
├── partitions.csv
└── sdkconfig
/.cproject:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
28 |
29 |
30 |
31 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | build/
2 | sdkconfig.old
3 |
--------------------------------------------------------------------------------
/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | ota_test1
4 |
5 |
6 |
7 |
8 |
9 | org.eclipse.cdt.managedbuilder.core.genmakebuilder
10 | clean,full,incremental,
11 |
12 |
13 |
14 |
15 | org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder
16 | full,incremental,
17 |
18 |
19 |
20 |
21 |
22 | org.eclipse.cdt.core.cnature
23 | org.eclipse.cdt.core.ccnature
24 | org.eclipse.cdt.managedbuilder.core.managedBuildNature
25 | org.eclipse.cdt.managedbuilder.core.ScannerConfigNature
26 |
27 |
28 |
--------------------------------------------------------------------------------
/.settings/language.settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 |
2 | Apache License
3 | Version 2.0, January 2004
4 | http://www.apache.org/licenses/
5 |
6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7 |
8 | 1. Definitions.
9 |
10 | "License" shall mean the terms and conditions for use, reproduction,
11 | and distribution as defined by Sections 1 through 9 of this document.
12 |
13 | "Licensor" shall mean the copyright owner or entity authorized by
14 | the copyright owner that is granting the License.
15 |
16 | "Legal Entity" shall mean the union of the acting entity and all
17 | other entities that control, are controlled by, or are under common
18 | control with that entity. For the purposes of this definition,
19 | "control" means (i) the power, direct or indirect, to cause the
20 | direction or management of such entity, whether by contract or
21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
22 | outstanding shares, or (iii) beneficial ownership of such entity.
23 |
24 | "You" (or "Your") shall mean an individual or Legal Entity
25 | exercising permissions granted by this License.
26 |
27 | "Source" form shall mean the preferred form for making modifications,
28 | including but not limited to software source code, documentation
29 | source, and configuration files.
30 |
31 | "Object" form shall mean any form resulting from mechanical
32 | transformation or translation of a Source form, including but
33 | not limited to compiled object code, generated documentation,
34 | and conversions to other media types.
35 |
36 | "Work" shall mean the work of authorship, whether in Source or
37 | Object form, made available under the License, as indicated by a
38 | copyright notice that is included in or attached to the work
39 | (an example is provided in the Appendix below).
40 |
41 | "Derivative Works" shall mean any work, whether in Source or Object
42 | form, that is based on (or derived from) the Work and for which the
43 | editorial revisions, annotations, elaborations, or other modifications
44 | represent, as a whole, an original work of authorship. For the purposes
45 | of this License, Derivative Works shall not include works that remain
46 | separable from, or merely link (or bind by name) to the interfaces of,
47 | the Work and Derivative Works thereof.
48 |
49 | "Contribution" shall mean any work of authorship, including
50 | the original version of the Work and any modifications or additions
51 | to that Work or Derivative Works thereof, that is intentionally
52 | submitted to Licensor for inclusion in the Work by the copyright owner
53 | or by an individual or Legal Entity authorized to submit on behalf of
54 | the copyright owner. For the purposes of this definition, "submitted"
55 | means any form of electronic, verbal, or written communication sent
56 | to the Licensor or its representatives, including but not limited to
57 | communication on electronic mailing lists, source code control systems,
58 | and issue tracking systems that are managed by, or on behalf of, the
59 | Licensor for the purpose of discussing and improving the Work, but
60 | excluding communication that is conspicuously marked or otherwise
61 | designated in writing by the copyright owner as "Not a Contribution."
62 |
63 | "Contributor" shall mean Licensor and any individual or Legal Entity
64 | on behalf of whom a Contribution has been received by Licensor and
65 | subsequently incorporated within the Work.
66 |
67 | 2. Grant of Copyright License. Subject to the terms and conditions of
68 | this License, each Contributor hereby grants to You a perpetual,
69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70 | copyright license to reproduce, prepare Derivative Works of,
71 | publicly display, publicly perform, sublicense, and distribute the
72 | Work and such Derivative Works in Source or Object form.
73 |
74 | 3. Grant of Patent License. Subject to the terms and conditions of
75 | this License, each Contributor hereby grants to You a perpetual,
76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77 | (except as stated in this section) patent license to make, have made,
78 | use, offer to sell, sell, import, and otherwise transfer the Work,
79 | where such license applies only to those patent claims licensable
80 | by such Contributor that are necessarily infringed by their
81 | Contribution(s) alone or by combination of their Contribution(s)
82 | with the Work to which such Contribution(s) was submitted. If You
83 | institute patent litigation against any entity (including a
84 | cross-claim or counterclaim in a lawsuit) alleging that the Work
85 | or a Contribution incorporated within the Work constitutes direct
86 | or contributory patent infringement, then any patent licenses
87 | granted to You under this License for that Work shall terminate
88 | as of the date such litigation is filed.
89 |
90 | 4. Redistribution. You may reproduce and distribute copies of the
91 | Work or Derivative Works thereof in any medium, with or without
92 | modifications, and in Source or Object form, provided that You
93 | meet the following conditions:
94 |
95 | (a) You must give any other recipients of the Work or
96 | Derivative Works a copy of this License; and
97 |
98 | (b) You must cause any modified files to carry prominent notices
99 | stating that You changed the files; and
100 |
101 | (c) You must retain, in the Source form of any Derivative Works
102 | that You distribute, all copyright, patent, trademark, and
103 | attribution notices from the Source form of the Work,
104 | excluding those notices that do not pertain to any part of
105 | the Derivative Works; and
106 |
107 | (d) If the Work includes a "NOTICE" text file as part of its
108 | distribution, then any Derivative Works that You distribute must
109 | include a readable copy of the attribution notices contained
110 | within such NOTICE file, excluding those notices that do not
111 | pertain to any part of the Derivative Works, in at least one
112 | of the following places: within a NOTICE text file distributed
113 | as part of the Derivative Works; within the Source form or
114 | documentation, if provided along with the Derivative Works; or,
115 | within a display generated by the Derivative Works, if and
116 | wherever such third-party notices normally appear. The contents
117 | of the NOTICE file are for informational purposes only and
118 | do not modify the License. You may add Your own attribution
119 | notices within Derivative Works that You distribute, alongside
120 | or as an addendum to the NOTICE text from the Work, provided
121 | that such additional attribution notices cannot be construed
122 | as modifying the License.
123 |
124 | You may add Your own copyright statement to Your modifications and
125 | may provide additional or different license terms and conditions
126 | for use, reproduction, or distribution of Your modifications, or
127 | for any such Derivative Works as a whole, provided Your use,
128 | reproduction, and distribution of the Work otherwise complies with
129 | the conditions stated in this License.
130 |
131 | 5. Submission of Contributions. Unless You explicitly state otherwise,
132 | any Contribution intentionally submitted for inclusion in the Work
133 | by You to the Licensor shall be under the terms and conditions of
134 | this License, without any additional terms or conditions.
135 | Notwithstanding the above, nothing herein shall supersede or modify
136 | the terms of any separate license agreement you may have executed
137 | with Licensor regarding such Contributions.
138 |
139 | 6. Trademarks. This License does not grant permission to use the trade
140 | names, trademarks, service marks, or product names of the Licensor,
141 | except as required for reasonable and customary use in describing the
142 | origin of the Work and reproducing the content of the NOTICE file.
143 |
144 | 7. Disclaimer of Warranty. Unless required by applicable law or
145 | agreed to in writing, Licensor provides the Work (and each
146 | Contributor provides its Contributions) on an "AS IS" BASIS,
147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148 | implied, including, without limitation, any warranties or conditions
149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150 | PARTICULAR PURPOSE. You are solely responsible for determining the
151 | appropriateness of using or redistributing the Work and assume any
152 | risks associated with Your exercise of permissions under this License.
153 |
154 | 8. Limitation of Liability. In no event and under no legal theory,
155 | whether in tort (including negligence), contract, or otherwise,
156 | unless required by applicable law (such as deliberate and grossly
157 | negligent acts) or agreed to in writing, shall any Contributor be
158 | liable to You for damages, including any direct, indirect, special,
159 | incidental, or consequential damages of any character arising as a
160 | result of this License or out of the use or inability to use the
161 | Work (including but not limited to damages for loss of goodwill,
162 | work stoppage, computer failure or malfunction, or any and all
163 | other commercial damages or losses), even if such Contributor
164 | has been advised of the possibility of such damages.
165 |
166 | 9. Accepting Warranty or Additional Liability. While redistributing
167 | the Work or Derivative Works thereof, You may choose to offer,
168 | and charge a fee for, acceptance of support, warranty, indemnity,
169 | or other liability obligations and/or rights consistent with this
170 | License. However, in accepting such obligations, You may act only
171 | on Your own behalf and on Your sole responsibility, not on behalf
172 | of any other Contributor, and only if You agree to indemnify,
173 | defend, and hold each Contributor harmless for any liability
174 | incurred by, or claims asserted against, such Contributor by reason
175 | of your accepting any such warranty or additional liability.
176 |
177 | END OF TERMS AND CONDITIONS
178 |
179 | APPENDIX: How to apply the Apache License to your work.
180 |
181 | To apply the Apache License to your work, attach the following
182 | boilerplate notice, with the fields enclosed by brackets "[]"
183 | replaced with your own identifying information. (Don't include
184 | the brackets!) The text should be enclosed in the appropriate
185 | comment syntax for the file format. We also recommend that a
186 | file or class name and description of purpose be included on the
187 | same "printed page" as the copyright notice for easier
188 | identification within third-party archives.
189 |
190 | Copyright [yyyy] [name of copyright owner]
191 |
192 | Licensed under the Apache License, Version 2.0 (the "License");
193 | you may not use this file except in compliance with the License.
194 | You may obtain a copy of the License at
195 |
196 | http://www.apache.org/licenses/LICENSE-2.0
197 |
198 | Unless required by applicable law or agreed to in writing, software
199 | distributed under the License is distributed on an "AS IS" BASIS,
200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201 | See the License for the specific language governing permissions and
202 | limitations under the License.
203 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | #
2 | # This is a project Makefile. It is assumed the directory this Makefile resides in is a
3 | # project subdirectory.
4 | #
5 |
6 | PROJECT_NAME := ota-factory
7 |
8 | include $(IDF_PATH)/make/project.mk
9 |
10 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ESP32 OTA update app with ble setup
2 |
3 | This app is designed to be installed on smaller factory partition (about 1.2MB). Functionalities provided to end user are:
4 | - setup wifi credentials
5 | - setup informations required to connect to server and download bin file.
6 |
7 | All informations can be setup with bluetooth app like nRF connect or with android that is designed to communicate with ota app.
8 | Informations that can be setup to connect to server:
9 | - domain name (http only at the moment),
10 | - IP address (provided to connect with LAN server),
11 | - port,
12 | - path,
13 | - binary file name.
14 |
15 | There is still few more things to do.
16 | - Add exceptions when domain name cant be found by dns,
17 | - Add more exceptions when wifi credentials are wrong (ie cant connect to AP),
18 | - Add https server as option
19 | - Add gpio pin that will reset esp32 to boot from factory partition (done)
20 | - Add nvs save and retrive wifi credentials and ota info (done)
--------------------------------------------------------------------------------
/components/bootloader/Kconfig.projbuild:
--------------------------------------------------------------------------------
1 | menu "Bootloader config"
2 | choice LOG_BOOTLOADER_LEVEL
3 | bool "Bootloader log verbosity"
4 | default LOG_BOOTLOADER_LEVEL_INFO
5 | help
6 | Specify how much output to see in bootloader logs.
7 |
8 | config LOG_BOOTLOADER_LEVEL_NONE
9 | bool "No output"
10 | config LOG_BOOTLOADER_LEVEL_ERROR
11 | bool "Error"
12 | config LOG_BOOTLOADER_LEVEL_WARN
13 | bool "Warning"
14 | config LOG_BOOTLOADER_LEVEL_INFO
15 | bool "Info"
16 | config LOG_BOOTLOADER_LEVEL_DEBUG
17 | bool "Debug"
18 | config LOG_BOOTLOADER_LEVEL_VERBOSE
19 | bool "Verbose"
20 | endchoice
21 |
22 | config LOG_BOOTLOADER_LEVEL
23 | int
24 | default 0 if LOG_BOOTLOADER_LEVEL_NONE
25 | default 1 if LOG_BOOTLOADER_LEVEL_ERROR
26 | default 2 if LOG_BOOTLOADER_LEVEL_WARN
27 | default 3 if LOG_BOOTLOADER_LEVEL_INFO
28 | default 4 if LOG_BOOTLOADER_LEVEL_DEBUG
29 | default 5 if LOG_BOOTLOADER_LEVEL_VERBOSE
30 |
31 | config BOOTLOADER_SPI_WP_PIN
32 | int "SPI Flash WP Pin when customising pins via efuse (read help)"
33 | range 0 33
34 | default 7
35 | depends on FLASHMODE_QIO || FLASHMODE_QOUT
36 | help
37 | This value is ignored unless flash mode is set to QIO or QOUT *and* the SPI flash pins have been
38 | overriden by setting the efuses SPI_PAD_CONFIG_xxx.
39 |
40 | When this is the case, the Efuse config only defines 3 of the 4 Quad I/O data pins. The WP pin (aka ESP32
41 | pin "SD_DATA_3" or SPI flash pin "IO2") is not specified in Efuse. That pin number is compiled into the bootloader
42 | instead.
43 |
44 | The default value (GPIO 7) is correct for WP pin on ESP32-D2WD integrated flash.
45 |
46 | choice BOOTLOADER_VDDSDIO_BOOST
47 | bool "VDDSDIO LDO voltage"
48 | default BOOTLOADER_VDDSDIO_BOOST_1_9V
49 | help
50 | If this option is enabled, and VDDSDIO LDO is set to 1.8V (using EFUSE
51 | or MTDI bootstrapping pin), bootloader will change LDO settings to
52 | output 1.9V instead. This helps prevent flash chip from browning out
53 | during flash programming operations.
54 |
55 | This option has no effect if VDDSDIO is set to 3.3V, or if the internal
56 | VDDSDIO regulator is disabled via efuse.
57 |
58 | config BOOTLOADER_VDDSDIO_BOOST_1_8V
59 | bool "1.8V"
60 | depends on !ESPTOOLPY_FLASHFREQ_80M
61 | config BOOTLOADER_VDDSDIO_BOOST_1_9V
62 | bool "1.9V"
63 | endchoice
64 |
65 | endmenu # Bootloader
66 |
67 |
68 | menu "Security features"
69 |
70 | config SECURE_BOOT_ENABLED
71 | bool "Enable secure boot in bootloader (READ DOCS FIRST)"
72 | default N
73 | help
74 | Build a bootloader which enables secure boot on first boot.
75 |
76 | Once enabled, secure boot will not boot a modified bootloader. The bootloader will only load a partition table or boot an app if the data has a verified digital signature. There are implications for reflashing updated apps once secure boot is enabled.
77 |
78 | When enabling secure boot, JTAG and ROM BASIC Interpreter are permanently disabled by default.
79 |
80 | Refer to https://esp-idf.readthedocs.io/en/latest/security/secure-boot.html before enabling.
81 |
82 | choice SECURE_BOOTLOADER_MODE
83 | bool "Secure bootloader mode"
84 | depends on SECURE_BOOT_ENABLED
85 | default SECURE_BOOTLOADER_ONE_TIME_FLASH
86 |
87 | config SECURE_BOOTLOADER_ONE_TIME_FLASH
88 | bool "One-time flash"
89 | help
90 | On first boot, the bootloader will generate a key which is not readable externally or by software. A digest is generated from the bootloader image itself. This digest will be verified on each subsequent boot.
91 |
92 | Enabling this option means that the bootloader cannot be changed after the first time it is booted.
93 |
94 | config SECURE_BOOTLOADER_REFLASHABLE
95 | bool "Reflashable"
96 | help
97 | Generate a reusable secure bootloader key, derived (via SHA-256) from the secure boot signing key.
98 |
99 | This allows the secure bootloader to be re-flashed by anyone with access to the secure boot signing key.
100 |
101 | This option is less secure than one-time flash, because a leak of the digest key from one device allows reflashing of any device that uses it.
102 |
103 | endchoice
104 |
105 | config SECURE_BOOT_BUILD_SIGNED_BINARIES
106 | bool "Sign binaries during build"
107 | depends on SECURE_BOOT_ENABLED
108 | default y
109 | help
110 | Once secure boot is enabled, bootloader will only boot if partition table and app image are signed.
111 |
112 | If enabled, these binary files are signed as part of the build process. The file named in "Secure boot private signing key" will be used to sign the image.
113 |
114 | If disabled, unsigned app/partition data will be built. They must be signed manually using espsecure.py (for example, on a remote signing server.)
115 |
116 | config SECURE_BOOT_SIGNING_KEY
117 | string "Secure boot private signing key"
118 | depends on SECURE_BOOT_BUILD_SIGNED_BINARIES
119 | default secure_boot_signing_key.pem
120 | help
121 | Path to the key file used to sign partition tables and app images for secure boot. Once secure boot is enabled, bootloader will only boot if partition table and app image are signed.
122 |
123 | Key file is an ECDSA private key (NIST256p curve) in PEM format.
124 |
125 | Path is evaluated relative to the project directory.
126 |
127 | You can generate a new signing key by running the following command:
128 | espsecure.py generate_signing_key secure_boot_signing_key.pem
129 |
130 | See docs/security/secure-boot.rst for details.
131 |
132 | config SECURE_BOOT_VERIFICATION_KEY
133 | string "Secure boot public signature verification key"
134 | depends on SECURE_BOOT_ENABLED && !SECURE_BOOT_BUILD_SIGNED_BINARIES
135 | default signature_verification_key.bin
136 | help
137 | Path to a public key file used to verify signed images. This key is compiled into the bootloader,
138 | and may also be used to verify signatures on OTA images after download.
139 |
140 | Key file is in raw binary format, and can be extracted from a
141 | PEM formatted private key using the espsecure.py
142 | extract_public_key command.
143 |
144 | Refer to https://esp-idf.readthedocs.io/en/latest/security/secure-boot.html before enabling.
145 |
146 | config SECURE_BOOT_INSECURE
147 | bool "Allow potentially insecure options"
148 | depends on SECURE_BOOT_ENABLED
149 | default N
150 | help
151 | You can disable some of the default protections offered by secure boot, in order to enable testing or a custom combination of security features.
152 |
153 | Only enable these options if you are very sure.
154 |
155 | Refer to https://esp-idf.readthedocs.io/en/latest/security/secure-boot.html before enabling.
156 |
157 | config FLASH_ENCRYPTION_ENABLED
158 | bool "Enable flash encryption on boot (READ DOCS FIRST)"
159 | default N
160 | help
161 | If this option is set, flash contents will be encrypted by the bootloader on first boot.
162 |
163 | Note: After first boot, the system will be permanently encrypted. Re-flashing an encrypted
164 | system is complicated and not always possible.
165 |
166 | Read https://esp-idf.readthedocs.io/en/latest/security/flash-encryption.html before enabling.
167 |
168 | config FLASH_ENCRYPTION_INSECURE
169 | bool "Allow potentially insecure options"
170 | depends on FLASH_ENCRYPTION_ENABLED
171 | default N
172 | help
173 | You can disable some of the default protections offered by flash encryption, in order to enable testing or a custom combination of security features.
174 |
175 | Only enable these options if you are very sure.
176 |
177 | Refer to docs/security/secure-boot.rst and docs/security/flash-encryption.rst for details.
178 |
179 | menu "Potentially insecure options"
180 | visible if FLASH_ENCRYPTION_INSECURE || SECURE_BOOT_INSECURE
181 |
182 | # NOTE: Options in this menu NEED to have SECURE_BOOT_INSECURE
183 | # and/or FLASH_ENCRYPTION_INSECURE in "depends on", as the menu
184 | # itself doesn't enable/disable its children (if it's not set,
185 | # it's possible for the insecure menu to be disabled but the insecure option
186 | # to remain on which is very bad.)
187 |
188 | config SECURE_BOOT_ALLOW_ROM_BASIC
189 | bool "Leave ROM BASIC Interpreter available on reset"
190 | depends on SECURE_BOOT_INSECURE || FLASH_ENCRYPTION_INSECURE
191 | default N
192 | help
193 | By default, the BASIC ROM Console starts on reset if no valid bootloader is
194 | read from the flash.
195 |
196 | When either flash encryption or secure boot are enabled, the default is to
197 | disable this BASIC fallback mode permanently via efuse.
198 |
199 | If this option is set, this efuse is not burned and the BASIC ROM Console may
200 | remain accessible. Only set this option in testing environments.
201 |
202 | config SECURE_BOOT_ALLOW_JTAG
203 | bool "Allow JTAG Debugging"
204 | depends on SECURE_BOOT_INSECURE || FLASH_ENCRYPTION_INSECURE
205 | default N
206 | help
207 | If not set (default), the bootloader will permanently disable JTAG (across entire chip) on first boot when either secure boot or flash encryption is enabled.
208 |
209 | Setting this option leaves JTAG on for debugging, which negates all protections of flash encryption and some of the protections of secure boot.
210 |
211 | Only set this option in testing environments.
212 |
213 |
214 | config FLASH_ENCRYPTION_UART_BOOTLOADER_ALLOW_ENCRYPT
215 | bool "Leave UART bootloader encryption enabled"
216 | depends on FLASH_ENCRYPTION_INSECURE
217 | default N
218 | help
219 | If not set (default), the bootloader will permanently disable UART bootloader encryption access on first boot. If set, the UART bootloader will still be able to access hardware encryption.
220 |
221 | It is recommended to only set this option in testing environments.
222 |
223 | config FLASH_ENCRYPTION_UART_BOOTLOADER_ALLOW_DECRYPT
224 | bool "Leave UART bootloader decryption enabled"
225 | depends on FLASH_ENCRYPTION_INSECURE
226 | default N
227 | help
228 | If not set (default), the bootloader will permanently disable UART bootloader decryption access on first boot. If set, the UART bootloader will still be able to access hardware decryption.
229 |
230 | Only set this option in testing environments. Setting this option allows complete bypass of flash encryption.
231 |
232 | config FLASH_ENCRYPTION_UART_BOOTLOADER_ALLOW_CACHE
233 | bool "Leave UART bootloader flash cache enabled"
234 | depends on FLASH_ENCRYPTION_INSECURE
235 | default N
236 | help
237 | If not set (default), the bootloader will permanently disable UART bootloader flash cache access on first boot. If set, the UART bootloader will still be able to access the flash cache.
238 |
239 | Only set this option in testing environments.
240 |
241 | config SECURE_BOOT_TEST_MODE
242 | bool "Secure boot test mode: don't permanently set any efuses"
243 | depends on SECURE_BOOT_INSECURE
244 | default N
245 | help
246 | If this option is set, all permanent secure boot changes (via Efuse) are disabled.
247 |
248 | Log output will state changes which would be applied, but they will not be.
249 |
250 | This option is for testing purposes only - it completely disables secure boot protection.
251 |
252 |
253 | endmenu # Potentially Insecure
254 | endmenu # Security features
255 |
--------------------------------------------------------------------------------
/components/bootloader/Makefile.projbuild:
--------------------------------------------------------------------------------
1 | # Bootloader component (top-level project parts)
2 | #
3 | # The bootloader is not a real component that gets linked into the project.
4 | # Instead it is an entire standalone project (in subproject/) that gets
5 | # built in the upper project's build directory. This Makefile.projbuild provides
6 | # the glue to build the bootloader project from the original project. It
7 | # basically runs Make in the subproject/ directory but it needs to
8 | # zero some variables the ESP-IDF project.mk makefile exports first, to not
9 | # let them interfere.
10 | #
11 | BOOTLOADER_COMPONENT_PATH := $(COMPONENT_PATH)
12 | BOOTLOADER_BUILD_DIR=$(abspath $(BUILD_DIR_BASE)/bootloader)
13 | BOOTLOADER_BIN=$(BOOTLOADER_BUILD_DIR)/bootloader.bin
14 |
15 | # signing key path is resolved relative to the project directory
16 | CONFIG_SECURE_BOOT_SIGNING_KEY ?=
17 | SECURE_BOOT_SIGNING_KEY=$(abspath $(call dequote,$(CONFIG_SECURE_BOOT_SIGNING_KEY)))
18 | export SECURE_BOOT_SIGNING_KEY # used by bootloader_support component
19 |
20 | # Has a matching value in bootloader_support esp_flash_partitions.h
21 | BOOTLOADER_OFFSET := 0x1000
22 |
23 | # Custom recursive make for bootloader sub-project
24 | #
25 | # NB: Some variables are cleared in the environment, not
26 | # overriden, because they need to be re-defined in the child
27 | # project.
28 | BOOTLOADER_MAKE= +\
29 | PROJECT_PATH= \
30 | COMPONENT_DIRS= \
31 | $(MAKE) -C $(BOOTLOADER_COMPONENT_PATH)/subproject \
32 | V=$(V) \
33 | BUILD_DIR_BASE=$(BOOTLOADER_BUILD_DIR) \
34 | TEST_COMPONENTS= \
35 | TESTS_ALL=
36 |
37 | .PHONY: bootloader-clean bootloader-flash bootloader-list-components bootloader $(BOOTLOADER_BIN)
38 |
39 | $(BOOTLOADER_BIN): $(SDKCONFIG_MAKEFILE)
40 | $(BOOTLOADER_MAKE) $@
41 |
42 | clean: bootloader-clean
43 |
44 | bootloader-list-components:
45 | $(BOOTLOADER_MAKE) list-components
46 |
47 | ifndef CONFIG_SECURE_BOOT_ENABLED
48 | # If secure boot disabled, bootloader flashing is integrated
49 | # with 'make flash' and no warnings are printed.
50 |
51 | bootloader: $(BOOTLOADER_BIN)
52 | @echo $(SEPARATOR)
53 | @echo "Bootloader built. Default flash command is:"
54 | @echo "$(ESPTOOLPY_WRITE_FLASH) $(BOOTLOADER_OFFSET) $^"
55 |
56 | ESPTOOL_ALL_FLASH_ARGS += $(BOOTLOADER_OFFSET) $(BOOTLOADER_BIN)
57 |
58 | bootloader-flash: $(BOOTLOADER_BIN) $(call prereq_if_explicit,erase_flash)
59 | $(ESPTOOLPY_WRITE_FLASH) 0x1000 $^
60 |
61 | else ifdef CONFIG_SECURE_BOOTLOADER_ONE_TIME_FLASH
62 |
63 | # One time flashing requires user to run esptool.py command themselves,
64 | # and warning is printed about inability to reflash.
65 | #
66 | # The flashing command is deliberately printed without an auto-reset
67 | # step, so the device doesn't immediately reset to flash itself.
68 |
69 | bootloader: $(BOOTLOADER_BIN)
70 | @echo $(SEPARATOR)
71 | @echo "Bootloader built. One-time flash command is:"
72 | @echo "$(subst hard_reset,no_reset,$(ESPTOOLPY_WRITE_FLASH)) $(BOOTLOADER_OFFSET) $(BOOTLOADER_BIN)"
73 | @echo $(SEPARATOR)
74 | @echo "* IMPORTANT: After first boot, BOOTLOADER CANNOT BE RE-FLASHED on same device"
75 |
76 | else ifdef CONFIG_SECURE_BOOTLOADER_REFLASHABLE
77 | # Reflashable secure bootloader
78 | # generates a digest binary (bootloader + digest)
79 |
80 | BOOTLOADER_DIGEST_BIN := $(BOOTLOADER_BUILD_DIR)/bootloader-reflash-digest.bin
81 | SECURE_BOOTLOADER_KEY := $(BOOTLOADER_BUILD_DIR)/secure-bootloader-key.bin
82 |
83 | ifdef CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES
84 | $(SECURE_BOOTLOADER_KEY): $(SECURE_BOOT_SIGNING_KEY)
85 | $(ESPSECUREPY) digest_private_key -k $< $@
86 | else
87 | $(SECURE_BOOTLOADER_KEY):
88 | @echo "No pre-generated key for a reflashable secure bootloader is available, due to signing configuration."
89 | @echo "To generate one, you can use this command:"
90 | @echo "espsecure.py generate_flash_encryption_key $@"
91 | @echo "then re-run make."
92 | exit 1
93 | endif
94 |
95 | bootloader: $(BOOTLOADER_DIGEST_BIN)
96 | @echo $(SEPARATOR)
97 | @echo "Bootloader built and secure digest generated. First time flash command is:"
98 | @echo "$(ESPEFUSEPY) burn_key secure_boot $(SECURE_BOOTLOADER_KEY)"
99 | @echo "$(ESPTOOLPY_WRITE_FLASH) $(BOOTLOADER_OFFSET) $(BOOTLOADER_BIN)"
100 | @echo $(SEPARATOR)
101 | @echo "To reflash the bootloader after initial flash:"
102 | @echo "$(ESPTOOLPY_WRITE_FLASH) 0x0 $(BOOTLOADER_DIGEST_BIN)"
103 | @echo $(SEPARATOR)
104 | @echo "* After first boot, only re-flashes of this kind (with same key) will be accepted."
105 | @echo "* Not recommended to re-use the same secure boot keyfile on multiple production devices."
106 |
107 | $(BOOTLOADER_DIGEST_BIN): $(BOOTLOADER_BIN) $(SECURE_BOOTLOADER_KEY)
108 | @echo "DIGEST $(notdir $@)"
109 | $(Q) $(ESPSECUREPY) digest_secure_bootloader -k $(SECURE_BOOTLOADER_KEY) -o $@ $<
110 |
111 | else # CONFIG_SECURE_BOOT_ENABLED && !CONFIG_SECURE_BOOTLOADER_REFLASHABLE && !CONFIG_SECURE_BOOTLOADER_ONE_TIME_FLASH
112 | bootloader:
113 | @echo "Invalid bootloader target: bad sdkconfig?"
114 | @exit 1
115 | endif
116 |
117 | ifndef CONFIG_SECURE_BOOT_ENABLED
118 | # don't build bootloader by default is secure boot is enabled
119 | all_binaries: $(BOOTLOADER_BIN)
120 | endif
121 |
122 | bootloader-clean: $(SDKCONFIG_MAKEFILE)
123 | $(BOOTLOADER_MAKE) app-clean
124 | ifdef CONFIG_SECURE_BOOTLOADER_REFLASHABLE
125 | rm -f $(SECURE_BOOTLOADER_KEY) $(BOOTLOADER_DIGEST_BIN)
126 | endif
127 |
--------------------------------------------------------------------------------
/components/bootloader/component.mk:
--------------------------------------------------------------------------------
1 | # bootloader component is special, as bootloader is also a project.
2 | #
3 | # This top-level component is only configuration files for the IDF project.
4 | #
5 | # See Makefile.projbuild for the targets which actually build the bootloader.
6 | COMPONENT_CONFIG_ONLY := 1
7 |
8 |
--------------------------------------------------------------------------------
/components/bootloader/subproject/.gitignore:
--------------------------------------------------------------------------------
1 | build
2 | sdkconfig
3 |
--------------------------------------------------------------------------------
/components/bootloader/subproject/Makefile:
--------------------------------------------------------------------------------
1 | #
2 | # This is a project Makefile. It is assumed the directory this Makefile resides in is a
3 | # project subdirectory.
4 | #
5 | ifeq ("$(MAKELEVEL)","0")
6 | $(error Bootloader makefile expects to be run as part of 'make bootloader' from a top-level project.)
7 | endif
8 |
9 | PROJECT_NAME := bootloader
10 |
11 | COMPONENTS := esptool_py bootloader_support log spi_flash micro-ecc soc main
12 |
13 | # Clear C and CXX from top level project
14 | CFLAGS =
15 | CXXFLAGS =
16 |
17 | #We cannot include the esp32 component directly but we need its includes.
18 | CFLAGS += -I $(IDF_PATH)/components/esp32/include
19 |
20 | # The bootloader pseudo-component is also included in this build, for its Kconfig.projbuild to be included.
21 | #
22 | # IS_BOOTLOADER_BUILD tells the component Makefile.projbuild to be a no-op
23 | IS_BOOTLOADER_BUILD := 1
24 | export IS_BOOTLOADER_BUILD
25 |
26 | # BOOTLOADER_BUILD macro is the same, for source file changes
27 | CFLAGS += -D BOOTLOADER_BUILD=1
28 |
29 | # include the top-level "project" include directory, for sdkconfig.h
30 | CFLAGS += -I$(BUILD_DIR_BASE)/../include
31 |
32 | include $(IDF_PATH)/make/project.mk
33 |
--------------------------------------------------------------------------------
/components/bootloader/subproject/main/Makefile.projbuild:
--------------------------------------------------------------------------------
1 | # Submodules normally added in component.mk, but fully qualified
2 | # paths can be added at this level (we need binary librtc to be
3 | # available to link bootloader).
4 | COMPONENT_SUBMODULES += $(IDF_PATH)/components/esp32/lib
5 |
--------------------------------------------------------------------------------
/components/bootloader/subproject/main/bootloader_config.h:
--------------------------------------------------------------------------------
1 | // Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 |
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 | #ifndef __BOOT_CONFIG_H__
15 | #define __BOOT_CONFIG_H__
16 |
17 | #include
18 |
19 | #ifdef __cplusplus
20 | extern "C"
21 | {
22 | #endif
23 |
24 | #include "esp_flash_data_types.h"
25 | #include "soc/soc.h"
26 |
27 | #define SPI_SEC_SIZE 0x1000
28 |
29 | #define SPI_ERROR_LOG "spi flash error"
30 |
31 | #define MAX_OTA_SLOTS 16
32 |
33 | typedef struct {
34 | esp_partition_pos_t ota_info;
35 | esp_partition_pos_t factory;
36 | esp_partition_pos_t test;
37 | esp_partition_pos_t ota[MAX_OTA_SLOTS];
38 | uint32_t app_count;
39 | uint32_t selected_subtype;
40 | } bootloader_state_t;
41 |
42 | bool flash_encrypt(bootloader_state_t *bs);
43 |
44 | #ifdef __cplusplus
45 | }
46 | #endif
47 |
48 | #endif /* __BOOT_CONFIG_H__ */
49 |
--------------------------------------------------------------------------------
/components/bootloader/subproject/main/bootloader_start.c:
--------------------------------------------------------------------------------
1 | // Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 | #include
15 | #include
16 | #include
17 | #include
18 |
19 | #include "esp_attr.h"
20 | #include "esp_log.h"
21 |
22 | #include "rom/cache.h"
23 | #include "rom/efuse.h"
24 | #include "rom/ets_sys.h"
25 | #include "rom/spi_flash.h"
26 | #include "rom/crc.h"
27 | #include "rom/rtc.h"
28 | #include "rom/uart.h"
29 | #include "rom/gpio.h"
30 | #include "rom/secure_boot.h"
31 |
32 | #include "soc/soc.h"
33 | #include "soc/cpu.h"
34 | #include "soc/rtc.h"
35 | #include "soc/dport_reg.h"
36 | #include "soc/io_mux_reg.h"
37 | #include "soc/efuse_reg.h"
38 | #include "soc/rtc_cntl_reg.h"
39 | #include "soc/timer_group_reg.h"
40 | #include "soc/gpio_reg.h"
41 | #include "soc/gpio_sig_map.h"
42 |
43 | #include "sdkconfig.h"
44 | #include "esp_image_format.h"
45 | #include "esp_secure_boot.h"
46 | #include "esp_flash_encrypt.h"
47 | #include "esp_flash_partitions.h"
48 | #include "bootloader_flash.h"
49 | #include "bootloader_random.h"
50 | #include "bootloader_config.h"
51 | #include "bootloader_clock.h"
52 |
53 | #include "flash_qio_mode.h"
54 |
55 | extern int _bss_start;
56 | extern int _bss_end;
57 | extern int _data_start;
58 | extern int _data_end;
59 |
60 | static const char* TAG = "boot";
61 |
62 | /* Reduce literal size for some generic string literals */
63 | #define MAP_MSG "Mapping segment %d as %s"
64 | #define MAP_ERR_MSG "Image contains multiple %s segments. Only the last one will be mapped."
65 |
66 | void bootloader_main();
67 | static void unpack_load_app(const esp_image_metadata_t *data);
68 | static void print_flash_info(const esp_image_header_t* pfhdr);
69 | static void set_cache_and_start_app(uint32_t drom_addr,
70 | uint32_t drom_load_addr,
71 | uint32_t drom_size,
72 | uint32_t irom_addr,
73 | uint32_t irom_load_addr,
74 | uint32_t irom_size,
75 | uint32_t entry_addr);
76 | static void update_flash_config(const esp_image_header_t* pfhdr);
77 | static void vddsdio_configure();
78 | static void flash_gpio_configure();
79 | static void uart_console_configure(void);
80 | static void wdt_reset_check(void);
81 |
82 | /*
83 | * We arrive here after the ROM bootloader finished loading this second stage bootloader from flash.
84 | * The hardware is mostly uninitialized, flash cache is down and the app CPU is in reset.
85 | * We do have a stack, so we can do the initialization in C.
86 | */
87 | void call_start_cpu0()
88 | {
89 | cpu_configure_region_protection();
90 |
91 | /* Sanity check that static RAM is after the stack */
92 | #ifndef NDEBUG
93 | {
94 | int *sp = get_sp();
95 | assert(&_bss_start <= &_bss_end);
96 | assert(&_data_start <= &_data_end);
97 | assert(sp < &_bss_start);
98 | assert(sp < &_data_start);
99 | }
100 | #endif
101 |
102 | //Clear bss
103 | memset(&_bss_start, 0, (&_bss_end - &_bss_start) * sizeof(_bss_start));
104 |
105 | /* completely reset MMU for both CPUs
106 | (in case serial bootloader was running) */
107 | Cache_Read_Disable(0);
108 | Cache_Read_Disable(1);
109 | Cache_Flush(0);
110 | Cache_Flush(1);
111 | mmu_init(0);
112 | DPORT_REG_SET_BIT(DPORT_APP_CACHE_CTRL1_REG, DPORT_APP_CACHE_MMU_IA_CLR);
113 | mmu_init(1);
114 | DPORT_REG_CLR_BIT(DPORT_APP_CACHE_CTRL1_REG, DPORT_APP_CACHE_MMU_IA_CLR);
115 | /* (above steps probably unnecessary for most serial bootloader
116 | usage, all that's absolutely needed is that we unmask DROM0
117 | cache on the following two lines - normal ROM boot exits with
118 | DROM0 cache unmasked, but serial bootloader exits with it
119 | masked. However can't hurt to be thorough and reset
120 | everything.)
121 |
122 | The lines which manipulate DPORT_APP_CACHE_MMU_IA_CLR bit are
123 | necessary to work around a hardware bug.
124 | */
125 | DPORT_REG_CLR_BIT(DPORT_PRO_CACHE_CTRL1_REG, DPORT_PRO_CACHE_MASK_DROM0);
126 | DPORT_REG_CLR_BIT(DPORT_APP_CACHE_CTRL1_REG, DPORT_APP_CACHE_MASK_DROM0);
127 |
128 | bootloader_main();
129 | }
130 |
131 |
132 | /** @brief Load partition table
133 | *
134 | * Parse partition table, get useful data such as location of
135 | * OTA data partition, factory app partition, and test app partition.
136 | *
137 | * @param bs bootloader state structure used to save read data
138 | * @return return true if the partition table was succesfully loaded and MD5 checksum is valid.
139 | */
140 | bool load_partition_table(bootloader_state_t* bs)
141 | {
142 | const esp_partition_info_t *partitions;
143 | const int ESP_PARTITION_TABLE_DATA_LEN = 0xC00; /* length of actual data (signature is appended to this) */
144 | const char *partition_usage;
145 | esp_err_t err;
146 | int num_partitions;
147 |
148 | #ifdef CONFIG_SECURE_BOOT_ENABLED
149 | if(esp_secure_boot_enabled()) {
150 | ESP_LOGI(TAG, "Verifying partition table signature...");
151 | err = esp_secure_boot_verify_signature(ESP_PARTITION_TABLE_ADDR, ESP_PARTITION_TABLE_DATA_LEN);
152 | if (err != ESP_OK) {
153 | ESP_LOGE(TAG, "Failed to verify partition table signature.");
154 | return false;
155 | }
156 | ESP_LOGD(TAG, "Partition table signature verified");
157 | }
158 | #endif
159 |
160 | partitions = bootloader_mmap(ESP_PARTITION_TABLE_ADDR, ESP_PARTITION_TABLE_DATA_LEN);
161 | if (!partitions) {
162 | ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", ESP_PARTITION_TABLE_ADDR, ESP_PARTITION_TABLE_DATA_LEN);
163 | return false;
164 | }
165 | ESP_LOGD(TAG, "mapped partition table 0x%x at 0x%x", ESP_PARTITION_TABLE_ADDR, (intptr_t)partitions);
166 |
167 | err = esp_partition_table_basic_verify(partitions, true, &num_partitions);
168 | if (err != ESP_OK) {
169 | ESP_LOGE(TAG, "Failed to verify partition table");
170 | return false;
171 | }
172 |
173 | ESP_LOGI(TAG, "Partition Table:");
174 | ESP_LOGI(TAG, "## Label Usage Type ST Offset Length");
175 |
176 | for(int i = 0; i < num_partitions; i++) {
177 | const esp_partition_info_t *partition = &partitions[i];
178 | ESP_LOGD(TAG, "load partition table entry 0x%x", (intptr_t)partition);
179 | ESP_LOGD(TAG, "type=%x subtype=%x", partition->type, partition->subtype);
180 | partition_usage = "unknown";
181 |
182 | /* valid partition table */
183 | switch(partition->type) {
184 | case PART_TYPE_APP: /* app partition */
185 | switch(partition->subtype) {
186 | case PART_SUBTYPE_FACTORY: /* factory binary */
187 | bs->factory = partition->pos;
188 | partition_usage = "factory app";
189 | break;
190 | case PART_SUBTYPE_TEST: /* test binary */
191 | bs->test = partition->pos;
192 | partition_usage = "test app";
193 | break;
194 | default:
195 | /* OTA binary */
196 | if ((partition->subtype & ~PART_SUBTYPE_OTA_MASK) == PART_SUBTYPE_OTA_FLAG) {
197 | bs->ota[partition->subtype & PART_SUBTYPE_OTA_MASK] = partition->pos;
198 | ++bs->app_count;
199 | partition_usage = "OTA app";
200 | }
201 | else {
202 | partition_usage = "Unknown app";
203 | }
204 | break;
205 | }
206 | break; /* PART_TYPE_APP */
207 | case PART_TYPE_DATA: /* data partition */
208 | switch(partition->subtype) {
209 | case PART_SUBTYPE_DATA_OTA: /* ota data */
210 | bs->ota_info = partition->pos;
211 | partition_usage = "OTA data";
212 | break;
213 | case PART_SUBTYPE_DATA_RF:
214 | partition_usage = "RF data";
215 | break;
216 | case PART_SUBTYPE_DATA_WIFI:
217 | partition_usage = "WiFi data";
218 | break;
219 | default:
220 | partition_usage = "Unknown data";
221 | break;
222 | }
223 | break; /* PARTITION_USAGE_DATA */
224 | default: /* other partition type */
225 | break;
226 | }
227 |
228 | /* print partition type info */
229 | ESP_LOGI(TAG, "%2d %-16s %-16s %02x %02x %08x %08x", i, partition->label, partition_usage,
230 | partition->type, partition->subtype,
231 | partition->pos.offset, partition->pos.size);
232 | }
233 |
234 | bootloader_munmap(partitions);
235 |
236 | ESP_LOGI(TAG,"End of partition table");
237 | return true;
238 | }
239 |
240 | static uint32_t ota_select_crc(const esp_ota_select_entry_t *s)
241 | {
242 | return crc32_le(UINT32_MAX, (uint8_t*)&s->ota_seq, 4);
243 | }
244 |
245 | static bool ota_select_valid(const esp_ota_select_entry_t *s)
246 | {
247 | return s->ota_seq != UINT32_MAX && s->crc == ota_select_crc(s);
248 | }
249 |
250 | /* indexes used by index_to_partition are the OTA index
251 | number, or these special constants */
252 | #define FACTORY_INDEX (-1)
253 | #define TEST_APP_INDEX (-2)
254 | #define INVALID_INDEX (-99)
255 |
256 | /* Given a partition index, return the partition position data from the bootloader_state_t structure */
257 | static esp_partition_pos_t index_to_partition(const bootloader_state_t *bs, int index)
258 | {
259 | if (index == FACTORY_INDEX) {
260 | return bs->factory;
261 | }
262 |
263 | if (index == TEST_APP_INDEX) {
264 | return bs->test;
265 | }
266 |
267 | if (index >= 0 && index < MAX_OTA_SLOTS && index < bs->app_count) {
268 | return bs->ota[index];
269 | }
270 |
271 | esp_partition_pos_t invalid = { 0 };
272 | return invalid;
273 | }
274 |
275 | static void log_invalid_app_partition(int index)
276 | {
277 | const char *not_bootable = " is not bootable"; /* save a few string literal bytes */
278 | switch(index) {
279 | case FACTORY_INDEX:
280 | ESP_LOGE(TAG, "Factory app partition%s", not_bootable);
281 | break;
282 | case TEST_APP_INDEX:
283 | ESP_LOGE(TAG, "Factory test app partition%s", not_bootable);
284 | break;
285 | default:
286 | ESP_LOGE(TAG, "OTA app partition slot %d%s", index, not_bootable);
287 | break;
288 | }
289 | }
290 |
291 | /**
292 | * @function : ForceFactoryBoot
293 | * @description: Add by Imtiaz @ Syrp for failsafe mode
294 | *
295 | * @inputs: void
296 | */
297 | static uint8_t ForceFactoryBoot(void)
298 | {
299 | #define GPIO_INPUT_FORCE_FACTORY 2
300 | uint8_t timer = 0;
301 | gpio_pad_select_gpio(GPIO_INPUT_FORCE_FACTORY);
302 | ets_delay_us(10000); //delay 10 msecs
303 | while(GPIO_INPUT_GET(GPIO_INPUT_FORCE_FACTORY))
304 | {
305 | ESP_LOGE(TAG, "OTA Pin is Active : %d!",timer);
306 | ets_delay_us(1000000);
307 | timer++;
308 | if(timer == 10)
309 | {
310 | ESP_LOGE(TAG, "Forcing Factory : %d!",GPIO_INPUT_GET(GPIO_INPUT_FORCE_FACTORY));
311 | return 1;
312 | }
313 | }
314 | return 0;
315 | }
316 |
317 | /* Return the index of the selected boot partition.
318 |
319 | This is the preferred boot partition, as determined by the partition table &
320 | any OTA sequence number found in OTA data.
321 |
322 | This partition will only be booted if it contains a valid app image, otherwise load_boot_image() will search
323 | for a valid partition using this selection as the starting point.
324 | */
325 | static int get_selected_boot_partition(const bootloader_state_t *bs)
326 | {
327 | esp_ota_select_entry_t sa,sb;
328 | const esp_ota_select_entry_t *ota_select_map;
329 |
330 | if (bs->ota_info.offset != 0) {
331 | // partition table has OTA data partition
332 | if (bs->ota_info.size < 2 * SPI_SEC_SIZE) {
333 | ESP_LOGE(TAG, "ota_info partition size %d is too small (minimum %d bytes)", bs->ota_info.size, sizeof(esp_ota_select_entry_t));
334 | return INVALID_INDEX; // can't proceed
335 | }
336 |
337 | ESP_LOGD(TAG, "OTA data offset 0x%x", bs->ota_info.offset);
338 | ota_select_map = bootloader_mmap(bs->ota_info.offset, bs->ota_info.size);
339 | if (!ota_select_map) {
340 | ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", bs->ota_info.offset, bs->ota_info.size);
341 | return INVALID_INDEX; // can't proceed
342 | }
343 | memcpy(&sa, ota_select_map, sizeof(esp_ota_select_entry_t));
344 | memcpy(&sb, (uint8_t *)ota_select_map + SPI_SEC_SIZE, sizeof(esp_ota_select_entry_t));
345 | bootloader_munmap(ota_select_map);
346 |
347 | ESP_LOGD(TAG, "OTA sequence values A 0x%08x B 0x%08x", sa.ota_seq, sb.ota_seq);
348 | if(sa.ota_seq == UINT32_MAX && sb.ota_seq == UINT32_MAX) {
349 | ESP_LOGD(TAG, "OTA sequence numbers both empty (all-0xFF)");
350 | if (bs->factory.offset != 0) {
351 | ESP_LOGI(TAG, "Defaulting to factory image");
352 | return FACTORY_INDEX;
353 | } else {
354 | ESP_LOGI(TAG, "No factory image, trying OTA 0");
355 | return 0;
356 | }
357 | } else {
358 | bool ota_valid = false;
359 | const char *ota_msg;
360 | int ota_seq; // Raw OTA sequence number. May be more than # of OTA slots
361 | if(ota_select_valid(&sa) && ota_select_valid(&sb)) {
362 | ota_valid = true;
363 | ota_msg = "Both OTA values";
364 | ota_seq = MAX(sa.ota_seq, sb.ota_seq) - 1;
365 | } else if(ota_select_valid(&sa)) {
366 | ota_valid = true;
367 | ota_msg = "Only OTA sequence A is";
368 | ota_seq = sa.ota_seq - 1;
369 | } else if(ota_select_valid(&sb)) {
370 | ota_valid = true;
371 | ota_msg = "Only OTA sequence B is";
372 | ota_seq = sb.ota_seq - 1;
373 | }
374 |
375 | if (ota_valid) {
376 | int ota_slot = ota_seq % bs->app_count; // Actual OTA partition selection
377 | ESP_LOGD(TAG, "%s valid. Mapping seq %d -> OTA slot %d", ota_msg, ota_seq, ota_slot);
378 | return ota_slot;
379 | } else if (bs->factory.offset != 0) {
380 | ESP_LOGE(TAG, "ota data partition invalid, falling back to factory");
381 | return FACTORY_INDEX;
382 | } else {
383 | ESP_LOGE(TAG, "ota data partition invalid and no factory, will try all partitions");
384 | return FACTORY_INDEX;
385 | }
386 | }
387 | }
388 |
389 | // otherwise, start from factory app partition and let the search logic
390 | // proceed from there
391 | return FACTORY_INDEX;
392 | }
393 |
394 | /* Return true if a partition has a valid app image that was successfully loaded */
395 | static bool try_load_partition(const esp_partition_pos_t *partition, esp_image_metadata_t *data)
396 | {
397 | if (partition->size == 0) {
398 | ESP_LOGD(TAG, "Can't boot from zero-length partition");
399 | return false;
400 | }
401 |
402 | if (esp_image_load(ESP_IMAGE_LOAD, partition, data) == ESP_OK) {
403 | ESP_LOGI(TAG, "Loaded app from partition at offset 0x%x",
404 | partition->offset);
405 | return true;
406 | }
407 |
408 | return false;
409 | }
410 |
411 | #define TRY_LOG_FORMAT "Trying partition index %d offs 0x%x size 0x%x"
412 |
413 | /* Load the app for booting. Start from partition 'start_index', if not bootable then work backwards to FACTORY_INDEX
414 | * (ie try any OTA slots in descending order and then the factory partition).
415 | *
416 | * If still nothing, start from 'start_index + 1' and work up to highest numbered OTA partition.
417 | *
418 | * If still nothing, try TEST_APP_INDEX
419 | *
420 | * Returns true on success, false if there's no bootable app in the partition table.
421 | */
422 | static bool load_boot_image(const bootloader_state_t *bs, int start_index, esp_image_metadata_t *result)
423 | {
424 | int index = start_index;
425 | esp_partition_pos_t part;
426 |
427 | /* work backwards from start_index, down to the factory app */
428 | for(index = start_index; index >= FACTORY_INDEX; index--) {
429 | part = index_to_partition(bs, index);
430 | if (part.size == 0) {
431 | continue;
432 | }
433 | ESP_LOGD(TAG, TRY_LOG_FORMAT, index, part.offset, part.size);
434 | if (try_load_partition(&part, result)) {
435 | return true;
436 | }
437 | log_invalid_app_partition(index);
438 | }
439 |
440 | /* failing that work forwards from start_index, try valid OTA slots */
441 | for(index = start_index + 1; index < bs->app_count; index++) {
442 | part = index_to_partition(bs, index);
443 | if (part.size == 0) {
444 | continue;
445 | }
446 | ESP_LOGD(TAG, TRY_LOG_FORMAT, index, part.offset, part.size);
447 | if (try_load_partition(&part, result)) {
448 | return true;
449 | }
450 | log_invalid_app_partition(index);
451 | }
452 |
453 | if (try_load_partition(&bs->test, result)) {
454 | ESP_LOGW(TAG, "Falling back to test app as only bootable partition");
455 | return true;
456 | }
457 |
458 | ESP_LOGE(TAG, "No bootable app partitions in the partition table");
459 | bzero(result, sizeof(esp_image_metadata_t));
460 | return false;
461 | }
462 |
463 |
464 | /**
465 | * @function : bootloader_main
466 | * @description: entry function of 2nd bootloader
467 | *
468 | * @inputs: void
469 | */
470 |
471 | void bootloader_main()
472 | {
473 | vddsdio_configure();
474 | flash_gpio_configure();
475 | #if (CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ == 240)
476 | //Check if ESP32 is rated for a CPU frequency of 160MHz only
477 | if (REG_GET_BIT(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_CPU_FREQ_RATED) &&
478 | REG_GET_BIT(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_CPU_FREQ_LOW)) {
479 | ESP_LOGE(TAG, "Chip CPU frequency rated for 160MHz. Modify CPU frequency in menuconfig");
480 | return;
481 | }
482 | #endif
483 | bootloader_clock_configure();
484 | uart_console_configure();
485 | wdt_reset_check();
486 | ESP_LOGI(TAG, "ESP-IDF %s 2nd stage bootloader", IDF_VER);
487 | #if defined(CONFIG_SECURE_BOOT_ENABLED) || defined(CONFIG_FLASH_ENCRYPTION_ENABLED)
488 | esp_err_t err;
489 | #endif
490 | esp_image_header_t fhdr;
491 | bootloader_state_t bs = { 0 };
492 |
493 | ESP_LOGI(TAG, "compile time " __TIME__ );
494 | ets_set_appcpu_boot_addr(0);
495 |
496 | /* disable watch dog here */
497 | REG_CLR_BIT( RTC_CNTL_WDTCONFIG0_REG, RTC_CNTL_WDT_FLASHBOOT_MOD_EN );
498 | REG_CLR_BIT( TIMG_WDTCONFIG0_REG(0), TIMG_WDT_FLASHBOOT_MOD_EN );
499 |
500 | #ifndef CONFIG_SPI_FLASH_ROM_DRIVER_PATCH
501 | const uint32_t spiconfig = ets_efuse_get_spiconfig();
502 | if(spiconfig != EFUSE_SPICONFIG_SPI_DEFAULTS && spiconfig != EFUSE_SPICONFIG_HSPI_DEFAULTS) {
503 | ESP_LOGE(TAG, "SPI flash pins are overridden. \"Enable SPI flash ROM driver patched functions\" must be enabled in menuconfig");
504 | return;
505 | }
506 | #endif
507 |
508 | esp_rom_spiflash_unlock();
509 |
510 | ESP_LOGI(TAG, "Enabling RNG early entropy source...");
511 | bootloader_random_enable();
512 |
513 | #if CONFIG_FLASHMODE_QIO || CONFIG_FLASHMODE_QOUT
514 | bootloader_enable_qio_mode();
515 | #endif
516 |
517 | if (bootloader_flash_read(ESP_BOOTLOADER_OFFSET, &fhdr,
518 | sizeof(esp_image_header_t), true) != ESP_OK) {
519 | ESP_LOGE(TAG, "failed to load bootloader header!");
520 | return;
521 | }
522 |
523 | print_flash_info(&fhdr);
524 |
525 | update_flash_config(&fhdr);
526 |
527 | if (!load_partition_table(&bs)) {
528 | ESP_LOGE(TAG, "load partition table error!");
529 | return;
530 | }
531 |
532 | int boot_index = get_selected_boot_partition(&bs);
533 | if (boot_index == INVALID_INDEX) {
534 | return; // Unrecoverable failure (not due to corrupt ota data or bad partition contents)
535 | }
536 | // Start from the default, look for the first bootable partition
537 | esp_image_metadata_t image_data;
538 | if (!load_boot_image(&bs, boot_index, &image_data)) {
539 | return;
540 | }
541 |
542 | #ifdef CONFIG_SECURE_BOOT_ENABLED
543 | /* Generate secure digest from this bootloader to protect future
544 | modifications */
545 | ESP_LOGI(TAG, "Checking secure boot...");
546 | err = esp_secure_boot_permanently_enable();
547 | if (err != ESP_OK) {
548 | ESP_LOGE(TAG, "Bootloader digest generation failed (%d). SECURE BOOT IS NOT ENABLED.", err);
549 | /* Allow booting to continue, as the failure is probably
550 | due to user-configured EFUSEs for testing...
551 | */
552 | }
553 | #endif
554 |
555 | #ifdef CONFIG_FLASH_ENCRYPTION_ENABLED
556 | /* encrypt flash */
557 | ESP_LOGI(TAG, "Checking flash encryption...");
558 | bool flash_encryption_enabled = esp_flash_encryption_enabled();
559 | err = esp_flash_encrypt_check_and_update();
560 | if (err != ESP_OK) {
561 | ESP_LOGE(TAG, "Flash encryption check failed (%d).", err);
562 | return;
563 | }
564 |
565 | if (!flash_encryption_enabled && esp_flash_encryption_enabled()) {
566 | /* Flash encryption was just enabled for the first time,
567 | so issue a system reset to ensure flash encryption
568 | cache resets properly */
569 | ESP_LOGI(TAG, "Resetting with flash encryption enabled...");
570 | REG_WRITE(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_SW_SYS_RST);
571 | return;
572 | }
573 | #endif
574 |
575 | ESP_LOGI(TAG, "Disabling RNG early entropy source...");
576 | bootloader_random_disable();
577 |
578 | // copy loaded segments to RAM, set up caches for mapped segments, and start application
579 | unpack_load_app(&image_data);
580 | }
581 |
582 | static void unpack_load_app(const esp_image_metadata_t* data)
583 | {
584 | uint32_t drom_addr = 0;
585 | uint32_t drom_load_addr = 0;
586 | uint32_t drom_size = 0;
587 | uint32_t irom_addr = 0;
588 | uint32_t irom_load_addr = 0;
589 | uint32_t irom_size = 0;
590 |
591 | // Find DROM & IROM addresses, to configure cache mappings
592 | for (int i = 0; i < data->image.segment_count; i++) {
593 | const esp_image_segment_header_t *header = &data->segments[i];
594 | if (header->load_addr >= SOC_IROM_LOW && header->load_addr < SOC_IROM_HIGH) {
595 | if (drom_addr != 0) {
596 | ESP_LOGE(TAG, MAP_ERR_MSG, "DROM");
597 | } else {
598 | ESP_LOGD(TAG, "Mapping segment %d as %s", i, "DROM");
599 | }
600 | drom_addr = data->segment_data[i];
601 | drom_load_addr = header->load_addr;
602 | drom_size = header->data_len;
603 | }
604 | if (header->load_addr >= SOC_DROM_LOW && header->load_addr < SOC_DROM_HIGH) {
605 | if (irom_addr != 0) {
606 | ESP_LOGE(TAG, MAP_ERR_MSG, "IROM");
607 | } else {
608 | ESP_LOGD(TAG, "Mapping segment %d as %s", i, "IROM");
609 | }
610 | irom_addr = data->segment_data[i];
611 | irom_load_addr = header->load_addr;
612 | irom_size = header->data_len;
613 | }
614 | }
615 |
616 | ESP_LOGD(TAG, "calling set_cache_and_start_app");
617 | set_cache_and_start_app(drom_addr,
618 | drom_load_addr,
619 | drom_size,
620 | irom_addr,
621 | irom_load_addr,
622 | irom_size,
623 | data->image.entry_addr);
624 | }
625 |
626 | static void set_cache_and_start_app(
627 | uint32_t drom_addr,
628 | uint32_t drom_load_addr,
629 | uint32_t drom_size,
630 | uint32_t irom_addr,
631 | uint32_t irom_load_addr,
632 | uint32_t irom_size,
633 | uint32_t entry_addr)
634 | {
635 | ESP_LOGD(TAG, "configure drom and irom and start");
636 | Cache_Read_Disable( 0 );
637 | Cache_Flush( 0 );
638 |
639 | /* Clear the MMU entries that are already set up,
640 | so the new app only has the mappings it creates.
641 | */
642 | for (int i = 0; i < DPORT_FLASH_MMU_TABLE_SIZE; i++) {
643 | DPORT_PRO_FLASH_MMU_TABLE[i] = DPORT_FLASH_MMU_TABLE_INVALID_VAL;
644 | }
645 |
646 | uint32_t drom_page_count = (drom_size + 64*1024 - 1) / (64*1024); // round up to 64k
647 | ESP_LOGV(TAG, "d mmu set paddr=%08x vaddr=%08x size=%d n=%d", drom_addr & 0xffff0000, drom_load_addr & 0xffff0000, drom_size, drom_page_count );
648 | int rc = cache_flash_mmu_set( 0, 0, drom_load_addr & 0xffff0000, drom_addr & 0xffff0000, 64, drom_page_count );
649 | ESP_LOGV(TAG, "rc=%d", rc );
650 | rc = cache_flash_mmu_set( 1, 0, drom_load_addr & 0xffff0000, drom_addr & 0xffff0000, 64, drom_page_count );
651 | ESP_LOGV(TAG, "rc=%d", rc );
652 | uint32_t irom_page_count = (irom_size + 64*1024 - 1) / (64*1024); // round up to 64k
653 | ESP_LOGV(TAG, "i mmu set paddr=%08x vaddr=%08x size=%d n=%d", irom_addr & 0xffff0000, irom_load_addr & 0xffff0000, irom_size, irom_page_count );
654 | rc = cache_flash_mmu_set( 0, 0, irom_load_addr & 0xffff0000, irom_addr & 0xffff0000, 64, irom_page_count );
655 | ESP_LOGV(TAG, "rc=%d", rc );
656 | rc = cache_flash_mmu_set( 1, 0, irom_load_addr & 0xffff0000, irom_addr & 0xffff0000, 64, irom_page_count );
657 | ESP_LOGV(TAG, "rc=%d", rc );
658 | DPORT_REG_CLR_BIT( DPORT_PRO_CACHE_CTRL1_REG, (DPORT_PRO_CACHE_MASK_IRAM0) | (DPORT_PRO_CACHE_MASK_IRAM1 & 0) | (DPORT_PRO_CACHE_MASK_IROM0 & 0) | DPORT_PRO_CACHE_MASK_DROM0 | DPORT_PRO_CACHE_MASK_DRAM1 );
659 | DPORT_REG_CLR_BIT( DPORT_APP_CACHE_CTRL1_REG, (DPORT_APP_CACHE_MASK_IRAM0) | (DPORT_APP_CACHE_MASK_IRAM1 & 0) | (DPORT_APP_CACHE_MASK_IROM0 & 0) | DPORT_APP_CACHE_MASK_DROM0 | DPORT_APP_CACHE_MASK_DRAM1 );
660 | Cache_Read_Enable( 0 );
661 |
662 | // Application will need to do Cache_Flush(1) and Cache_Read_Enable(1)
663 |
664 | ESP_LOGD(TAG, "start: 0x%08x", entry_addr);
665 | typedef void (*entry_t)(void);
666 | entry_t entry = ((entry_t) entry_addr);
667 |
668 | // TODO: we have used quite a bit of stack at this point.
669 | // use "movsp" instruction to reset stack back to where ROM stack starts.
670 | (*entry)();
671 | }
672 |
673 | static void update_flash_config(const esp_image_header_t* pfhdr)
674 | {
675 | uint32_t size;
676 | switch(pfhdr->spi_size) {
677 | case ESP_IMAGE_FLASH_SIZE_1MB:
678 | size = 1;
679 | break;
680 | case ESP_IMAGE_FLASH_SIZE_2MB:
681 | size = 2;
682 | break;
683 | case ESP_IMAGE_FLASH_SIZE_4MB:
684 | size = 4;
685 | break;
686 | case ESP_IMAGE_FLASH_SIZE_8MB:
687 | size = 8;
688 | break;
689 | case ESP_IMAGE_FLASH_SIZE_16MB:
690 | size = 16;
691 | break;
692 | default:
693 | size = 2;
694 | }
695 | Cache_Read_Disable( 0 );
696 | // Set flash chip size
697 | esp_rom_spiflash_config_param(g_rom_flashchip.device_id, size * 0x100000, 0x10000, 0x1000, 0x100, 0xffff);
698 | // TODO: set mode
699 | // TODO: set frequency
700 | Cache_Flush(0);
701 | Cache_Read_Enable( 0 );
702 | }
703 |
704 | static void print_flash_info(const esp_image_header_t* phdr)
705 | {
706 | #if (BOOT_LOG_LEVEL >= BOOT_LOG_LEVEL_NOTICE)
707 |
708 | ESP_LOGD(TAG, "magic %02x", phdr->magic );
709 | ESP_LOGD(TAG, "segments %02x", phdr->segment_count );
710 | ESP_LOGD(TAG, "spi_mode %02x", phdr->spi_mode );
711 | ESP_LOGD(TAG, "spi_speed %02x", phdr->spi_speed );
712 | ESP_LOGD(TAG, "spi_size %02x", phdr->spi_size );
713 |
714 | const char* str;
715 | switch ( phdr->spi_speed ) {
716 | case ESP_IMAGE_SPI_SPEED_40M:
717 | str = "40MHz";
718 | break;
719 | case ESP_IMAGE_SPI_SPEED_26M:
720 | str = "26.7MHz";
721 | break;
722 | case ESP_IMAGE_SPI_SPEED_20M:
723 | str = "20MHz";
724 | break;
725 | case ESP_IMAGE_SPI_SPEED_80M:
726 | str = "80MHz";
727 | break;
728 | default:
729 | str = "20MHz";
730 | break;
731 | }
732 | ESP_LOGI(TAG, "SPI Speed : %s", str );
733 |
734 | /* SPI mode could have been set to QIO during boot already,
735 | so test the SPI registers not the flash header */
736 | uint32_t spi_ctrl = REG_READ(SPI_CTRL_REG(0));
737 | if (spi_ctrl & SPI_FREAD_QIO) {
738 | str = "QIO";
739 | } else if (spi_ctrl & SPI_FREAD_QUAD) {
740 | str = "QOUT";
741 | } else if (spi_ctrl & SPI_FREAD_DIO) {
742 | str = "DIO";
743 | } else if (spi_ctrl & SPI_FREAD_DUAL) {
744 | str = "DOUT";
745 | } else if (spi_ctrl & SPI_FASTRD_MODE) {
746 | str = "FAST READ";
747 | } else {
748 | str = "SLOW READ";
749 | }
750 | ESP_LOGI(TAG, "SPI Mode : %s", str );
751 |
752 | switch ( phdr->spi_size ) {
753 | case ESP_IMAGE_FLASH_SIZE_1MB:
754 | str = "1MB";
755 | break;
756 | case ESP_IMAGE_FLASH_SIZE_2MB:
757 | str = "2MB";
758 | break;
759 | case ESP_IMAGE_FLASH_SIZE_4MB:
760 | str = "4MB";
761 | break;
762 | case ESP_IMAGE_FLASH_SIZE_8MB:
763 | str = "8MB";
764 | break;
765 | case ESP_IMAGE_FLASH_SIZE_16MB:
766 | str = "16MB";
767 | break;
768 | default:
769 | str = "2MB";
770 | break;
771 | }
772 | ESP_LOGI(TAG, "SPI Flash Size : %s", str );
773 | #endif
774 | }
775 |
776 |
777 | static void vddsdio_configure()
778 | {
779 | #if CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_9V
780 | rtc_vddsdio_config_t cfg = rtc_vddsdio_get_config();
781 | if (cfg.enable == 1 && cfg.tieh == 0) { // VDDSDIO regulator is enabled @ 1.8V
782 | cfg.drefh = 3;
783 | cfg.drefm = 3;
784 | cfg.drefl = 3;
785 | cfg.force = 1;
786 | rtc_vddsdio_set_config(cfg);
787 | ets_delay_us(10); // wait for regulator to become stable
788 | }
789 | #endif // CONFIG_BOOTLOADER_VDDSDIO_BOOST
790 | }
791 |
792 |
793 | #define FLASH_CLK_IO 6
794 | #define FLASH_CS_IO 11
795 | #define FLASH_SPIQ_IO 7
796 | #define FLASH_SPID_IO 8
797 | #define FLASH_SPIWP_IO 10
798 | #define FLASH_SPIHD_IO 9
799 | #define FLASH_IO_MATRIX_DUMMY_40M 1
800 | #define FLASH_IO_MATRIX_DUMMY_80M 2
801 | static void IRAM_ATTR flash_gpio_configure()
802 | {
803 | int spi_cache_dummy = 0;
804 | int drv = 2;
805 | #if CONFIG_FLASHMODE_QIO
806 | spi_cache_dummy = SPI0_R_QIO_DUMMY_CYCLELEN; //qio 3
807 | #elif CONFIG_FLASHMODE_QOUT
808 | spi_cache_dummy = SPI0_R_FAST_DUMMY_CYCLELEN; //qout 7
809 | #elif CONFIG_FLASHMODE_DIO
810 | spi_cache_dummy = SPI0_R_DIO_DUMMY_CYCLELEN; //dio 3
811 | #elif CONFIG_FLASHMODE_DOUT
812 | spi_cache_dummy = SPI0_R_FAST_DUMMY_CYCLELEN; //dout 7
813 | #endif
814 | /* dummy_len_plus values defined in ROM for SPI flash configuration */
815 | extern uint8_t g_rom_spiflash_dummy_len_plus[];
816 | #if CONFIG_ESPTOOLPY_FLASHFREQ_40M
817 | g_rom_spiflash_dummy_len_plus[0] = FLASH_IO_MATRIX_DUMMY_40M;
818 | g_rom_spiflash_dummy_len_plus[1] = FLASH_IO_MATRIX_DUMMY_40M;
819 | SET_PERI_REG_BITS(SPI_USER1_REG(0), SPI_USR_DUMMY_CYCLELEN_V, spi_cache_dummy + FLASH_IO_MATRIX_DUMMY_40M, SPI_USR_DUMMY_CYCLELEN_S); //DUMMY
820 | #elif CONFIG_ESPTOOLPY_FLASHFREQ_80M
821 | g_rom_spiflash_dummy_len_plus[0] = FLASH_IO_MATRIX_DUMMY_80M;
822 | g_rom_spiflash_dummy_len_plus[1] = FLASH_IO_MATRIX_DUMMY_80M;
823 | SET_PERI_REG_BITS(SPI_USER1_REG(0), SPI_USR_DUMMY_CYCLELEN_V, spi_cache_dummy + FLASH_IO_MATRIX_DUMMY_80M, SPI_USR_DUMMY_CYCLELEN_S); //DUMMY
824 | drv = 3;
825 | #endif
826 |
827 | uint32_t chip_ver = REG_GET_FIELD(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_VER_PKG);
828 | uint32_t pkg_ver = chip_ver & 0x7;
829 |
830 | if (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32D2WDQ5) {
831 | // For ESP32D2WD the SPI pins are already configured
832 | // flash clock signal should come from IO MUX.
833 | PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK);
834 | SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, drv, FUN_DRV_S);
835 | } else if (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD2) {
836 | // For ESP32PICOD2 the SPI pins are already configured
837 | // flash clock signal should come from IO MUX.
838 | PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK);
839 | SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, drv, FUN_DRV_S);
840 | } else if (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD4) {
841 | // For ESP32PICOD4 the SPI pins are already configured
842 | // flash clock signal should come from IO MUX.
843 | PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK);
844 | SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, drv, FUN_DRV_S);
845 | } else {
846 | const uint32_t spiconfig = ets_efuse_get_spiconfig();
847 | if (spiconfig == EFUSE_SPICONFIG_SPI_DEFAULTS) {
848 | gpio_matrix_out(FLASH_CS_IO, SPICS0_OUT_IDX, 0, 0);
849 | gpio_matrix_out(FLASH_SPIQ_IO, SPIQ_OUT_IDX, 0, 0);
850 | gpio_matrix_in(FLASH_SPIQ_IO, SPIQ_IN_IDX, 0);
851 | gpio_matrix_out(FLASH_SPID_IO, SPID_OUT_IDX, 0, 0);
852 | gpio_matrix_in(FLASH_SPID_IO, SPID_IN_IDX, 0);
853 | gpio_matrix_out(FLASH_SPIWP_IO, SPIWP_OUT_IDX, 0, 0);
854 | gpio_matrix_in(FLASH_SPIWP_IO, SPIWP_IN_IDX, 0);
855 | gpio_matrix_out(FLASH_SPIHD_IO, SPIHD_OUT_IDX, 0, 0);
856 | gpio_matrix_in(FLASH_SPIHD_IO, SPIHD_IN_IDX, 0);
857 | //select pin function gpio
858 | PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA0_U, PIN_FUNC_GPIO);
859 | PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA1_U, PIN_FUNC_GPIO);
860 | PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA2_U, PIN_FUNC_GPIO);
861 | PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA3_U, PIN_FUNC_GPIO);
862 | PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CMD_U, PIN_FUNC_GPIO);
863 | // flash clock signal should come from IO MUX.
864 | // set drive ability for clock
865 | PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK);
866 | SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, drv, FUN_DRV_S);
867 | }
868 | }
869 | }
870 |
871 |
872 | static void uart_console_configure(void)
873 | {
874 | #if CONFIG_CONSOLE_UART_NONE
875 | ets_install_putc1(NULL);
876 | ets_install_putc2(NULL);
877 | #else // CONFIG_CONSOLE_UART_NONE
878 | const int uart_num = CONFIG_CONSOLE_UART_NUM;
879 |
880 | uartAttach();
881 | ets_install_uart_printf();
882 |
883 | // Wait for UART FIFO to be empty.
884 | uart_tx_wait_idle(0);
885 |
886 | #if CONFIG_CONSOLE_UART_CUSTOM
887 | // Some constants to make the following code less upper-case
888 | const int uart_tx_gpio = CONFIG_CONSOLE_UART_TX_GPIO;
889 | const int uart_rx_gpio = CONFIG_CONSOLE_UART_RX_GPIO;
890 | // Switch to the new UART (this just changes UART number used for
891 | // ets_printf in ROM code).
892 | uart_tx_switch(uart_num);
893 | // If console is attached to UART1 or if non-default pins are used,
894 | // need to reconfigure pins using GPIO matrix
895 | if (uart_num != 0 || uart_tx_gpio != 1 || uart_rx_gpio != 3) {
896 | // Change pin mode for GPIO1/3 from UART to GPIO
897 | PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, FUNC_U0RXD_GPIO3);
898 | PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD_GPIO1);
899 | // Route GPIO signals to/from pins
900 | // (arrays should be optimized away by the compiler)
901 | const uint32_t tx_idx_list[3] = { U0TXD_OUT_IDX, U1TXD_OUT_IDX, U2TXD_OUT_IDX };
902 | const uint32_t rx_idx_list[3] = { U0RXD_IN_IDX, U1RXD_IN_IDX, U2RXD_IN_IDX };
903 | const uint32_t tx_idx = tx_idx_list[uart_num];
904 | const uint32_t rx_idx = rx_idx_list[uart_num];
905 | gpio_matrix_out(uart_tx_gpio, tx_idx, 0, 0);
906 | gpio_matrix_in(uart_rx_gpio, rx_idx, 0);
907 | }
908 | #endif // CONFIG_CONSOLE_UART_CUSTOM
909 |
910 | // Set configured UART console baud rate
911 | const int uart_baud = CONFIG_CONSOLE_UART_BAUDRATE;
912 | uart_div_modify(uart_num, (rtc_clk_apb_freq_get() << 4) / uart_baud);
913 |
914 | #endif // CONFIG_CONSOLE_UART_NONE
915 | }
916 |
917 | static void wdt_reset_cpu0_info_enable(void)
918 | {
919 | //We do not reset core1 info here because it didn't work before cpu1 was up. So we put it into call_start_cpu1.
920 | DPORT_REG_SET_BIT(DPORT_PRO_CPU_RECORD_CTRL_REG, DPORT_PRO_CPU_PDEBUG_ENABLE | DPORT_PRO_CPU_RECORD_ENABLE);
921 | DPORT_REG_CLR_BIT(DPORT_PRO_CPU_RECORD_CTRL_REG, DPORT_PRO_CPU_RECORD_ENABLE);
922 | }
923 |
924 | static void wdt_reset_info_dump(int cpu)
925 | {
926 | uint32_t inst = 0, pid = 0, stat = 0, data = 0, pc = 0,
927 | lsstat = 0, lsaddr = 0, lsdata = 0, dstat = 0;
928 | const char *cpu_name = cpu ? "APP" : "PRO";
929 |
930 | if (cpu == 0) {
931 | stat = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_STATUS_REG);
932 | pid = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_PID_REG);
933 | inst = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_PDEBUGINST_REG);
934 | dstat = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_PDEBUGSTATUS_REG);
935 | data = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_PDEBUGDATA_REG);
936 | pc = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_PDEBUGPC_REG);
937 | lsstat = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_PDEBUGLS0STAT_REG);
938 | lsaddr = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_PDEBUGLS0ADDR_REG);
939 | lsdata = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_PDEBUGLS0DATA_REG);
940 |
941 | } else {
942 | stat = DPORT_REG_READ(DPORT_APP_CPU_RECORD_STATUS_REG);
943 | pid = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PID_REG);
944 | inst = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PDEBUGINST_REG);
945 | dstat = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PDEBUGSTATUS_REG);
946 | data = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PDEBUGDATA_REG);
947 | pc = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PDEBUGPC_REG);
948 | lsstat = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PDEBUGLS0STAT_REG);
949 | lsaddr = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PDEBUGLS0ADDR_REG);
950 | lsdata = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PDEBUGLS0DATA_REG);
951 | }
952 | if (DPORT_RECORD_PDEBUGINST_SZ(inst) == 0 &&
953 | DPORT_RECORD_PDEBUGSTATUS_BBCAUSE(dstat) == DPORT_RECORD_PDEBUGSTATUS_BBCAUSE_WAITI) {
954 | ESP_LOGW(TAG, "WDT reset info: %s CPU PC=0x%x (waiti mode)", cpu_name, pc);
955 | } else {
956 | ESP_LOGW(TAG, "WDT reset info: %s CPU PC=0x%x", cpu_name, pc);
957 | }
958 | ESP_LOGD(TAG, "WDT reset info: %s CPU STATUS 0x%08x", cpu_name, stat);
959 | ESP_LOGD(TAG, "WDT reset info: %s CPU PID 0x%08x", cpu_name, pid);
960 | ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGINST 0x%08x", cpu_name, inst);
961 | ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGSTATUS 0x%08x", cpu_name, dstat);
962 | ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGDATA 0x%08x", cpu_name, data);
963 | ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGPC 0x%08x", cpu_name, pc);
964 | ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGLS0STAT 0x%08x", cpu_name, lsstat);
965 | ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGLS0ADDR 0x%08x", cpu_name, lsaddr);
966 | ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGLS0DATA 0x%08x", cpu_name, lsdata);
967 | }
968 |
969 | static void wdt_reset_check(void)
970 | {
971 | int wdt_rst = 0;
972 | RESET_REASON rst_reas[2];
973 |
974 | rst_reas[0] = rtc_get_reset_reason(0);
975 | rst_reas[1] = rtc_get_reset_reason(1);
976 | if (rst_reas[0] == RTCWDT_SYS_RESET || rst_reas[0] == TG0WDT_SYS_RESET || rst_reas[0] == TG1WDT_SYS_RESET ||
977 | rst_reas[0] == TGWDT_CPU_RESET || rst_reas[0] == RTCWDT_CPU_RESET) {
978 | ESP_LOGW(TAG, "PRO CPU has been reset by WDT.");
979 | wdt_rst = 1;
980 | }
981 | if (rst_reas[1] == RTCWDT_SYS_RESET || rst_reas[1] == TG0WDT_SYS_RESET || rst_reas[1] == TG1WDT_SYS_RESET ||
982 | rst_reas[1] == TGWDT_CPU_RESET || rst_reas[1] == RTCWDT_CPU_RESET) {
983 | ESP_LOGW(TAG, "APP CPU has been reset by WDT.");
984 | wdt_rst = 1;
985 | }
986 | if (wdt_rst) {
987 | // if reset by WDT dump info from trace port
988 | wdt_reset_info_dump(0);
989 | wdt_reset_info_dump(1);
990 | }
991 | wdt_reset_cpu0_info_enable();
992 | }
993 |
994 | void __assert_func(const char *file, int line, const char *func, const char *expr)
995 | {
996 | ESP_LOGE(TAG, "Assert failed in %s, %s:%d (%s)", func, file, line, expr);
997 | while(1) {}
998 | }
999 |
--------------------------------------------------------------------------------
/components/bootloader/subproject/main/component.mk:
--------------------------------------------------------------------------------
1 | #
2 | # Main bootloader Makefile.
3 | #
4 | # This is basically the same as a component makefile, but in the case of the bootloader
5 | # we pull in bootloader-specific linker arguments.
6 | #
7 |
8 | LINKER_SCRIPTS := \
9 | esp32.bootloader.ld \
10 | $(IDF_PATH)/components/esp32/ld/esp32.rom.ld \
11 | $(IDF_PATH)/components/esp32/ld/esp32.rom.spiram_incompatible_fns.ld \
12 | $(IDF_PATH)/components/esp32/ld/esp32.peripherals.ld \
13 | esp32.bootloader.rom.ld
14 |
15 | ifndef CONFIG_SPI_FLASH_ROM_DRIVER_PATCH
16 | LINKER_SCRIPTS += $(IDF_PATH)/components/esp32/ld/esp32.rom.spiflash.ld
17 | endif
18 |
19 | COMPONENT_ADD_LDFLAGS += -L $(COMPONENT_PATH) $(addprefix -T ,$(LINKER_SCRIPTS))
20 |
21 | COMPONENT_ADD_LINKER_DEPS := $(LINKER_SCRIPTS)
22 |
--------------------------------------------------------------------------------
/components/bootloader/subproject/main/esp32.bootloader.ld:
--------------------------------------------------------------------------------
1 | /*
2 | Linker file used to link the bootloader.
3 | */
4 |
5 |
6 | /* Simplified memory map for the bootloader
7 |
8 | The main purpose is to make sure the bootloader can load into main memory
9 | without overwriting itself.
10 | */
11 | MEMORY
12 | {
13 | /* I/O */
14 | dport0_seg (RW) : org = 0x3FF00000, len = 0x10
15 | /* IRAM POOL1, used for APP CPU cache. We can abuse it in bootloader because APP CPU is still held in reset, the main app enables APP CPU cache */
16 | iram_seg (RWX) : org = 0x40078000, len = 0x8000
17 | /* 64k at the end of DRAM, after ROM bootloader stack */
18 | dram_seg (RW) : org = 0x3FFF0000, len = 0x10000
19 | }
20 |
21 | /* Default entry point: */
22 | ENTRY(call_start_cpu0);
23 |
24 |
25 | SECTIONS
26 | {
27 | .iram1.text :
28 | {
29 | . = ALIGN (16);
30 | *(.entry.text)
31 | *(.init.literal)
32 | *(.init)
33 | } > iram_seg
34 |
35 |
36 | /* Shared RAM */
37 | .dram0.bss (NOLOAD) :
38 | {
39 | . = ALIGN (8);
40 | _bss_start = ABSOLUTE(.);
41 | *(.dynsbss)
42 | *(.sbss)
43 | *(.sbss.*)
44 | *(.gnu.linkonce.sb.*)
45 | *(.scommon)
46 | *(.sbss2)
47 | *(.sbss2.*)
48 | *(.gnu.linkonce.sb2.*)
49 | *(.dynbss)
50 | *(.bss)
51 | *(.bss.*)
52 | *(.gnu.linkonce.b.*)
53 | *(COMMON)
54 | . = ALIGN (8);
55 | _bss_end = ABSOLUTE(.);
56 | } >dram_seg
57 |
58 | .dram0.data :
59 | {
60 | _data_start = ABSOLUTE(.);
61 | *(.data)
62 | *(.data.*)
63 | *(.gnu.linkonce.d.*)
64 | *(.data1)
65 | *(.sdata)
66 | *(.sdata.*)
67 | *(.gnu.linkonce.s.*)
68 | *(.sdata2)
69 | *(.sdata2.*)
70 | *(.gnu.linkonce.s2.*)
71 | *(.jcr)
72 | _data_end = ABSOLUTE(.);
73 | } >dram_seg
74 |
75 | .dram0.rodata :
76 | {
77 | _rodata_start = ABSOLUTE(.);
78 | *(.rodata)
79 | *(.rodata.*)
80 | *(.gnu.linkonce.r.*)
81 | *(.rodata1)
82 | __XT_EXCEPTION_TABLE_ = ABSOLUTE(.);
83 | *(.xt_except_table)
84 | *(.gcc_except_table)
85 | *(.gnu.linkonce.e.*)
86 | *(.gnu.version_r)
87 | *(.eh_frame)
88 | . = (. + 3) & ~ 3;
89 | /* C++ constructor and destructor tables, properly ordered: */
90 | __init_array_start = ABSOLUTE(.);
91 | KEEP (*crtbegin.o(.ctors))
92 | KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
93 | KEEP (*(SORT(.ctors.*)))
94 | KEEP (*(.ctors))
95 | __init_array_end = ABSOLUTE(.);
96 | KEEP (*crtbegin.o(.dtors))
97 | KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
98 | KEEP (*(SORT(.dtors.*)))
99 | KEEP (*(.dtors))
100 | /* C++ exception handlers table: */
101 | __XT_EXCEPTION_DESCS_ = ABSOLUTE(.);
102 | *(.xt_except_desc)
103 | *(.gnu.linkonce.h.*)
104 | __XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.);
105 | *(.xt_except_desc_end)
106 | *(.dynamic)
107 | *(.gnu.version_d)
108 | _rodata_end = ABSOLUTE(.);
109 | /* Literals are also RO data. */
110 | _lit4_start = ABSOLUTE(.);
111 | *(*.lit4)
112 | *(.lit4.*)
113 | *(.gnu.linkonce.lit4.*)
114 | _lit4_end = ABSOLUTE(.);
115 | . = ALIGN(4);
116 | _heap_start = ABSOLUTE(.);
117 | } >dram_seg
118 |
119 | .iram.text :
120 | {
121 | _stext = .;
122 | _text_start = ABSOLUTE(.);
123 | *(.literal .text .literal.* .text.* .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
124 | *(.iram1 .iram1.*) /* catch stray IRAM_ATTR */
125 | *(.fini.literal)
126 | *(.fini)
127 | *(.gnu.version)
128 | _text_end = ABSOLUTE(.);
129 | _etext = .;
130 | } > iram_seg
131 |
132 | }
133 |
--------------------------------------------------------------------------------
/components/bootloader/subproject/main/esp32.bootloader.rom.ld:
--------------------------------------------------------------------------------
1 | PROVIDE ( ets_update_cpu_frequency = 0x40008550 ); /* Updates g_ticks_per_us on the current CPU only; not on the other core */
2 |
--------------------------------------------------------------------------------
/components/bootloader/subproject/main/flash_qio_mode.c:
--------------------------------------------------------------------------------
1 | // Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 |
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 | #include
15 | #include
16 | #include "flash_qio_mode.h"
17 | #include "esp_log.h"
18 | #include "esp_err.h"
19 | #include "rom/spi_flash.h"
20 | #include "rom/efuse.h"
21 | #include "soc/spi_struct.h"
22 | #include "soc/efuse_reg.h"
23 | #include "sdkconfig.h"
24 |
25 | /* SPI flash controller */
26 | #define SPIFLASH SPI1
27 |
28 | /* SPI commands (actual on-wire commands not SPI controller bitmasks)
29 | Suitable for use with the execute_flash_command static function.
30 | */
31 | #define CMD_RDID 0x9F
32 | #define CMD_WRSR 0x01
33 | #define CMD_WRSR2 0x31 /* Not all SPI flash uses this command */
34 | #define CMD_WREN 0x06
35 | #define CMD_WRDI 0x04
36 | #define CMD_RDSR 0x05
37 | #define CMD_RDSR2 0x35 /* Not all SPI flash uses this command */
38 |
39 | static const char *TAG = "qio_mode";
40 |
41 | typedef unsigned (*read_status_fn_t)();
42 | typedef void (*write_status_fn_t)(unsigned);
43 |
44 | typedef struct __attribute__((packed)) {
45 | const char *manufacturer;
46 | uint8_t mfg_id; /* 8-bit JEDEC manufacturer ID */
47 | uint16_t flash_id; /* 16-bit JEDEC flash chip ID */
48 | uint16_t id_mask; /* Bits to match on in flash chip ID */
49 | read_status_fn_t read_status_fn;
50 | write_status_fn_t write_status_fn;
51 | uint8_t status_qio_bit;
52 | } qio_info_t;
53 |
54 | /* Read 8 bit status using RDSR command */
55 | static unsigned read_status_8b_rdsr();
56 | /* Read 8 bit status (second byte) using RDSR2 command */
57 | static unsigned read_status_8b_rdsr2();
58 | /* read 16 bit status using RDSR & RDSR2 (low and high bytes) */
59 | static unsigned read_status_16b_rdsr_rdsr2();
60 |
61 | /* Write 8 bit status using WRSR */
62 | static void write_status_8b_wrsr(unsigned new_status);
63 | /* Write 8 bit status (second byte) using WRSR2 */
64 | static void write_status_8b_wrsr2(unsigned new_status);
65 | /* Write 16 bit status using WRSR */
66 | static void write_status_16b_wrsr(unsigned new_status);
67 |
68 | #define ESP32_D2WD_WP_GPIO 7 /* ESP32-D2WD has this GPIO wired to WP pin of flash */
69 |
70 | #ifndef CONFIG_BOOTLOADER_SPI_WP_PIN // Set in menuconfig if SPI flasher config is set to a quad mode
71 | #define CONFIG_BOOTLOADER_SPI_WP_PIN ESP32_D2WD_WP_GPIO
72 | #endif
73 |
74 | /* Array of known flash chips and data to enable Quad I/O mode
75 |
76 | Manufacturer & flash ID can be tested by running "esptool.py
77 | flash_id"
78 |
79 | If manufacturer ID matches, and flash ID ORed with flash ID mask
80 | matches, enable_qio_mode() will execute "Read Cmd", test if bit
81 | number "QIE Bit" is set, and if not set it will call "Write Cmd"
82 | with this bit set.
83 |
84 | Searching of this table stops when the first match is found.
85 | */
86 | const static qio_info_t chip_data[] = {
87 | /* Manufacturer, mfg_id, flash_id, id mask, Read Status, Write Status, QIE Bit */
88 | { "MXIC", 0xC2, 0x2000, 0xFF00, read_status_8b_rdsr, write_status_8b_wrsr, 6 },
89 | { "ISSI", 0x9D, 0x4000, 0xCF00, read_status_8b_rdsr, write_status_8b_wrsr, 6 }, /* IDs 0x40xx, 0x70xx */
90 | { "WinBond", 0xEF, 0x4000, 0xFF00, read_status_16b_rdsr_rdsr2, write_status_16b_wrsr, 9 },
91 | { "GD", 0xC8, 0x6000, 0xFF00, read_status_16b_rdsr_rdsr2, write_status_16b_wrsr, 9 },
92 |
93 | /* Final entry is default entry, if no other IDs have matched.
94 |
95 | This approach works for chips including:
96 | GigaDevice (mfg ID 0xC8, flash IDs including 4016),
97 | FM25Q32 (QOUT mode only, mfg ID 0xA1, flash IDs including 4016)
98 | */
99 | { NULL, 0xFF, 0xFFFF, 0xFFFF, read_status_8b_rdsr2, write_status_8b_wrsr2, 1 },
100 | };
101 |
102 | #define NUM_CHIPS (sizeof(chip_data) / sizeof(qio_info_t))
103 |
104 | static esp_err_t enable_qio_mode(read_status_fn_t read_status_fn,
105 | write_status_fn_t write_status_fn,
106 | uint8_t status_qio_bit);
107 |
108 | /* Generic function to use the "user command" SPI controller functionality
109 | to send commands to the SPI flash and read the respopnse.
110 |
111 | The command passed here is always the on-the-wire command given to the SPI flash unit.
112 | */
113 | static uint32_t execute_flash_command(uint8_t command, uint32_t mosi_data, uint8_t mosi_len, uint8_t miso_len);
114 |
115 | /* dummy_len_plus values defined in ROM for SPI flash configuration */
116 | extern uint8_t g_rom_spiflash_dummy_len_plus[];
117 |
118 | void bootloader_enable_qio_mode(void)
119 | {
120 | uint32_t old_ctrl_reg;
121 | uint32_t raw_flash_id;
122 | uint8_t mfg_id;
123 | uint16_t flash_id;
124 | int i;
125 |
126 | ESP_LOGD(TAG, "Probing for QIO mode enable...");
127 | esp_rom_spiflash_wait_idle(&g_rom_flashchip);
128 |
129 | /* Set up some of the SPIFLASH user/ctrl variables which don't change
130 | while we're probing using execute_flash_command() */
131 | old_ctrl_reg = SPIFLASH.ctrl.val;
132 | SPIFLASH.ctrl.val = SPI_WP_REG; // keep WP high while idle, otherwise leave DIO mode
133 | SPIFLASH.user.usr_dummy = 0;
134 | SPIFLASH.user.usr_addr = 0;
135 | SPIFLASH.user.usr_command = 1;
136 | SPIFLASH.user2.usr_command_bitlen = 7;
137 |
138 | raw_flash_id = execute_flash_command(CMD_RDID, 0, 0, 24);
139 | ESP_LOGD(TAG, "Raw SPI flash chip id 0x%x", raw_flash_id);
140 |
141 | mfg_id = raw_flash_id & 0xFF;
142 | flash_id = (raw_flash_id >> 16) | (raw_flash_id & 0xFF00);
143 | ESP_LOGD(TAG, "Manufacturer ID 0x%02x chip ID 0x%04x", mfg_id, flash_id);
144 |
145 | for (i = 0; i < NUM_CHIPS-1; i++) {
146 | const qio_info_t *chip = &chip_data[i];
147 | if (mfg_id == chip->mfg_id && (flash_id & chip->id_mask) == (chip->flash_id & chip->id_mask)) {
148 | ESP_LOGI(TAG, "Enabling QIO for flash chip %s", chip_data[i].manufacturer);
149 | break;
150 | }
151 | }
152 |
153 | if (i == NUM_CHIPS - 1) {
154 | ESP_LOGI(TAG, "Enabling default flash chip QIO");
155 | }
156 |
157 | esp_err_t res = enable_qio_mode(chip_data[i].read_status_fn,
158 | chip_data[i].write_status_fn,
159 | chip_data[i].status_qio_bit);
160 | if (res != ESP_OK) {
161 | // Restore SPI flash CTRL setting, to keep us in DIO/DOUT mode
162 | SPIFLASH.ctrl.val = old_ctrl_reg;
163 | }
164 | }
165 |
166 | static esp_err_t enable_qio_mode(read_status_fn_t read_status_fn,
167 | write_status_fn_t write_status_fn,
168 | uint8_t status_qio_bit)
169 | {
170 | uint32_t status;
171 | const uint32_t spiconfig = ets_efuse_get_spiconfig();
172 |
173 | if (spiconfig != EFUSE_SPICONFIG_SPI_DEFAULTS && spiconfig != EFUSE_SPICONFIG_HSPI_DEFAULTS) {
174 | // spiconfig specifies a custom efuse pin configuration. This config defines all pins -except- WP,
175 | // which is compiled into the bootloader instead.
176 | //
177 | // Most commonly an overriden pin mapping means ESP32-D2WD or ESP32-PICOD4.
178 | //Warn if chip is ESP32-D2WD/ESP32-PICOD4 but someone has changed the WP pin
179 | //assignment from that chip's WP pin.
180 | uint32_t pkg_ver = REG_GET_FIELD(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_VER_PKG);
181 | if (CONFIG_BOOTLOADER_SPI_WP_PIN != ESP32_D2WD_WP_GPIO &&
182 | (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32D2WDQ5 ||
183 | pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD2 ||
184 | pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD4)) {
185 | ESP_LOGW(TAG, "Chip is ESP32-D2WD/ESP32-PICOD4 but flash WP pin is different value to internal flash");
186 | }
187 | }
188 |
189 | esp_rom_spiflash_wait_idle(&g_rom_flashchip);
190 |
191 | status = read_status_fn();
192 | ESP_LOGD(TAG, "Initial flash chip status 0x%x", status);
193 |
194 | if ((status & (1< 0;
261 | SPIFLASH.miso_dlen.usr_miso_dbitlen = miso_len ? (miso_len - 1) : 0;
262 | SPIFLASH.user.usr_mosi = mosi_len > 0;
263 | SPIFLASH.mosi_dlen.usr_mosi_dbitlen = mosi_len ? (mosi_len - 1) : 0;
264 | SPIFLASH.data_buf[0] = mosi_data;
265 |
266 | if (g_rom_spiflash_dummy_len_plus[1]) {
267 | /* When flash pins are mapped via GPIO matrix, need a dummy cycle before reading via MISO */
268 | if (miso_len > 0) {
269 | SPIFLASH.user.usr_dummy = 1;
270 | SPIFLASH.user1.usr_dummy_cyclelen = g_rom_spiflash_dummy_len_plus[1] - 1;
271 | } else {
272 | SPIFLASH.user.usr_dummy = 0;
273 | SPIFLASH.user1.usr_dummy_cyclelen = 0;
274 | }
275 | }
276 |
277 | SPIFLASH.cmd.usr = 1;
278 | while(SPIFLASH.cmd.usr != 0)
279 | { }
280 |
281 | return SPIFLASH.data_buf[0];
282 | }
283 |
--------------------------------------------------------------------------------
/components/bootloader/subproject/main/flash_qio_mode.h:
--------------------------------------------------------------------------------
1 | // Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 |
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 | #pragma once
15 |
16 | #ifdef __cplusplus
17 | extern "C" {
18 | #endif
19 |
20 | /** @brief Enable Quad I/O mode in bootloader (if configured)
21 | *
22 | * Queries attached SPI flash ID and sends correct SPI flash
23 | * commands to enable QIO or QOUT mode, then enables this mode.
24 | */
25 | void bootloader_enable_qio_mode(void);
26 |
27 | #ifdef __cplusplus
28 | }
29 | #endif
30 |
--------------------------------------------------------------------------------
/components/cpp_utils:
--------------------------------------------------------------------------------
1 | /home/esp32/esp/esp32-snippets/cpp_utils/
--------------------------------------------------------------------------------
/main/OTAServer.cpp:
--------------------------------------------------------------------------------
1 | #include "BLEDevice.h"
2 | #include "BLEServer.h"
3 | #include "BLEUtils.h"
4 | #include "BLE2902.h"
5 | #include
6 | #include
7 | #include
8 | #include "sdkconfig.h"
9 | #include
10 | #include
11 | #include "CPPNVS.h"
12 |
13 | #define WIFIINFO "wifi_info"
14 | #define OTAINFO "ota_info"
15 |
16 | extern void ota_app_main(void*, std::string, std::string);
17 | NVS* otaNVS;
18 |
19 | static char LOG_TAG[] = "SampleServer";
20 |
21 | typedef struct {
22 | char ip[16];
23 | char domain[64];
24 | char port[16];
25 | char path[64];
26 | char file_name[128];
27 | } ota_info_t ;
28 | ota_info_t ota;
29 |
30 | typedef struct {
31 | char ssid[32];
32 | char password[64];
33 | } wifi_info_t;
34 | wifi_info_t wifi;
35 |
36 | class CharacteristicCallback1 : public BLECharacteristicCallbacks { // domain name
37 | void onWrite(BLECharacteristic* pChar){
38 | sprintf(ota.domain, "%s", pChar->getValue().c_str());
39 | }
40 | };
41 |
42 | class CharacteristicCallback2 : public BLECharacteristicCallbacks { // ip
43 | void onWrite(BLECharacteristic* pChar){
44 | sprintf(ota.ip, "%s", pChar->getValue().c_str());
45 | }
46 | };
47 |
48 | class CharacteristicCallback3 : public BLECharacteristicCallbacks { // port
49 | void onWrite(BLECharacteristic* pChar){
50 | sprintf(ota.port, "%s", pChar->getValue().c_str());
51 | }
52 | };
53 |
54 | class CharacteristicCallback4 : public BLECharacteristicCallbacks { // path
55 | void onWrite(BLECharacteristic* pChar){
56 | sprintf(ota.path, "%s", pChar->getValue().c_str());
57 | }
58 | };
59 |
60 | class CharacteristicCallback5 : public BLECharacteristicCallbacks { // file name
61 | void onWrite(BLECharacteristic* pChar){
62 | sprintf(ota.file_name, "%s", pChar->getValue().c_str());
63 | otaNVS->set(OTAINFO, (uint8_t*)&ota, sizeof(ota_info_t));
64 | otaNVS->commit();
65 | ota_app_main(&ota, wifi.ssid, wifi.password);
66 | }
67 | };
68 |
69 | class CharacteristicCallback6 : public BLECharacteristicCallbacks { // wifi ssid
70 | void onWrite(BLECharacteristic* pChar){
71 | sprintf(wifi.ssid, "%s", pChar->getValue().c_str());
72 | }
73 | };
74 |
75 | class CharacteristicCallback7 : public BLECharacteristicCallbacks { // wifi password
76 | void onWrite(BLECharacteristic* pChar){
77 | sprintf(wifi.password, "%s", pChar->getValue().c_str());
78 | otaNVS->set(WIFIINFO, (uint8_t*)&wifi, sizeof(wifi_info_t));
79 | otaNVS->commit();
80 | }
81 | };
82 |
83 | class MySecurity : public BLESecurityCallbacks {
84 | uint32_t onPassKeyRequest(){
85 | ESP_LOGI(LOG_TAG, "PassKeyRequest");
86 | return 123456;
87 | }
88 | void onPassKeyNotify(uint32_t pass_key){
89 | ESP_LOGI(LOG_TAG, "On passkey Notify number:%d", pass_key);
90 | }
91 | bool onConfirmPIN(uint32_t){
92 | return true;
93 | }
94 | bool onSecurityRequest(){
95 | ESP_LOGI(LOG_TAG, "On Security Request");
96 | return true;
97 | }
98 |
99 | void onAuthenticationComplete(esp_ble_auth_cmpl_t cmpl){
100 | if(cmpl.success){
101 | uint16_t length;
102 | esp_ble_gap_get_whitelist_size(&length);
103 | ESP_LOGD(LOG_TAG, "size: %d", length);
104 | }
105 | }
106 | };
107 |
108 | class MainBLEServer: public Task {
109 | void run(void *data) {
110 |
111 | BLEDevice::init("ESP32");
112 | BLEServer* pServer = BLEDevice::createServer();
113 | // BLEDevice::setMTU(100);
114 | // BLEDevice::setEncryptionLevel(ESP_BLE_SEC_ENCRYPT);
115 | // BLEDevice::setSecurityCallbacks(new MySecurity());
116 |
117 | BLEService* pService = pServer->createService("00005b60-2745-479b-b006-56f3b4043c2c");
118 | BLEService* pService2 = pServer->createService("000018b0-f642-42dd-b048-aeb8e76e93de");
119 | size_t size = sizeof(ota_info_t);
120 | otaNVS->get(OTAINFO, (uint8_t*)&ota, size);
121 |
122 | BLECharacteristic* pCharacteristic = pService->createCharacteristic( // domain name
123 | BLEUUID("00005b61-2745-479b-b006-56f3b4043c2c"),
124 | BLECharacteristic::PROPERTY_READ |
125 | BLECharacteristic::PROPERTY_WRITE
126 | );
127 |
128 | // pCharacteristic->setAccessPermissions(ESP_GATT_PERM_READ_ENCRYPTED | ESP_GATT_PERM_WRITE_ENCRYPTED);
129 | pCharacteristic->setCallbacks(new CharacteristicCallback1());
130 |
131 | BLECharacteristic* pCharacteristic1 = pService->createCharacteristic( // IP
132 | BLEUUID("00005b62-2745-479b-b006-56f3b4043c2c"),
133 | BLECharacteristic::PROPERTY_READ |
134 | BLECharacteristic::PROPERTY_WRITE
135 | );
136 |
137 | // pCharacteristic1->setAccessPermissions(ESP_GATT_PERM_READ_ENCRYPTED | ESP_GATT_PERM_WRITE_ENCRYPTED);
138 | pCharacteristic1->setCallbacks(new CharacteristicCallback2());
139 |
140 | BLECharacteristic* pCharacteristic2 = pService->createCharacteristic( // port
141 | BLEUUID("00005b63-2745-479b-b006-56f3b4043c2c"),
142 | BLECharacteristic::PROPERTY_READ |
143 | BLECharacteristic::PROPERTY_WRITE
144 | );
145 |
146 | // pCharacteristic2->setAccessPermissions(ESP_GATT_PERM_READ_ENCRYPTED | ESP_GATT_PERM_WRITE_ENCRYPTED);
147 | pCharacteristic2->setCallbacks(new CharacteristicCallback3());
148 |
149 | BLECharacteristic* pCharacteristic3 = pService->createCharacteristic( // path
150 | BLEUUID("00005b64-2745-479b-b006-56f3b4043c2c"),
151 | BLECharacteristic::PROPERTY_READ |
152 | BLECharacteristic::PROPERTY_WRITE
153 | );
154 |
155 | // pCharacteristic3->setAccessPermissions(ESP_GATT_PERM_READ_ENCRYPTED | ESP_GATT_PERM_WRITE_ENCRYPTED);
156 | pCharacteristic3->setCallbacks(new CharacteristicCallback4());
157 |
158 | BLECharacteristic* pCharacteristic4 = pService->createCharacteristic( // file name
159 | BLEUUID("00005b65-2745-479b-b006-56f3b4043c2c"),
160 | BLECharacteristic::PROPERTY_READ |
161 | BLECharacteristic::PROPERTY_WRITE
162 | );
163 |
164 | // pCharacteristic4->setAccessPermissions(ESP_GATT_PERM_READ_ENCRYPTED | ESP_GATT_PERM_WRITE_ENCRYPTED);
165 | pCharacteristic4->setCallbacks(new CharacteristicCallback5());
166 |
167 | size = sizeof(wifi_info_t);
168 | otaNVS->get(WIFIINFO, (uint8_t*)&wifi, size);
169 | BLECharacteristic* pCharacteristic5 = pService2->createCharacteristic( // wifi ssid
170 | BLEUUID("000018b1-f642-42dd-b048-aeb8e76e93de"),
171 | BLECharacteristic::PROPERTY_READ |
172 | BLECharacteristic::PROPERTY_WRITE
173 | );
174 |
175 | // pCharacteristic5->setAccessPermissions(ESP_GATT_PERM_READ_ENCRYPTED | ESP_GATT_PERM_WRITE_ENCRYPTED);
176 | pCharacteristic5->setCallbacks(new CharacteristicCallback6());
177 |
178 | BLECharacteristic* pCharacteristic6 = pService2->createCharacteristic( // wifi password
179 | BLEUUID("000018b2-f642-42dd-b048-aeb8e76e93de"),
180 | BLECharacteristic::PROPERTY_READ |
181 | BLECharacteristic::PROPERTY_WRITE
182 | );
183 |
184 | // pCharacteristic6->setAccessPermissions(ESP_GATT_PERM_READ_ENCRYPTED | ESP_GATT_PERM_WRITE_ENCRYPTED);
185 | pCharacteristic6->setCallbacks(new CharacteristicCallback7());
186 |
187 | pService->start();
188 | pService2->start();
189 | if (strlen(ota.port) != 0) {
190 | pCharacteristic->setValue(ota.domain);
191 | pCharacteristic1->setValue(ota.ip);
192 | pCharacteristic2->setValue(ota.port);
193 | pCharacteristic3->setValue(ota.path);
194 | pCharacteristic4->setValue(ota.file_name);
195 | }
196 | if (strlen(wifi.ssid) != 0) {
197 | pCharacteristic5->setValue(wifi.ssid);
198 | pCharacteristic6->setValue(wifi.password);
199 | }
200 |
201 | BLEAdvertising* pAdvertising = pServer->getAdvertising();
202 | pAdvertising->start();
203 | /*
204 | BLESecurity *pSecurity = new BLESecurity();
205 | pSecurity->setAuthenticationMode(ESP_LE_AUTH_REQ_SC_BOND);
206 | pSecurity->setCapability(ESP_IO_CAP_NONE);
207 | pSecurity->setInitEncryptionKey(ESP_BLE_ENC_KEY_MASK | ESP_BLE_ID_KEY_MASK);
208 | */
209 | ESP_LOGD(LOG_TAG, "Advertising started!");
210 | delay(portMAX_DELAY);
211 | }
212 | };
213 |
214 |
215 | void OTAServer(void)
216 | {
217 |
218 | otaNVS = new NVS("ota_nvs");
219 | memset(&ota, 0, sizeof(ota));
220 | memset(&wifi, 0, sizeof(wifi));
221 |
222 | MainBLEServer* pMainBleServer = new MainBLEServer();
223 | pMainBleServer->setStackSize(20000);
224 | pMainBleServer->start();
225 |
226 | } // app_main
227 |
--------------------------------------------------------------------------------
/main/component.mk:
--------------------------------------------------------------------------------
1 | #
2 | # Main component makefile.
3 | #
4 | # This Makefile can be left empty. By default, it will take the sources in the
5 | # src/ directory, compile them and link them into lib(subdirectory_name).a
6 | # in the build directory. This behaviour is entirely configurable,
7 | # please read the ESP-IDF documents if you need to do this.
8 | #
9 |
--------------------------------------------------------------------------------
/main/main.cpp:
--------------------------------------------------------------------------------
1 | /**
2 | * Main file for running the BLE samples.
3 | */
4 | #include
5 | #include
6 | #include
7 |
8 |
9 | extern void OTAServer(void);
10 | extern "C" {
11 | void app_main(void);
12 | }
13 |
14 | void app_main(void) {
15 | OTAServer();
16 | } // app_main
17 |
18 |
--------------------------------------------------------------------------------
/main/ota_main.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 |
7 | #include "freertos/FreeRTOS.h"
8 | #include "freertos/task.h"
9 | #include "freertos/event_groups.h"
10 |
11 | #include "esp_system.h"
12 | #include "esp_wifi.h"
13 | #include "esp_event_loop.h"
14 | #include "esp_log.h"
15 | #include "esp_ota_ops.h"
16 |
17 | #include "nvs.h"
18 | #include "nvs_flash.h"
19 | #include "sdkconfig.h"
20 |
21 | #define EXAMPLE_WIFI_SSID
22 | #define EXAMPLE_WIFI_PASS
23 | /*#define OTA_SERVER_IP "esp32.chege.eu.org"
24 | #define EXAMPLE_SERVER_PORT "80"
25 | #define EXAMPLE_PATH "examples"
26 | #define EXAMPLE_FILENAME "ota.bin"*/
27 | #define BUFFSIZE 1024
28 | #define TEXT_BUFFSIZE 1024
29 | const int CONNECTED_BIT = BIT0;
30 |
31 | std::string ssid;
32 | std::string pass;
33 |
34 | typedef struct {
35 | char ip[16];
36 | char domain[64];
37 | char port[16];
38 | char path[64];
39 | char file_name[128];
40 | } ota_info_t ;
41 |
42 | static EventGroupHandle_t wifi_event_group;
43 |
44 | static const char *TAG = "ota";
45 | /*an ota data write buffer ready to write to the flash*/
46 | static char ota_write_data[BUFFSIZE + 1] = { 0 };
47 | /*an packet receive buffer*/
48 | static char text[BUFFSIZE + 1] = { 0 };
49 | /* an image total length*/
50 | static int binary_file_length = 0;
51 | /*socket id*/
52 | static int socket_id = -1;
53 | static char http_request[64] = {0};
54 | static ota_info_t* otaInfo;
55 | static void __attribute__((noreturn)) task_fatal_error()
56 | {
57 | ESP_LOGE(TAG, "Exiting task due to fatal error...");
58 | close(socket_id);
59 | (void)vTaskDelete(NULL);
60 |
61 | while (1) {
62 | ;
63 | }
64 | }
65 |
66 | static int read_until(char *buffer, char delim, int len)
67 | {
68 | int i = 0;
69 | while (buffer[i] != delim && i < len) {
70 | ++i;
71 | }
72 | return i + 1;
73 | }
74 |
75 | /* resolve a packet from http socket
76 | * return true if packet including \r\n\r\n that means http packet header finished,start to receive packet body
77 | * otherwise return false
78 | * */
79 | static bool read_past_http_header(char text[], int total_len, esp_ota_handle_t update_handle)
80 | {
81 | /* i means current position */
82 | int i = 0, i_read_len = 0;
83 | while (text[i] != 0 && i < total_len) {
84 | i_read_len = read_until(&text[i], '\n', total_len);
85 | // if we resolve \r\n line,we think packet header is finished
86 | if (i_read_len == 2) {
87 | int i_write_len = total_len - (i + 2);
88 | memset(ota_write_data, 0, BUFFSIZE);
89 | /*copy first http packet body to write buffer*/
90 | memcpy(ota_write_data, &(text[i + 2]), i_write_len);
91 |
92 | esp_err_t err = esp_ota_write( update_handle, (const void *)ota_write_data, i_write_len);
93 | if (err != ESP_OK) {
94 | ESP_LOGE(TAG, "Error: esp_ota_write failed! err=0x%x", err);
95 | return false;
96 | } else {
97 | ESP_LOGI(TAG, "esp_ota_write header OK");
98 | binary_file_length += i_write_len;
99 | }
100 | return true;
101 | }
102 | i += i_read_len;
103 | }
104 | return false;
105 | }
106 |
107 | ip_addr_t addr;
108 | bool bDNSFound = false;
109 | static void dns_found_cb(const char *name, const ip_addr_t *ipaddr, void *callback_arg)
110 | {
111 | ESP_LOGI("ota", "%sfound host ip %s", ipaddr == NULL?"NOT ":"", otaInfo->domain);
112 | if(ipaddr == NULL)
113 | task_fatal_error();
114 | addr = *ipaddr;
115 | bDNSFound = true;
116 | ESP_LOGI("ota", "DNS found IP: %i.%i.%i.%i, host name: %s",
117 | ip4_addr1(&addr.u_addr.ip4),
118 | ip4_addr2(&addr.u_addr.ip4),
119 | ip4_addr3(&addr.u_addr.ip4),
120 | ip4_addr4(&addr.u_addr.ip4),
121 | otaInfo->domain);
122 | vTaskDelay(2000/portTICK_PERIOD_MS);
123 | }
124 |
125 | static bool connect_to_http_server()
126 | {
127 |
128 | // todo if nvs ota path empty set default file name
129 | // todo if nvs ota server empty set default server
130 | // todo if nvs ota server ip set server ip
131 | ip_addr_t addr1;
132 | IP_ADDR4( &addr1, 8,8,4,4 ); // DNS server 0
133 | dns_setserver(0, &addr1);
134 | IP_ADDR4( &addr1, 8,8,8,8 ); // DNS server 1
135 | dns_setserver(1, &addr1);
136 |
137 | err_t err = dns_gethostbyname(otaInfo->domain, &addr, &dns_found_cb, NULL);
138 |
139 | while( !bDNSFound ){
140 | vTaskDelay(150/portTICK_PERIOD_MS);
141 | }
142 |
143 | inet_pton(AF_INET, otaInfo->ip, &addr.u_addr.ip4);
144 | ESP_LOGD(TAG, "Server IP: %d Server Port:%s", addr.u_addr.ip4.addr, otaInfo->port);
145 | sprintf(http_request, "GET /%s/%s HTTP/1.1\r\nHost: %s:%s \r\n\r\n", otaInfo->path, otaInfo->file_name, strlen(otaInfo->ip)!=0 ? otaInfo->ip : otaInfo->domain, otaInfo->port);
146 | ESP_LOGI(TAG, "request: %s", http_request);
147 |
148 | int http_connect_flag = -1;
149 | struct sockaddr_in sock_info;
150 |
151 | socket_id = socket(AF_INET, SOCK_STREAM, 0);
152 | if (socket_id == -1) {
153 | ESP_LOGE(TAG, "Create socket failed!");
154 | return false;
155 | }
156 |
157 | // set connect info
158 | memset(&sock_info, 0, sizeof(struct sockaddr_in));
159 | sock_info.sin_family = AF_INET;
160 | sock_info.sin_addr.s_addr = addr.u_addr.ip4.addr;
161 | sock_info.sin_port = htons(atoi(otaInfo->port));
162 |
163 | // connect to http server
164 | http_connect_flag = connect(socket_id, (struct sockaddr *)&sock_info, sizeof(sock_info));
165 | if (http_connect_flag == -1) {
166 | ESP_LOGE(TAG, "Connect to server failed! errno=%d", errno);
167 | close(socket_id);
168 | return false;
169 | } else {
170 | ESP_LOGI(TAG, "Connected to server");
171 | return true;
172 | }
173 | return false;
174 | }
175 |
176 | static void ota_example_task(void *pvParameter)
177 | {
178 | esp_err_t err;
179 | /* update handle : set by esp_ota_begin(), must be freed via esp_ota_end() */
180 | esp_ota_handle_t update_handle = 0 ;
181 | const esp_partition_t *update_partition = NULL;
182 |
183 | ESP_LOGI(TAG, "Starting OTA example...");
184 |
185 | const esp_partition_t *configured = esp_ota_get_boot_partition();
186 | const esp_partition_t *running = esp_ota_get_running_partition();
187 |
188 | if (configured != running) {
189 | ESP_LOGW(TAG, "Configured OTA boot partition at offset 0x%08x, but running from offset 0x%08x",
190 | configured->address, running->address);
191 | ESP_LOGW(TAG, "(This can happen if either the OTA boot data or preferred boot image become corrupted somehow.)");
192 | }
193 | ESP_LOGI(TAG, "Running partition type %d subtype %d (offset 0x%08x)",
194 | running->type, running->subtype, running->address);
195 |
196 | ESP_LOGI(TAG, "Connect to Wifi ! Start to Connect to Server....");
197 |
198 | /*connect to http server*/
199 | if (connect_to_http_server()) {
200 | ESP_LOGI(TAG, "Connected to http server");
201 | } else {
202 | ESP_LOGE(TAG, "Connect to http server failed!");
203 | task_fatal_error();
204 | }
205 |
206 | int res = -1;
207 | /*send GET request to http server*/
208 | res = send(socket_id, http_request, strlen(http_request), 0);
209 | if (res == -1) {
210 | ESP_LOGE(TAG, "Send GET request to server failed");
211 | task_fatal_error();
212 | } else {
213 | ESP_LOGI(TAG, "Send GET request to server succeeded");
214 | }
215 |
216 | update_partition = esp_ota_get_next_update_partition(NULL);
217 | assert(update_partition != NULL);
218 | ESP_LOGI(TAG, "Writing to partition subtype %d at offset 0x%x",
219 | update_partition->subtype, update_partition->address);
220 |
221 | err = esp_ota_begin(update_partition, OTA_SIZE_UNKNOWN, &update_handle);
222 | if (err != ESP_OK) {
223 | ESP_LOGE(TAG, "esp_ota_begin failed, error=%d", err);
224 | task_fatal_error();
225 | }
226 | ESP_LOGI(TAG, "esp_ota_begin succeeded");
227 |
228 | bool resp_body_start = false, flag = true;
229 | /*deal with all receive packet*/
230 | while (flag) {
231 | memset(text, 0, TEXT_BUFFSIZE);
232 | memset(ota_write_data, 0, BUFFSIZE);
233 | int buff_len = recv(socket_id, text, TEXT_BUFFSIZE, 0);
234 | if (buff_len < 0) { /*receive error*/
235 | ESP_LOGE(TAG, "Error: receive data error! errno=%d", errno);
236 | task_fatal_error();
237 | } else if (buff_len > 0 && !resp_body_start) { /*deal with response header*/
238 | memcpy(ota_write_data, text, buff_len);
239 | resp_body_start = read_past_http_header(text, buff_len, update_handle);
240 | } else if (buff_len > 0 && resp_body_start) { /*deal with response body*/
241 | memcpy(ota_write_data, text, buff_len);
242 | err = esp_ota_write( update_handle, (const void *)ota_write_data, buff_len);
243 | if (err != ESP_OK) {
244 | ESP_LOGE(TAG, "Error: esp_ota_write failed! err=0x%x", err);
245 | task_fatal_error();
246 | }
247 | binary_file_length += buff_len;
248 | ESP_LOGI(TAG, "Have written image length %d", binary_file_length);
249 | } else if (buff_len == 0) { /*packet over*/
250 | flag = false;
251 | ESP_LOGI(TAG, "Connection closed, all packets received");
252 | close(socket_id);
253 | } else {
254 | ESP_LOGE(TAG, "Unexpected recv result");
255 | }
256 | }
257 |
258 | ESP_LOGI(TAG, "Total Write binary data length : %d", binary_file_length);
259 |
260 | if (esp_ota_end(update_handle) != ESP_OK) {
261 | ESP_LOGE(TAG, "esp_ota_end failed!");
262 | task_fatal_error();
263 | }
264 | err = esp_ota_set_boot_partition(update_partition);
265 | if (err != ESP_OK) {
266 | ESP_LOGE(TAG, "esp_ota_set_boot_partition failed! err=0x%x", err);
267 | task_fatal_error();
268 | }
269 | ESP_LOGI(TAG, "Prepare to restart system!");
270 | esp_restart();
271 | return ;
272 | }
273 |
274 | static esp_err_t event_handler(void *ctx, system_event_t *event)
275 | {
276 | switch (event->event_id) {
277 | case SYSTEM_EVENT_STA_START:
278 | esp_wifi_connect();
279 | break;
280 | case SYSTEM_EVENT_STA_GOT_IP:
281 | xEventGroupSetBits(wifi_event_group, CONNECTED_BIT);
282 | break;
283 | case SYSTEM_EVENT_STA_DISCONNECTED:
284 | /* This is a workaround as ESP32 WiFi libs don't currently
285 | auto-reassociate. */
286 | esp_wifi_connect();
287 | xEventGroupClearBits(wifi_event_group, CONNECTED_BIT);
288 | break;
289 | default:
290 | break;
291 | }
292 | return ESP_OK;
293 | }
294 |
295 | static void initialise_wifi(void)
296 | {
297 | tcpip_adapter_init();
298 | wifi_event_group = xEventGroupCreate();
299 | ESP_ERROR_CHECK( esp_event_loop_init(event_handler, NULL) );
300 | wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
301 | ESP_ERROR_CHECK( esp_wifi_init(&cfg) );
302 | ESP_ERROR_CHECK( esp_wifi_set_storage(WIFI_STORAGE_RAM) );
303 | wifi_config_t sta_config;
304 | ::memset(&sta_config, 0, sizeof(sta_config));
305 | ::memcpy(sta_config.sta.ssid, ssid.data(), ssid.size());
306 | ::memcpy(sta_config.sta.password, pass.data(), pass.size());
307 | sta_config.sta.bssid_set = 0;
308 |
309 | ESP_LOGI(TAG, "Setting WiFi configuration SSID %s...", sta_config.sta.ssid);
310 | ESP_ERROR_CHECK( esp_wifi_set_mode(WIFI_MODE_STA) );
311 | ESP_ERROR_CHECK( esp_wifi_set_config(ESP_IF_WIFI_STA, &sta_config) );
312 | ESP_ERROR_CHECK( esp_wifi_start() );
313 | }
314 | #include "CPPNVS.h"
315 | #define WIFIINFO "wifi_info"
316 | #define OTAINFO "ota_info"
317 |
318 | //void ota_app_main()
319 | void ota_app_main(void* conn, std::string wifi_ssid, std::string wifi_pass)
320 | {
321 | // Initialize NVS.
322 | esp_err_t err = nvs_flash_init();
323 | if (err == ESP_ERR_NVS_NO_FREE_PAGES) {
324 | // OTA app partition table has a smaller NVS partition size than the non-OTA
325 | // partition table. This size mismatch may cause NVS initialization to fail.
326 | // If this happens, we erase NVS partition and initialize NVS again.
327 | ESP_ERROR_CHECK(nvs_flash_erase());
328 | err = nvs_flash_init();
329 | }
330 | ESP_ERROR_CHECK( err );
331 |
332 | if(wifi_ssid!=""){
333 | ssid = wifi_ssid;
334 | pass = wifi_pass;
335 | }//else{
336 | /* typedef struct {
337 | char ssid[32];
338 | char password[64];
339 | } wifi_info_t;
340 | wifi_info_t wifi;
341 |
342 | NVS* otaNVS = new NVS("ota_nvs");
343 | size_t size = sizeof(wifi_info_t);
344 | otaNVS->get(WIFIINFO, (uint8_t*)&wifi, size);*/
345 |
346 | // }
347 | if(conn!=nullptr){
348 | otaInfo = (ota_info_t*)conn;
349 | ESP_LOGI(TAG, "GET /%s/%s HTTP/1.1\r\nHost: %s:%s \r\n\r\n", otaInfo->path, otaInfo->file_name, otaInfo->domain, otaInfo->port);
350 | }
351 | initialise_wifi();
352 |
353 | xTaskCreate(&ota_example_task, "ota_example_task", 8192, NULL, 5, NULL);
354 | }
355 |
--------------------------------------------------------------------------------
/ota_app1.aia:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chegewara/esp32-ota-with-ble-setup/7bb46defccc4b051e4904c3e54c3e97b609ae345/ota_app1.aia
--------------------------------------------------------------------------------
/partitions.csv:
--------------------------------------------------------------------------------
1 | # Espressif ESP32 Partition Table
2 | # Name, Type, SubType, Offset, Size
3 | nvs, data, nvs, 0x9000, 0x4000
4 | otadata, data, ota, 0xd000, 0x2000
5 | phy_init, data, phy, 0xf000, 0x1000
6 | factory, app, factory, 0x10000, 0x140000
7 | ota, app, ota_0, , 0x2b0000
8 |
--------------------------------------------------------------------------------
/sdkconfig:
--------------------------------------------------------------------------------
1 | #
2 | # Automatically generated file; DO NOT EDIT.
3 | # Espressif IoT Development Framework Configuration
4 | #
5 |
6 | #
7 | # SDK tool configuration
8 | #
9 | CONFIG_TOOLPREFIX="xtensa-esp32-elf-"
10 | CONFIG_PYTHON="python"
11 | CONFIG_MAKE_WARN_UNDEFINED_VARIABLES=y
12 |
13 | #
14 | # Bootloader config
15 | #
16 | CONFIG_LOG_BOOTLOADER_LEVEL_NONE=
17 | CONFIG_LOG_BOOTLOADER_LEVEL_ERROR=
18 | CONFIG_LOG_BOOTLOADER_LEVEL_WARN=
19 | CONFIG_LOG_BOOTLOADER_LEVEL_INFO=
20 | CONFIG_LOG_BOOTLOADER_LEVEL_DEBUG=
21 | CONFIG_LOG_BOOTLOADER_LEVEL_VERBOSE=y
22 | CONFIG_LOG_BOOTLOADER_LEVEL=5
23 | CONFIG_BOOTLOADER_SPI_WP_PIN=7
24 | CONFIG_BOOTLOADER_VDDSDIO_BOOST=y
25 |
26 | #
27 | # Security features
28 | #
29 | CONFIG_SECURE_BOOT_ENABLED=
30 | CONFIG_FLASH_ENCRYPTION_ENABLED=
31 |
32 | #
33 | # Serial flasher config
34 | #
35 | CONFIG_ESPTOOLPY_PORT="/dev/ttyUSB0"
36 | CONFIG_ESPTOOLPY_BAUD_115200B=
37 | CONFIG_ESPTOOLPY_BAUD_230400B=
38 | CONFIG_ESPTOOLPY_BAUD_921600B=y
39 | CONFIG_ESPTOOLPY_BAUD_2MB=
40 | CONFIG_ESPTOOLPY_BAUD_OTHER=
41 | CONFIG_ESPTOOLPY_BAUD_OTHER_VAL=115200
42 | CONFIG_ESPTOOLPY_BAUD=921600
43 | CONFIG_ESPTOOLPY_COMPRESSED=y
44 | CONFIG_FLASHMODE_QIO=y
45 | CONFIG_FLASHMODE_QOUT=
46 | CONFIG_FLASHMODE_DIO=
47 | CONFIG_FLASHMODE_DOUT=
48 | CONFIG_ESPTOOLPY_FLASHMODE="dio"
49 | CONFIG_ESPTOOLPY_FLASHFREQ_80M=
50 | CONFIG_ESPTOOLPY_FLASHFREQ_40M=y
51 | CONFIG_ESPTOOLPY_FLASHFREQ_26M=
52 | CONFIG_ESPTOOLPY_FLASHFREQ_20M=
53 | CONFIG_ESPTOOLPY_FLASHFREQ="40m"
54 | CONFIG_ESPTOOLPY_FLASHSIZE_1MB=
55 | CONFIG_ESPTOOLPY_FLASHSIZE_2MB=
56 | CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
57 | CONFIG_ESPTOOLPY_FLASHSIZE_8MB=
58 | CONFIG_ESPTOOLPY_FLASHSIZE_16MB=
59 | CONFIG_ESPTOOLPY_FLASHSIZE="4MB"
60 | CONFIG_ESPTOOLPY_FLASHSIZE_DETECT=
61 | CONFIG_ESPTOOLPY_BEFORE_RESET=y
62 | CONFIG_ESPTOOLPY_BEFORE_NORESET=
63 | CONFIG_ESPTOOLPY_BEFORE="default_reset"
64 | CONFIG_ESPTOOLPY_AFTER_RESET=y
65 | CONFIG_ESPTOOLPY_AFTER_NORESET=
66 | CONFIG_ESPTOOLPY_AFTER="hard_reset"
67 | CONFIG_MONITOR_BAUD_9600B=
68 | CONFIG_MONITOR_BAUD_57600B=
69 | CONFIG_MONITOR_BAUD_115200B=y
70 | CONFIG_MONITOR_BAUD_230400B=
71 | CONFIG_MONITOR_BAUD_921600B=
72 | CONFIG_MONITOR_BAUD_2MB=
73 | CONFIG_MONITOR_BAUD_OTHER=
74 | CONFIG_MONITOR_BAUD_OTHER_VAL=115200
75 | CONFIG_MONITOR_BAUD=115200
76 |
77 | #
78 | # Partition Table
79 | #
80 | CONFIG_PARTITION_TABLE_SINGLE_APP=
81 | CONFIG_PARTITION_TABLE_TWO_OTA=
82 | CONFIG_PARTITION_TABLE_CUSTOM=y
83 | CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
84 | CONFIG_PARTITION_TABLE_CUSTOM_APP_BIN_OFFSET=0x10000
85 | CONFIG_PARTITION_TABLE_FILENAME="partitions.csv"
86 | CONFIG_APP_OFFSET=0x10000
87 |
88 | #
89 | # Compiler options
90 | #
91 | CONFIG_OPTIMIZATION_LEVEL_DEBUG=
92 | CONFIG_OPTIMIZATION_LEVEL_RELEASE=y
93 | CONFIG_OPTIMIZATION_ASSERTIONS_ENABLED=y
94 | CONFIG_OPTIMIZATION_ASSERTIONS_SILENT=
95 | CONFIG_OPTIMIZATION_ASSERTIONS_DISABLED=
96 | CONFIG_CXX_EXCEPTIONS=y
97 | CONFIG_CXX_EXCEPTIONS_EMG_POOL_SIZE=0
98 | CONFIG_STACK_CHECK_NONE=y
99 | CONFIG_STACK_CHECK_NORM=
100 | CONFIG_STACK_CHECK_STRONG=
101 | CONFIG_STACK_CHECK_ALL=
102 | CONFIG_STACK_CHECK=
103 |
104 | #
105 | # Component config
106 | #
107 |
108 | #
109 | # Application Level Tracing
110 | #
111 | CONFIG_ESP32_APPTRACE_DEST_TRAX=
112 | CONFIG_ESP32_APPTRACE_DEST_NONE=y
113 | CONFIG_ESP32_APPTRACE_ENABLE=
114 | CONFIG_ESP32_APPTRACE_LOCK_ENABLE=y
115 |
116 | #
117 | # FreeRTOS SystemView Tracing
118 | #
119 | CONFIG_AWS_IOT_SDK=
120 |
121 | #
122 | # Bluetooth
123 | #
124 | CONFIG_BT_ENABLED=y
125 | CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE_0=y
126 | CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE_1=
127 | CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE=0
128 | CONFIG_BTDM_CONTROLLER_HCI_MODE_VHCI=y
129 | CONFIG_BTDM_CONTROLLER_HCI_MODE_UART_H4=
130 | CONFIG_BLUEDROID_ENABLED=y
131 | CONFIG_BLUEDROID_PINNED_TO_CORE_0=y
132 | CONFIG_BLUEDROID_PINNED_TO_CORE_1=
133 | CONFIG_BLUEDROID_PINNED_TO_CORE=0
134 | CONFIG_BTC_TASK_STACK_SIZE=3072
135 | CONFIG_BLUEDROID_MEM_DEBUG=
136 | CONFIG_CLASSIC_BT_ENABLED=
137 | CONFIG_GATTS_ENABLE=y
138 | CONFIG_GATTC_ENABLE=y
139 | CONFIG_BLE_SMP_ENABLE=y
140 | CONFIG_BT_STACK_NO_LOG=
141 | CONFIG_BT_ACL_CONNECTIONS=4
142 | CONFIG_SMP_ENABLE=y
143 | CONFIG_BT_RESERVE_DRAM=0x10000
144 |
145 | #
146 | # C++ settings
147 | #
148 | CONFIG_LIBCURL_PRESENT=
149 | CONFIG_U8G2_PRESENT=
150 | CONFIG_MONGOOSE_PRESENT=
151 |
152 | #
153 | # ESP32-specific
154 | #
155 | CONFIG_ESP32_DEFAULT_CPU_FREQ_80=
156 | CONFIG_ESP32_DEFAULT_CPU_FREQ_160=
157 | CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y
158 | CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ=240
159 | CONFIG_MEMMAP_SMP=y
160 | CONFIG_SPIRAM_SUPPORT=
161 | CONFIG_MEMMAP_TRACEMEM=
162 | CONFIG_MEMMAP_TRACEMEM_TWOBANKS=
163 | CONFIG_ESP32_TRAX=
164 | CONFIG_TRACEMEM_RESERVE_DRAM=0x0
165 | CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH=
166 | CONFIG_ESP32_ENABLE_COREDUMP_TO_UART=
167 | CONFIG_ESP32_ENABLE_COREDUMP_TO_NONE=y
168 | CONFIG_ESP32_ENABLE_COREDUMP=
169 | CONFIG_TWO_UNIVERSAL_MAC_ADDRESS=
170 | CONFIG_FOUR_UNIVERSAL_MAC_ADDRESS=y
171 | CONFIG_NUMBER_OF_UNIVERSAL_MAC_ADDRESS=4
172 | CONFIG_SYSTEM_EVENT_QUEUE_SIZE=32
173 | CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE=2048
174 | CONFIG_MAIN_TASK_STACK_SIZE=4096
175 | CONFIG_IPC_TASK_STACK_SIZE=1024
176 | CONFIG_TIMER_TASK_STACK_SIZE=3584
177 | CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF=y
178 | CONFIG_NEWLIB_STDOUT_LINE_ENDING_LF=
179 | CONFIG_NEWLIB_STDOUT_LINE_ENDING_CR=
180 | CONFIG_NEWLIB_STDIN_LINE_ENDING_CRLF=
181 | CONFIG_NEWLIB_STDIN_LINE_ENDING_LF=
182 | CONFIG_NEWLIB_STDIN_LINE_ENDING_CR=y
183 | CONFIG_NEWLIB_NANO_FORMAT=
184 | CONFIG_CONSOLE_UART_DEFAULT=y
185 | CONFIG_CONSOLE_UART_CUSTOM=
186 | CONFIG_CONSOLE_UART_NONE=
187 | CONFIG_CONSOLE_UART_NUM=0
188 | CONFIG_CONSOLE_UART_BAUDRATE=115200
189 | CONFIG_ULP_COPROC_ENABLED=
190 | CONFIG_ULP_COPROC_RESERVE_MEM=0
191 | CONFIG_ESP32_PANIC_PRINT_HALT=
192 | CONFIG_ESP32_PANIC_PRINT_REBOOT=y
193 | CONFIG_ESP32_PANIC_SILENT_REBOOT=
194 | CONFIG_ESP32_PANIC_GDBSTUB=
195 | CONFIG_ESP32_DEBUG_OCDAWARE=y
196 | CONFIG_INT_WDT=y
197 | CONFIG_INT_WDT_TIMEOUT_MS=300
198 | CONFIG_INT_WDT_CHECK_CPU1=y
199 | CONFIG_TASK_WDT=y
200 | CONFIG_TASK_WDT_PANIC=
201 | CONFIG_TASK_WDT_TIMEOUT_S=5
202 | CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU0=y
203 | CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU1=y
204 | CONFIG_BROWNOUT_DET=y
205 | CONFIG_BROWNOUT_DET_LVL_SEL_0=y
206 | CONFIG_BROWNOUT_DET_LVL_SEL_1=
207 | CONFIG_BROWNOUT_DET_LVL_SEL_2=
208 | CONFIG_BROWNOUT_DET_LVL_SEL_3=
209 | CONFIG_BROWNOUT_DET_LVL_SEL_4=
210 | CONFIG_BROWNOUT_DET_LVL_SEL_5=
211 | CONFIG_BROWNOUT_DET_LVL_SEL_6=
212 | CONFIG_BROWNOUT_DET_LVL_SEL_7=
213 | CONFIG_BROWNOUT_DET_LVL=0
214 | CONFIG_ESP32_TIME_SYSCALL_USE_RTC_FRC1=y
215 | CONFIG_ESP32_TIME_SYSCALL_USE_RTC=
216 | CONFIG_ESP32_TIME_SYSCALL_USE_FRC1=
217 | CONFIG_ESP32_TIME_SYSCALL_USE_NONE=
218 | CONFIG_ESP32_RTC_CLOCK_SOURCE_INTERNAL_RC=y
219 | CONFIG_ESP32_RTC_CLOCK_SOURCE_EXTERNAL_CRYSTAL=
220 | CONFIG_ESP32_RTC_CLK_CAL_CYCLES=1024
221 | CONFIG_ESP32_DEEP_SLEEP_WAKEUP_DELAY=2000
222 | CONFIG_ESP32_XTAL_FREQ_40=y
223 | CONFIG_ESP32_XTAL_FREQ_26=
224 | CONFIG_ESP32_XTAL_FREQ_AUTO=
225 | CONFIG_ESP32_XTAL_FREQ=40
226 | CONFIG_DISABLE_BASIC_ROM_CONSOLE=
227 | CONFIG_ESP_TIMER_PROFILING=
228 | CONFIG_COMPATIBLE_PRE_V2_1_BOOTLOADERS=
229 |
230 | #
231 | # Wi-Fi
232 | #
233 | CONFIG_SW_COEXIST_ENABLE=
234 | CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=6
235 | CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=12
236 | CONFIG_ESP32_WIFI_STATIC_TX_BUFFER=
237 | CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER=y
238 | CONFIG_ESP32_WIFI_TX_BUFFER_TYPE=1
239 | CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM=16
240 | CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED=y
241 | CONFIG_ESP32_WIFI_TX_BA_WIN=6
242 | CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED=y
243 | CONFIG_ESP32_WIFI_RX_BA_WIN=6
244 | CONFIG_ESP32_WIFI_NVS_ENABLED=y
245 |
246 | #
247 | # PHY
248 | #
249 | CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE=y
250 | CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION=
251 | CONFIG_ESP32_PHY_MAX_WIFI_TX_POWER=20
252 | CONFIG_ESP32_PHY_MAX_TX_POWER=20
253 |
254 | #
255 | # Power Management
256 | #
257 | CONFIG_PM_ENABLE=
258 |
259 | #
260 | # Ethernet
261 | #
262 | CONFIG_DMA_RX_BUF_NUM=10
263 | CONFIG_DMA_TX_BUF_NUM=10
264 | CONFIG_EMAC_L2_TO_L3_RX_BUF_MODE=
265 | CONFIG_EMAC_TASK_PRIORITY=20
266 |
267 | #
268 | # FAT Filesystem support
269 | #
270 | CONFIG_FATFS_CODEPAGE_DYNAMIC=
271 | CONFIG_FATFS_CODEPAGE_437=y
272 | CONFIG_FATFS_CODEPAGE_720=
273 | CONFIG_FATFS_CODEPAGE_737=
274 | CONFIG_FATFS_CODEPAGE_771=
275 | CONFIG_FATFS_CODEPAGE_775=
276 | CONFIG_FATFS_CODEPAGE_850=
277 | CONFIG_FATFS_CODEPAGE_852=
278 | CONFIG_FATFS_CODEPAGE_855=
279 | CONFIG_FATFS_CODEPAGE_857=
280 | CONFIG_FATFS_CODEPAGE_860=
281 | CONFIG_FATFS_CODEPAGE_861=
282 | CONFIG_FATFS_CODEPAGE_862=
283 | CONFIG_FATFS_CODEPAGE_863=
284 | CONFIG_FATFS_CODEPAGE_864=
285 | CONFIG_FATFS_CODEPAGE_865=
286 | CONFIG_FATFS_CODEPAGE_866=
287 | CONFIG_FATFS_CODEPAGE_869=
288 | CONFIG_FATFS_CODEPAGE_932=
289 | CONFIG_FATFS_CODEPAGE_936=
290 | CONFIG_FATFS_CODEPAGE_949=
291 | CONFIG_FATFS_CODEPAGE_950=
292 | CONFIG_FATFS_CODEPAGE=437
293 | CONFIG_FATFS_LFN_NONE=y
294 | CONFIG_FATFS_LFN_HEAP=
295 | CONFIG_FATFS_LFN_STACK=
296 | CONFIG_FATFS_FS_LOCK=0
297 | CONFIG_FATFS_TIMEOUT_MS=10000
298 | CONFIG_FATFS_PER_FILE_CACHE=y
299 |
300 | #
301 | # FreeRTOS
302 | #
303 | CONFIG_FREERTOS_UNICORE=
304 | CONFIG_FREERTOS_CORETIMER_0=y
305 | CONFIG_FREERTOS_CORETIMER_1=
306 | CONFIG_FREERTOS_HZ=1000
307 | CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION=y
308 | CONFIG_FREERTOS_CHECK_STACKOVERFLOW_NONE=
309 | CONFIG_FREERTOS_CHECK_STACKOVERFLOW_PTRVAL=y
310 | CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY=
311 | CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK=
312 | CONFIG_FREERTOS_INTERRUPT_BACKTRACE=y
313 | CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS=3
314 | CONFIG_FREERTOS_ASSERT_FAIL_ABORT=y
315 | CONFIG_FREERTOS_ASSERT_FAIL_PRINT_CONTINUE=
316 | CONFIG_FREERTOS_ASSERT_DISABLE=
317 | CONFIG_FREERTOS_IDLE_TASK_STACKSIZE=1024
318 | CONFIG_FREERTOS_ISR_STACKSIZE=1536
319 | CONFIG_FREERTOS_LEGACY_HOOKS=
320 | CONFIG_FREERTOS_MAX_TASK_NAME_LEN=16
321 | CONFIG_SUPPORT_STATIC_ALLOCATION=
322 | CONFIG_TIMER_TASK_PRIORITY=1
323 | CONFIG_TIMER_TASK_STACK_DEPTH=2048
324 | CONFIG_TIMER_QUEUE_LENGTH=10
325 | CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE=0
326 | CONFIG_FREERTOS_USE_TRACE_FACILITY=
327 | CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS=
328 | CONFIG_FREERTOS_DEBUG_INTERNALS=
329 |
330 | #
331 | # Heap memory debugging
332 | #
333 | CONFIG_HEAP_POISONING_DISABLED=y
334 | CONFIG_HEAP_POISONING_LIGHT=
335 | CONFIG_HEAP_POISONING_COMPREHENSIVE=
336 | CONFIG_HEAP_TRACING=
337 |
338 | #
339 | # libsodium
340 | #
341 | CONFIG_LIBSODIUM_USE_MBEDTLS_SHA=y
342 |
343 | #
344 | # Log output
345 | #
346 | CONFIG_LOG_DEFAULT_LEVEL_NONE=
347 | CONFIG_LOG_DEFAULT_LEVEL_ERROR=
348 | CONFIG_LOG_DEFAULT_LEVEL_WARN=
349 | CONFIG_LOG_DEFAULT_LEVEL_INFO=
350 | CONFIG_LOG_DEFAULT_LEVEL_DEBUG=
351 | CONFIG_LOG_DEFAULT_LEVEL_VERBOSE=y
352 | CONFIG_LOG_DEFAULT_LEVEL=5
353 | CONFIG_LOG_COLORS=y
354 |
355 | #
356 | # LWIP
357 | #
358 | CONFIG_L2_TO_L3_COPY=
359 | CONFIG_LWIP_MAX_SOCKETS=4
360 | CONFIG_LWIP_SO_REUSE=
361 | CONFIG_LWIP_SO_RCVBUF=
362 | CONFIG_LWIP_DHCP_MAX_NTP_SERVERS=1
363 | CONFIG_LWIP_IP_FRAG=
364 | CONFIG_LWIP_IP_REASSEMBLY=
365 | CONFIG_LWIP_STATS=
366 | CONFIG_LWIP_ETHARP_TRUST_IP_MAC=y
367 | CONFIG_TCPIP_RECVMBOX_SIZE=32
368 | CONFIG_LWIP_DHCP_DOES_ARP_CHECK=y
369 |
370 | #
371 | # DHCP server
372 | #
373 | CONFIG_LWIP_DHCPS_LEASE_UNIT=60
374 | CONFIG_LWIP_DHCPS_MAX_STATION_NUM=8
375 | CONFIG_LWIP_AUTOIP=
376 | CONFIG_LWIP_NETIF_LOOPBACK=y
377 | CONFIG_LWIP_LOOPBACK_MAX_PBUFS=8
378 |
379 | #
380 | # TCP
381 | #
382 | CONFIG_LWIP_MAX_ACTIVE_TCP=16
383 | CONFIG_LWIP_MAX_LISTENING_TCP=16
384 | CONFIG_TCP_MAXRTX=12
385 | CONFIG_TCP_SYNMAXRTX=6
386 | CONFIG_TCP_MSS=1436
387 | CONFIG_TCP_MSL=60000
388 | CONFIG_TCP_SND_BUF_DEFAULT=5744
389 | CONFIG_TCP_WND_DEFAULT=5744
390 | CONFIG_TCP_RECVMBOX_SIZE=6
391 | CONFIG_TCP_QUEUE_OOSEQ=y
392 | CONFIG_TCP_OVERSIZE_MSS=y
393 | CONFIG_TCP_OVERSIZE_QUARTER_MSS=
394 | CONFIG_TCP_OVERSIZE_DISABLE=
395 |
396 | #
397 | # UDP
398 | #
399 | CONFIG_LWIP_MAX_UDP_PCBS=16
400 | CONFIG_UDP_RECVMBOX_SIZE=6
401 | CONFIG_TCPIP_TASK_STACK_SIZE=2560
402 | CONFIG_PPP_SUPPORT=
403 |
404 | #
405 | # ICMP
406 | #
407 | CONFIG_LWIP_MULTICAST_PING=
408 | CONFIG_LWIP_BROADCAST_PING=
409 |
410 | #
411 | # LWIP RAW API
412 | #
413 | CONFIG_LWIP_MAX_RAW_PCBS=16
414 |
415 | #
416 | # mbedTLS
417 | #
418 | CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN=1512
419 | CONFIG_MBEDTLS_DEBUG=
420 | CONFIG_MBEDTLS_HARDWARE_AES=y
421 | CONFIG_MBEDTLS_HARDWARE_MPI=y
422 | CONFIG_MBEDTLS_MPI_USE_INTERRUPT=y
423 | CONFIG_MBEDTLS_HARDWARE_SHA=
424 | CONFIG_MBEDTLS_HAVE_TIME=y
425 | CONFIG_MBEDTLS_HAVE_TIME_DATE=
426 | CONFIG_MBEDTLS_TLS_SERVER_AND_CLIENT=y
427 | CONFIG_MBEDTLS_TLS_SERVER_ONLY=
428 | CONFIG_MBEDTLS_TLS_CLIENT_ONLY=
429 | CONFIG_MBEDTLS_TLS_DISABLED=
430 | CONFIG_MBEDTLS_TLS_SERVER=y
431 | CONFIG_MBEDTLS_TLS_CLIENT=y
432 | CONFIG_MBEDTLS_TLS_ENABLED=y
433 |
434 | #
435 | # TLS Key Exchange Methods
436 | #
437 | CONFIG_MBEDTLS_PSK_MODES=
438 | CONFIG_MBEDTLS_KEY_EXCHANGE_RSA=y
439 | CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_RSA=y
440 | CONFIG_MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE=y
441 | CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_RSA=y
442 | CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA=y
443 | CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA=y
444 | CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_RSA=y
445 | CONFIG_MBEDTLS_SSL_RENEGOTIATION=y
446 | CONFIG_MBEDTLS_SSL_PROTO_SSL3=
447 | CONFIG_MBEDTLS_SSL_PROTO_TLS1=y
448 | CONFIG_MBEDTLS_SSL_PROTO_TLS1_1=y
449 | CONFIG_MBEDTLS_SSL_PROTO_TLS1_2=y
450 | CONFIG_MBEDTLS_SSL_PROTO_DTLS=
451 | CONFIG_MBEDTLS_SSL_ALPN=y
452 | CONFIG_MBEDTLS_SSL_SESSION_TICKETS=y
453 |
454 | #
455 | # Symmetric Ciphers
456 | #
457 | CONFIG_MBEDTLS_AES_C=y
458 | CONFIG_MBEDTLS_CAMELLIA_C=
459 | CONFIG_MBEDTLS_DES_C=
460 | CONFIG_MBEDTLS_RC4_DISABLED=y
461 | CONFIG_MBEDTLS_RC4_ENABLED_NO_DEFAULT=
462 | CONFIG_MBEDTLS_RC4_ENABLED=
463 | CONFIG_MBEDTLS_BLOWFISH_C=
464 | CONFIG_MBEDTLS_XTEA_C=
465 | CONFIG_MBEDTLS_CCM_C=y
466 | CONFIG_MBEDTLS_GCM_C=y
467 | CONFIG_MBEDTLS_RIPEMD160_C=
468 |
469 | #
470 | # Certificates
471 | #
472 | CONFIG_MBEDTLS_PEM_PARSE_C=y
473 | CONFIG_MBEDTLS_PEM_WRITE_C=y
474 | CONFIG_MBEDTLS_X509_CRL_PARSE_C=y
475 | CONFIG_MBEDTLS_X509_CSR_PARSE_C=y
476 | CONFIG_MBEDTLS_ECP_C=y
477 | CONFIG_MBEDTLS_ECDH_C=y
478 | CONFIG_MBEDTLS_ECDSA_C=y
479 | CONFIG_MBEDTLS_ECP_DP_SECP192R1_ENABLED=y
480 | CONFIG_MBEDTLS_ECP_DP_SECP224R1_ENABLED=y
481 | CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED=y
482 | CONFIG_MBEDTLS_ECP_DP_SECP384R1_ENABLED=y
483 | CONFIG_MBEDTLS_ECP_DP_SECP521R1_ENABLED=y
484 | CONFIG_MBEDTLS_ECP_DP_SECP192K1_ENABLED=y
485 | CONFIG_MBEDTLS_ECP_DP_SECP224K1_ENABLED=y
486 | CONFIG_MBEDTLS_ECP_DP_SECP256K1_ENABLED=y
487 | CONFIG_MBEDTLS_ECP_DP_BP256R1_ENABLED=y
488 | CONFIG_MBEDTLS_ECP_DP_BP384R1_ENABLED=y
489 | CONFIG_MBEDTLS_ECP_DP_BP512R1_ENABLED=y
490 | CONFIG_MBEDTLS_ECP_DP_CURVE25519_ENABLED=y
491 | CONFIG_MBEDTLS_ECP_NIST_OPTIM=y
492 |
493 | #
494 | # OpenSSL
495 | #
496 | CONFIG_OPENSSL_DEBUG=
497 | CONFIG_OPENSSL_ASSERT_DO_NOTHING=y
498 | CONFIG_OPENSSL_ASSERT_EXIT=
499 |
500 | #
501 | # PThreads
502 | #
503 | CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT=5
504 | CONFIG_ESP32_PTHREAD_TASK_STACK_SIZE_DEFAULT=2048
505 |
506 | #
507 | # SPI Flash driver
508 | #
509 | CONFIG_SPI_FLASH_VERIFY_WRITE=
510 | CONFIG_SPI_FLASH_ENABLE_COUNTERS=
511 | CONFIG_SPI_FLASH_ROM_DRIVER_PATCH=y
512 | CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ABORTS=y
513 | CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_FAILS=
514 | CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ALLOWED=
515 |
516 | #
517 | # SPIFFS Configuration
518 | #
519 | CONFIG_SPIFFS_MAX_PARTITIONS=3
520 |
521 | #
522 | # SPIFFS Cache Configuration
523 | #
524 | CONFIG_SPIFFS_CACHE=y
525 | CONFIG_SPIFFS_CACHE_WR=y
526 | CONFIG_SPIFFS_CACHE_STATS=
527 | CONFIG_SPIFFS_PAGE_CHECK=y
528 | CONFIG_SPIFFS_GC_MAX_RUNS=10
529 | CONFIG_SPIFFS_GC_STATS=
530 | CONFIG_SPIFFS_OBJ_NAME_LEN=32
531 | CONFIG_SPIFFS_USE_MAGIC=y
532 | CONFIG_SPIFFS_USE_MAGIC_LENGTH=y
533 | CONFIG_SPIFFS_META_LENGTH=4
534 | CONFIG_SPIFFS_USE_MTIME=y
535 |
536 | #
537 | # Debug Configuration
538 | #
539 | CONFIG_SPIFFS_DBG=
540 | CONFIG_SPIFFS_API_DBG=
541 | CONFIG_SPIFFS_GC_DBG=
542 | CONFIG_SPIFFS_CACHE_DBG=
543 | CONFIG_SPIFFS_CHECK_DBG=
544 | CONFIG_SPIFFS_TEST_VISUALISATION=
545 |
546 | #
547 | # tcpip adapter
548 | #
549 | CONFIG_IP_LOST_TIMER_INTERVAL=120
550 |
551 | #
552 | # Wear Levelling
553 | #
554 | CONFIG_WL_SECTOR_SIZE_512=
555 | CONFIG_WL_SECTOR_SIZE_4096=y
556 | CONFIG_WL_SECTOR_SIZE=4096
557 |
--------------------------------------------------------------------------------