Skip to content

Commit 828d63d

Browse files
committed
add ULP support with uPython assembler
1 parent fff2e19 commit 828d63d

File tree

18 files changed

+2313
-15
lines changed

18 files changed

+2313
-15
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -52,3 +52,4 @@ xtensa-esp32-elf/
5252
xtensa-esp32-elf_psram/
5353

5454
backup.sh
55+
.DS_Store
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
"""
2+
Very basic example showing data exchange main CPU <--> ULP coprocessor.
3+
4+
To show that the ULP is doing something, it just increments the value <data>.
5+
It does that once per ulp timer wakeup (and then the ULP halts until it gets
6+
waked up via the timer again).
7+
8+
The timer is set to a rather long period, so you can watch the data value
9+
incrementing (see loop at the end).
10+
"""
11+
12+
from machine import ULP
13+
from machine import mem32
14+
import utime
15+
import machine
16+
17+
from esp32_ulp.__main__ import src_to_binary
18+
19+
source = """\
20+
data: .long 0
21+
22+
entry: move r3, data # load address of data into r3
23+
ld r2, r3, 0 # load data contents ([r3+0]) into r2
24+
add r2, r2, 1 # increment r2
25+
st r2, r3, 0 # store r2 contents into data ([r3+0])
26+
halt # halt ULP co-processor (until next wake-up)
27+
"""
28+
29+
30+
print ("Wake Reason:",machine.wake_reason())
31+
binary = src_to_binary(source)
32+
33+
load_addr, entry_addr = 0, 4
34+
35+
ULP_MEM_BASE = 0x50000000
36+
ULP_DATA_MASK = 0xffff # ULP data is only in lower 16 bits
37+
38+
ulp = ULP()
39+
ulp.set_wakeup_period(0, 1000000) # use timer0, wakeup after 1s
40+
ulp.load_binary(load_addr, binary)
41+
42+
mem32[ULP_MEM_BASE + load_addr] = 0x1000
43+
ulp.run(entry_addr)
44+
45+
while True:
46+
print(hex(mem32[ULP_MEM_BASE + load_addr] & ULP_DATA_MASK))
47+
utime.sleep(1)

MicroPython_BUILD/components/micropython/component.mk

