Skip to content

Commit 3ad96f3

Browse files
committed
feat: add plugin system support for loading optional features
1 parent 888aab3 commit 3ad96f3

File tree

5 files changed

+264
-0
lines changed

5 files changed

+264
-0
lines changed
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
/*
2+
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
3+
*
4+
* SPDX-License-Identifier: Apache-2.0 OR MIT
5+
*/
6+
7+
#pragma once
8+
9+
#include <stdbool.h>
10+
#include <stdint.h>
11+
12+
#ifdef __cplusplus
13+
extern "C" {
14+
#endif
15+
16+
// Error codes returned by NAND functions
17+
#define NAND_ERR_PROGRAM_FAILED (-3)
18+
19+
// NAND flash configuration
20+
typedef struct {
21+
uint32_t page_size; // typically 2048 bytes
22+
uint32_t pages_per_block; // typically 64
23+
uint32_t block_size; // page_size * pages_per_block
24+
bool initialized;
25+
} nand_config_t;
26+
27+
/**
28+
* @brief Initialize NAND flash interface
29+
* @param hspi_arg SPI configuration argument.
30+
*
31+
* On targets that support configurable GPIO routing (e.g. ESP32-S3), this
32+
* argument is interpreted as a packed pin mapping with the following bit fields:
33+
* - bits 0..5 : CLK GPIO number
34+
* - bits 6..11 : Q (MISO) GPIO number
35+
* - bits 12..17 : D (MOSI) GPIO number
36+
* - bits 18..23 : CS GPIO number
37+
* - bits 24..29 : HD (hold / IO2) GPIO number
38+
* Remaining bits are reserved and must be zero.
39+
* Pass 0 to use the default native FSPI pins.
40+
*
41+
* On targets that do not implement pin remapping, this argument is ignored.
42+
* @return 0 on success, negative on error
43+
*/
44+
int stub_target_nand_attach(uint32_t hspi_arg);
45+
46+
/**
47+
* @brief Read bad-block marker from the spare area of a page
48+
* @param page_number Page number to read bad-block marker from
49+
* @param spare_data Output buffer for spare data (at least 2 bytes)
50+
* @return 0 on success, negative on error
51+
*/
52+
int stub_target_nand_read_bbm(uint32_t page_number, uint8_t *spare_data);
53+
54+
/**
55+
* @brief Write bad-block marker to the spare area of a page
56+
* @param page_number Page number to write bad-block marker to
57+
* @param is_bad 1 to mark as bad block, 0 to mark as good
58+
* @return 0 on success, negative on error
59+
*/
60+
int stub_target_nand_write_bbm(uint32_t page_number, uint8_t is_bad);
61+
62+
/**
63+
* @brief Read JEDEC ID from NAND flash (0x9F command)
64+
* @param manufacturer_id Output: manufacturer ID (0xEF for Winbond)
65+
* @param device_id Output: 2-byte device ID (0xAA21 for W25N01GVZEIG)
66+
* @return 0 on success, negative on error
67+
*/
68+
int stub_target_nand_read_id(uint8_t *manufacturer_id, uint16_t *device_id);
69+
70+
/**
71+
* @brief Read main area of a single NAND page
72+
* @param page_number Page number to read
73+
* @param buf Output buffer (must be at least buf_size bytes)
74+
* @param buf_size Number of bytes to read (up to page_size)
75+
* @return 0 on success, negative on error
76+
*/
77+
int stub_target_nand_read_page(uint32_t page_number, uint8_t *buf, uint32_t buf_size);
78+
79+
/**
80+
* @brief Write full main area of a single NAND page (2048 bytes)
81+
* @param page_number Page number to write
82+
* @param buf Data to write (must be at least page_size bytes)
83+
* @return 0 on success, negative on error
84+
*/
85+
int stub_target_nand_write_page(uint32_t page_number, const uint8_t *buf);
86+
87+
/**
88+
* @brief Erase a block (64 pages, 128KB)
89+
* @param page_number First page number of the block (must be block-aligned)
90+
* @return 0 on success, negative on error
91+
*/
92+
int stub_target_nand_erase_block(uint32_t page_number);
93+
94+
/**
95+
* @brief Get the configured page size
96+
* @return Page size in bytes
97+
*/
98+
uint32_t stub_target_nand_get_page_size(void);
99+
100+
/**
101+
* @brief Read a NAND configuration register (status, protect, config)
102+
* @param reg Register address (NAND_REG_STATUS, NAND_REG_PROTECT, NAND_REG_CONFIG)
103+
* @param val Output byte
104+
* @return 0 on success, negative on error
105+
*/
106+
int stub_target_nand_read_register(uint8_t reg, uint8_t *val);
107+
108+
#ifdef __cplusplus
109+
}
110+
#endif

src/target/common/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ set(common_srcs
99
src/usb_serial_jtag.c
1010
src/usb_otg.c
1111
src/md5.c
12+
src/nand.c
1213
)
1314

1415
add_library(${ESP_COMMON_LIB} STATIC ${common_srcs})

