-
-
Notifications
You must be signed in to change notification settings - Fork 3.9k
Import RmtHI driver #4890
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Import RmtHI driver #4890
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
19a49e8
Import RmtHI driver
willmmiles 91d7e0c
RmtHI: Remove incorrect default selection block
willmmiles 5e3803a
RmtHI: Fix incorrect method typedefs
willmmiles 831b68e
usermods CI: Use correct base esp32 platform
willmmiles 3e9e18d
Undo RMTHi change to platformio.ini
willmmiles 2e83485
RmtHI: Add missing includes
willmmiles File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| { | ||
| "name": "NeoESP32RmtHI", | ||
| "build": { "libArchive": false }, | ||
| "platforms": ["espressif32"], | ||
| "dependencies": [ | ||
| { | ||
| "owner": "makuna", | ||
| "name": "NeoPixelBus", | ||
| "version": "^2.8.3" | ||
| } | ||
| ] | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,263 @@ | ||
| /* RMT ISR shim | ||
| * Bridges from a high-level interrupt to the C++ code. | ||
| * | ||
| * This code is largely derived from Espressif's 'hli_vector.S' Bluetooth ISR. | ||
| * | ||
| */ | ||
|
|
||
| #if defined(__XTENSA__) && defined(ESP32) && !defined(CONFIG_BTDM_CTRL_HLI) | ||
|
|
||
| #include <freertos/xtensa_context.h> | ||
| #include "sdkconfig.h" | ||
| #include "soc/soc.h" | ||
|
|
||
| /* If the Bluetooth driver has hooked the high-priority interrupt, we piggyback on it and don't need this. */ | ||
| #ifndef CONFIG_BTDM_CTRL_HLI | ||
|
|
||
willmmiles marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| /* | ||
| Select interrupt based on system check level | ||
| - Base ESP32: could be 4 or 5, depends on platform config | ||
| - S2: 5 | ||
| - S3: 5 | ||
| */ | ||
|
|
||
| #if CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL_5 | ||
| /* Use level 4 */ | ||
| #define RFI_X 4 | ||
| #define xt_highintx xt_highint4 | ||
| #else /* !CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL_5 */ | ||
| /* Use level 5 */ | ||
| #define RFI_X 5 | ||
| #define xt_highintx xt_highint5 | ||
| #endif /* CONFIG_ESP_SYSTEM_CHECK_INT_LEVEL_5 */ | ||
|
|
||
| // Register map, based on interrupt level | ||
| #define EPC_X (EPC + RFI_X) | ||
| #define EXCSAVE_X (EXCSAVE + RFI_X) | ||
|
|
||
| // The sp mnemonic is used all over in ESP's assembly, though I'm not sure where it's expected to be defined? | ||
| #define sp a1 | ||
|
|
||
| /* Interrupt stack size, for C code. */ | ||
| #define RMT_INTR_STACK_SIZE 512 | ||
|
|
||
| /* Save area for the CPU state: | ||
| * - 64 words for the general purpose registers | ||
| * - 7 words for some of the special registers: | ||
| * - WINDOWBASE, WINDOWSTART — only WINDOWSTART is truly needed | ||
| * - SAR, LBEG, LEND, LCOUNT — since the C code might use these | ||
| * - EPC1 — since the C code might cause window overflow exceptions | ||
| * This is not laid out as standard exception frame structure | ||
| * for simplicity of the save/restore code. | ||
| */ | ||
| #define REG_FILE_SIZE (64 * 4) | ||
| #define SPECREG_OFFSET REG_FILE_SIZE | ||
| #define SPECREG_SIZE (7 * 4) | ||
| #define REG_SAVE_AREA_SIZE (SPECREG_OFFSET + SPECREG_SIZE) | ||
|
|
||
| .data | ||
| _rmt_intr_stack: | ||
| .space RMT_INTR_STACK_SIZE | ||
| _rmt_save_ctx: | ||
| .space REG_SAVE_AREA_SIZE | ||
|
|
||
| .section .iram1,"ax" | ||
| .global xt_highintx | ||
| .type xt_highintx,@function | ||
| .align 4 | ||
|
|
||
| xt_highintx: | ||
|
|
||
| movi a0, _rmt_save_ctx | ||
| /* save 4 lower registers */ | ||
| s32i a1, a0, 4 | ||
| s32i a2, a0, 8 | ||
| s32i a3, a0, 12 | ||
| rsr a2, EXCSAVE_X /* holds the value of a0 */ | ||
| s32i a2, a0, 0 | ||
|
|
||
| /* Save special registers */ | ||
| addi a0, a0, SPECREG_OFFSET | ||
| rsr a2, WINDOWBASE | ||
| s32i a2, a0, 0 | ||
| rsr a2, WINDOWSTART | ||
| s32i a2, a0, 4 | ||
| rsr a2, SAR | ||
| s32i a2, a0, 8 | ||
| #if XCHAL_HAVE_LOOPS | ||
| rsr a2, LBEG | ||
| s32i a2, a0, 12 | ||
| rsr a2, LEND | ||
| s32i a2, a0, 16 | ||
| rsr a2, LCOUNT | ||
| s32i a2, a0, 20 | ||
| #endif | ||
| rsr a2, EPC1 | ||
| s32i a2, a0, 24 | ||
|
|
||
| /* disable exception mode, window overflow */ | ||
| movi a0, PS_INTLEVEL(RFI_X+1) | PS_EXCM | ||
| wsr a0, PS | ||
| rsync | ||
|
|
||
| /* Save the remaining physical registers. | ||
| * 4 registers are already saved, which leaves 60 registers to save. | ||
| * (FIXME: consider the case when the CPU is configured with physical 32 registers) | ||
| * These 60 registers are saved in 5 iterations, 12 registers at a time. | ||
| */ | ||
| movi a1, 5 | ||
| movi a3, _rmt_save_ctx + 4 * 4 | ||
|
|
||
| /* This is repeated 5 times, each time the window is shifted by 12 registers. | ||
| * We come here with a1 = downcounter, a3 = save pointer, a2 and a0 unused. | ||
| */ | ||
| 1: | ||
| s32i a4, a3, 0 | ||
| s32i a5, a3, 4 | ||
| s32i a6, a3, 8 | ||
| s32i a7, a3, 12 | ||
| s32i a8, a3, 16 | ||
| s32i a9, a3, 20 | ||
| s32i a10, a3, 24 | ||
| s32i a11, a3, 28 | ||
| s32i a12, a3, 32 | ||
| s32i a13, a3, 36 | ||
| s32i a14, a3, 40 | ||
| s32i a15, a3, 44 | ||
|
|
||
| /* We are about to rotate the window, so that a12-a15 will become the new a0-a3. | ||
| * Copy a0-a3 to a12-15 to still have access to these values. | ||
| * At the same time we can decrement the counter and adjust the save area pointer | ||
| */ | ||
|
|
||
| /* a0 is constant (_rmt_save_ctx), no need to copy */ | ||
| addi a13, a1, -1 /* copy and decrement the downcounter */ | ||
| /* a2 is scratch so no need to copy */ | ||
| addi a15, a3, 48 /* copy and adjust the save area pointer */ | ||
| beqz a13, 2f /* have saved all registers ? */ | ||
| rotw 3 /* rotate the window and go back */ | ||
| j 1b | ||
|
|
||
| /* the loop is complete */ | ||
| 2: | ||
| rotw 4 /* this brings us back to the original window */ | ||
| /* a0 still points to _rmt_save_ctx */ | ||
|
|
||
| /* Can clear WINDOWSTART now, all registers are saved */ | ||
| rsr a2, WINDOWBASE | ||
| /* WINDOWSTART = (1 << WINDOWBASE) */ | ||
| movi a3, 1 | ||
| ssl a2 | ||
| sll a3, a3 | ||
| wsr a3, WINDOWSTART | ||
|
|
||
| _highint_stack_switch: | ||
| movi a0, 0 | ||
| movi sp, _rmt_intr_stack + RMT_INTR_STACK_SIZE - 16 | ||
| s32e a0, sp, -12 /* For GDB: set null SP */ | ||
| s32e a0, sp, -16 /* For GDB: set null PC */ | ||
| movi a0, _highint_stack_switch /* For GDB: cosmetics, for the frame where stack switch happened */ | ||
|
|
||
| /* Set up PS for C, disable all interrupts except NMI and debug, and clear EXCM. */ | ||
| movi a6, PS_INTLEVEL(RFI_X) | PS_UM | PS_WOE | ||
| wsr a6, PS | ||
| rsync | ||
|
|
||
| /* Call C handler */ | ||
| mov a6, sp | ||
| call4 NeoEsp32RmtMethodIsr | ||
|
|
||
| l32e sp, sp, -12 /* switch back to the original stack */ | ||
|
|
||
| /* Done with C handler; re-enable exception mode, disabling window overflow */ | ||
| movi a2, PS_INTLEVEL(RFI_X+1) | PS_EXCM /* TOCHECK */ | ||
| wsr a2, PS | ||
| rsync | ||
|
|
||
| /* Restore the special registers. | ||
| * WINDOWSTART will be restored near the end. | ||
| */ | ||
| movi a0, _rmt_save_ctx + SPECREG_OFFSET | ||
| l32i a2, a0, 8 | ||
| wsr a2, SAR | ||
| #if XCHAL_HAVE_LOOPS | ||
| l32i a2, a0, 12 | ||
| wsr a2, LBEG | ||
| l32i a2, a0, 16 | ||
| wsr a2, LEND | ||
| l32i a2, a0, 20 | ||
| wsr a2, LCOUNT | ||
| #endif | ||
| l32i a2, a0, 24 | ||
| wsr a2, EPC1 | ||
|
|
||
| /* Restoring the physical registers. | ||
| * This is the reverse to the saving process above. | ||
| */ | ||
|
|
||
| /* Rotate back to the final window, then start loading 12 registers at a time, | ||
| * in 5 iterations. | ||
| * Again, a1 is the downcounter and a3 is the save area pointer. | ||
| * After each rotation, a1 and a3 are copied from a13 and a15. | ||
| * To simplify the loop, we put the initial values into a13 and a15. | ||
| */ | ||
| rotw -4 | ||
| movi a15, _rmt_save_ctx + 64 * 4 /* point to the end of the save area */ | ||
| movi a13, 5 | ||
|
|
||
| 1: | ||
| /* Copy a1 and a3 from their previous location, | ||
| * at the same time decrementing and adjusting the save area pointer. | ||
| */ | ||
| addi a1, a13, -1 | ||
| addi a3, a15, -48 | ||
|
|
||
| /* Load 12 registers */ | ||
| l32i a4, a3, 0 | ||
| l32i a5, a3, 4 | ||
| l32i a6, a3, 8 | ||
| l32i a7, a3, 12 | ||
| l32i a8, a3, 16 | ||
| l32i a9, a3, 20 | ||
| l32i a10, a3, 24 | ||
| l32i a11, a3, 28 /* ensure PS and EPC written */ | ||
| l32i a12, a3, 32 | ||
| l32i a13, a3, 36 | ||
| l32i a14, a3, 40 | ||
| l32i a15, a3, 44 | ||
|
|
||
| /* Done with the loop? */ | ||
| beqz a1, 2f | ||
| /* If no, rotate the window and repeat */ | ||
| rotw -3 | ||
| j 1b | ||
|
|
||
| 2: | ||
| /* Done with the loop. Only 4 registers (a0-a3 in the original window) remain | ||
| * to be restored. Also need to restore WINDOWSTART, since all the general | ||
| * registers are now in place. | ||
| */ | ||
| movi a0, _rmt_save_ctx | ||
|
|
||
| l32i a2, a0, SPECREG_OFFSET + 4 | ||
| wsr a2, WINDOWSTART | ||
|
|
||
| l32i a1, a0, 4 | ||
| l32i a2, a0, 8 | ||
| l32i a3, a0, 12 | ||
| rsr a0, EXCSAVE_X /* holds the value of a0 before the interrupt handler */ | ||
|
|
||
| /* Return from the interrupt, restoring PS from EPS_X */ | ||
| rfi RFI_X | ||
|
|
||
|
|
||
| /* The linker has no reason to link in this file; all symbols it exports are already defined | ||
| (weakly!) in the default int handler. Define a symbol here so we can use it to have the | ||
| linker inspect this anyway. */ | ||
|
|
||
| .global ld_include_hli_vectors_rmt | ||
| ld_include_hli_vectors_rmt: | ||
|
|
||
|
|
||
| #endif // CONFIG_BTDM_CTRL_HLI | ||
| #endif // XTensa | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.