main.c 9.46 KB
Newer Older
Dave Hylands's avatar
Dave Hylands committed
1
2
3
4
5
6
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#include "mpconfig.h"
7
#include "misc.h"
8
#include "qstr.h"
Dave Hylands's avatar
Dave Hylands committed
9
#include "nlr.h"
Dave Hylands's avatar
Dave Hylands committed
10
#include "lexer.h"
11
#include "lexermemzip.h"
Dave Hylands's avatar
Dave Hylands committed
12
13
14
#include "parse.h"
#include "obj.h"
#include "runtime.h"
Dave Hylands's avatar
Dave Hylands committed
15
16
17
18
19
20
#include "gc.h"
#include "gccollect.h"
#include "pyexec.h"
#include "readline.h"

#include "Arduino.h"
21
#include MICROPY_HAL_H
Dave Hylands's avatar
Dave Hylands committed
22

23
#include "servo.h"
Dave Hylands's avatar
Dave Hylands committed
24
25
#include "usb.h"
#include "led.h"
26
#include "uart.h"
Dave Hylands's avatar
Dave Hylands committed
27
//#include "pin.h"
28
#include "pybstdio.h"
Dave Hylands's avatar
Dave Hylands committed
29
30


Dave Hylands's avatar
Dave Hylands committed
31
extern uint32_t _heap_start;
Dave Hylands's avatar
Dave Hylands committed
32

33
34
35
36
37
38
void flash_error(int n) {
    for (int i = 0; i < n; i++) {
        led_state(PYB_LED_BUILTIN, 1);
        delay(250);
        led_state(PYB_LED_BUILTIN, 0);
        delay(250);
Dave Hylands's avatar
Dave Hylands committed
39
40
41
    }
}

42
void NORETURN __fatal_error(const char *msg) {
Dave Hylands's avatar
Dave Hylands committed
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
    for (volatile uint delay = 0; delay < 10000000; delay++) {
    }
    led_state(1, 1);
    led_state(2, 1);
    led_state(3, 1);
    led_state(4, 1);
    stdout_tx_strn("\nFATAL ERROR:\n", 14);
    stdout_tx_strn(msg, strlen(msg));
    for (uint i = 0;;) {
        led_toggle(((i++) & 3) + 1);
        for (volatile uint delay = 0; delay < 10000000; delay++) {
        }
        if (i >= 16) {
            // to conserve power
            __WFI();
        }
    }
}

void nlr_jump_fail(void *val) {
    printf("FATAL: uncaught exception %p\n", val);
    __fatal_error("");
}

void __assert_func(const char *file, int line, const char *func, const char *expr) {

    printf("Assertion failed: %s, file %s, line %d\n", expr, file, line);
    __fatal_error("");
}
Dave Hylands's avatar
Dave Hylands committed
72

73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
mp_obj_t pyb_analog_read(mp_obj_t pin_obj) {
    uint pin = mp_obj_get_int(pin_obj);
    int val = analogRead(pin);
    return MP_OBJ_NEW_SMALL_INT(val);
}

mp_obj_t pyb_analog_write(mp_obj_t pin_obj, mp_obj_t val_obj) {
    uint pin = mp_obj_get_int(pin_obj);
    int val = mp_obj_get_int(val_obj);
    analogWrite(pin, val);
    return mp_const_none;
}

mp_obj_t pyb_analog_write_resolution(mp_obj_t res_obj) {
    int res = mp_obj_get_int(res_obj);
    analogWriteResolution(res);
    return mp_const_none;
}

mp_obj_t pyb_analog_write_frequency(mp_obj_t pin_obj, mp_obj_t freq_obj) {
    uint pin = mp_obj_get_int(pin_obj);
    int freq = mp_obj_get_int(freq_obj);
    analogWriteFrequency(pin, freq);
    return mp_const_none;
}

