Skip to content

Commit 7df1530

Browse files
authored
Use callx4 to call the init function (#4815)
* Use callx4 to call the init function * Avoid using 0-byte stack frames * Reduce stack size of initial frames
1 parent 0fe44c1 commit 7df1530

File tree

3 files changed

+51
-48
lines changed

3 files changed

+51
-48
lines changed

esp-hal/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
5151
- The `Peripherals` struct is now marked as `#[non_exhaustive]`. This is a breaking change. (#4729)
5252
- All GPIOs are now available without unsafe code. The potentially reserved GPIOs are now documented. (#4728)
5353
- Make sure we added all relevant section to `.rwtext.wifi` (#4808)
54+
- ESP32-S3: Fixed startup code to prevent a linker error (#4815)
5455

5556
### Removed
5657

esp-hal/src/soc/mod.rs

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -148,29 +148,29 @@ mod xtensa {
148148
extern "C" fn post_init() {
149149
naked_asm!(
150150
"
151-
entry a1, 0
151+
entry a1, 0x10 // 4 words for callx4 spill area
152152
153-
l32r a6, sym_xtensa_lx_rt_zero_fill // Pre-load address of zero-fill function
153+
l32r a2, sym_xtensa_lx_rt_zero_fill // Pre-load address of zero-fill function
154154
155-
l32r a10, sym_rtc_fast_bss_start // Set input range to .rtc_fast.bss
156-
l32r a11, sym_rtc_fast_bss_end //
157-
callx8 a6 // Zero-fill
155+
l32r a6, sym_rtc_fast_bss_start // Set input range to .rtc_fast.bss
156+
l32r a7, sym_rtc_fast_bss_end //
157+
callx4 a2 // Zero-fill
158158
159-
l32r a10, sym_rtc_slow_bss_start // Set input range to .rtc_slow.bss
160-
l32r a11, sym_rtc_slow_bss_end //
161-
callx8 a6 // Zero-fill
159+
l32r a6, sym_rtc_slow_bss_start // Set input range to .rtc_slow.bss
160+
l32r a7, sym_rtc_slow_bss_end //
161+
callx4 a2 // Zero-fill
162162
163-
l32r a5, sym_init_persistent // Do we need to initialize persistent data?
164-
callx8 a5
165-
beqz a10, .Lpost_init_return // If not, skip initialization
163+
l32r a3, sym_init_persistent // Do we need to initialize persistent data?
164+
callx4 a3
165+
beqz a6, .Lpost_init_return // If not, skip initialization
166166
167-
l32r a10, sym_rtc_fast_persistent_start // Set input range to .rtc_fast.persistent
168-
l32r a11, sym_rtc_fast_persistent_end //
169-
callx8 a6 // Zero-fill
167+
l32r a6, sym_rtc_fast_persistent_start // Set input range to .rtc_fast.persistent
168+
l32r a7, sym_rtc_fast_persistent_end //
169+
callx4 a2 // Zero-fill
170170
171-
l32r a10, sym_rtc_slow_persistent_start // Set input range to .rtc_slow.persistent
172-
l32r a11, sym_rtc_slow_persistent_end //
173-
callx8 a6 // Zero-fill
171+
l32r a6, sym_rtc_slow_persistent_start // Set input range to .rtc_slow.persistent
172+
l32r a7, sym_rtc_slow_persistent_end //
173+
callx4 a2 // Zero-fill
174174
175175
.Lpost_init_return:
176176
retw.n
@@ -184,12 +184,14 @@ mod xtensa {
184184
"
185185
.literal sym_stack_chk_guard, {__stack_chk_guard}
186186
.literal stack_guard_value, {stack_guard_value}
187+
.literal sym_esp32_init, {__esp32_init}
187188
",
188189
__stack_chk_guard = sym __stack_chk_guard,
189190
stack_guard_value = const esp_config::esp_config_int!(
190191
u32,
191192
"ESP_HAL_CONFIG_STACK_GUARD_VALUE"
192-
)
193+
),
194+
__esp32_init = sym esp32_init,
193195
);
194196

195197
#[cfg_attr(esp32s3, unsafe(link_section = ".rwtext"))]
@@ -199,18 +201,18 @@ mod xtensa {
199201
// Set up stack protector value before jumping to a rust function
200202
naked_asm! {
201203
"
202-
entry a1, 0x20
204+
entry a1, 0x10 // 4 words for callx4 spill area
203205
204206
// Set up the stack protector value
205207
l32r a2, sym_stack_chk_guard
206208
l32r a3, stack_guard_value
207209
s32i.n a3, a2, 0
208210
209-
call8 {esp32_init}
211+
l32r a2, sym_esp32_init
212+
callx4 a2
210213
211214
retw.n
212-
",
213-
esp32_init = sym esp32_init
215+
"
214216
}
215217
}
216218

xtensa-lx-rt/src/lib.rs

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ global_asm!(
8888
.p2align 2
8989
.type _xtensa_lx_rt_zero_fill,@function
9090
_xtensa_lx_rt_zero_fill:
91-
entry a1, 0
91+
entry a1, 0 // Leaf function, no need to reserve stack
9292
bgeu a2, a3, .Lfill_done // If start >= end, skip zeroing
9393
movi.n a5, 0
9494
@@ -111,7 +111,7 @@ _xtensa_lx_rt_zero_fill:
111111
.p2align 2
112112
.type _xtensa_lx_rt_copy,@function
113113
_xtensa_lx_rt_copy:
114-
entry a1, 0
114+
entry a1, 0 // Leaf function, no need to reserve stack
115115
bgeu a3, a4, .Lcopy_done // If start >= end, skip copying
116116
.Lcopy_loop:
117117
l32i.n a5, a2, 0 // Load word from source pointer
@@ -127,35 +127,35 @@ _xtensa_lx_rt_copy:
127127
.p2align 2
128128
.type Reset,@function
129129
Reset:
130-
entry a1, 0
130+
entry a1, 0x10 // We're using call4/callx4, reserve 16 bytes for register spill area
131131
movi a0, 0 // Trash the return address. Debuggers may use this to stop unwinding.
132132
133133
wsr.intenable a0 // Disable interrupts
134134
135-
l32r a5, sym_stack_start_cpu0 // a5 is our temporary value register
136-
mov sp, a5 // Set the stack pointer.
135+
l32r a2, sym_stack_start_cpu0 // a2 is our temporary value register
136+
mov sp, a2 // Set the stack pointer.
137137
138-
l32r a5, sym__pre_init
139-
callx8 a5 // Call the pre-initialization function.
138+
l32r a2, sym__pre_init
139+
callx4 a2 // Call the pre-initialization function.
140140
141141
.Linit_bss:
142-
l32r a5, sym__zero_bss // Do we need to zero-initialize memory?
143-
callx8 a5
144-
beqz a10, .Linit_data // No -> skip to copying initialized data
142+
l32r a2, sym__zero_bss // Do we need to zero-initialize memory?
143+
callx4 a2
144+
beqz a6, .Linit_data // No -> skip to copying initialized data
145145
146-
l32r a10, sym_bss_start // Set input range to .bss
147-
l32r a11, sym_bss_end //
148-
call8 _xtensa_lx_rt_zero_fill // Zero-fill
146+
l32r a6, sym_bss_start // Set input range to .bss
147+
l32r a7, sym_bss_end //
148+
call4 _xtensa_lx_rt_zero_fill // Zero-fill
149149
150150
.Linit_data:
151-
l32r a5, sym__init_data // Do we need to initialize data sections?
152-
callx8 a5
153-
beqz a10, .Linit_data_done // If not, skip initialization
151+
l32r a2, sym__init_data // Do we need to initialize data sections?
152+
callx4 a2
153+
beqz a6, .Linit_data_done // If not, skip initialization
154154
155-
l32r a10, sym_sidata // Arguments - source data pointer
156-
l32r a11, sym_data_start // - destination pointer
157-
l32r a12, sym_data_end // - destination end pointer
158-
call8 _xtensa_lx_rt_copy // Copy .data section
155+
l32r a6, sym_sidata // Arguments - source data pointer
156+
l32r a7, sym_data_start // - destination pointer
157+
l32r a8, sym_data_end // - destination end pointer
158+
call4 _xtensa_lx_rt_copy // Copy .data section
159159
160160
.Linit_data_done:
161161
memw // Make sure all writes are completed before proceeding. At this point, all static variables have been initialized.
@@ -184,14 +184,14 @@ cfg_global_asm!(
184184

185185
global_asm!(
186186
"
187-
l32r a5, sym_init_start // vector table address
188-
wsr.vecbase a5
187+
l32r a2, sym_init_start // vector table address
188+
wsr.vecbase a2
189189
190-
l32r a5, sym__post_init
191-
callx8 a5
190+
l32r a2, sym__post_init
191+
callx4 a2
192192
193-
l32r a5, sym_main // program entry point
194-
callx8 a5
193+
l32r a2, sym_main // program entry point
194+
callx4 a2
195195
",
196196
);
197197

0 commit comments

Comments
 (0)