4
4
//
5
5
// In-application programming
6
6
//
7
+ // This module is responsible for writing the firmware to the flash.
8
+ // It manages the write buffer, writing to the flash, selecting the
9
+ // correct partition and activating the partition.
10
+ //
7
11
// Created by Andreas Schweizer on 11.01.2017.
8
12
// Copyright © 2017 Classy Code GmbH
9
13
//
20
24
// limitations under the License.
21
25
//
22
26
23
- #include <stdio.h>
24
27
#include <stdlib.h>
25
28
#include <string.h>
26
29
27
- #include "esp_system.h"
28
30
#include "esp_ota_ops.h"
29
- #include "esp_spi_flash.h"
30
- #include "esp_partition.h"
31
31
#include "esp_log.h"
32
32
33
33
#include "iap.h"
39
39
#define IAP_STATE_INITIALIZED (1 << 0)
40
40
#define IAP_STATE_SESSION_OPEN (1 << 1)
41
41
42
+ // While the session is open ('iap_begin' called), this module uses a
43
+ // heap-allocated page buffer to accumulate data for writing.
42
44
#define IAP_PAGE_SIZE 4096
43
45
44
46
#define MIN (a , b ) ((a) < (b) ? (a) : (b))
@@ -95,7 +97,7 @@ iap_err_t iap_begin()
95
97
96
98
// The module needs to be initialized for this method to work.
97
99
if (!(iap_state .module_state_flags & IAP_STATE_INITIALIZED )) {
98
- ESP_LOGE (TAG , "iap_begin: The module hasn't been initialized!" );
100
+ ESP_LOGE (TAG , "iap_begin: the module hasn't been initialized!" );
99
101
return IAP_ERR_NOT_INITIALIZED ;
100
102
}
101
103
@@ -109,18 +111,18 @@ iap_err_t iap_begin()
109
111
iap_state .page_buffer_ix = 0 ;
110
112
iap_state .page_buffer = malloc (IAP_PAGE_SIZE );
111
113
if (!iap_state .page_buffer ) {
112
- ESP_LOGE (TAG , "iap_begin: Not enough heap memory to allocate the page buffer!" );
114
+ ESP_LOGE (TAG , "iap_begin: not enough heap memory to allocate the page buffer!" );
113
115
return IAP_ERR_OUT_OF_MEMORY ;
114
116
}
115
117
116
118
iap_state .partition_to_program = iap_find_next_boot_partition ();
117
119
if (!iap_state .partition_to_program ) {
118
- ESP_LOGE (TAG , "iap_begin: Partition for firmware update not found!" );
120
+ ESP_LOGE (TAG , "iap_begin: partition for firmware update not found!" );
119
121
free (iap_state .page_buffer );
120
122
return IAP_ERR_PARTITION_NOT_FOUND ;
121
123
}
122
124
123
- ESP_LOGD (TAG , "iap_begin: Next boot partition is '%s'." , iap_state .partition_to_program -> label );
125
+ ESP_LOGD (TAG , "iap_begin: next boot partition is '%s'." , iap_state .partition_to_program -> label );
124
126
125
127
iap_state .cur_flash_address = iap_state .partition_to_program -> address ;
126
128
@@ -131,7 +133,7 @@ iap_err_t iap_begin()
131
133
return IAP_FAIL ;
132
134
}
133
135
134
- ESP_LOGI (TAG , "iap_begin: Opened session for partition '%s', address 0x%08x." ,
136
+ ESP_LOGI (TAG , "iap_begin: opened IAP session for partition '%s', address 0x%08x." ,
135
137
iap_state .partition_to_program -> label , iap_state .cur_flash_address );
136
138
137
139
iap_state .module_state_flags |= IAP_STATE_SESSION_OPEN ;
@@ -144,13 +146,13 @@ iap_err_t iap_write(uint8_t *bytes, uint16_t len)
144
146
145
147
// The module needs to be initialized for this method to work.
146
148
if (!(iap_state .module_state_flags & IAP_STATE_INITIALIZED )) {
147
- ESP_LOGE (TAG , "iap_write: The module hasn't been initialized!" );
149
+ ESP_LOGE (TAG , "iap_write: the module hasn't been initialized!" );
148
150
return IAP_ERR_NOT_INITIALIZED ;
149
151
}
150
152
151
153
// The session needs to be open for this method to work.
152
154
if (!(iap_state .module_state_flags & IAP_STATE_SESSION_OPEN )) {
153
- ESP_LOGE (TAG , "iap_write: Programming session not open!" );
155
+ ESP_LOGE (TAG , "iap_write: programming session not open!" );
154
156
return IAP_ERR_NO_SESSION ;
155
157
}
156
158
@@ -180,7 +182,7 @@ iap_err_t iap_write(uint8_t *bytes, uint16_t len)
180
182
esp_err_t result = iap_write_page_buffer ();
181
183
182
184
if (result != ESP_OK ) {
183
- ESP_LOGE (TAG , "iap_write: Write failed (%d)!" , result );
185
+ ESP_LOGE (TAG , "iap_write: write failed (%d)!" , result );
184
186
return IAP_ERR_WRITE_FAILED ;
185
187
}
186
188
}
@@ -195,15 +197,15 @@ iap_err_t iap_commit()
195
197
196
198
iap_err_t result = iap_write_page_buffer ();
197
199
if (result != IAP_OK ) {
198
- ESP_LOGE (TAG , "iap_commit: Programming session failed in final write." );
200
+ ESP_LOGE (TAG , "iap_commit: programming session failed in final write." );
199
201
}
200
202
201
203
result = iap_finish (1 );
202
204
if (result != IAP_OK ) {
203
- ESP_LOGE (TAG , "iap_commit: Programming session failed in iap_finish." );
205
+ ESP_LOGE (TAG , "iap_commit: programming session failed in iap_finish." );
204
206
}
205
207
206
- ESP_LOGI (TAG , "iap_commit: Programming session successfully completed, partition activated." );
208
+ ESP_LOGI (TAG , "iap_commit: programming session successfully completed, partition activated." );
207
209
return result ;
208
210
}
209
211
@@ -213,7 +215,7 @@ iap_err_t iap_abort()
213
215
214
216
iap_err_t result = iap_finish (0 );
215
217
if (result == IAP_OK ) {
216
- ESP_LOGI (TAG , "iap_abort: Programming session successfully aborted." );
218
+ ESP_LOGI (TAG , "iap_abort: programming session successfully aborted." );
217
219
}
218
220
219
221
return result ;
@@ -226,11 +228,11 @@ static iap_err_t iap_write_page_buffer()
226
228
return IAP_OK ;
227
229
}
228
230
229
- ESP_LOGD (TAG , "iap_write_page_buffer: Writing %u bytes to address 0x%08x" ,
231
+ ESP_LOGD (TAG , "iap_write_page_buffer: writing %u bytes to address 0x%08x" ,
230
232
iap_state .page_buffer_ix , iap_state .cur_flash_address );
231
233
esp_err_t result = esp_ota_write (iap_state .ota_handle , iap_state .page_buffer , iap_state .page_buffer_ix );
232
234
if (result != ESP_OK ) {
233
- ESP_LOGE (TAG , "iap_write_page_buffer: Write failed in esp_ota_write (%d)!" , result );
235
+ ESP_LOGE (TAG , "iap_write_page_buffer: write failed in esp_ota_write (%d)!" , result );
234
236
return IAP_ERR_WRITE_FAILED ;
235
237
}
236
238
@@ -246,13 +248,13 @@ static iap_err_t iap_finish(int commit)
246
248
{
247
249
// The module needs to be initialized for this method to work.
248
250
if (!(iap_state .module_state_flags & IAP_STATE_INITIALIZED )) {
249
- ESP_LOGE (TAG , "iap_finish: The module hasn't been initialized!" );
251
+ ESP_LOGE (TAG , "iap_finish: the module hasn't been initialized!" );
250
252
return IAP_ERR_NOT_INITIALIZED ;
251
253
}
252
254
253
255
// The session needs to be open for this method to work.
254
256
if (!(iap_state .module_state_flags & IAP_STATE_SESSION_OPEN )) {
255
- ESP_LOGE (TAG , "iap_finish: Programming session not open!" );
257
+ ESP_LOGE (TAG , "iap_finish: programming session not open!" );
256
258
return IAP_ERR_NO_SESSION ;
257
259
}
258
260
@@ -261,12 +263,13 @@ static iap_err_t iap_finish(int commit)
261
263
iap_state .page_buffer_ix = 0 ;
262
264
iap_state .cur_flash_address = 0 ;
263
265
264
- // TODO HIGH
266
+ // TODO
265
267
// There's currently no way to abort an on-going OTA update.
266
268
// http://www.esp32.com/viewtopic.php?f=14&t=1093
267
269
270
+ esp_err_t result = esp_ota_end (iap_state .ota_handle );
271
+
268
272
if (commit ) {
269
- esp_err_t result = esp_ota_end (iap_state .ota_handle );
270
273
if (result != ESP_OK ) {
271
274
ESP_LOGE (TAG , "iap_finish: esp_ota_end failed (%d)!" , result );
272
275
return IAP_FAIL ;
0 commit comments