Dave Hylands's avatar
Dave Hylands committed
99
#if 0
Dave Hylands's avatar
Dave Hylands committed
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
// get lots of info about the board
static mp_obj_t pyb_info(void) {
    // get and print unique id; 96 bits
    {
        byte *id = (byte*)0x40048058;
        printf("ID=%02x%02x%02x%02x:%02x%02x%02x%02x:%02x%02x%02x%02x\n", id[0], id[1], id[2], id[3], id[4], id[5], id[6], id[7], id[8], id[9], id[10], id[11]);
    }

    // get and print clock speeds
    printf("CPU=%u\nBUS=%u\nMEM=%u\n", F_CPU, F_BUS, F_MEM);

    // to print info about memory
    {
        printf("_sdata=%p\n", &_sdata);
        printf("_edata=%p\n", &_edata);
        printf("_sbss=%p\n", &_sbss);
        printf("_ebss=%p\n", &_ebss);
        printf("_estack=%p\n", &_estack);
        printf("_etext=%p\n", &_etext);
        printf("_heap_start=%p\n", &_heap_start);
    }

    // GC info
    {
        gc_info_t info;
        gc_info(&info);
        printf("GC:\n");
Dave Hylands's avatar
Dave Hylands committed
127
128
129
        printf("  %u total\n", info.total);
        printf("  %u used %u free\n", info.used, info.free);
        printf("  1=%u 2=%u m=%u\n", info.num_1block, info.num_2block, info.max_block);
Dave Hylands's avatar
Dave Hylands committed
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
    }

#if 0
    // free space on flash
    {
        DWORD nclst;
        FATFS *fatfs;
        f_getfree("0:", &nclst, &fatfs);
        printf("LFS free: %u bytes\n", (uint)(nclst * fatfs->csize * 512));
    }
#endif

    return mp_const_none;
}

Dave Hylands's avatar
Dave Hylands committed
145
146
#endif

Dave Hylands's avatar
Dave Hylands committed
147
148
149
150
#define RAM_START (0x1FFF8000) // fixed for chip
#define HEAP_END  (0x20006000) // tunable
#define RAM_END   (0x20008000) // fixed for chip

Dave Hylands's avatar
Dave Hylands committed
151
#if 0
Dave Hylands's avatar
Dave Hylands committed
152

153
void gc_helper_get_regs_and_clean_stack(mp_uint_t *regs, mp_uint_t heap_end);
Dave Hylands's avatar
Dave Hylands committed
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175

mp_obj_t pyb_gc(void) {
    gc_collect();
    return mp_const_none;
}

mp_obj_t pyb_gpio(int n_args, mp_obj_t *args) {
    //assert(1 <= n_args && n_args <= 2);

    uint pin = mp_obj_get_int(args[0]);
    if (pin > CORE_NUM_DIGITAL) {
        goto pin_error;
    }

    if (n_args == 1) {
        // get pin
        pinMode(pin, INPUT);
        return MP_OBJ_NEW_SMALL_INT(digitalRead(pin));
    }
    
    // set pin
    pinMode(pin, OUTPUT);
Damien George's avatar
Damien George committed
176
    digitalWrite(pin, mp_obj_is_true(args[1]));
Dave Hylands's avatar
Dave Hylands committed
177
178
179
    return mp_const_none;

pin_error:
Dave Hylands's avatar
Dave Hylands committed
180
    nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "pin %d does not exist", pin));
Dave Hylands's avatar
Dave Hylands committed
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
}

MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_gpio_obj, 1, 2, pyb_gpio);

#if 0
mp_obj_t pyb_hid_send_report(mp_obj_t arg) {
    mp_obj_t *items = mp_obj_get_array_fixed_n(arg, 4);
    uint8_t data[4];
    data[0] = mp_obj_get_int(items[0]);
    data[1] = mp_obj_get_int(items[1]);
    data[2] = mp_obj_get_int(items[2]);
    data[3] = mp_obj_get_int(items[3]);
    usb_hid_send_report(data);
    return mp_const_none;
}
#endif

Dave Hylands's avatar
Dave Hylands committed
198
199
200
201
202
#endif // 0

STATIC mp_obj_t pyb_config_source_dir = MP_OBJ_NULL;
STATIC mp_obj_t pyb_config_main = MP_OBJ_NULL;
STATIC mp_obj_t pyb_config_usb_mode = MP_OBJ_NULL;
203
204

