|
| 1 | +""" |
| 2 | +Very basic example showing how to read a GPIO pin from the ULP and access |
| 3 | +that data from the main CPU. |
| 4 | +
|
| 5 | +In this case GPIO4 is being read. Note that the ULP needs to refer to GPIOs |
| 6 | +via their RTC channel number. You can see the mapping in this file: |
| 7 | +https://github.com/espressif/esp-idf/blob/v4.4.1/components/soc/esp32/include/soc/rtc_io_channel.h#L51 |
| 8 | +
|
| 9 | +If you change to a different GPIO number, make sure to modify both the channel |
| 10 | +number and also the RTC_IO_TOUCH_PAD0_* references appropriately. The best place |
| 11 | +to see the mappings might be this table here (notice the "real GPIO numbers" as |
| 12 | +comments to each line): |
| 13 | +https://github.com/espressif/esp-idf/blob/v4.4.1/components/soc/esp32/rtc_io_periph.c#L61 |
| 14 | +
|
| 15 | +The timer is set to a rather long period, so you can watch the data value |
| 16 | +change as you change the GPIO input (see loop at the end). |
| 17 | +""" |
| 18 | + |
| 19 | +from esp32 import ULP |
| 20 | +from machine import mem32 |
| 21 | + |
| 22 | +from esp32_ulp import src_to_binary |
| 23 | + |
| 24 | +source = """\ |
| 25 | +#define DR_REG_RTCIO_BASE 0x3ff48400 |
| 26 | +#define RTC_IO_TOUCH_PAD0_REG (DR_REG_RTCIO_BASE + 0x94) |
| 27 | +#define RTC_IO_TOUCH_PAD0_MUX_SEL_M (BIT(19)) |
| 28 | +#define RTC_IO_TOUCH_PAD0_FUN_IE_M (BIT(13)) |
| 29 | +#define RTC_GPIO_IN_REG (DR_REG_RTCIO_BASE + 0x24) |
| 30 | +#define RTC_GPIO_IN_NEXT_S 14 |
| 31 | +.set channel, 10 # 10 is the channel no. of gpio4 |
| 32 | +
|
| 33 | +state: .long 0 |
| 34 | +
|
| 35 | +entry: |
| 36 | + # connect GPIO to the RTC subsystem so the ULP can read it |
| 37 | + WRITE_RTC_REG(RTC_IO_TOUCH_PAD0_REG, RTC_IO_TOUCH_PAD0_MUX_SEL_M, 1, 1) |
| 38 | +
|
| 39 | + # switch the GPIO into input mode |
| 40 | + WRITE_RTC_REG(RTC_IO_TOUCH_PAD0_REG, RTC_IO_TOUCH_PAD0_FUN_IE_M, 1, 1) |
| 41 | +
|
| 42 | + # read the GPIO's current state into r0 |
| 43 | + READ_RTC_REG(RTC_GPIO_IN_REG, RTC_GPIO_IN_NEXT_S + channel, 1) |
| 44 | +
|
| 45 | + # set r3 to the memory address of "state" |
| 46 | + move r3, state |
| 47 | +
|
| 48 | + # store what was read into r0 into the "state" variable |
| 49 | + st r0, r3, 0 |
| 50 | +
|
| 51 | + # halt ULP co-processor (until it gets woken up again) |
| 52 | + halt |
| 53 | +""" |
| 54 | + |
| 55 | +binary = src_to_binary(source) |
| 56 | + |
| 57 | +load_addr, entry_addr = 0, 4 |
| 58 | + |
| 59 | +ULP_MEM_BASE = 0x50000000 |
| 60 | +ULP_DATA_MASK = 0xffff # ULP data is only in lower 16 bits |
| 61 | + |
| 62 | +ulp = ULP() |
| 63 | +ulp.set_wakeup_period(0, 50000) # use timer0, wakeup after 50.000 cycles |
| 64 | +ulp.load_binary(load_addr, binary) |
| 65 | + |
| 66 | +mem32[ULP_MEM_BASE + load_addr] = 0x0 # initialise state to 0 |
| 67 | +ulp.run(entry_addr) |
| 68 | + |
| 69 | +while True: |
| 70 | + print(hex(mem32[ULP_MEM_BASE + load_addr] & ULP_DATA_MASK)) |
| 71 | + |
0 commit comments