Skip to content

Commit e238977

Browse files
committed
Merge branch 'feat/support_reading_flash' into 'master'
feat: Add support for reading from flash Closes ESF-93 See merge request espressif/esp-serial-flasher!128
2 parents 2837d52 + 400d614 commit e238977

File tree

10 files changed

+417
-4
lines changed

10 files changed

+417
-4
lines changed
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# The following lines of boilerplate have to be in your project's CMakeLists
2+
# in this exact order for cmake to work correctly
3+
cmake_minimum_required(VERSION 3.5)
4+
5+
set(EXTRA_COMPONENT_DIRS ../../)
6+
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
7+
project(esp-serial-flasher)
8+
9+
# There are issues with ESP-IDF 4.4 and -Wunused-parameter
10+
if ("${IDF_VERSION_MAJOR}.${IDF_VERSION_MINOR}" VERSION_GREATER "4.4")
11+
idf_component_get_property(flasher esp-serial-flasher COMPONENT_LIB)
12+
13+
target_compile_options(${flasher}
14+
PRIVATE
15+
-Wunused-parameter
16+
-Wshadow
17+
)
18+
endif()
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
# Read from target flash example
2+
3+
## Overview
4+
5+
This example demonstrates how to read from target flash.
6+
7+
The following steps are performed to demonstrate the flash reading functionality:
8+
9+
1. UART1 through which the the new binary will be transferred is initialized.
10+
2. The host puts the target device into the boot mode and tries to connect by calling `esp_loader_connect()`.
11+
3. `esp_loader_flash_start()` is called to enter the flashing mode and erase the amount of memory to be flashed.
12+
5. `esp_loader_flash_write()` function is called repeatedly until the whole example data is transfered.
13+
6. `esp_loader_flash_read()` is called to read back the data programmed into the target flash
14+
7. Data is compared to verify successful reading
15+
16+
Note: In addition to the steps mentioned above, `esp_loader_change_transmission_rate()` is called after the connection is established in order to increase the flashing and reading speed. This does not apply for the ESP8266, as its bootloader does not support this command. However, the ESP8266 is capable of detecting the baud rate during connection phase and can be changed before calling `esp_loader_connect()`, if necessary.
17+
18+
## Connection configuration
19+
20+
In the majority of cases `ESP_LOADER_CONNECT_DEFAULT` helper macro is used in order to initialize `loader_connect_args_t` data structure passed to `esp_loader_connect()`. Helper macro sets the maximum time to wait for a response and the number of retrials. For more detailed information refer to [serial protocol](https://docs.espressif.com/projects/esptool/en/latest/esp32s3/advanced-topics/serial-protocol.html).
21+
22+
## Hardware Required
23+
24+
* Two development boards with the ESP32 SoC (e.g., ESP32-DevKitC, ESP-WROVER-KIT, etc.).
25+
26+
* One or two USB cables for power supply and programming.
27+
28+
* Cables to connect host to target according to table below.
29+
30+
## Hardware connection
31+
32+
Table below shows connection between the two ESP32 devices.
33+
34+
| ESP32 (host) | ESP32 (target) |
35+
|:------------:|:-------------:|
36+
| IO26 | IO0 |
37+
| IO25 | RESET |
38+
| IO4 | RX0 |
39+
| IO5 | TX0 |
40+
41+
Note: interconnection is the same for ESP32, ESP32-S2 and ESP8266 targets.
42+
43+
## Build and flash
44+
45+
To run the example, type the following command:
46+
47+
```CMake
48+
idf.py -p PORT flash monitor
49+
```
50+
51+
(To exit the serial monitor, type ``Ctrl-]``.)
52+
53+
See the [Getting Started Guide](https://docs.espressif.com/projects/esp-idf/en/stable/esp32/index.html) for full steps to configure and use ESP-IDF to build projects.
54+
55+
## Configuration
56+
57+
For details about available configuration options, please refer to the top level [README.md](../../README.md).
58+
Compile definitions can be specified in the command line when running `idf.py`, for example:
59+
60+
```
61+
idf.py build -DMD5_ENABLED=1
62+
```
63+
64+
## Example output
65+
66+
Here is the example's console output:
67+
68+
```
69+
...
70+
Connected to target
71+
Transmission rate changed.
72+
I (703) serial_flasher: Loading example data
73+
Erasing flash (this may take a while)...
74+
Start programming
75+
Progress: 100 %
76+
Finished programming
77+
Flash verified
78+
I (1013) serial_flasher: Flash contents match example data
79+
```
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
set(srcs main.c ../../common/example_common.c)
2+
set(include_dirs . ../../common)
3+
4+
idf_component_register(SRCS ${srcs}
5+
INCLUDE_DIRS ${include_dirs})
6+
set(target ${COMPONENT_LIB})
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
/* Flash multiple partitions example
2+
3+
This example code is in the Public Domain (or CC0 licensed, at your option.)
4+
5+
Unless required by applicable law or agreed to in writing, this
6+
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
7+
CONDITIONS OF ANY KIND, either express or implied.
8+
*/
9+
10+
#include <sys/param.h>
11+
#include <string.h>
12+
#include "esp_err.h"
13+
#include "esp_log.h"
14+
#include "driver/uart.h"
15+
#include "driver/gpio.h"
16+
#include "esp32_port.h"
17+
#include "esp_loader.h"
18+
#include "example_common.h"
19+
20+
static const char *TAG = "serial_flasher";
21+
static const char example_data[] = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. "
22+
"Donec pretium sem et condimentum tincidunt.n "
23+
"Quisque tristique in enim elementum aliquet. "
24+
"Integer consequat sodales bibendum. "
25+
"Nam enim quam, tristique id dui ut, fermentum porta felis. "
26+
"Phasellus vulputate sem quis ligula egestas, sed ullamcorper eros tincidunt. "
27+
"Donec imperdiet ac urna in placerat. "
28+
"Praesent ultrices velit nulla, eu rutrum nisi maximus in."
29+
"Donec non ligula molestie, blandit massa vel, auctor ipsum. "
30+
"Nunc consectetur mi nulla, a ultricies odio vehicula a. "
31+
"Praesent hendrerit tellus nunc, a interdum lectus mollis eget. "
32+
"Nullam in felis vitae diam posuere dignissim quis non urna. "
33+
"Quisque elementum ante at sapien condimentum, sit amet ultricies tortor feugiat. "
34+
"Aliquam id mi at purus maximus lobortis. "
35+
"Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. "
36+
"Nunc consequat lorem turpis, vitae dignissim leo fringilla eget. "
37+
"In ornare convallis finibus. "
38+
"Morbi libero neque, pretium et mollis non, dictum eget felis. "
39+
"Ut mattis vitae urna id vulputate. "
40+
"Nam porttitor dolor diam, eu rutrum tortor auctor id...";
41+
static uint8_t read_buf[sizeof(example_data)];
42+
43+
#define HIGHER_BAUDRATE 230400
44+
45+
void app_main(void)
46+
{
47+
const loader_esp32_config_t config = {
48+
.baud_rate = 115200,
49+
.uart_port = UART_NUM_1,
50+
.uart_rx_pin = GPIO_NUM_5,
51+
.uart_tx_pin = GPIO_NUM_4,
52+
.reset_trigger_pin = GPIO_NUM_25,
53+
.gpio0_trigger_pin = GPIO_NUM_26,
54+
};
55+
56+
if (loader_port_esp32_init(&config) != ESP_LOADER_SUCCESS) {
57+
ESP_LOGE(TAG, "serial initialization failed.");
58+
return;
59+
}
60+
61+
if (connect_to_target(HIGHER_BAUDRATE) == ESP_LOADER_SUCCESS) {
62+
63+
ESP_LOGI(TAG, "Loading example data");
64+
flash_binary((const uint8_t *)example_data, sizeof(example_data), 0x00000000);
65+
66+
if (esp_loader_flash_read(read_buf, 0x00000000, sizeof(read_buf)) == ESP_LOADER_SUCCESS) {
67+
if (!memcmp(example_data, read_buf, sizeof(read_buf))) {
68+
ESP_LOGI(TAG, "Flash contents match example data");
69+
} else {
70+
ESP_LOGE(TAG, "Flash contents do not match example data");
71+
ESP_LOG_BUFFER_HEXDUMP("Programmed data: ", example_data, sizeof(read_buf), ESP_LOG_ERROR);
72+
ESP_LOG_BUFFER_HEXDUMP("Read data: ", read_buf, sizeof(read_buf), ESP_LOG_ERROR);
73+
}
74+
} else {
75+
ESP_LOGE(TAG, "Could not read from flash!");
76+
}
77+
78+
79+
}
80+
vTaskDelete(NULL);
81+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import pytest
2+
from pytest_embedded import Dut
3+
4+
5+
@pytest.mark.esp32
6+
def test_esp32_read_flash_example(dut: Dut) -> None:
7+
dut.expect("Loading example data")
8+
dut.expect("Start programming")
9+
dut.expect("Finished programming", not_matching="Error")
10+
dut.expect("Flash contents match example data")
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
CONFIG_IDF_TARGET="esp32"

include/esp_loader.h

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -181,9 +181,9 @@ esp_loader_error_t esp_loader_connect_secure_download_mode(esp_loader_connect_ar
181181
/**
182182
* @brief Initiates flash operation
183183
*
184-
* @param offset[in] Address from which flash operation will be performed.
185-
* @param image_size[in] Size of the whole binary to be loaded into flash.
186-
* @param block_size[in] Size of buffer used in subsequent calls to esp_loader_flash_write.
184+
* @param offset[in] Address from which flash operation will be performed. Must be 4 byte aligned.
185+
* @param image_size[in] Size of the whole binary to be loaded into flash. Must be 4 byte aligned.
186+
* @param block_size[in] Size of buffer used in subsequent calls to esp_loader_flash_write.
187187
*
188188
* @note image_size is size of the whole image, whereas, block_size is chunk of data sent
189189
* to the target, each time esp_loader_flash_write function is called.
@@ -237,6 +237,22 @@ esp_loader_error_t esp_loader_flash_finish(bool reboot);
237237
*/
238238
esp_loader_error_t esp_loader_flash_detect_size(uint32_t *flash_size);
239239

240+
/**
241+
* @brief Reads from the target flash.
242+
*
243+
* @param buf[out] Buffer to read into
244+
* @param address[in] Flash address to read from.
245+
* @param length[in] Read length in bytes.
246+
*
247+
* @note Higher read speeds can be achieved by using the flasher stub.
248+
*
249+
* @return
250+
* - ESP_LOADER_SUCCESS Success
251+
* - ESP_LOADER_ERROR_UNSUPPORTED_CHIP The target flash chip is not known
252+
* - ESP_LOADER_ERROR_UNSUPPORTED_FUNC The target chip is running in secure download mode
253+
*/
254+
esp_loader_error_t esp_loader_flash_read(uint8_t *buf, uint32_t address, uint32_t length);
255+
240256
/**
241257
* @brief Change baud rate of the stub running on the target
242258
*

private_include/protocol.h

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,11 @@ extern "C" {
4444
#endif
4545

4646
#ifndef ROUNDUP
47-
#define ROUNDUP(a, b) (((int)a + (int)b - 1) / (int)b)
47+
#define ROUNDUP(a, b) ((((unsigned)a + (unsigned)b - 1) / (unsigned)b) * (unsigned)b)
4848
#endif
4949

5050
#define MAX_RESP_DATA_SIZE 64
51+
#define READ_FLASH_ROM_DATA_SIZE 64
5152

5253
typedef enum __attribute__((packed))
5354
{
@@ -62,12 +63,14 @@ typedef enum __attribute__((packed))
6263
READ_REG = 0x0a,
6364
SPI_SET_PARAMS = 0x0b,
6465
SPI_ATTACH = 0x0d,
66+
READ_FLASH_ROM = 0x0e,
6567
CHANGE_BAUDRATE = 0x0f,
6668
FLASH_DEFL_BEGIN = 0x10,
6769
FLASH_DEFL_DATA = 0x11,
6870
FLASH_DEFL_END = 0x12,
6971
SPI_FLASH_MD5 = 0x13,
7072
GET_SECURITY_INFO = 0x14,
73+
READ_FLASH_STUB = 0xd2,
7174
} command_t;
7275

7376
typedef enum __attribute__((packed))
@@ -115,6 +118,22 @@ typedef struct __attribute__((packed))
115118
uint32_t stay_in_loader;
116119
} flash_end_command_t;
117120

121+
typedef struct __attribute__((packed))
122+
{
123+
command_common_t common;
124+
uint32_t address;
125+
uint32_t size;
126+
} flash_read_rom_cmd;
127+
128+
typedef struct __attribute__((packed))
129+
{
130+
command_common_t common;
131+
uint32_t address;
132+
uint32_t total_size;
133+
uint32_t packet_data_size;
134+
uint32_t max_inflight_packets;
135+
} flash_read_stub_cmd;
136+
118137
typedef struct __attribute__((packed))
119138
{
120139
command_common_t common;
@@ -235,6 +254,10 @@ esp_loader_error_t loader_flash_data_cmd(const uint8_t *data, uint32_t size);
235254

236255
esp_loader_error_t loader_flash_end_cmd(bool stay_in_loader);
237256

257+
esp_loader_error_t loader_flash_read_rom_cmd(uint32_t address, uint8_t *data);
258+
259+
esp_loader_error_t loader_flash_read_stub_cmd(uint32_t address, uint32_t size, uint32_t size_per_packet);
260+
238261
esp_loader_error_t loader_sync_cmd(void);
239262

240263
esp_loader_error_t loader_spi_attach_cmd(uint32_t config);

0 commit comments

Comments
 (0)