mp_obj_t pyb_source_dir(mp_obj_t source_dir) {
205
206
207
    if (MP_OBJ_IS_STR(source_dir)) {
        pyb_config_source_dir = source_dir;
    }
208
209
210
    return mp_const_none;
}

Dave Hylands's avatar
Dave Hylands committed
211
212
MP_DEFINE_CONST_FUN_OBJ_1(pyb_source_dir_obj, pyb_source_dir);

213
mp_obj_t pyb_main(mp_obj_t main) {
214
215
216
    if (MP_OBJ_IS_STR(main)) {
        pyb_config_main = main;
    }
217
218
219
    return mp_const_none;
}

Dave Hylands's avatar
Dave Hylands committed
220
221
222
223
224
225
226
227
228
229
230
231
232
MP_DEFINE_CONST_FUN_OBJ_1(pyb_main_obj, pyb_main);

STATIC mp_obj_t pyb_usb_mode(mp_obj_t usb_mode) {
    if (MP_OBJ_IS_STR(usb_mode)) {
        pyb_config_usb_mode = usb_mode;
    }
    return mp_const_none;
}

MP_DEFINE_CONST_FUN_OBJ_1(pyb_usb_mode_obj, pyb_usb_mode);

#if 0

Dave Hylands's avatar
Dave Hylands committed
233
234
235
236
237
238
mp_obj_t pyb_delay(mp_obj_t count) {
    delay(mp_obj_get_int(count));
    return mp_const_none;
}

mp_obj_t pyb_led(mp_obj_t state) {
Damien George's avatar
Damien George committed
239
    led_state(PYB_LED_BUILTIN, mp_obj_is_true(state));
Dave Hylands's avatar
Dave Hylands committed
240
241
242
    return state;
}

Dave Hylands's avatar
Dave Hylands committed
243
#endif  // 0
244

Dave Hylands's avatar
Dave Hylands committed
245
#if 0
Dave Hylands's avatar
Dave Hylands committed
246
247
248
249
250
251
252
253
254
char *strdup(const char *str) {
    uint32_t len = strlen(str);
    char *s2 = m_new(char, len + 1);
    memcpy(s2, str, len);
    s2[len] = 0;
    return s2;
}
#endif

