Skip to content

Commit c849da3

Browse files
authored
NimBLE bluetooth support (#54)
* add nimble bluetooth - change micropython module to url = https://github.com/hfmanson/micropython.git - ... so mpy-cross compiles on modern compilers - reserve 128 kB PSIRAM for internal use * working pairing and bondig - remove generated main/platform_gen.c on clean - add reconfigure option - add bt_secrets.c - #define MICROPY_PY_BLUETOOTH_ENABLE_PAIRING_BONDING (1) - new micropython commit * working BLE bonding * no network audio to save DRAM * NimBLE bluetooth support - No bonding allows for BLE peripherals, like keyboards and mice - Audio works with bluetooth, not with wifi therefore network support removed from `python_modules/common/audio.py` - Wifi still works, no audio support
1 parent 1893fba commit c849da3

10 files changed

Lines changed: 494 additions & 52 deletions

File tree

Makefile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ prepare-sha2017: prepare
3030
clean:
3131
rm -rf "$(BUILDDIR)"
3232
rm components/micropython/mpconfigoverrides.h
33+
rm main/platform_gen.c
3334
source "$(IDF_PATH)/export.sh" && idf.py clean
3435

3536
build:
@@ -41,6 +42,9 @@ flash: build
4142
erase:
4243
source "$(IDF_PATH)/export.sh" && idf.py erase-flash -p $(PORT)
4344

45+
reconfigure:
46+
source "$(IDF_PATH)/export.sh" && idf.py reconfigure
47+
4448
monitor:
4549
source "$(IDF_PATH)/export.sh" && idf.py monitor -p $(PORT)
4650

README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
# BadgePython
22
Experimental try at making an ESP-IDF v4.0 compatible Badge oriented Micropython firmware
33

4+
## New: NimBLE bluetooth support
5+
- No bonding
6+
allows for BLE peripherals, like keyboards and mice
7+
- Audio works with bluetooth, not with wifi
8+
therefore network support removed from `python_modules/common/audio.py`
9+
- Wifi still works, no audio support
10+
411
## Supported environments
512
* Linux
613
* Mac OS

components/micropython/CMakeLists.txt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -207,8 +207,10 @@ add_custom_command(
207207
${COMPONENT_DIR}/mpconfigoverrides.h
208208
COMMAND echo extmods: ${EXTMODS} &&
209209
python3 mpconfigover_generator.py -b ./ \"${EXTMODS_NAMES}\" &&
210-
cp mpconfigport.h micropython/ports/esp32/ &&
211-
cp help.c micropython/ports/esp32/
210+
cp patches/ports/esp32/mpconfigport.h micropython/ports/esp32 &&
211+
cp patches/ports/esp32/help.c micropython/ports/esp32 &&
212+
cp patches/mpy-cross/main.c micropython/mpy-cross &&
213+
cp patches/py/stackctrl.c micropython/py
212214
WORKING_DIRECTORY ${COMPONENT_DIR}
213215
DEPENDS ${EXTMODS}
214216
)

components/micropython/main.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ void mp_task(void *pvParameter) {
114114
case ESP_SPIRAM_SIZE_32MBITS:
115115
case ESP_SPIRAM_SIZE_64MBITS:
116116
mp_task_heap_size = heap_caps_get_largest_free_block(MALLOC_CAP_SPIRAM);
117+
mp_task_heap_size -= 128 * 1024;
117118
mp_task_heap = heap_caps_malloc(mp_task_heap_size, MALLOC_CAP_SPIRAM);
118119
break;
119120
default:
Lines changed: 342 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,342 @@
1+
/*
2+
* This file is part of the MicroPython project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2013-2016 Damien P. George
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+
#include <stdio.h>
28+
#include <string.h>
29+
#include <stdlib.h>
30+
#include <unistd.h>
31+
32+
#include "py/compile.h"
33+
#include "py/persistentcode.h"
34+
#include "py/runtime.h"
35+
#include "py/gc.h"
36+
#include "py/stackctrl.h"
37+
#include "genhdr/mpversion.h"
38+
#ifdef _WIN32
39+
#include "ports/windows/fmode.h"
40+
#endif
41+
42+
// Command line options, with their defaults
43+
STATIC uint emit_opt = MP_EMIT_OPT_NONE;
44+
mp_uint_t mp_verbose_flag = 0;
45+
46+
// Heap size of GC heap (if enabled)
47+
// Make it larger on a 64 bit machine, because pointers are larger.
48+
long heap_size = 1024 * 1024 * (sizeof(mp_uint_t) / 4);
49+
50+
STATIC void stderr_print_strn(void *env, const char *str, size_t len) {
51+
(void)env;
52+
ssize_t dummy = write(STDERR_FILENO, str, len);
53+
(void)dummy;
54+
}
55+
56+
STATIC const mp_print_t mp_stderr_print = {NULL, stderr_print_strn};
57+
58+
STATIC int compile_and_save(const char *file, const char *output_file, const char *source_file) {
59+
nlr_buf_t nlr;
60+
if (nlr_push(&nlr) == 0) {
61+
mp_lexer_t *lex = mp_lexer_new_from_file(file);
62+
63+
qstr source_name;
64+
if (source_file == NULL) {
65+
source_name = lex->source_name;
66+
} else {
67+
source_name = qstr_from_str(source_file);
68+
}
69+
70+
#if MICROPY_PY___FILE__
71+
mp_store_global(MP_QSTR___file__, MP_OBJ_NEW_QSTR(source_name));
72+
#endif
73+
74+
mp_parse_tree_t parse_tree = mp_parse(lex, MP_PARSE_FILE_INPUT);
75+
mp_raw_code_t *rc = mp_compile_to_raw_code(&parse_tree, source_name, false);
76+
77+
vstr_t vstr;
78+
vstr_init(&vstr, 16);
79+
if (output_file == NULL) {
80+
vstr_add_str(&vstr, file);
81+
vstr_cut_tail_bytes(&vstr, 2);
82+
vstr_add_str(&vstr, "mpy");
83+
} else {
84+
vstr_add_str(&vstr, output_file);
85+
}
86+
mp_raw_code_save_file(rc, vstr_null_terminated_str(&vstr));
87+
vstr_clear(&vstr);
88+
89+
nlr_pop();
90+
return 0;
91+
} else {
92+
// uncaught exception
93+
mp_obj_print_exception(&mp_stderr_print, (mp_obj_t)nlr.ret_val);
94+
return 1;
95+
}
96+
}
97+
98+
STATIC int usage(char **argv) {
99+
printf(
100+
"usage: %s [<opts>] [-X <implopt>] <input filename>\n"
101+
"Options:\n"
102+
"--version : show version information\n"
103+
"-o : output file for compiled bytecode (defaults to input with .mpy extension)\n"
104+
"-s : source filename to embed in the compiled bytecode (defaults to input file)\n"
105+
"-v : verbose (trace various operations); can be multiple\n"
106+
"-O[N] : apply bytecode optimizations of level N\n"
107+
"\n"
108+
"Target specific options:\n"
109+
"-msmall-int-bits=number : set the maximum bits used to encode a small-int\n"
110+
"-mno-unicode : don't support unicode in compiled strings\n"
111+
"-march=<arch> : set architecture for native emitter; x86, x64, armv6, armv7m, armv7em, armv7emsp, armv7emdp, xtensa, xtensawin\n"
112+
"\n"
113+
"Implementation specific options:\n", argv[0]
114+
);
115+
int impl_opts_cnt = 0;
116+
printf(
117+
#if MICROPY_EMIT_NATIVE
118+
" emit={bytecode,native,viper} -- set the default code emitter\n"
119+
#else
120+
" emit=bytecode -- set the default code emitter\n"
121+
#endif
122+
);
123+
impl_opts_cnt++;
124+
printf(
125+
" heapsize=<n> -- set the heap size for the GC (default %ld)\n"
126+
, heap_size);
127+
impl_opts_cnt++;
128+
129+
if (impl_opts_cnt == 0) {
130+
printf(" (none)\n");
131+
}
132+
133+
return 1;
134+
}
135+
136+
// Process options which set interpreter init options
137+
STATIC void pre_process_options(int argc, char **argv) {
138+
for (int a = 1; a < argc; a++) {
139+
if (argv[a][0] == '-') {
140+
if (strcmp(argv[a], "-X") == 0) {
141+
if (a + 1 >= argc) {
142+
exit(usage(argv));
143+
}
144+
if (strcmp(argv[a + 1], "emit=bytecode") == 0) {
145+
emit_opt = MP_EMIT_OPT_BYTECODE;
146+
#if MICROPY_EMIT_NATIVE
147+
} else if (strcmp(argv[a + 1], "emit=native") == 0) {
148+
emit_opt = MP_EMIT_OPT_NATIVE_PYTHON;
149+
} else if (strcmp(argv[a + 1], "emit=viper") == 0) {
150+
emit_opt = MP_EMIT_OPT_VIPER;
151+
#endif
152+
} else if (strncmp(argv[a + 1], "heapsize=", sizeof("heapsize=") - 1) == 0) {
153+
char *end;
154+
heap_size = strtol(argv[a + 1] + sizeof("heapsize=") - 1, &end, 0);
155+
// Don't bring unneeded libc dependencies like tolower()
156+
// If there's 'w' immediately after number, adjust it for
157+
// target word size. Note that it should be *before* size
158+
// suffix like K or M, to avoid confusion with kilowords,
159+
// etc. the size is still in bytes, just can be adjusted
160+
// for word size (taking 32bit as baseline).
161+
bool word_adjust = false;
162+
if ((*end | 0x20) == 'w') {
163+
word_adjust = true;
164+
end++;
165+
}
166+
if ((*end | 0x20) == 'k') {
167+
heap_size *= 1024;
168+
} else if ((*end | 0x20) == 'm') {
169+
heap_size *= 1024 * 1024;
170+
}
171+
if (word_adjust) {
172+
heap_size = heap_size * MP_BYTES_PER_OBJ_WORD / 4;
173+
}
174+
} else {
175+
exit(usage(argv));
176+
}
177+
a++;
178+
}
179+
}
180+
}
181+
}
182+
183+
MP_NOINLINE int main_(int argc, char **argv) {
184+
mp_stack_set_limit(40000 * (sizeof(void *) / 4));
185+
186+
pre_process_options(argc, argv);
187+
188+
char *heap = malloc(heap_size);
189+
gc_init(heap, heap + heap_size);
190+
191+
mp_init();
192+
#ifdef _WIN32
193+
set_fmode_binary();
194+
#endif
195+
196+
#if MICROPY_EMIT_NATIVE
197+
// Set default emitter options
198+
MP_STATE_VM(default_emit_opt) = emit_opt;
199+
#else
200+
(void)emit_opt;
201+
#endif
202+
203+
// set default compiler configuration
204+
mp_dynamic_compiler.small_int_bits = 31;
205+
mp_dynamic_compiler.py_builtins_str_unicode = 1;
206+
#if defined(__i386__)
207+
mp_dynamic_compiler.native_arch = MP_NATIVE_ARCH_X86;
208+
mp_dynamic_compiler.nlr_buf_num_regs = MICROPY_NLR_NUM_REGS_X86;
209+
#elif defined(__x86_64__)
210+
mp_dynamic_compiler.native_arch = MP_NATIVE_ARCH_X64;
211+
mp_dynamic_compiler.nlr_buf_num_regs = MAX(MICROPY_NLR_NUM_REGS_X64, MICROPY_NLR_NUM_REGS_X64_WIN);
212+
#elif defined(__arm__) && !defined(__thumb2__)
213+
mp_dynamic_compiler.native_arch = MP_NATIVE_ARCH_ARMV6;
214+
mp_dynamic_compiler.nlr_buf_num_regs = MICROPY_NLR_NUM_REGS_ARM_THUMB_FP;
215+
#else
216+
mp_dynamic_compiler.native_arch = MP_NATIVE_ARCH_NONE;
217+
mp_dynamic_compiler.nlr_buf_num_regs = 0;
218+
#endif
219+
220+
const char *input_file = NULL;
221+
const char *output_file = NULL;
222+
const char *source_file = NULL;
223+
224+
// parse main options
225+
for (int a = 1; a < argc; a++) {
226+
if (argv[a][0] == '-') {
227+
if (strcmp(argv[a], "-X") == 0) {
228+
a += 1;
229+
} else if (strcmp(argv[a], "--version") == 0) {
230+
printf("MicroPython " MICROPY_GIT_TAG " on " MICROPY_BUILD_DATE
231+
"; mpy-cross emitting mpy v" MP_STRINGIFY(MPY_VERSION) "\n");
232+
return 0;
233+
} else if (strcmp(argv[a], "-v") == 0) {
234+
mp_verbose_flag++;
235+
} else if (strncmp(argv[a], "-O", 2) == 0) {
236+
if (unichar_isdigit(argv[a][2])) {
237+
MP_STATE_VM(mp_optimise_value) = argv[a][2] & 0xf;
238+
} else {
239+
MP_STATE_VM(mp_optimise_value) = 0;
240+
for (char *p = argv[a] + 1; *p && *p == 'O'; p++, MP_STATE_VM(mp_optimise_value)++) {;
241+
}
242+
}
243+
} else if (strcmp(argv[a], "-o") == 0) {
244+
if (a + 1 >= argc) {
245+
exit(usage(argv));
246+
}
247+
a += 1;
248+
output_file = argv[a];
249+
} else if (strcmp(argv[a], "-s") == 0) {
250+
if (a + 1 >= argc) {
251+
exit(usage(argv));
252+
}
253+
a += 1;
254+
source_file = argv[a];
255+
} else if (strncmp(argv[a], "-msmall-int-bits=", sizeof("-msmall-int-bits=") - 1) == 0) {
256+
char *end;
257+
mp_dynamic_compiler.small_int_bits =
258+
strtol(argv[a] + sizeof("-msmall-int-bits=") - 1, &end, 0);
259+
if (*end) {
260+
return usage(argv);
261+
}
262+
// TODO check that small_int_bits is within range of host's capabilities
263+
} else if (strcmp(argv[a], "-mno-unicode") == 0) {
264+
mp_dynamic_compiler.py_builtins_str_unicode = 0;
265+
} else if (strcmp(argv[a], "-municode") == 0) {
266+
mp_dynamic_compiler.py_builtins_str_unicode = 1;
267+
} else if (strncmp(argv[a], "-march=", sizeof("-march=") - 1) == 0) {
268+
const char *arch = argv[a] + sizeof("-march=") - 1;
269+
if (strcmp(arch, "x86") == 0) {
270+
mp_dynamic_compiler.native_arch = MP_NATIVE_ARCH_X86;
271+
mp_dynamic_compiler.nlr_buf_num_regs = MICROPY_NLR_NUM_REGS_X86;
272+
} else if (strcmp(arch, "x64") == 0) {
273+
mp_dynamic_compiler.native_arch = MP_NATIVE_ARCH_X64;
274+
mp_dynamic_compiler.nlr_buf_num_regs = MAX(MICROPY_NLR_NUM_REGS_X64, MICROPY_NLR_NUM_REGS_X64_WIN);
275+
} else if (strcmp(arch, "armv6") == 0) {
276+
mp_dynamic_compiler.native_arch = MP_NATIVE_ARCH_ARMV6;
277+
mp_dynamic_compiler.nlr_buf_num_regs = MICROPY_NLR_NUM_REGS_ARM_THUMB_FP;
278+
} else if (strcmp(arch, "armv7m") == 0) {
279+
mp_dynamic_compiler.native_arch = MP_NATIVE_ARCH_ARMV7M;
280+
mp_dynamic_compiler.nlr_buf_num_regs = MICROPY_NLR_NUM_REGS_ARM_THUMB_FP;
281+
} else if (strcmp(arch, "armv7em") == 0) {
282+
mp_dynamic_compiler.native_arch = MP_NATIVE_ARCH_ARMV7EM;
283+
mp_dynamic_compiler.nlr_buf_num_regs = MICROPY_NLR_NUM_REGS_ARM_THUMB_FP;
284+
} else if (strcmp(arch, "armv7emsp") == 0) {
285+
mp_dynamic_compiler.native_arch = MP_NATIVE_ARCH_ARMV7EMSP;
286+
mp_dynamic_compiler.nlr_buf_num_regs = MICROPY_NLR_NUM_REGS_ARM_THUMB_FP;
287+
} else if (strcmp(arch, "armv7emdp") == 0) {
288+
mp_dynamic_compiler.native_arch = MP_NATIVE_ARCH_ARMV7EMDP;
289+
mp_dynamic_compiler.nlr_buf_num_regs = MICROPY_NLR_NUM_REGS_ARM_THUMB_FP;
290+
} else if (strcmp(arch, "xtensa") == 0) {
291+
mp_dynamic_compiler.native_arch = MP_NATIVE_ARCH_XTENSA;
292+
mp_dynamic_compiler.nlr_buf_num_regs = MICROPY_NLR_NUM_REGS_XTENSA;
293+
} else if (strcmp(arch, "xtensawin") == 0) {
294+
mp_dynamic_compiler.native_arch = MP_NATIVE_ARCH_XTENSAWIN;
295+
mp_dynamic_compiler.nlr_buf_num_regs = MICROPY_NLR_NUM_REGS_XTENSAWIN;
296+
} else {
297+
return usage(argv);
298+
}
299+
} else {
300+
return usage(argv);
301+
}
302+
} else {
303+
if (input_file != NULL) {
304+
mp_printf(&mp_stderr_print, "multiple input files\n");
305+
exit(1);
306+
}
307+
input_file = argv[a];
308+
}
309+
}
310+
311+
if (input_file == NULL) {
312+
mp_printf(&mp_stderr_print, "no input file\n");
313+
exit(1);
314+
}
315+
316+
int ret = compile_and_save(input_file, output_file, source_file);
317+
318+
#if MICROPY_PY_MICROPYTHON_MEM_INFO
319+
if (mp_verbose_flag) {
320+
mp_micropython_mem_info(0, NULL);
321+
}
322+
#endif
323+
324+
mp_deinit();
325+
326+
return ret & 0xff;
327+
}
328+
329+
int main(int argc, char **argv) {
330+
mp_stack_ctrl_init();
331+
return main_(argc, argv);
332+
}
333+
334+
mp_import_stat_t mp_import_stat(const char *path) {
335+
(void)path;
336+
return MP_IMPORT_STAT_NO_EXIST;
337+
}
338+
339+
void nlr_jump_fail(void *val) {
340+
fprintf(stderr, "FATAL: uncaught NLR %p\n", val);
341+
exit(1);
342+
}
File renamed without changes.

0 commit comments

Comments
 (0)