src/target/common/src/nand.c

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*
2+
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
3+
*
4+
* SPDX-License-Identifier: Apache-2.0 OR MIT
5+
*
6+
* Weak NAND implementation for chips that do not support SPI NAND.
7+
* Target-specific chips that support NAND provide strong symbols that override these.
8+
*/
9+
10+
#include <target/nand.h>
11+
12+
__attribute__((weak)) int stub_target_nand_attach(uint32_t hspi_arg)
13+
{
14+
(void)hspi_arg;
15+
return -1;
16+
}
17+
18+
__attribute__((weak)) int stub_target_nand_read_bbm(uint32_t page_number, uint8_t *spare_data)
19+
{
20+
(void)page_number;
21+
(void)spare_data;
22+
return -1;
23+
}
24+
25+
__attribute__((weak)) int stub_target_nand_write_bbm(uint32_t page_number, uint8_t is_bad)
26+
{
27+
(void)page_number;
28+
(void)is_bad;
29+
return -1;
30+
}
31+
32+
__attribute__((weak)) int stub_target_nand_read_id(uint8_t *manufacturer_id, uint16_t *device_id)
33+
{
34+
(void)manufacturer_id;
35+
(void)device_id;
36+
return -1;
37+
}
38+
39+
__attribute__((weak)) int stub_target_nand_read_page(uint32_t page_number, uint8_t *buf, uint32_t buf_size)
40+
{
41+
(void)page_number;
42+
(void)buf;
43+
(void)buf_size;
44+
return -1;
45+
}
46+
47+
__attribute__((weak)) int stub_target_nand_write_page(uint32_t page_number, const uint8_t *buf)
48+
{
49+
(void)page_number;
50+
(void)buf;
51+
return -1;
52+
}
53+
54+
__attribute__((weak)) int stub_target_nand_erase_block(uint32_t page_number)
55+
{
56+
(void)page_number;
57+
return -1;
58+
}
59+
60+
__attribute__((weak)) uint32_t stub_target_nand_get_page_size(void)
61+
{
62+
return 0;
63+
}

src/target/esp32s3/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ set(srcs
66
src/usb_otg.c
77
src/clock.c
88
src/aes_xts.c
9+
src/nand.c
910
)
1011

1112
add_library(${ESP_TARGET_LIB} STATIC ${srcs})

src/target/esp32s3/src/nand.c

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
/*
2+
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
3+
*
4+
* SPDX-License-Identifier: Apache-2.0 OR MIT
5+
*/
6+
7+
/*
8+
* Stub implementations of NAND target functions.
9+
*
10+
* These strong-symbol stubs override the weak fallbacks in
11+
* esp-stub-lib/src/target/common/src/nand.c. They return sentinel values
12+
* that allow the plugin dispatch path to be exercised end-to-end without
13+
* any real NAND hardware or SPI peripheral access.
14+
*/
15+
16+
#include <stdint.h>
17+
#include <string.h>
18+
19+
#include <target/nand.h>
20+
21+
int stub_target_nand_attach(uint32_t hspi_arg)
22+
{
23+
(void)hspi_arg;
24+
return 0;
25+
}
26+
27+
uint32_t stub_target_nand_get_page_size(void)
28+
{
29+
return 2048;
30+
}
31+
32+
int stub_target_nand_read_id(uint8_t *manufacturer_id, uint16_t *device_id)
33+
{
34+
if (manufacturer_id) {
35+
*manufacturer_id = 0xAA;
36+
}
37+
if (device_id) {
38+
*device_id = 0x0000;
39+
}
40+
return 0;
41+
}
42+
43+
int stub_target_nand_read_register(uint8_t reg, uint8_t *val)
44+
{
45+
(void)reg;
46+
if (val) {
47+
*val = 0x00;
48+
}
49+
return 0;
50+
}
51+
52+
int stub_target_nand_read_bbm(uint32_t page_number, uint8_t *spare_data)
53+
{
54+
(void)page_number;
55+
if (spare_data) {
56+
spare_data[0] = 0xFF;
57+
spare_data[1] = 0xFF;
58+
}
59+
return 0;
60+
}
61+
62+
int stub_target_nand_write_bbm(uint32_t page_number, uint8_t is_bad)
63+
{
64+
(void)page_number;
65+
(void)is_bad;
66+
return 0;
67+
}
68+
69+
int stub_target_nand_erase_block(uint32_t page_number)
70+
{
71+
(void)page_number;
72+
return 0;
73+
}
74+
75+
int stub_target_nand_read_page(uint32_t page_number, uint8_t *buf, uint32_t buf_size)
76+
{
77+
(void)page_number;
78+
if (buf && buf_size > 0) {
79+
memset(buf, 0xFF, buf_size);
80+
}
81+
return 0;
82+
}
83+
84+
int stub_target_nand_write_page(uint32_t page_number, const uint8_t *buf)
85+
{
86+
(void)page_number;
87+
(void)buf;
88+
return NAND_ERR_PROGRAM_FAILED;
89+
}

0 commit comments

Comments
 (0)