-
Notifications
You must be signed in to change notification settings - Fork 144
Expand file tree
/
Copy pathesp_loader_io.h
More file actions
158 lines (136 loc) · 5.54 KB
/
esp_loader_io.h
File metadata and controls
158 lines (136 loc) · 5.54 KB
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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
/* Copyright 2020-2026 Espressif Systems (Shanghai) CO LTD
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <stdint.h>
#include <stddef.h>
#include "esp_loader_error.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Recovers a pointer to the outer struct from a pointer to one of its members.
*
* This is the standard "inheritance by embedding" pattern used throughout the
* Linux kernel. Given a pointer @p ptr to member @p member inside a struct of
* type @p type, this macro returns a pointer to the enclosing struct.
*
* Example:
* @code
* typedef struct {
* // ... config / state fields ...
* esp_loader_port_t base; // embedded handle
* } my_port_t;
*
* static void my_start_timer(esp_loader_port_t *port, uint32_t ms)
* {
* my_port_t *p = container_of(port, my_port_t, base);
* p->time_end = get_time_ms() + ms;
* }
* @endcode
*/
#ifndef container_of
#define container_of(ptr, type, member) \
((type *)((char *)(ptr) - offsetof(type, member)))
#endif
/**
* @brief Forward declaration of the port base handle type.
*
* Full definition follows below. The forward declaration is needed because
* @c esp_loader_port_ops_t references @c esp_loader_port_t in its callback signatures.
*/
typedef struct esp_loader_port_s esp_loader_port_t;
/**
* @brief Unified port operations vtable.
*
* Every callback receives an @c esp_loader_port_t * (self-pointer).
* Use @c container_of to recover the full concrete port struct and access
* per-instance state.
*
* Set unused function pointers to NULL:
* - @c init / @c deinit — NULL if no hardware setup is needed
* - @c change_transmission_rate — NULL for SDIO (host driver manages speed)
* - @c write / @c read — NULL for SDIO ports
* - @c spi_set_cs — NULL for non-SPI ports
* - @c sdio_write / @c sdio_read / @c sdio_card_init — NULL for non-SDIO ports
*/
typedef struct {
/**
* Initializes the hardware peripheral (UART driver, GPIO pins, etc.).
* Called automatically by esp_loader_init_*(). NULL if not needed.
*/
esp_loader_error_t (*init)(esp_loader_port_t *port);
/**
* Deinitializes the hardware peripheral.
* The caller is responsible for invoking this when the port is no longer needed.
* NULL if not needed.
*/
void (*deinit)(esp_loader_port_t *port);
/** Asserts bootstrap pins to enter boot mode and toggles reset. */
void (*enter_bootloader)(esp_loader_port_t *port);
/** Toggles the reset pin. */
void (*reset_target)(esp_loader_port_t *port);
/** Starts a one-shot timeout timer. */
void (*start_timer)(esp_loader_port_t *port, uint32_t ms);
/**
* Returns remaining milliseconds since the last start_timer call.
* Returns 0 if the timer has elapsed.
*/
uint32_t (*remaining_time)(esp_loader_port_t *port);
/** Delays execution for the given number of milliseconds. */
void (*delay_ms)(esp_loader_port_t *port, uint32_t ms);
/**
* Prints a debug message string.
* Set to NULL to suppress debug output.
*/
void (*debug_print)(esp_loader_port_t *port, const char *str);
/**
* Changes the peripheral clock/baud rate.
* Set to NULL when not supported (e.g. SDIO).
*/
esp_loader_error_t (*change_transmission_rate)(esp_loader_port_t *port, uint32_t rate);
/** Writes bytes to the peripheral (UART/USB/SPI). NULL for SDIO. */
esp_loader_error_t (*write)(esp_loader_port_t *port, const uint8_t *data, uint16_t size, uint32_t timeout);
/** Reads bytes from the peripheral (UART/USB/SPI). NULL for SDIO. */
esp_loader_error_t (*read)(esp_loader_port_t *port, uint8_t *data, uint16_t size, uint32_t timeout);
/** Controls the SPI chip-select pin. NULL for non-SPI ports. */
void (*spi_set_cs)(esp_loader_port_t *port, uint32_t level);
/** Writes data over SDIO. NULL for non-SDIO ports. */
esp_loader_error_t (*sdio_write)(esp_loader_port_t *port, uint32_t function, uint32_t addr,
const uint8_t *data, uint16_t size, uint32_t timeout);
/** Reads data over SDIO. NULL for non-SDIO ports. */
esp_loader_error_t (*sdio_read)(esp_loader_port_t *port, uint32_t function, uint32_t addr,
uint8_t *data, uint16_t size, uint32_t timeout);
/** Initializes the SDIO card. NULL for non-SDIO ports. */
esp_loader_error_t (*sdio_card_init)(esp_loader_port_t *port);
} esp_loader_port_ops_t;
/**
* @brief Port handle.
*
* For Phase 1, declare a plain @c esp_loader_port_t with @c ops pointing at
* your static ops table and pass its address to @c esp_loader_init_*().
*
* In Phase 2 (after static variable migration) embed this struct inside a
* larger per-instance struct and use @c container_of inside callbacks to
* recover the full struct.
*
* The library stores @c esp_loader_port_t * internally and dispatches all
* operations through @c port->ops->fn(port, ...).
*/
struct esp_loader_port_s {
const esp_loader_port_ops_t *ops;
};
#ifdef __cplusplus
}
#endif