Skip to content

Instantly share code, notes, and snippets.

@tomtor
Last active January 11, 2023 13:05
Show Gist options
  • Save tomtor/fa7d6d2cbd8d9b076a503107330be3a1 to your computer and use it in GitHub Desktop.
Save tomtor/fa7d6d2cbd8d9b076a503107330be3a1 to your computer and use it in GitHub Desktop.
ESP32 ULP subroutine and stack macros and multiply routine
/*
* 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
@tomtor
Copy link
Author

tomtor commented Jan 11, 2023

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

@Edzelf
Copy link

Edzelf commented Jan 11, 2023

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