255
int main(void) {
256
257
    pinMode(LED_BUILTIN, OUTPUT);
    delay(1000);
Dave Hylands's avatar
Dave Hylands committed
258
259
260
261
262
263
264

    led_init();

//    int first_soft_reset = true;

soft_reset:

Dave Hylands's avatar
Dave Hylands committed
265
266
    led_state(PYB_LED_BUILTIN, 1);

Dave Hylands's avatar
Dave Hylands committed
267
268
269
270
    // GC init
    gc_init(&_heap_start, (void*)HEAP_END);

    qstr_init();
Damien George's avatar
Damien George committed
271
    mp_init();
Dave Hylands's avatar
Dave Hylands committed
272

Dave Hylands's avatar
Dave Hylands committed
273
274
275
276
277
    readline_init();

    //pin_init();

#if 0
Dave Hylands's avatar
Dave Hylands committed
278
279
    // add some functions to the python namespace
    {
Damien George's avatar
Damien George committed
280
        mp_store_name(MP_QSTR_help, mp_make_function_n(0, pyb_help));
281
        mp_obj_t m = mp_obj_new_module(MP_QSTR_pyb);
Damien George's avatar
Damien George committed
282
283
284
285
286
287
        mp_store_attr(m, MP_QSTR_info, mp_make_function_n(0, pyb_info));
        mp_store_attr(m, MP_QSTR_source_dir, mp_make_function_n(1, pyb_source_dir));
        mp_store_attr(m, MP_QSTR_main, mp_make_function_n(1, pyb_main));
        mp_store_attr(m, MP_QSTR_gc, mp_make_function_n(0, pyb_gc));
        mp_store_attr(m, MP_QSTR_delay, mp_make_function_n(1, pyb_delay));
        mp_store_attr(m, MP_QSTR_led, mp_make_function_n(1, pyb_led));
Dave Hylands's avatar
Dave Hylands committed
288
        mp_store_attr(m, MP_QSTR_LED, (mp_obj_t)&pyb_led_type);
Damien George's avatar
Damien George committed
289
290
291
292
293
294
295
296
        mp_store_attr(m, MP_QSTR_analogRead, mp_make_function_n(1, pyb_analog_read));
        mp_store_attr(m, MP_QSTR_analogWrite, mp_make_function_n(2, pyb_analog_write));
        mp_store_attr(m, MP_QSTR_analogWriteResolution, mp_make_function_n(1, pyb_analog_write_resolution));
        mp_store_attr(m, MP_QSTR_analogWriteFrequency, mp_make_function_n(2, pyb_analog_write_frequency));

        mp_store_attr(m, MP_QSTR_gpio, (mp_obj_t)&pyb_gpio_obj);
        mp_store_attr(m, MP_QSTR_Servo, mp_make_function_n(0, pyb_Servo));
        mp_store_name(MP_QSTR_pyb, m);
Dave Hylands's avatar
Dave Hylands committed
297
    }
Dave Hylands's avatar
Dave Hylands committed
298
#endif
Dave Hylands's avatar
Dave Hylands committed
299

Dave Hylands's avatar
Dave Hylands committed
300
    if (!pyexec_file("/boot.py")) {
301
302
303
        flash_error(4);
    }

Dave Hylands's avatar
Dave Hylands committed
304
305
306
    // Turn bootup LED off
    led_state(PYB_LED_BUILTIN, 0);

307
308
309
310
    // run main script
    {
        vstr_t *vstr = vstr_new();
        vstr_add_str(vstr, "/");
311
        if (pyb_config_main == MP_OBJ_NULL) {
312
313
            vstr_add_str(vstr, "main.py");
        } else {
314
            vstr_add_str(vstr, mp_obj_str_get_str(pyb_config_main));
315
        }
Dave Hylands's avatar
Dave Hylands committed
316
        if (!pyexec_file(vstr_str(vstr))) {
317
318
319
320
321
            flash_error(3);
        }
        vstr_free(vstr);
    }

Dave Hylands's avatar
Dave Hylands committed
322
323
324
325
326
327
328
329
330
331
332
333
334
    // enter REPL
    // REPL mode can change, or it can request a soft reset
    for (;;) {
        if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) {
            if (pyexec_raw_repl() != 0) {
                break;
            }
        } else {
            if (pyexec_friendly_repl() != 0) {
                break;
            }
        }
    }
Dave Hylands's avatar
Dave Hylands committed
335
336
337
338
339
340
341
342
343
344
345
346
347

    printf("PYB: soft reboot\n");

//    first_soft_reset = false;
    goto soft_reset;
}

// stub out __libc_init_array. It's called by mk20dx128.c and is used to call
// global C++ constructors. Since this is a C-only projects, we don't need to
// call constructors.
void __libc_init_array(void) {
}

Dave Hylands's avatar
Dave Hylands committed
348
349
350
// ultoa is used by usb_init_serialnumber. Normally ultoa would be provided
// by nonstd.c from the teensy core, but it conflicts with some of the
// MicroPython functions in string0.c, so we provide ultoa here.
Dave Hylands's avatar
Dave Hylands committed
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
char * ultoa(unsigned long val, char *buf, int radix) 	
{
	unsigned digit;
	int i=0, j;
	char t;

	while (1) {
		digit = val % radix;
		buf[i] = ((digit < 10) ? '0' + digit : 'A' + digit - 10);
		val /= radix;
		if (val == 0) break;
		i++;
	}
	buf[i + 1] = 0;
	for (j=0; j < i; j++, i--) {
		t = buf[j];
		buf[j] = buf[i];
		buf[i] = t;
	}
	return buf;
}
Dave Hylands's avatar
Dave Hylands committed
372
373
374
375
376
377
378
379
380

STATIC NORETURN mp_obj_t mp_sys_exit(uint n_args, const mp_obj_t *args) {
    int rc = 0;
    if (n_args > 0) {
        rc = mp_obj_get_int(args[0]);
    }
    nlr_raise(mp_obj_new_exception_arg1(&mp_type_SystemExit, mp_obj_new_int(rc)));
}
MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_sys_exit_obj, 0, 1, mp_sys_exit);