44//
55// In-application programming
66//
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+ //
711// Created by Andreas Schweizer on 11.01.2017.
812// Copyright © 2017 Classy Code GmbH
913//
2024// limitations under the License.
2125//
2226
23- #include <stdio.h>
2427#include <stdlib.h>
2528#include <string.h>
2629
27- #include "esp_system.h"
2830#include "esp_ota_ops.h"
29- #include "esp_spi_flash.h"
30- #include "esp_partition.h"
3131#include "esp_log.h"
3232
3333#include "iap.h"
3939#define IAP_STATE_INITIALIZED (1 << 0)
4040#define IAP_STATE_SESSION_OPEN (1 << 1)
4141
42+ // While the session is open ('iap_begin' called), this module uses a
43+ // heap-allocated page buffer to accumulate data for writing.
4244#define IAP_PAGE_SIZE 4096
4345
4446#define MIN (a , b ) ((a) < (b) ? (a) : (b))
@@ -95,7 +97,7 @@ iap_err_t iap_begin()
9597
9698 // The module needs to be initialized for this method to work.
9799 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!" );
99101 return IAP_ERR_NOT_INITIALIZED ;
100102 }
101103
@@ -109,18 +111,18 @@ iap_err_t iap_begin()
109111 iap_state .page_buffer_ix = 0 ;
110112 iap_state .page_buffer = malloc (IAP_PAGE_SIZE );
111113 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!" );
113115 return IAP_ERR_OUT_OF_MEMORY ;
114116 }
115117
116118 iap_state .partition_to_program = iap_find_next_boot_partition ();
117119 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!" );
119121 free (iap_state .page_buffer );
120122 return IAP_ERR_PARTITION_NOT_FOUND ;
121123 }
122124
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 );
124126
125127 iap_state .cur_flash_address = iap_state .partition_to_program -> address ;
126128
@@ -131,7 +133,7 @@ iap_err_t iap_begin()
131133 return IAP_FAIL ;
132134 }
133135
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." ,
135137 iap_state .partition_to_program -> label , iap_state .cur_flash_address );
136138
137139 iap_state .module_state_flags |= IAP_STATE_SESSION_OPEN ;
@@ -144,13 +146,13 @@ iap_err_t iap_write(uint8_t *bytes, uint16_t len)
144146
145147 // The module needs to be initialized for this method to work.
146148 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!" );
148150 return IAP_ERR_NOT_INITIALIZED ;
149151 }
150152
151153 // The session needs to be open for this method to work.
152154 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!" );
154156 return IAP_ERR_NO_SESSION ;
155157 }
156158
@@ -180,7 +182,7 @@ iap_err_t iap_write(uint8_t *bytes, uint16_t len)
180182 esp_err_t result = iap_write_page_buffer ();
181183
182184 if (result != ESP_OK ) {
183- ESP_LOGE (TAG , "iap_write: Write failed (%d)!" , result );
185+ ESP_LOGE (TAG , "iap_write: write failed (%d)!" , result );
184186 return IAP_ERR_WRITE_FAILED ;
185187 }
186188 }
@@ -195,15 +197,15 @@ iap_err_t iap_commit()
195197
196198 iap_err_t result = iap_write_page_buffer ();
197199 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." );
199201 }
200202
201203 result = iap_finish (1 );
202204 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." );
204206 }
205207
206- ESP_LOGI (TAG , "iap_commit: Programming session successfully completed, partition activated." );
208+ ESP_LOGI (TAG , "iap_commit: programming session successfully completed, partition activated." );
207209 return result ;
208210}
209211
@@ -213,7 +215,7 @@ iap_err_t iap_abort()
213215
214216 iap_err_t result = iap_finish (0 );
215217 if (result == IAP_OK ) {
216- ESP_LOGI (TAG , "iap_abort: Programming session successfully aborted." );
218+ ESP_LOGI (TAG , "iap_abort: programming session successfully aborted." );
217219 }
218220
219221 return result ;
@@ -226,11 +228,11 @@ static iap_err_t iap_write_page_buffer()
226228 return IAP_OK ;
227229 }
228230
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" ,
230232 iap_state .page_buffer_ix , iap_state .cur_flash_address );
231233 esp_err_t result = esp_ota_write (iap_state .ota_handle , iap_state .page_buffer , iap_state .page_buffer_ix );
232234 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 );
234236 return IAP_ERR_WRITE_FAILED ;
235237 }
236238
@@ -246,13 +248,13 @@ static iap_err_t iap_finish(int commit)
246248{
247249 // The module needs to be initialized for this method to work.
248250 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!" );
250252 return IAP_ERR_NOT_INITIALIZED ;
251253 }
252254
253255 // The session needs to be open for this method to work.
254256 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!" );
256258 return IAP_ERR_NO_SESSION ;
257259 }
258260
@@ -261,12 +263,13 @@ static iap_err_t iap_finish(int commit)
261263 iap_state .page_buffer_ix = 0 ;
262264 iap_state .cur_flash_address = 0 ;
263265
264- // TODO HIGH
266+ // TODO
265267 // There's currently no way to abort an on-going OTA update.
266268 // http://www.esp32.com/viewtopic.php?f=14&t=1093
267269
270+ esp_err_t result = esp_ota_end (iap_state .ota_handle );
271+
268272 if (commit ) {
269- esp_err_t result = esp_ota_end (iap_state .ota_handle );
270273 if (result != ESP_OK ) {
271274 ESP_LOGE (TAG , "iap_finish: esp_ota_end failed (%d)!" , result );
272275 return IAP_FAIL ;
0 commit comments