Last active
January 11, 2023 13:05
-
-
Save tomtor/fa7d6d2cbd8d9b076a503107330be3a1 to your computer and use it in GitHub Desktop.
ESP32 ULP subroutine and stack macros and multiply routine
This file contains 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
/* | |
* Demo of Stack and subroutine macros for ESP32 ULP | |
* | |
* R3 is the SP | |
*/ | |
#include "soc/rtc_cntl_reg.h" | |
#include "soc/rtc_io_reg.h" | |
#include "soc/soc_ulp.h" | |
.macro push rx | |
st \rx,r3,0 | |
sub r3,r3,1 | |
.endm | |
.macro pop rx | |
add r3,r3,1 | |
ld \rx,r3,0 | |
.endm | |
// Prepare subroutine jump, uses scratch register sr | |
.macro psr sr=r1 pos=. | |
.set _next2,(\pos+16) | |
move \sr,_next2 | |
push \sr | |
.endm | |
// Return from subroutine | |
.macro ret sr=r1 | |
pop \sr | |
jump \sr | |
.endm | |
/* Define variables, which go into .bss section (zero-initialized data) */ | |
.bss | |
.global stack | |
stack: | |
.skip 400 | |
.global stackEnd | |
stackEnd: | |
.long 0 | |
/* Code goes into .text section */ | |
.text | |
.global entry | |
entry: | |
move r3,stackEnd | |
move r2,7 // loop counter | |
odd: | |
push r2 // save r2 (needed if subroutine overwrites it) | |
psr | |
jump flash // r2 has number of pin toggles | |
pop r2 // restore r2 | |
sub r2,r2,2 | |
jump done,ov | |
jump odd | |
done: | |
move r2,3 | |
psr | |
jump flash | |
move r2,2 | |
psr | |
jump flash | |
move r2,1 | |
psr | |
jump flash | |
move r0,4 | |
move r2,3 | |
psr | |
jump multiply // multiply 4 x 3 | |
move r2,r0 | |
psr | |
jump flash | |
jump wake_up | |
flash: | |
move r0,r2 | |
jumpr tail,1,lt | |
loop: | |
WRITE_RTC_REG(RTC_GPIO_OUT_REG, RTC_GPIO_OUT_DATA_S + 12, 1, 1) | |
move r2,200 // wait 200 ms | |
psr | |
jump waitMs | |
WRITE_RTC_REG(RTC_GPIO_OUT_REG, RTC_GPIO_OUT_DATA_S + 12, 1, 0) | |
move r2,400 | |
psr | |
jump waitMs | |
sub r0,r0,1 | |
jumpr loop,1,ge | |
tail: | |
move r2,800 | |
psr | |
jump waitMs | |
ret | |
waitMs: | |
wait 8000 | |
sub r2,r2,1 | |
jump doneWaitMs,eq | |
jump waitMs | |
doneWaitMs: | |
ret | |
multiply: // r0 x r2, result in r0 | |
move r1,0 // accumulates result | |
nextMultiply: | |
st r0,r3,0 // Hack: save r0 at top of the stack, to safe a few instructions instead of push/pop | |
and r0,r0,1 | |
jump noAdd,eq | |
add r1,r1,r2 | |
noAdd: | |
lsh r2,r2,1 | |
ld r0,r3,0 // restore r0 | |
rsh r0,r0,1 | |
jump doneMultiply,eq | |
jump nextMultiply | |
doneMultiply: | |
move r0,r1 | |
ret | |
wake_up: | |
/* Wake up the SoC, end program */ | |
wake | |
halt |
Hi Tom, How about this macro:
.macro jsr sadr pos=. .set _next2,(\pos+16) // Set return address move r1,_next2 push r1 jump \sadr // Jump to the subroutine .endm
Then you can simply write a call like this:
jsr waitMs
I tried this when I wrote the code originally but probably due to an assembler bug that did not work :(
If you get it to work with recent software I would be happy to merge your changes
Yes, I used parts of your code to successfully read a Bosch BMA400 3 axis acceleration sensor over I2C. Thanks!
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi Tom,
How about this macro:
Then you can simply write a call like this:
jsr waitMs