1
1
#include <stdint.h>
2
2
#include <stdio.h>
3
+ #include <stdlib.h>
3
4
#include <string.h>
5
+ #include <sys/stat.h>
4
6
5
7
#include "py/nlr.h"
6
8
#include "py/compile.h"
9
11
#include "py/gc.h"
10
12
#include "lib/utils/pyexec.h"
11
13
14
+ #include "emscripten.h"
15
+
16
+ // TODO: make this work properly with emscripten
17
+ #ifdef _WIN32
18
+ #define PATHLIST_SEP_CHAR ';'
19
+ #else
20
+ #define PATHLIST_SEP_CHAR ':'
21
+ #endif
22
+
12
23
void do_str (const char * src , mp_parse_input_kind_t input_kind ) {
13
24
mp_lexer_t * lex = mp_lexer_new_from_str_len (MP_QSTR__lt_stdin_gt_ , src , strlen (src ), 0 );
14
25
if (lex == NULL ) {
@@ -38,6 +49,48 @@ static char heap[2048];
38
49
void mp_js_init () {
39
50
gc_init (heap , heap + sizeof (heap ));
40
51
mp_init ();
52
+
53
+ char * home = getenv ("HOME" );
54
+ char * path = getenv ("MICROPYPATH" );
55
+ if (path == NULL ) {
56
+ #ifdef MICROPY_PY_SYS_PATH_DEFAULT
57
+ path = MICROPY_PY_SYS_PATH_DEFAULT ;
58
+ #else
59
+ path = "~/.micropython/lib:/usr/lib/micropython" ;
60
+ #endif
61
+ }
62
+ mp_uint_t path_num = 1 ; // [0] is for current dir (or base dir of the script)
63
+ for (char * p = path ; p != NULL ; p = strchr (p , PATHLIST_SEP_CHAR )) {
64
+ path_num ++ ;
65
+ if (p != NULL ) {
66
+ p ++ ;
67
+ }
68
+ }
69
+ mp_obj_list_init (MP_OBJ_TO_PTR (mp_sys_path ), path_num );
70
+ mp_obj_t * path_items ;
71
+ mp_obj_list_get (mp_sys_path , & path_num , & path_items );
72
+ path_items [0 ] = MP_OBJ_NEW_QSTR (MP_QSTR_ );
73
+ {
74
+ char * p = path ;
75
+ for (mp_uint_t i = 1 ; i < path_num ; i ++ ) {
76
+ char * p1 = strchr (p , PATHLIST_SEP_CHAR );
77
+ if (p1 == NULL ) {
78
+ p1 = p + strlen (p );
79
+ }
80
+ if (p [0 ] == '~' && p [1 ] == '/' && home != NULL ) {
81
+ // Expand standalone ~ to $HOME
82
+ int home_l = strlen (home );
83
+ vstr_t vstr ;
84
+ vstr_init (& vstr , home_l + (p1 - p - 1 ) + 1 );
85
+ vstr_add_strn (& vstr , home , home_l );
86
+ vstr_add_strn (& vstr , p + 1 , p1 - p - 1 );
87
+ path_items [i ] = mp_obj_new_str_from_vstr (& mp_type_str , & vstr );
88
+ } else {
89
+ path_items [i ] = MP_OBJ_NEW_QSTR (qstr_from_strn (p , p1 - p ));
90
+ }
91
+ p = p1 + 1 ;
92
+ }
93
+ }
41
94
}
42
95
43
96
void mp_js_run (const char * code ) {
@@ -55,11 +108,53 @@ void gc_collect(void) {
55
108
}
56
109
57
110
mp_lexer_t * mp_lexer_new_from_file (const char * filename ) {
58
- return NULL ;
111
+ // to do this by calling out to node.js code, we'll have to do something like
112
+ // fs.readFileSync(filename, 'utf-8')
113
+ // and then put that back into the emscripten heap, so that it's a pointer we can access from C
114
+ // and then use that to produce a micropython lexer as above.
115
+
116
+ // eurgh this is disgusting, let's just implement this in JS
117
+
118
+ const char * code_buf = (const char * )EM_ASM_INT ({
119
+ try {
120
+ var file = UTF8ToString ($0 );
121
+ var fs = require ('fs' );
122
+
123
+ var code = fs .readFileSync (file , 'utf-8' );
124
+ ret = Runtime .stackAlloc ((code .length << 2 ) + 1 );
125
+ writeStringToMemory (code , ret );
126
+ return ret ;
127
+ } catch (e ) {
128
+ return 0 ;
129
+ }
130
+ }, filename );
131
+
132
+ if (code_buf == 0 ) {
133
+ return NULL ;
134
+ } else {
135
+ mp_lexer_t * lex = mp_lexer_new_from_str_len (qstr_from_str (filename ), code_buf , strlen (code_buf ), 0 );
136
+ return lex ;
137
+ }
59
138
}
60
139
61
140
mp_import_stat_t mp_import_stat (const char * path ) {
62
- return MP_IMPORT_STAT_NO_EXIST ;
141
+ int s = EM_ASM_INT ({
142
+ try {
143
+ var fs = require ('fs' );
144
+ var stat = fs .statSync (UTF8ToString ($0 ));
145
+ return stat .isDirectory () ? 1 : 0 ;
146
+ } catch (e ) {
147
+ return -1 ;
148
+ }
149
+ }, path );
150
+
151
+ if (s == -1 ) {
152
+ return MP_IMPORT_STAT_NO_EXIST ;
153
+ } else if (s == 1 ) {
154
+ return MP_IMPORT_STAT_DIR ;
155
+ } else {
156
+ return MP_IMPORT_STAT_FILE ;
157
+ }
63
158
}
64
159
65
160
mp_obj_t mp_builtin_open (size_t n_args , const mp_obj_t * args , mp_map_t * kwargs ) {
@@ -82,161 +177,3 @@ void MP_WEAK __assert_func(const char *file, int line, const char *func, const c
82
177
}
83
178
#endif
84
179
85
- #if MICROPY_MIN_USE_CORTEX_CPU
86
-
87
- // this is a minimal IRQ and reset framework for any Cortex-M CPU
88
-
89
- extern uint32_t _estack , _sidata , _sdata , _edata , _sbss , _ebss ;
90
-
91
- void Reset_Handler (void ) __attribute__((naked ));
92
- void Reset_Handler (void ) {
93
- // set stack pointer
94
- asm volatile ("ldr sp, =_estack" );
95
- // copy .data section from flash to RAM
96
- for (uint32_t * src = & _sidata , * dest = & _sdata ; dest < & _edata ;) {
97
- * dest ++ = * src ++ ;
98
- }
99
- // zero out .bss section
100
- for (uint32_t * dest = & _sbss ; dest < & _ebss ;) {
101
- * dest ++ = 0 ;
102
- }
103
- // jump to board initialisation
104
- void _start (void );
105
- _start ();
106
- }
107
-
108
- void Default_Handler (void ) {
109
- for (;;) {
110
- }
111
- }
112
-
113
- uint32_t isr_vector [] __attribute__((section (".isr_vector" ))) = {
114
- (uint32_t )& _estack ,
115
- (uint32_t )& Reset_Handler ,
116
- (uint32_t )& Default_Handler , // NMI_Handler
117
- (uint32_t )& Default_Handler , // HardFault_Handler
118
- (uint32_t )& Default_Handler , // MemManage_Handler
119
- (uint32_t )& Default_Handler , // BusFault_Handler
120
- (uint32_t )& Default_Handler , // UsageFault_Handler
121
- 0 ,
122
- 0 ,
123
- 0 ,
124
- 0 ,
125
- (uint32_t )& Default_Handler , // SVC_Handler
126
- (uint32_t )& Default_Handler , // DebugMon_Handler
127
- 0 ,
128
- (uint32_t )& Default_Handler , // PendSV_Handler
129
- (uint32_t )& Default_Handler , // SysTick_Handler
130
- };
131
-
132
- void _start (void ) {
133
- // when we get here: stack is initialised, bss is clear, data is copied
134
-
135
- // SCB->CCR: enable 8-byte stack alignment for IRQ handlers, in accord with EABI
136
- * ((volatile uint32_t * )0xe000ed14 ) |= 1 << 9 ;
137
-
138
- // initialise the cpu and peripherals
139
- #if MICROPY_MIN_USE_STM32_MCU
140
- void stm32_init (void );
141
- stm32_init ();
142
- #endif
143
-
144
- // now that we have a basic system up and running we can call main
145
- main (0 , NULL );
146
-
147
- // we must not return
148
- for (;;) {
149
- }
150
- }
151
-
152
- #endif
153
-
154
- #if MICROPY_MIN_USE_STM32_MCU
155
-
156
- // this is minimal set-up code for an STM32 MCU
157
-
158
- typedef struct {
159
- volatile uint32_t CR ;
160
- volatile uint32_t PLLCFGR ;
161
- volatile uint32_t CFGR ;
162
- volatile uint32_t CIR ;
163
- uint32_t _1 [8 ];
164
- volatile uint32_t AHB1ENR ;
165
- volatile uint32_t AHB2ENR ;
166
- volatile uint32_t AHB3ENR ;
167
- uint32_t _2 ;
168
- volatile uint32_t APB1ENR ;
169
- volatile uint32_t APB2ENR ;
170
- } periph_rcc_t ;
171
-
172
- typedef struct {
173
- volatile uint32_t MODER ;
174
- volatile uint32_t OTYPER ;
175
- volatile uint32_t OSPEEDR ;
176
- volatile uint32_t PUPDR ;
177
- volatile uint32_t IDR ;
178
- volatile uint32_t ODR ;
179
- volatile uint16_t BSRRL ;
180
- volatile uint16_t BSRRH ;
181
- volatile uint32_t LCKR ;
182
- volatile uint32_t AFR [2 ];
183
- } periph_gpio_t ;
184
-
185
- typedef struct {
186
- volatile uint32_t SR ;
187
- volatile uint32_t DR ;
188
- volatile uint32_t BRR ;
189
- volatile uint32_t CR1 ;
190
- } periph_uart_t ;
191
-
192
- #define USART1 ((periph_uart_t*) 0x40011000)
193
- #define GPIOA ((periph_gpio_t*) 0x40020000)
194
- #define GPIOB ((periph_gpio_t*) 0x40020400)
195
- #define RCC ((periph_rcc_t*) 0x40023800)
196
-
197
- // simple GPIO interface
198
- #define GPIO_MODE_IN (0)
199
- #define GPIO_MODE_OUT (1)
200
- #define GPIO_MODE_ALT (2)
201
- #define GPIO_PULL_NONE (0)
202
- #define GPIO_PULL_UP (0)
203
- #define GPIO_PULL_DOWN (1)
204
- void gpio_init (periph_gpio_t * gpio , int pin , int mode , int pull , int alt ) {
205
- gpio -> MODER = (gpio -> MODER & ~(3 << (2 * pin ))) | (mode << (2 * pin ));
206
- // OTYPER is left as default push-pull
207
- // OSPEEDR is left as default low speed
208
- gpio -> PUPDR = (gpio -> PUPDR & ~(3 << (2 * pin ))) | (pull << (2 * pin ));
209
- gpio -> AFR [pin >> 3 ] = (gpio -> AFR [pin >> 3 ] & ~(15 << (4 * (pin & 7 )))) | (alt << (4 * (pin & 7 )));
210
- }
211
- #define gpio_get (gpio , pin ) ((gpio->IDR >> (pin)) & 1)
212
- #define gpio_set (gpio , pin , value ) do { gpio->ODR = (gpio->ODR & ~(1 << (pin))) | (value << pin); } while (0)
213
- #define gpio_low (gpio , pin ) do { gpio->BSRRH = (1 << (pin)); } while (0)
214
- #define gpio_high (gpio , pin ) do { gpio->BSRRL = (1 << (pin)); } while (0)
215
-
216
- void stm32_init (void ) {
217
- // basic MCU config
218
- RCC -> CR |= (uint32_t )0x00000001 ; // set HSION
219
- RCC -> CFGR = 0x00000000 ; // reset all
220
- RCC -> CR &= (uint32_t )0xfef6ffff ; // reset HSEON, CSSON, PLLON
221
- RCC -> PLLCFGR = 0x24003010 ; // reset PLLCFGR
222
- RCC -> CR &= (uint32_t )0xfffbffff ; // reset HSEBYP
223
- RCC -> CIR = 0x00000000 ; // disable IRQs
224
-
225
- // leave the clock as-is (internal 16MHz)
226
-
227
- // enable GPIO clocks
228
- RCC -> AHB1ENR |= 0x00000003 ; // GPIOAEN, GPIOBEN
229
-
230
- // turn on an LED! (on pyboard it's the red one)
231
- gpio_init (GPIOA , 13 , GPIO_MODE_OUT , GPIO_PULL_NONE , 0 );
232
- gpio_high (GPIOA , 13 );
233
-
234
- // enable UART1 at 9600 baud (TX=B6, RX=B7)
235
- gpio_init (GPIOB , 6 , GPIO_MODE_ALT , GPIO_PULL_NONE , 7 );
236
- gpio_init (GPIOB , 7 , GPIO_MODE_ALT , GPIO_PULL_NONE , 7 );
237
- RCC -> APB2ENR |= 0x00000010 ; // USART1EN
238
- USART1 -> BRR = (104 << 4 ) | 3 ; // 16MHz/(16*104.1875) = 9598 baud
239
- USART1 -> CR1 = 0x0000200c ; // USART enable, tx enable, rx enable
240
- }
241
-
242
- #endif
0 commit comments