Skip to content

Commit 5cbb3f0

Browse files
author
Felipe Neves
committed
freertos: Added experimental, optional FPU usage on level 1 ISR
1 parent 670ea56 commit 5cbb3f0

File tree

5 files changed

+61
-10
lines changed

5 files changed

+61
-10
lines changed

components/freertos/Kconfig

+8
Original file line numberDiff line numberDiff line change
@@ -420,4 +420,12 @@ menu "FreeRTOS"
420420
help
421421
Hidden option, gets selected by CONFIG_ESPxx_DEBUG_OCDAWARE
422422

423+
config FREERTOS_FPU_IN_ISR
424+
bool "Allow use of float inside Level 1 ISR (EXPERIMENTAL)"
425+
depends on IDF_TARGET_ESP32
426+
default n
427+
help
428+
When enabled, the usage of float type is allowed inside Level 1
429+
ISRs.
430+
423431
endmenu

components/freertos/portasm.S

+25-1
Original file line numberDiff line numberDiff line change
@@ -138,8 +138,24 @@ _frxt_int_enter:
138138
mull a2, a4, a2
139139
add a1, a1, a2 /* for current proc */
140140

141+
#ifdef CONFIG_FREERTOS_FPU_IN_ISR
142+
#if XCHAL_CP_NUM > 0
143+
rsr a3, CPENABLE /* Restore thread scope CPENABLE */
144+
addi sp, sp,-4 /* ISR will manage FPU coprocessor by forcing */
145+
s32i a3, a1, 0 /* its trigger */
146+
#endif
147+
#endif
148+
141149
.Lnested:
142150
1:
151+
#ifdef CONFIG_FREERTOS_FPU_IN_ISR
152+
#if XCHAL_CP_NUM > 0
153+
movi a3, 0 /* whilst ISRs pending keep CPENABLE exception active */
154+
wsr a3, CPENABLE
155+
rsync
156+
#endif
157+
#endif
158+
143159
mov a0, a12 /* restore return addr and return */
144160
ret
145161

@@ -176,6 +192,15 @@ _frxt_int_exit:
176192
s32i a2, a3, 0 /* save nesting count */
177193
bnez a2, .Lnesting /* !=0 after decr so still nested */
178194

195+
#ifdef CONFIG_FREERTOS_FPU_IN_ISR
196+
#if XCHAL_CP_NUM > 0
197+
l32i a3, sp, 0 /* Grab last CPENABLE before leave ISR */
198+
addi sp, sp, 4
199+
wsr a3, CPENABLE
200+
rsync /* ensure CPENABLE was modified */
201+
#endif
202+
#endif
203+
179204
movi a2, pxCurrentTCB
180205
addx4 a2, a4, a2
181206
l32i a2, a2, 0 /* a2 = current TCB */
@@ -642,7 +667,6 @@ _frxt_task_coproc_state:
642667
addx4 a15, a3, a15
643668
l32i a15, a15, 0 /* && pxCurrentTCB != 0) { */
644669

645-
646670
beqz a15, 2f
647671
l32i a15, a15, CP_TOPOFSTACK_OFFS
648672
ret

components/freertos/test/test_float_in_isr.c

+12-5
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "math.h"
1515

1616
#define SW_ISR_LEVEL_1 7
17+
#ifdef CONFIG_FREERTOS_FPU_IN_ISR
1718