+1
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,7 @@ SRC_C = $(addprefix esp32/,\
181181
modymodem.c \
182182
machine_hw_i2c.c \
183183
machine_neopixel.c \
184+
machine_ulp.c \
184185
machine_dht.c \
185186
machine_ow.c \
186187
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
/*
2+
* This file is part of the MicroPython project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2017 "Eric Poulsen" <[email protected]>
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*/
26+
#include "machine_ulp.h"
27+
28+
#include "py/obj.h"
29+
#include "py/runtime.h"
30+
#include "py/mperrno.h"
31+
32+
#include "ulp.h"
33+
#include "esp_err.h"
34+
35+
typedef struct _machine_ulp_obj_t {
36+
mp_obj_base_t base;
37+
} machine_ulp_obj_t;
38+
39+
const mp_obj_type_t machine_ulp_type;
40+
41+
// singleton ULP object
42+
STATIC const machine_ulp_obj_t machine_ulp_obj = {{&machine_ulp_type}};
43+
44+
STATIC mp_obj_t machine_ulp_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
45+
// check arguments
46+
mp_arg_check_num(n_args, n_kw, 0, 0, false);
47+
48+
// return constant object
49+
return (mp_obj_t)&machine_ulp_obj;
50+
}
51+
52+
STATIC mp_obj_t machine_ulp_set_wakeup_period(mp_obj_t self_in, mp_obj_t period_index_in, mp_obj_t period_us_in) {
53+
mp_uint_t period_index = mp_obj_get_int(period_index_in);
54+
mp_uint_t period_us = mp_obj_get_int(period_us_in);
55+
int _errno = ulp_set_wakeup_period(period_index, period_us);
56+
if (_errno != ESP_OK) {
57+
mp_raise_OSError(_errno);
58+
}
59+
return mp_const_none;
60+
}
61+
STATIC MP_DEFINE_CONST_FUN_OBJ_3(machine_ulp_set_wakeup_period_obj, machine_ulp_set_wakeup_period);
62+
63+
STATIC mp_obj_t machine_ulp_load_binary(mp_obj_t self_in, mp_obj_t load_addr_in, mp_obj_t program_binary_in) {
64+
mp_uint_t load_addr = mp_obj_get_int(load_addr_in);
65+
66+
mp_buffer_info_t bufinfo;
67+
mp_get_buffer_raise(program_binary_in, &bufinfo, MP_BUFFER_READ);
68+
69+
int _errno = ulp_load_binary(load_addr, bufinfo.buf, bufinfo.len/sizeof(uint32_t));
70+
if (_errno != ESP_OK) {
71+
mp_raise_OSError(_errno);
72+
}
73+
return mp_const_none;
74+
}
75+
STATIC MP_DEFINE_CONST_FUN_OBJ_3(machine_ulp_load_binary_obj, machine_ulp_load_binary);
76+
77+
STATIC mp_obj_t machine_ulp_run(mp_obj_t self_in, mp_obj_t entry_point_in) {
78+
mp_uint_t entry_point = mp_obj_get_int(entry_point_in);
79+
int _errno = ulp_run(entry_point/sizeof(uint32_t));
80+
if (_errno != ESP_OK) {
81+
mp_raise_OSError(_errno);
82+
}
83+
return mp_const_none;
84+
}
85+
STATIC MP_DEFINE_CONST_FUN_OBJ_2(machine_ulp_run_obj, machine_ulp_run);
86+
87+
STATIC const mp_map_elem_t machine_ulp_locals_dict_table[] = {
88+
{ MP_OBJ_NEW_QSTR(MP_QSTR_set_wakeup_period), (mp_obj_t)&machine_ulp_set_wakeup_period_obj },
89+
{ MP_OBJ_NEW_QSTR(MP_QSTR_load_binary), (mp_obj_t)&machine_ulp_load_binary_obj },
90+
{ MP_OBJ_NEW_QSTR(MP_QSTR_run), (mp_obj_t)&machine_ulp_run_obj },
91+
{ MP_OBJ_NEW_QSTR(MP_QSTR_COPROC_RESERVE_MEM), MP_ROM_INT(CONFIG_ULP_COPROC_RESERVE_MEM) },
92+
};
93+
STATIC MP_DEFINE_CONST_DICT(machine_ulp_locals_dict, machine_ulp_locals_dict_table);
94+
95+
const mp_obj_type_t machine_ulp_type = {
96+
{ &mp_type_type },
97+
.name = MP_QSTR_ULP,
98+
.make_new = machine_ulp_make_new,
99+
.locals_dict = (mp_obj_t)&machine_ulp_locals_dict,
100+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
* This file is part of the MicroPython project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2017 "Eric Poulsen" <[email protected]>
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*/
26+
27+
#ifndef MICROPY_INCLUDED_ESP32_MACINE_ULP_H
28+
#define MICROPY_INCLUDED_ESP32_MACINE_ULP_H
29+
30+
#endif
Binary file not shown.

MicroPython_BUILD/components/micropython/esp32/modmachine.c

+2
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
#include "extmod/machine_pulse.h"
6565
#include "extmod/vfs_native.h"
6666
#include "modmachine.h"
67+
#include "machine_ulp.h"
6768
#include "mpsleep.h"
6869
#include "machine_rtc.h"
6970
#include "uart.h"
@@ -1013,6 +1014,7 @@ STATIC const mp_rom_map_elem_t machine_module_globals_table[] = {
10131014
{ MP_ROM_QSTR(MP_QSTR_ADC), MP_ROM_PTR(&machine_adc_type) },
10141015
{ MP_ROM_QSTR(MP_QSTR_DAC), MP_ROM_PTR(&machine_dac_type) },
10151016
{ MP_ROM_QSTR(MP_QSTR_I2C), MP_ROM_PTR(&machine_hw_i2c_type) },
1017+
{ MP_ROM_QSTR(MP_QSTR_ULP), MP_ROM_PTR(&machine_ulp_type) },
10161018
{ MP_ROM_QSTR(MP_QSTR_PWM), MP_ROM_PTR(&machine_pwm_type) },
10171019
{ MP_ROM_QSTR(MP_QSTR_SPI), MP_ROM_PTR(&machine_hw_spi_type) },
10181020
{ MP_ROM_QSTR(MP_QSTR_UART), MP_ROM_PTR(&machine_uart_type) },

MicroPython_BUILD/components/micropython/esp32/modmachine.h

+1
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ extern const mp_obj_type_t machine_pin_type;
115115
extern const mp_obj_type_t machine_touchpad_type;
116116
extern const mp_obj_type_t machine_adc_type;
117117
extern const mp_obj_type_t machine_dac_type;
118+
extern const mp_obj_type_t machine_ulp_type;
118119
extern const mp_obj_type_t machine_pwm_type;
119120
extern const mp_obj_type_t machine_hw_spi_type;
120121
extern const mp_obj_type_t machine_hw_i2c_type;

MicroPython_BUILD/components/micropython/esp32/modules/esp32_ulp/__init__.py

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import sys
2+
3+
from .util import garbage_collect
4+
5+
from .assemble import Assembler
6+
from .link import make_binary
7+
garbage_collect('after import')
8+
9+
10+
def src_to_binary(src):
11+
assembler = Assembler()
12+
assembler.assemble(src)
13+
garbage_collect('before symbols export')
14+
addrs_syms = assembler.symbols.export()
15+
for addr, sym in addrs_syms:
16+
print('%04d %s' % (addr, sym))
17+
18+
text, data, bss_len = assembler.fetch()
19+
return make_binary(text, data, bss_len)
20+
21+
22+
def main(fn):
23+
with open(fn) as f:
24+
src = f.read()
25+
26+
binary = src_to_binary(src)
27+
28+
if fn.endswith('.s') or fn.endswith('.S'):
29+
fn = fn[:-2]
30+
with open(fn + '.ulp', 'wb') as f:
31+
f.write(binary)
32+
33+
34+
if __name__ == '__main__':
35+
main(sys.argv[1])
36+

0 commit comments

Comments
 (0)