1819
struct fp_test_context {
1920
SemaphoreHandle_t sync;
@@ -27,8 +28,8 @@ static void software_isr(void *arg) {
2728

2829
struct fp_test_context *ctx = (struct fp_test_context *)arg;
2930

30-
for(int i = 0; i < 10; i++) {
31-
ctx->expected = ctx->expected * 2.0f;
31+
for(int i = 0; i < 16; i++) {
32+
ctx->expected = ctx->expected * 2.0f * cosf(0.0f);
3233
}
3334

3435
xSemaphoreGiveFromISR(ctx->sync, &yield);
@@ -38,9 +39,10 @@ static void software_isr(void *arg) {
3839
}
3940

4041

41-
TEST_CASE("Floating point usage in ISR test", "[freertos] [ignore]")
42+
TEST_CASE("Floating point usage in ISR test", "[freertos]" "[fp]")
4243
{
4344
struct fp_test_context ctx;
45+
float fp_math_operation_result = 0.0f;
4446

4547
intr_handle_t handle;
4648
esp_err_t err = esp_intr_alloc(ETS_INTERNAL_SW0_INTR_SOURCE, ESP_INTR_FLAG_LEVEL1, &software_isr, &ctx, &handle);
@@ -50,11 +52,16 @@ TEST_CASE("Floating point usage in ISR test", "[freertos] [ignore]")
5052
TEST_ASSERT(ctx.sync != NULL);
5153
ctx.expected = 1.0f;
5254

55+
fp_math_operation_result = cosf(0.0f);
56+
5357
xt_set_intset(1 << SW_ISR_LEVEL_1);
5458
xSemaphoreTake(ctx.sync, portMAX_DELAY);
5559

5660
esp_intr_free(handle);
5761
vSemaphoreDelete(ctx.sync);
5862

59-
TEST_ASSERT_FLOAT_WITHIN(0.1f, ctx.expected, 1024.0f);
60-
}
63+
printf("FP math isr result: %f \n", ctx.expected);
64+
TEST_ASSERT_FLOAT_WITHIN(0.1f, ctx.expected, fp_math_operation_result * 65536.0f);
65+
}
66+
67+
#endif

components/freertos/xtensa_vectors.S

+13-2
Original file line numberDiff line numberDiff line change
@@ -955,7 +955,12 @@ _xt_coproc_exc:
955955

956956
/* Get co-processor state save area of new owner thread. */
957957
call0 XT_RTOS_CP_STATE /* a15 = new owner's save area */
958-
beqz a15, .L_goto_invalid /* not in a thread (invalid) */
958+
959+
#ifndef CONFIG_FREERTOS_FPU_IN_ISR
960+
beqz a15, .L_goto_invalid
961+
#endif
962+
963+
/*When FPU in ISR is enabled we could deal with zeroed a15 */
959964

960965
/* Enable the co-processor's bit in CPENABLE. */
961966
movi a0, _xt_coproc_mask
@@ -997,7 +1002,13 @@ locking.
9971002
rsync /* ensure wsr.CPENABLE is complete */
9981003

9991004
/* Only need to context switch if new owner != old owner. */
1005+
/* If float is necessary on ISR, we need to remove this check */
1006+
/* below, because on restoring from ISR we may have new == old condition used
1007+
* to force cp restore to next thread
1008+
*/
1009+
#ifndef CONFIG_FREERTOS_FPU_IN_ISR
10001010
beq a15, a2, .L_goto_done /* new owner == old, we're done */
1011+
#endif
10011012

10021013
/* If no old owner then nothing to save. */
10031014
beqz a2, .L_check_new
@@ -1039,6 +1050,7 @@ locking.
10391050
.L_check_new:
10401051
/* Check if any state has to be restored for new owner. */
10411052
/* NOTE: a15 = new owner's save area, cannot be zero when we get here. */
1053+
beqz a15, .L_xt_coproc_done
10421054

10431055
l16ui a3, a15, XT_CPSTORED /* a3 = new owner's CPSTORED */
10441056
movi a4, _xt_coproc_sa_offset
@@ -1133,7 +1145,6 @@ _xt_lowint1:
11331145
#endif
11341146
#endif
11351147

1136-
11371148
/* Save rest of interrupt context and enter RTOS. */
11381149
call0 XT_RTOS_INT_ENTER /* common RTOS interrupt entry */
11391150

docs/en/api-guides/freertos-smp.rst

+3-2
Original file line numberDiff line numberDiff line change
@@ -409,8 +409,9 @@ the state of a core's FPU registers are not immediately saved when a context
409409
switch occurs. Therefore, tasks that utilize ``float`` must be pinned to a
410410
particular core upon creation. If not, ESP-IDF FreeRTOS will automatically pin
411411
the task in question to whichever core the task was running on upon the task's
412-
first use of ``float``. Likewise due to Lazy Context Switching, interrupt service
413-
routines must also not use ``float``.
412+
first use of ``float``. Likewise due to Lazy Context Switching, only interrupt
413+
service routines of lowest priority (that is it the Level 1) can use ``float``,
414+
higher priority interrupts do not support FPU usage.
414415

415416
ESP32 does not support hardware acceleration for double precision floating point
416417
arithmetic (``double``). Instead ``double`` is implemented via software hence the

0 commit comments

Comments
 (0)