blob: d212344bd6951a06a03016a9f2a8e2d5d70a6ebb [file] [log] [blame]
Damien4b6e85c2013-10-21 09:56:56 +01001#include <stdio.h>
Damiened656052013-10-13 00:42:20 +01002#include <stm32f4xx.h>
3#include <stm32f4xx_rcc.h>
Damien52851552013-12-11 00:40:15 +00004#include <stm32f4xx_syscfg.h>
Damien00ff04f2013-10-19 14:40:54 +01005#include <stm32f4xx_gpio.h>
Damien52851552013-12-11 00:40:15 +00006#include <stm32f4xx_exti.h>
Damien0f654512013-10-23 20:39:20 +01007#include <stm32f4xx_tim.h>
Damien9281cd62013-10-26 02:29:02 +01008#include <stm32f4xx_pwr.h>
Damien81289412013-10-26 02:06:37 +01009#include <stm32f4xx_rtc.h>
Damien8f7491a2013-10-26 18:01:48 +010010#include <stm32f4xx_usart.h>
Damien39c6c592013-11-09 20:15:48 +000011#include <stm32f4xx_rng.h>
Damien00ff04f2013-10-19 14:40:54 +010012#include <stm_misc.h>
Damiened656052013-10-13 00:42:20 +010013#include "std.h"
14
Damien995b8aa2013-10-18 23:44:05 +010015#include "misc.h"
Damiend99b0522013-12-21 18:17:45 +000016#include "ff.h"
17#include "mpconfig.h"
Damien Georgeeb7bfcb2014-01-04 15:57:35 +000018#include "mpqstr.h"
Damiend99b0522013-12-21 18:17:45 +000019#include "nlr.h"
20#include "misc.h"
21#include "lexer.h"
22#include "lexerstm.h"
23#include "parse.h"
Damiend99b0522013-12-21 18:17:45 +000024#include "obj.h"
Damien George1fb03172014-01-03 14:22:03 +000025#include "compile.h"
Damiend99b0522013-12-21 18:17:45 +000026#include "runtime0.h"
27#include "runtime.h"
28#include "repl.h"
Damien3f69aca2013-10-21 23:46:04 +010029#include "gc.h"
Damien00ff04f2013-10-19 14:40:54 +010030#include "systick.h"
Damien995b8aa2013-10-18 23:44:05 +010031#include "led.h"
Damiend99b0522013-12-21 18:17:45 +000032#include "servo.h"
Damien00ff04f2013-10-19 14:40:54 +010033#include "lcd.h"
Damien995b8aa2013-10-18 23:44:05 +010034#include "storage.h"
Damienafe12bc2013-10-19 18:13:48 +010035#include "mma.h"
Damien8f7491a2013-10-26 18:01:48 +010036#include "usart.h"
Damienfb42ec12013-10-19 15:37:09 +010037#include "usb.h"
Damienbd8e1102013-11-06 23:04:33 +000038#include "timer.h"
Damien1c62d042013-11-04 23:05:48 +000039#include "audio.h"
Damien065f8a52013-12-05 20:38:23 +000040#include "pybwlan.h"
Hagen Kaye07590c22013-12-28 20:22:12 -050041#include "i2c.h"
muxde7fcc02014-01-05 14:52:37 +020042#include "usrsw.h"
Damien065f8a52013-12-05 20:38:23 +000043
44int errno;
Damiened656052013-10-13 00:42:20 +010045
Damien3f69aca2013-10-21 23:46:04 +010046extern uint32_t _heap_start;
47
Damien8fe84132013-11-30 15:06:24 +000048static FATFS fatfs0;
49
Damien94186c82013-10-23 00:02:06 +010050void flash_error(int n) {
51 for (int i = 0; i < n; i++) {
52 led_state(PYB_LED_R1, 1);
53 led_state(PYB_LED_R2, 0);
54 sys_tick_delay_ms(250);
55 led_state(PYB_LED_R1, 0);
56 led_state(PYB_LED_R2, 1);
57 sys_tick_delay_ms(250);
58 }
59 led_state(PYB_LED_R2, 0);
60}
61
Damien0f654512013-10-23 20:39:20 +010062static void impl02_c_version(void) {
Damiened656052013-10-13 00:42:20 +010063 int x = 0;
64 while (x < 400) {
65 int y = 0;
66 while (y < 400) {
67 volatile int z = 0;
68 while (z < 400) {
69 z = z + 1;
70 }
71 y = y + 1;
72 }
73 x = x + 1;
74 }
75}
76
Damiened656052013-10-13 00:42:20 +010077void __fatal_error(const char *msg) {
78 lcd_print_strn("\nFATAL ERROR:\n", 14);
79 lcd_print_strn(msg, strlen(msg));
Damiened656052013-10-13 00:42:20 +010080 for (;;) {
Damien94186c82013-10-23 00:02:06 +010081 flash_error(1);
Damiened656052013-10-13 00:42:20 +010082 }
83}
84
Damien94186c82013-10-23 00:02:06 +010085static qstr pyb_config_source_dir = 0;
86static qstr pyb_config_main = 0;
87
Damiend99b0522013-12-21 18:17:45 +000088mp_obj_t pyb_source_dir(mp_obj_t source_dir) {
89 pyb_config_source_dir = mp_obj_get_qstr(source_dir);
90 return mp_const_none;
Damiene9f1e502013-10-22 23:09:25 +010091}
92
Damiend99b0522013-12-21 18:17:45 +000093mp_obj_t pyb_main(mp_obj_t main) {
94 pyb_config_main = mp_obj_get_qstr(main);
95 return mp_const_none;
Damien94186c82013-10-23 00:02:06 +010096}
97
98// sync all file systems
Damiend99b0522013-12-21 18:17:45 +000099mp_obj_t pyb_sync(void) {
Damien94186c82013-10-23 00:02:06 +0100100 storage_flush();
Damiend99b0522013-12-21 18:17:45 +0000101 return mp_const_none;
Damiene9f1e502013-10-22 23:09:25 +0100102}
Damiened656052013-10-13 00:42:20 +0100103
Damiend99b0522013-12-21 18:17:45 +0000104mp_obj_t pyb_delay(mp_obj_t count) {
105 sys_tick_delay_ms(mp_obj_get_int(count));
106 return mp_const_none;
Damiened656052013-10-13 00:42:20 +0100107}
108
Damiend99b0522013-12-21 18:17:45 +0000109mp_obj_t pyb_led(mp_obj_t state) {
Damien995b8aa2013-10-18 23:44:05 +0100110 led_state(PYB_LED_G1, rt_is_true(state));
Damiened656052013-10-13 00:42:20 +0100111 return state;
112}
113
Damien4a175e12013-10-17 22:50:21 +0100114/*
Damien152568b2013-10-16 00:46:39 +0100115void g(uint i) {
116 printf("g:%d\n", i);
117 if (i & 1) {
118 nlr_jump((void*)(42 + i));
119 }
120}
Damien0f654512013-10-23 20:39:20 +0100121void f(void) {
Damien152568b2013-10-16 00:46:39 +0100122 nlr_buf_t nlr;
123 int i;
124 for (i = 0; i < 4; i++) {
125 printf("f:loop:%d:%p\n", i, &nlr);
126 if (nlr_push(&nlr) == 0) {
127 // normal
128 //printf("a:%p:%p %p %p %u\n", &nlr, nlr.ip, nlr.sp, nlr.prev, nlr.ret_val);
129 g(i);
130 printf("f:lp:%d:nrm\n", i);
131 nlr_pop();
132 } else {
133 // nlr
134 //printf("b:%p:%p %p %p %u\n", &nlr, nlr.ip, nlr.sp, nlr.prev, nlr.ret_val);
135 printf("f:lp:%d:nlr:%d\n", i, (int)nlr.ret_val);
136 }
137 }
138}
Damien0f654512013-10-23 20:39:20 +0100139void nlr_test(void) {
Damien152568b2013-10-16 00:46:39 +0100140 f(1);
141}
Damien4a175e12013-10-17 22:50:21 +0100142*/
143
Damien0f654512013-10-23 20:39:20 +0100144void fatality(void) {
Damien00ff04f2013-10-19 14:40:54 +0100145 led_state(PYB_LED_R1, 1);
146 led_state(PYB_LED_G1, 1);
147 led_state(PYB_LED_R2, 1);
148 led_state(PYB_LED_G2, 1);
149}
Damiened656052013-10-13 00:42:20 +0100150
Damienafe12bc2013-10-19 18:13:48 +0100151static const char fresh_boot_py[] =
Damien00ff04f2013-10-19 14:40:54 +0100152"# boot.py -- run on boot-up\n"
153"# can run arbitrary Python, but best to keep it minimal\n"
154"\n"
155"pyb.source_dir('/src')\n"
156"pyb.main('main.py')\n"
157"#pyb.usb_usr('VCP')\n"
158"#pyb.usb_msd(True, 'dual partition')\n"
159"#pyb.flush_cache(False)\n"
160"#pyb.error_log('error.txt')\n"
161;
Damiened656052013-10-13 00:42:20 +0100162
Damien8c3da5c2013-12-17 18:36:19 +0000163static const char fresh_main_py[] =
164"# main.py -- put your code here!\n"
165;
166
167static const char *help_text =
168"Welcome to Micro Python!\n\n"
169"This is a *very* early version of Micro Python and has minimal functionality.\n\n"
170"Specific commands for the board:\n"
171" pyb.info() -- print some general information\n"
172" pyb.gc() -- run the garbage collector\n"
173" pyb.delay(<n>) -- wait for n milliseconds\n"
174" pyb.Led(<n>) -- create Led object for LED n (n=1,2)\n"
175" Led methods: on(), off()\n"
176" pyb.Servo(<n>) -- create Servo object for servo n (n=1,2,3,4)\n"
177" Servo methods: angle(<x>)\n"
178" pyb.switch() -- return True/False if switch pressed or not\n"
179" pyb.accel() -- get accelerometer values\n"
180" pyb.rand() -- get a 16-bit random number\n"
181;
182
183// get some help about available functions
Damiend99b0522013-12-21 18:17:45 +0000184static mp_obj_t pyb_help(void) {
Damien8c3da5c2013-12-17 18:36:19 +0000185 printf("%s", help_text);
Damiend99b0522013-12-21 18:17:45 +0000186 return mp_const_none;
Damien8c3da5c2013-12-17 18:36:19 +0000187}
188
Damien00ff04f2013-10-19 14:40:54 +0100189// get lots of info about the board
Damiend99b0522013-12-21 18:17:45 +0000190static mp_obj_t pyb_info(void) {
Damien8c3da5c2013-12-17 18:36:19 +0000191 // get and print unique id; 96 bits
192 {
193 byte *id = (byte*)0x1fff7a10;
194 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]);
195 }
196
Damiened656052013-10-13 00:42:20 +0100197 // get and print clock speeds
198 // SYSCLK=168MHz, HCLK=168MHz, PCLK1=42MHz, PCLK2=84MHz
Damiened656052013-10-13 00:42:20 +0100199 {
200 RCC_ClocksTypeDef rcc_clocks;
201 RCC_GetClocksFreq(&rcc_clocks);
Damien00ff04f2013-10-19 14:40:54 +0100202 printf("S=%lu\nH=%lu\nP1=%lu\nP2=%lu\n", rcc_clocks.SYSCLK_Frequency, rcc_clocks.HCLK_Frequency, rcc_clocks.PCLK1_Frequency, rcc_clocks.PCLK2_Frequency);
Damien4a175e12013-10-17 22:50:21 +0100203 }
204
Damien995b8aa2013-10-18 23:44:05 +0100205 // to print info about memory
Damien00ff04f2013-10-19 14:40:54 +0100206 {
Damien4a175e12013-10-17 22:50:21 +0100207 extern void *_sidata;
208 extern void *_sdata;
209 extern void *_edata;
210 extern void *_sbss;
211 extern void *_ebss;
212 extern void *_estack;
213 extern void *_etext;
Damien00ff04f2013-10-19 14:40:54 +0100214 printf("_sidata=%p\n", &_sidata);
215 printf("_sdata=%p\n", &_sdata);
216 printf("_edata=%p\n", &_edata);
217 printf("_sbss=%p\n", &_sbss);
218 printf("_ebss=%p\n", &_ebss);
219 printf("_estack=%p\n", &_estack);
220 printf("_etext=%p\n", &_etext);
221 printf("_heap_start=%p\n", &_heap_start);
222 }
223
Damien94186c82013-10-23 00:02:06 +0100224 // GC info
225 {
226 gc_info_t info;
227 gc_info(&info);
228 printf("GC:\n");
229 printf(" %lu total\n", info.total);
230 printf(" %lu : %lu\n", info.used, info.free);
231 printf(" 1=%lu 2=%lu m=%lu\n", info.num_1block, info.num_2block, info.max_block);
232 }
233
Damien00ff04f2013-10-19 14:40:54 +0100234 // free space on flash
235 {
236 DWORD nclst;
237 FATFS *fatfs;
238 f_getfree("0:", &nclst, &fatfs);
Damien94186c82013-10-23 00:02:06 +0100239 printf("LFS free: %u bytes\n", (uint)(nclst * fatfs->csize * 512));
Damien00ff04f2013-10-19 14:40:54 +0100240 }
Damien00ff04f2013-10-19 14:40:54 +0100241
Damiend99b0522013-12-21 18:17:45 +0000242 return mp_const_none;
Damien4b6e85c2013-10-21 09:56:56 +0100243}
244
Damienb73085d2013-12-20 11:45:06 +0000245// SD card test
Damiend99b0522013-12-21 18:17:45 +0000246static mp_obj_t pyb_sd_test(void) {
Damienb73085d2013-12-20 11:45:06 +0000247 extern void sdio_init(void);
248 sdio_init();
Damiend99b0522013-12-21 18:17:45 +0000249 return mp_const_none;
Damienb73085d2013-12-20 11:45:06 +0000250}
251
Damien52851552013-12-11 00:40:15 +0000252static void SYSCLKConfig_STOP(void) {
253 /* After wake-up from STOP reconfigure the system clock */
254 /* Enable HSE */
255 RCC_HSEConfig(RCC_HSE_ON);
256
257 /* Wait till HSE is ready */
258 while (RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET) {
259 }
260
261 /* Enable PLL */
262 RCC_PLLCmd(ENABLE);
263
264 /* Wait till PLL is ready */
265 while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET) {
266 }
267
268 /* Select PLL as system clock source */
269 RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
270
271 /* Wait till PLL is used as system clock source */
272 while (RCC_GetSYSCLKSource() != 0x08) {
273 }
274}
275
Damiend99b0522013-12-21 18:17:45 +0000276static mp_obj_t pyb_stop(void) {
Damien52851552013-12-11 00:40:15 +0000277 PWR_EnterSTANDBYMode();
278 //PWR_FlashPowerDownCmd(ENABLE); don't know what the logic is with this
279
280 /* Enter Stop Mode */
281 PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI);
282
283 /* Configures system clock after wake-up from STOP: enable HSE, PLL and select
284 * PLL as system clock source (HSE and PLL are disabled in STOP mode) */
285 SYSCLKConfig_STOP();
286
287 //PWR_FlashPowerDownCmd(DISABLE);
288
Damiend99b0522013-12-21 18:17:45 +0000289 return mp_const_none;
Damien52851552013-12-11 00:40:15 +0000290}
291
Damiend99b0522013-12-21 18:17:45 +0000292static mp_obj_t pyb_standby(void) {
Damien52851552013-12-11 00:40:15 +0000293 PWR_EnterSTANDBYMode();
Damiend99b0522013-12-21 18:17:45 +0000294 return mp_const_none;
Damien52851552013-12-11 00:40:15 +0000295}
296
Damiend99b0522013-12-21 18:17:45 +0000297mp_obj_t pyb_usart_send(mp_obj_t data) {
298 usart_tx_char(mp_obj_get_int(data));
299 return mp_const_none;
Damien8f7491a2013-10-26 18:01:48 +0100300}
301
Damiend99b0522013-12-21 18:17:45 +0000302mp_obj_t pyb_usart_receive(void) {
303 return mp_obj_new_int(usart_rx_char());
Damien8f7491a2013-10-26 18:01:48 +0100304}
305
Damiend99b0522013-12-21 18:17:45 +0000306mp_obj_t pyb_usart_status(void) {
Damien8f7491a2013-10-26 18:01:48 +0100307 if (usart_rx_any()) {
Damiend99b0522013-12-21 18:17:45 +0000308 return mp_const_true;
Damien8f7491a2013-10-26 18:01:48 +0100309 } else {
Damiend99b0522013-12-21 18:17:45 +0000310 return mp_const_false;
Damien8f7491a2013-10-26 18:01:48 +0100311 }
312}
313
Damien9281cd62013-10-26 02:29:02 +0100314char *strdup(const char *str) {
315 uint32_t len = strlen(str);
316 char *s2 = m_new(char, len + 1);
317 memcpy(s2, str, len);
318 s2[len] = 0;
319 return s2;
320}
321
322#define READLINE_HIST_SIZE (8)
323
324static const char *readline_hist[READLINE_HIST_SIZE] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
325
Damien8f7491a2013-10-26 18:01:48 +0100326void stdout_tx_str(const char *str) {
327 usart_tx_str(str);
328 usb_vcp_send_str(str);
329}
330
Damiene9f1e502013-10-22 23:09:25 +0100331int readline(vstr_t *line, const char *prompt) {
Damien8f7491a2013-10-26 18:01:48 +0100332 stdout_tx_str(prompt);
Damiene9f1e502013-10-22 23:09:25 +0100333 int len = vstr_len(line);
Damien9281cd62013-10-26 02:29:02 +0100334 int escape = 0;
335 int hist_num = 0;
Damiene9f1e502013-10-22 23:09:25 +0100336 for (;;) {
Damien8f7491a2013-10-26 18:01:48 +0100337 char c;
338 for (;;) {
339 if (usb_vcp_rx_any() != 0) {
340 c = usb_vcp_rx_get();
341 break;
342 } else if (usart_rx_any()) {
343 c = usart_rx_char();
344 break;
345 }
Damien9281cd62013-10-26 02:29:02 +0100346 sys_tick_delay_ms(1);
Damien52851552013-12-11 00:40:15 +0000347 if (storage_needs_flush()) {
348 storage_flush();
349 }
Damiene9f1e502013-10-22 23:09:25 +0100350 }
Damien9281cd62013-10-26 02:29:02 +0100351 if (escape == 0) {
352 if (c == 4 && vstr_len(line) == len) {
353 return 0;
354 } else if (c == '\r') {
Damien8f7491a2013-10-26 18:01:48 +0100355 stdout_tx_str("\r\n");
Damien9281cd62013-10-26 02:29:02 +0100356 for (int i = READLINE_HIST_SIZE - 1; i > 0; i--) {
357 readline_hist[i] = readline_hist[i - 1];
358 }
359 readline_hist[0] = strdup(vstr_str(line));
360 return 1;
361 } else if (c == 27) {
362 escape = true;
363 } else if (c == 127) {
364 if (vstr_len(line) > len) {
365 vstr_cut_tail(line, 1);
Damien8f7491a2013-10-26 18:01:48 +0100366 stdout_tx_str("\b \b");
Damien9281cd62013-10-26 02:29:02 +0100367 }
368 } else if (32 <= c && c <= 126) {
369 vstr_add_char(line, c);
Damien8f7491a2013-10-26 18:01:48 +0100370 stdout_tx_str(line->buf + line->len - 1);
Damiene9f1e502013-10-22 23:09:25 +0100371 }
Damien9281cd62013-10-26 02:29:02 +0100372 } else if (escape == 1) {
373 if (c == '[') {
374 escape = 2;
375 } else {
376 escape = 0;
377 }
378 } else if (escape == 2) {
379 escape = 0;
380 if (c == 'A') {
381 // up arrow
382 if (hist_num < READLINE_HIST_SIZE && readline_hist[hist_num] != NULL) {
383 // erase line
384 for (int i = line->len - len; i > 0; i--) {
Damien8f7491a2013-10-26 18:01:48 +0100385 stdout_tx_str("\b \b");
Damien9281cd62013-10-26 02:29:02 +0100386 }
387 // set line to history
388 line->len = len;
389 vstr_add_str(line, readline_hist[hist_num]);
390 // draw line
Damien8f7491a2013-10-26 18:01:48 +0100391 stdout_tx_str(readline_hist[hist_num]);
Damien9281cd62013-10-26 02:29:02 +0100392 // increase hist num
393 hist_num += 1;
394 }
395 }
396 } else {
397 escape = 0;
Damiene9f1e502013-10-22 23:09:25 +0100398 }
Damien9281cd62013-10-26 02:29:02 +0100399 sys_tick_delay_ms(10);
Damiene9f1e502013-10-22 23:09:25 +0100400 }
401}
402
Damien0f654512013-10-23 20:39:20 +0100403void do_repl(void) {
Damien George28708622014-01-02 21:30:26 +0000404 stdout_tx_str("Micro Python build <git hash> on 2/1/2014; PYBv3 with STM32F405RG\r\n");
Damien8c3da5c2013-12-17 18:36:19 +0000405 stdout_tx_str("Type \"help()\" for more information.\r\n");
Damiene9f1e502013-10-22 23:09:25 +0100406
407 vstr_t line;
408 vstr_init(&line);
Damien4b6e85c2013-10-21 09:56:56 +0100409
410 for (;;) {
Damiene9f1e502013-10-22 23:09:25 +0100411 vstr_reset(&line);
412 int ret = readline(&line, ">>> ");
413 if (ret == 0) {
Damien4b6e85c2013-10-21 09:56:56 +0100414 // EOF
Damiene9f1e502013-10-22 23:09:25 +0100415 break;
Damien4b6e85c2013-10-21 09:56:56 +0100416 }
Damiene9f1e502013-10-22 23:09:25 +0100417
418 if (vstr_len(&line) == 0) {
419 continue;
420 }
421
Damiend99b0522013-12-21 18:17:45 +0000422 if (mp_repl_is_compound_stmt(vstr_str(&line))) {
Damien4b6e85c2013-10-21 09:56:56 +0100423 for (;;) {
Damiene9f1e502013-10-22 23:09:25 +0100424 vstr_add_char(&line, '\n');
425 int len = vstr_len(&line);
426 int ret = readline(&line, "... ");
427 if (ret == 0 || vstr_len(&line) == len) {
428 // done entering compound statement
Damien4b6e85c2013-10-21 09:56:56 +0100429 break;
430 }
Damien4b6e85c2013-10-21 09:56:56 +0100431 }
432 }
Damien4b6e85c2013-10-21 09:56:56 +0100433
Damiend99b0522013-12-21 18:17:45 +0000434 mp_lexer_str_buf_t sb;
435 mp_lexer_t *lex = mp_lexer_new_from_str_len("<stdin>", vstr_str(&line), vstr_len(&line), false, &sb);
436 mp_parse_node_t pn = mp_parse(lex, MP_PARSE_SINGLE_INPUT);
437 mp_lexer_free(lex);
Damien4b6e85c2013-10-21 09:56:56 +0100438
Damiend99b0522013-12-21 18:17:45 +0000439 if (pn != MP_PARSE_NODE_NULL) {
Damien George1fb03172014-01-03 14:22:03 +0000440 mp_obj_t module_fun = mp_compile(pn, true);
441 if (module_fun != mp_const_none) {
442 nlr_buf_t nlr;
443 uint32_t start = sys_tick_counter;
444 if (nlr_push(&nlr) == 0) {
445 rt_call_function_0(module_fun);
446 nlr_pop();
447 // optional timing
448 if (0) {
449 uint32_t ticks = sys_tick_counter - start; // TODO implement a function that does this properly
450 printf("(took %lu ms)\n", ticks);
Damien4b6e85c2013-10-21 09:56:56 +0100451 }
Damien George1fb03172014-01-03 14:22:03 +0000452 } else {
453 // uncaught exception
454 mp_obj_print((mp_obj_t)nlr.ret_val);
455 printf("\n");
Damien4b6e85c2013-10-21 09:56:56 +0100456 }
457 }
458 }
459 }
Damiene9f1e502013-10-22 23:09:25 +0100460
Damien8f7491a2013-10-26 18:01:48 +0100461 stdout_tx_str("\r\n");
Damien94186c82013-10-23 00:02:06 +0100462}
463
464bool do_file(const char *filename) {
Damiend99b0522013-12-21 18:17:45 +0000465 mp_lexer_file_buf_t fb;
466 mp_lexer_t *lex = mp_lexer_new_from_file(filename, &fb);
Damien94186c82013-10-23 00:02:06 +0100467
468 if (lex == NULL) {
469 printf("could not open file '%s' for reading\n", filename);
470 return false;
471 }
472
Damiend99b0522013-12-21 18:17:45 +0000473 mp_parse_node_t pn = mp_parse(lex, MP_PARSE_FILE_INPUT);
474 mp_lexer_free(lex);
Damien94186c82013-10-23 00:02:06 +0100475
Damiend99b0522013-12-21 18:17:45 +0000476 if (pn == MP_PARSE_NODE_NULL) {
Damien94186c82013-10-23 00:02:06 +0100477 return false;
478 }
479
Damien George1fb03172014-01-03 14:22:03 +0000480 mp_obj_t module_fun = mp_compile(pn, false);
Damiend99b0522013-12-21 18:17:45 +0000481 if (module_fun == mp_const_none) {
Damien94186c82013-10-23 00:02:06 +0100482 return false;
483 }
484
485 nlr_buf_t nlr;
486 if (nlr_push(&nlr) == 0) {
487 rt_call_function_0(module_fun);
488 nlr_pop();
489 return true;
490 } else {
491 // uncaught exception
Damiend99b0522013-12-21 18:17:45 +0000492 mp_obj_print((mp_obj_t)nlr.ret_val);
Damien94186c82013-10-23 00:02:06 +0100493 printf("\n");
494 return false;
495 }
Damien4b6e85c2013-10-21 09:56:56 +0100496}
497
Damien0c5827f2013-10-22 21:13:36 +0100498#define RAM_START (0x20000000) // fixed for chip
499#define HEAP_END (0x2001c000) // tunable
500#define RAM_END (0x20020000) // fixed for chip
501
502void gc_helper_get_regs_and_clean_stack(machine_uint_t *regs, machine_uint_t heap_end);
503
Damien0f654512013-10-23 20:39:20 +0100504void gc_collect(void) {
Damien0c5827f2013-10-22 21:13:36 +0100505 uint32_t start = sys_tick_counter;
Damien3f69aca2013-10-21 23:46:04 +0100506 gc_collect_start();
Damien0c5827f2013-10-22 21:13:36 +0100507 gc_collect_root((void**)RAM_START, (((uint32_t)&_heap_start) - RAM_START) / 4);
508 machine_uint_t regs[10];
509 gc_helper_get_regs_and_clean_stack(regs, HEAP_END);
510 gc_collect_root((void**)HEAP_END, (RAM_END - HEAP_END) / 4); // will trace regs since they now live in this function on the stack
Damien3f69aca2013-10-21 23:46:04 +0100511 gc_collect_end();
Damien0c5827f2013-10-22 21:13:36 +0100512 uint32_t ticks = sys_tick_counter - start; // TODO implement a function that does this properly
Damien8c3da5c2013-12-17 18:36:19 +0000513
514 if (0) {
515 // print GC info
516 gc_info_t info;
517 gc_info(&info);
518 printf("GC@%lu %lums\n", start, ticks);
519 printf(" %lu total\n", info.total);
520 printf(" %lu : %lu\n", info.used, info.free);
521 printf(" 1=%lu 2=%lu m=%lu\n", info.num_1block, info.num_2block, info.max_block);
522 }
Damien0c5827f2013-10-22 21:13:36 +0100523}
524
Damiend99b0522013-12-21 18:17:45 +0000525mp_obj_t pyb_gc(void) {
Damien0c5827f2013-10-22 21:13:36 +0100526 gc_collect();
Damiend99b0522013-12-21 18:17:45 +0000527 return mp_const_none;
Damien0c70f882013-11-03 18:30:57 +0000528}
529
Damien George28708622014-01-02 21:30:26 +0000530mp_obj_t pyb_gpio(int n_args, mp_obj_t *args) {
531 //assert(1 <= n_args && n_args <= 2);
Damien6f08f8c2013-10-23 22:17:26 +0100532
Damien George28708622014-01-02 21:30:26 +0000533 const char *pin_name = qstr_str(mp_obj_get_qstr(args[0]));
534 GPIO_TypeDef *port;
535 switch (pin_name[0]) {
536 case 'A': case 'a': port = GPIOA; break;
537 case 'B': case 'b': port = GPIOB; break;
538 case 'C': case 'c': port = GPIOC; break;
539 default: goto pin_error;
Damien8fe84132013-11-30 15:06:24 +0000540 }
Damien George28708622014-01-02 21:30:26 +0000541 uint pin_num = 0;
542 for (const char *s = pin_name + 1; *s; s++) {
543 if (!('0' <= *s && *s <= '9')) {
544 goto pin_error;
Damien6f08f8c2013-10-23 22:17:26 +0100545 }
Damien George28708622014-01-02 21:30:26 +0000546 pin_num = 10 * pin_num + *s - '0';
Damien6f08f8c2013-10-23 22:17:26 +0100547 }
Damien George28708622014-01-02 21:30:26 +0000548 if (!(0 <= pin_num && pin_num <= 15)) {
549 goto pin_error;
550 }
Damien8fe84132013-11-30 15:06:24 +0000551
Damien George28708622014-01-02 21:30:26 +0000552 if (n_args == 1) {
553 // get pin
554 if ((port->IDR & (1 << pin_num)) != (uint32_t)Bit_RESET) {
555 return MP_OBJ_NEW_SMALL_INT(1);
556 } else {
557 return MP_OBJ_NEW_SMALL_INT(0);
558 }
559 } else {
560 // set pin
561 if (rt_is_true(args[1])) {
562 // set pin high
563 port->BSRRL = 1 << pin_num;
564 } else {
565 // set pin low
566 port->BSRRH = 1 << pin_num;
567 }
568 return mp_const_none;
569 }
Damien8fe84132013-11-30 15:06:24 +0000570
Damien George28708622014-01-02 21:30:26 +0000571pin_error:
Damien Georgeeb7bfcb2014-01-04 15:57:35 +0000572 nlr_jump(mp_obj_new_exception_msg_1_arg(MP_QSTR_ValueError, "pin %s does not exist", pin_name));
Damien6f08f8c2013-10-23 22:17:26 +0100573}
574
Damien George28708622014-01-02 21:30:26 +0000575MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_gpio_obj, 1, 2, pyb_gpio);
576
Damiend99b0522013-12-21 18:17:45 +0000577mp_obj_t pyb_hid_send_report(mp_obj_t arg) {
578 mp_obj_t *items = mp_obj_get_array_fixed_n(arg, 4);
Damien58a1b4c2013-10-25 20:53:54 +0100579 uint8_t data[4];
Damiend99b0522013-12-21 18:17:45 +0000580 data[0] = mp_obj_get_int(items[0]);
581 data[1] = mp_obj_get_int(items[1]);
582 data[2] = mp_obj_get_int(items[2]);
583 data[3] = mp_obj_get_int(items[3]);
Damien58a1b4c2013-10-25 20:53:54 +0100584 usb_hid_send_report(data);
Damiend99b0522013-12-21 18:17:45 +0000585 return mp_const_none;
Damien58a1b4c2013-10-25 20:53:54 +0100586}
587
Damien81289412013-10-26 02:06:37 +0100588static void rtc_init(void) {
mux5df3d472014-01-08 11:26:18 +0200589 uint32_t rtc_clksrc;
590 uint32_t timeout =10000;
591
Damien81289412013-10-26 02:06:37 +0100592 /* Enable the PWR clock */
593 RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
594
595 /* Allow access to RTC */
596 PWR_BackupAccessCmd(ENABLE);
597
598 /* Enable the LSE OSC */
599 RCC_LSEConfig(RCC_LSE_ON);
600
601 /* Wait till LSE is ready */
mux5df3d472014-01-08 11:26:18 +0200602 while((RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET) && (--timeout > 0)) {
603 }
604
605 /* If LSE timed out, use LSI instead */
606 if (timeout == 0) {
607 /* Enable the LSI OSC */
608 RCC_LSICmd(ENABLE);
609
610 /* Wait till LSI is ready */
611 while(RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET) {
612 }
613
614 /* Use LSI as the RTC Clock Source */
615 rtc_clksrc = RCC_RTCCLKSource_LSI;
616 } else {
617 /* Use LSE as the RTC Clock Source */
618 rtc_clksrc = RCC_RTCCLKSource_LSE;
Damien81289412013-10-26 02:06:37 +0100619 }
620
621 /* Select the RTC Clock Source */
mux5df3d472014-01-08 11:26:18 +0200622 RCC_RTCCLKConfig(rtc_clksrc);
623
624 /* Note: LSI is around (32KHz), these dividers should work either way */
Damien81289412013-10-26 02:06:37 +0100625 /* ck_spre(1Hz) = RTCCLK(LSE) /(uwAsynchPrediv + 1)*(uwSynchPrediv + 1)*/
626 uint32_t uwSynchPrediv = 0xFF;
627 uint32_t uwAsynchPrediv = 0x7F;
628
629 /* Enable the RTC Clock */
630 RCC_RTCCLKCmd(ENABLE);
631
632 /* Wait for RTC APB registers synchronisation */
633 RTC_WaitForSynchro();
634
635 /* Configure the RTC data register and RTC prescaler */
636 RTC_InitTypeDef RTC_InitStructure;
637 RTC_InitStructure.RTC_AsynchPrediv = uwAsynchPrediv;
638 RTC_InitStructure.RTC_SynchPrediv = uwSynchPrediv;
639 RTC_InitStructure.RTC_HourFormat = RTC_HourFormat_24;
640 RTC_Init(&RTC_InitStructure);
641
642 // Set the date (BCD)
643 RTC_DateTypeDef RTC_DateStructure;
644 RTC_DateStructure.RTC_Year = 0x13;
645 RTC_DateStructure.RTC_Month = RTC_Month_October;
646 RTC_DateStructure.RTC_Date = 0x26;
647 RTC_DateStructure.RTC_WeekDay = RTC_Weekday_Saturday;
648 RTC_SetDate(RTC_Format_BCD, &RTC_DateStructure);
649
650 // Set the time (BCD)
651 RTC_TimeTypeDef RTC_TimeStructure;
652 RTC_TimeStructure.RTC_H12 = RTC_H12_AM;
653 RTC_TimeStructure.RTC_Hours = 0x01;
654 RTC_TimeStructure.RTC_Minutes = 0x53;
655 RTC_TimeStructure.RTC_Seconds = 0x00;
656 RTC_SetTime(RTC_Format_BCD, &RTC_TimeStructure);
657
658 // Indicator for the RTC configuration
659 //RTC_WriteBackupRegister(RTC_BKP_DR0, 0x32F2);
660}
661
Damiend99b0522013-12-21 18:17:45 +0000662mp_obj_t pyb_rtc_read(void) {
Damien81289412013-10-26 02:06:37 +0100663 RTC_TimeTypeDef RTC_TimeStructure;
664 RTC_GetTime(RTC_Format_BIN, &RTC_TimeStructure);
665 printf("%02d:%02d:%02d\n", RTC_TimeStructure.RTC_Hours, RTC_TimeStructure.RTC_Minutes, RTC_TimeStructure.RTC_Seconds);
Damiend99b0522013-12-21 18:17:45 +0000666 return mp_const_none;
Damien81289412013-10-26 02:06:37 +0100667}
668
Damiend99b0522013-12-21 18:17:45 +0000669typedef struct _pyb_file_obj_t {
670 mp_obj_base_t base;
671 FIL fp;
672} pyb_file_obj_t;
673
674void file_obj_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in) {
675 printf("<file %p>", self_in);
Damien0e496732013-11-03 14:53:34 +0000676}
677
Damiend99b0522013-12-21 18:17:45 +0000678mp_obj_t file_obj_read(mp_obj_t self_in, mp_obj_t arg) {
679 pyb_file_obj_t *self = self_in;
680 int n = mp_obj_get_int(arg);
Damien0e496732013-11-03 14:53:34 +0000681 char *buf = m_new(char, n + 1);
682 UINT n_out;
Damiend99b0522013-12-21 18:17:45 +0000683 f_read(&self->fp, buf, n, &n_out);
Damien0e496732013-11-03 14:53:34 +0000684 buf[n_out] = 0;
Damien732407f2013-12-29 19:33:23 +0000685 return mp_obj_new_str(qstr_from_str_take(buf, n + 1));
Damien0e496732013-11-03 14:53:34 +0000686}
687
Damiend99b0522013-12-21 18:17:45 +0000688mp_obj_t file_obj_write(mp_obj_t self_in, mp_obj_t arg) {
689 pyb_file_obj_t *self = self_in;
690 const char *s = qstr_str(mp_obj_get_qstr(arg));
Damien0e496732013-11-03 14:53:34 +0000691 UINT n_out;
Damiend99b0522013-12-21 18:17:45 +0000692 FRESULT res = f_write(&self->fp, s, strlen(s), &n_out);
Damien0e496732013-11-03 14:53:34 +0000693 if (res != FR_OK) {
694 printf("File error: could not write to file; error code %d\n", res);
695 } else if (n_out != strlen(s)) {
696 printf("File error: could not write all data to file; wrote %d / %d bytes\n", n_out, strlen(s));
697 }
Damiend99b0522013-12-21 18:17:45 +0000698 return mp_const_none;
Damien0e496732013-11-03 14:53:34 +0000699}
700
Damiend99b0522013-12-21 18:17:45 +0000701mp_obj_t file_obj_close(mp_obj_t self_in) {
702 pyb_file_obj_t *self = self_in;
703 f_close(&self->fp);
704 return mp_const_none;
Damien0e496732013-11-03 14:53:34 +0000705}
706
Damiend99b0522013-12-21 18:17:45 +0000707static MP_DEFINE_CONST_FUN_OBJ_2(file_obj_read_obj, file_obj_read);
708static MP_DEFINE_CONST_FUN_OBJ_2(file_obj_write_obj, file_obj_write);
709static MP_DEFINE_CONST_FUN_OBJ_1(file_obj_close_obj, file_obj_close);
710
Damien0e496732013-11-03 14:53:34 +0000711// TODO gc hook to close the file if not already closed
Damiend99b0522013-12-21 18:17:45 +0000712
Damien George97209d32014-01-07 15:58:30 +0000713static const mp_method_t file_methods[] = {
714 { "read", &file_obj_read_obj },
715 { "write", &file_obj_write_obj },
716 { "close", &file_obj_close_obj },
717 {NULL, NULL},
718};
719
Damiend99b0522013-12-21 18:17:45 +0000720static const mp_obj_type_t file_obj_type = {
721 { &mp_const_type },
Damien0e496732013-11-03 14:53:34 +0000722 "File",
Damien George97209d32014-01-07 15:58:30 +0000723 .print = file_obj_print,
724 .methods = file_methods,
Damien0e496732013-11-03 14:53:34 +0000725};
726
Damiend99b0522013-12-21 18:17:45 +0000727mp_obj_t pyb_io_open(mp_obj_t o_filename, mp_obj_t o_mode) {
728 const char *filename = qstr_str(mp_obj_get_qstr(o_filename));
729 const char *mode = qstr_str(mp_obj_get_qstr(o_mode));
730 pyb_file_obj_t *self = m_new_obj(pyb_file_obj_t);
731 self->base.type = &file_obj_type;
Damien0e496732013-11-03 14:53:34 +0000732 if (mode[0] == 'r') {
733 // open for reading
Damiend99b0522013-12-21 18:17:45 +0000734 FRESULT res = f_open(&self->fp, filename, FA_READ);
Damien0e496732013-11-03 14:53:34 +0000735 if (res != FR_OK) {
736 printf("FileNotFoundError: [Errno 2] No such file or directory: '%s'\n", filename);
Damiend99b0522013-12-21 18:17:45 +0000737 return mp_const_none;
Damien0e496732013-11-03 14:53:34 +0000738 }
739 } else if (mode[0] == 'w') {
740 // open for writing, truncate the file first
Damiend99b0522013-12-21 18:17:45 +0000741 FRESULT res = f_open(&self->fp, filename, FA_WRITE | FA_CREATE_ALWAYS);
Damien0e496732013-11-03 14:53:34 +0000742 if (res != FR_OK) {
743 printf("?FileError: could not create file: '%s'\n", filename);
Damiend99b0522013-12-21 18:17:45 +0000744 return mp_const_none;
Damien0e496732013-11-03 14:53:34 +0000745 }
746 } else {
747 printf("ValueError: invalid mode: '%s'\n", mode);
Damiend99b0522013-12-21 18:17:45 +0000748 return mp_const_none;
Damien0e496732013-11-03 14:53:34 +0000749 }
Damiend99b0522013-12-21 18:17:45 +0000750 return self;
Damien0e496732013-11-03 14:53:34 +0000751}
752
Damiend99b0522013-12-21 18:17:45 +0000753mp_obj_t pyb_rng_get(void) {
754 return mp_obj_new_int(RNG_GetRandomNumber() >> 16);
Damien39c6c592013-11-09 20:15:48 +0000755}
756
Damien0f654512013-10-23 20:39:20 +0100757int main(void) {
Damien00ff04f2013-10-19 14:40:54 +0100758 // TODO disable JTAG
759
Damiend6b4c662013-12-06 00:41:33 +0000760 // update the SystemCoreClock variable
761 SystemCoreClockUpdate();
762
Damienafe12bc2013-10-19 18:13:48 +0100763 // set interrupt priority config to use all 4 bits for pre-empting
764 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
765
766 // enable the CCM RAM and the GPIO's
767 RCC->AHB1ENR |= RCC_AHB1ENR_CCMDATARAMEN | RCC_AHB1ENR_GPIOAEN | RCC_AHB1ENR_GPIOBEN | RCC_AHB1ENR_GPIOCEN;
768
Damien5892f472013-10-26 18:02:46 +0100769 // configure SDIO pins to be high to start with (apparently makes it more robust)
Damien7ee80ba2013-10-24 00:22:27 +0100770 {
771 GPIO_InitTypeDef GPIO_InitStructure;
772 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12;
773 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_25MHz;
774 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
775 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
776 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
777 GPIO_Init(GPIOC, &GPIO_InitStructure);
778
779 // Configure PD.02 CMD line
780 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
781 GPIO_Init(GPIOD, &GPIO_InitStructure);
782 }
783
Damien00ff04f2013-10-19 14:40:54 +0100784 // basic sub-system init
785 sys_tick_init();
Damien00ff04f2013-10-19 14:40:54 +0100786 led_init();
Damien81289412013-10-26 02:06:37 +0100787 rtc_init();
Damien00ff04f2013-10-19 14:40:54 +0100788
789 // turn on LED to indicate bootup
790 led_state(PYB_LED_G1, 1);
791
792 // more sub-system init
Damien George823877b2014-01-05 14:04:55 +0000793 switch_init();
Damien00ff04f2013-10-19 14:40:54 +0100794 storage_init();
Damien065f8a52013-12-05 20:38:23 +0000795
796 //usart_init(); disabled while wi-fi is enabled
Damien00ff04f2013-10-19 14:40:54 +0100797
Damienbd8e1102013-11-06 23:04:33 +0000798 int first_soft_reset = true;
799
Damiene9f1e502013-10-22 23:09:25 +0100800soft_reset:
801
Damien3f69aca2013-10-21 23:46:04 +0100802 // GC init
Damien0c5827f2013-10-22 21:13:36 +0100803 gc_init(&_heap_start, (void*)HEAP_END);
Damien3f69aca2013-10-21 23:46:04 +0100804
Damiene9f1e502013-10-22 23:09:25 +0100805 // Micro Python init
Damienafe12bc2013-10-19 18:13:48 +0100806 qstr_init();
807 rt_init();
Damien00ff04f2013-10-19 14:40:54 +0100808
Damien39c6c592013-11-09 20:15:48 +0000809 // LCD init
Damien8fe84132013-11-30 15:06:24 +0000810 //lcd_init(); disabled while servos on PA0 PA1
Damien39c6c592013-11-09 20:15:48 +0000811
Damien0f654512013-10-23 20:39:20 +0100812 // servo
813 servo_init();
814
Damien1c62d042013-11-04 23:05:48 +0000815 // audio
Damien52851552013-12-11 00:40:15 +0000816 //audio_init();
Damien1c62d042013-11-04 23:05:48 +0000817
Damienbd8e1102013-11-06 23:04:33 +0000818 // timer
819 timer_init();
820
Damien39c6c592013-11-09 20:15:48 +0000821 // RNG
Damien8c3da5c2013-12-17 18:36:19 +0000822 if (1) {
Damien39c6c592013-11-09 20:15:48 +0000823 RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_RNG, ENABLE);
824 RNG_Cmd(ENABLE);
825 }
826
Damienf48cf672013-10-21 10:42:06 +0100827 // add some functions to the python namespace
Damiene9f1e502013-10-22 23:09:25 +0100828 {
Damien8c3da5c2013-12-17 18:36:19 +0000829 rt_store_name(qstr_from_str_static("help"), rt_make_function_0(pyb_help));
830
Damien George28708622014-01-02 21:30:26 +0000831 mp_obj_t m = mp_obj_new_module(qstr_from_str_static("pyb"));
Damiene9f1e502013-10-22 23:09:25 +0100832 rt_store_attr(m, qstr_from_str_static("info"), rt_make_function_0(pyb_info));
Damienb73085d2013-12-20 11:45:06 +0000833 rt_store_attr(m, qstr_from_str_static("sd_test"), rt_make_function_0(pyb_sd_test));
Damien52851552013-12-11 00:40:15 +0000834 rt_store_attr(m, qstr_from_str_static("stop"), rt_make_function_0(pyb_stop));
835 rt_store_attr(m, qstr_from_str_static("standby"), rt_make_function_0(pyb_standby));
Damiene9f1e502013-10-22 23:09:25 +0100836 rt_store_attr(m, qstr_from_str_static("source_dir"), rt_make_function_1(pyb_source_dir));
837 rt_store_attr(m, qstr_from_str_static("main"), rt_make_function_1(pyb_main));
Damien94186c82013-10-23 00:02:06 +0100838 rt_store_attr(m, qstr_from_str_static("sync"), rt_make_function_0(pyb_sync));
Damiene9f1e502013-10-22 23:09:25 +0100839 rt_store_attr(m, qstr_from_str_static("gc"), rt_make_function_0(pyb_gc));
840 rt_store_attr(m, qstr_from_str_static("delay"), rt_make_function_1(pyb_delay));
841 rt_store_attr(m, qstr_from_str_static("led"), rt_make_function_1(pyb_led));
Damien George823877b2014-01-05 14:04:55 +0000842 rt_store_attr(m, qstr_from_str_static("switch"), (mp_obj_t)&pyb_switch_obj);
Damien8fe84132013-11-30 15:06:24 +0000843 rt_store_attr(m, qstr_from_str_static("servo"), rt_make_function_2(pyb_servo_set));
Damien0c70f882013-11-03 18:30:57 +0000844 rt_store_attr(m, qstr_from_str_static("pwm"), rt_make_function_2(pyb_pwm_set));
Damien George28708622014-01-02 21:30:26 +0000845 rt_store_attr(m, qstr_from_str_static("accel"), (mp_obj_t)&pyb_mma_read_obj);
846 rt_store_attr(m, qstr_from_str_static("mma_read"), (mp_obj_t)&pyb_mma_read_all_obj);
847 rt_store_attr(m, qstr_from_str_static("mma_mode"), (mp_obj_t)&pyb_mma_write_mode_obj);
Damien58a1b4c2013-10-25 20:53:54 +0100848 rt_store_attr(m, qstr_from_str_static("hid"), rt_make_function_1(pyb_hid_send_report));
Damien81289412013-10-26 02:06:37 +0100849 rt_store_attr(m, qstr_from_str_static("time"), rt_make_function_0(pyb_rtc_read));
Damien8f7491a2013-10-26 18:01:48 +0100850 rt_store_attr(m, qstr_from_str_static("uout"), rt_make_function_1(pyb_usart_send));
851 rt_store_attr(m, qstr_from_str_static("uin"), rt_make_function_0(pyb_usart_receive));
852 rt_store_attr(m, qstr_from_str_static("ustat"), rt_make_function_0(pyb_usart_status));
Damien8c3da5c2013-12-17 18:36:19 +0000853 rt_store_attr(m, qstr_from_str_static("rand"), rt_make_function_0(pyb_rng_get));
Damiend6b4c662013-12-06 00:41:33 +0000854 rt_store_attr(m, qstr_from_str_static("Led"), rt_make_function_1(pyb_Led));
Damien52851552013-12-11 00:40:15 +0000855 rt_store_attr(m, qstr_from_str_static("Servo"), rt_make_function_1(pyb_Servo));
Hagen Kaye07590c22013-12-28 20:22:12 -0500856 rt_store_attr(m, qstr_from_str_static("I2C"), rt_make_function_2(pyb_I2C));
Damien George28708622014-01-02 21:30:26 +0000857 rt_store_attr(m, qstr_from_str_static("gpio"), (mp_obj_t)&pyb_gpio_obj);
Damiene9f1e502013-10-22 23:09:25 +0100858 rt_store_name(qstr_from_str_static("pyb"), m);
Damien0e496732013-11-03 14:53:34 +0000859
860 rt_store_name(qstr_from_str_static("open"), rt_make_function_2(pyb_io_open));
Damiene9f1e502013-10-22 23:09:25 +0100861 }
Damienf48cf672013-10-21 10:42:06 +0100862
Damiene9f1e502013-10-22 23:09:25 +0100863 // print a message to the LCD
864 lcd_print_str(" micro py board\n");
Damien00ff04f2013-10-19 14:40:54 +0100865
Damiend6b4c662013-12-06 00:41:33 +0000866 // check if user switch held (initiates reset of filesystem)
867 bool reset_filesystem = false;
Damien George823877b2014-01-05 14:04:55 +0000868 if (switch_get()) {
Damiend6b4c662013-12-06 00:41:33 +0000869 reset_filesystem = true;
870 for (int i = 0; i < 50; i++) {
Damien George823877b2014-01-05 14:04:55 +0000871 if (!switch_get()) {
Damiend6b4c662013-12-06 00:41:33 +0000872 reset_filesystem = false;
873 break;
874 }
875 sys_tick_delay_ms(10);
876 }
877 }
878
Damien00ff04f2013-10-19 14:40:54 +0100879 // local filesystem init
880 {
881 // try to mount the flash
882 FRESULT res = f_mount(&fatfs0, "0:", 1);
Damiend6b4c662013-12-06 00:41:33 +0000883 if (!reset_filesystem && res == FR_OK) {
Damien00ff04f2013-10-19 14:40:54 +0100884 // mount sucessful
Damiend6b4c662013-12-06 00:41:33 +0000885 } else if (reset_filesystem || res == FR_NO_FILESYSTEM) {
Damien00ff04f2013-10-19 14:40:54 +0100886 // no filesystem, so create a fresh one
Damiend6b4c662013-12-06 00:41:33 +0000887 // TODO doesn't seem to work correctly when reset_filesystem is true...
Damien00ff04f2013-10-19 14:40:54 +0100888
889 // LED on to indicate creation of LFS
890 led_state(PYB_LED_R2, 1);
891 uint32_t stc = sys_tick_counter;
892
893 res = f_mkfs("0:", 0, 0);
894 if (res == FR_OK) {
895 // success creating fresh LFS
896 } else {
897 __fatal_error("could not create LFS");
898 }
899
Damien8c3da5c2013-12-17 18:36:19 +0000900 // create src directory
901 res = f_mkdir("0:/src");
902 // ignore result from mkdir
903
904 // create empty main.py
905 FIL fp;
906 f_open(&fp, "0:/src/main.py", FA_WRITE | FA_CREATE_ALWAYS);
907 UINT n;
908 f_write(&fp, fresh_main_py, sizeof(fresh_main_py) - 1 /* don't count null terminator */, &n);
909 // TODO check we could write n bytes
910 f_close(&fp);
911
Damienafe12bc2013-10-19 18:13:48 +0100912 // keep LED on for at least 200ms
913 sys_tick_wait_at_least(stc, 200);
Damien00ff04f2013-10-19 14:40:54 +0100914 led_state(PYB_LED_R2, 0);
915 } else {
916 __fatal_error("could not access LFS");
Damien4a175e12013-10-17 22:50:21 +0100917 }
Damien00ff04f2013-10-19 14:40:54 +0100918 }
919
920 // make sure we have a /boot.py
921 {
922 FILINFO fno;
923 FRESULT res = f_stat("0:/boot.py", &fno);
924 if (res == FR_OK) {
925 if (fno.fattrib & AM_DIR) {
926 // exists as a directory
927 // TODO handle this case
928 // see http://elm-chan.org/fsw/ff/img/app2.c for a "rm -rf" implementation
929 } else {
930 // exists as a file, good!
931 }
932 } else {
933 // doesn't exist, create fresh file
934
935 // LED on to indicate creation of boot.py
936 led_state(PYB_LED_R2, 1);
937 uint32_t stc = sys_tick_counter;
938
939 FIL fp;
940 f_open(&fp, "0:/boot.py", FA_WRITE | FA_CREATE_ALWAYS);
941 UINT n;
Damiene9f1e502013-10-22 23:09:25 +0100942 f_write(&fp, fresh_boot_py, sizeof(fresh_boot_py) - 1 /* don't count null terminator */, &n);
Damien00ff04f2013-10-19 14:40:54 +0100943 // TODO check we could write n bytes
944 f_close(&fp);
945
Damienafe12bc2013-10-19 18:13:48 +0100946 // keep LED on for at least 200ms
947 sys_tick_wait_at_least(stc, 200);
Damien00ff04f2013-10-19 14:40:54 +0100948 led_state(PYB_LED_R2, 0);
949 }
950 }
951
Damien94186c82013-10-23 00:02:06 +0100952 // run /boot.py
953 if (!do_file("0:/boot.py")) {
954 flash_error(4);
955 }
956
Damiene9f1e502013-10-22 23:09:25 +0100957 // USB
958 usb_init();
959
Damien6f08f8c2013-10-23 22:17:26 +0100960 // MMA
Damienbd8e1102013-11-06 23:04:33 +0000961 if (first_soft_reset) {
Damien6f08f8c2013-10-23 22:17:26 +0100962 // init and reset address to zero
963 mma_init();
Damien6f08f8c2013-10-23 22:17:26 +0100964 }
965
Damien00ff04f2013-10-19 14:40:54 +0100966 // turn boot-up LED off
967 led_state(PYB_LED_G1, 0);
968
Damien94186c82013-10-23 00:02:06 +0100969 // run main script
970 {
971 vstr_t *vstr = vstr_new();
972 vstr_add_str(vstr, "0:/");
973 if (pyb_config_source_dir == 0) {
974 vstr_add_str(vstr, "src");
975 } else {
976 vstr_add_str(vstr, qstr_str(pyb_config_source_dir));
977 }
978 vstr_add_char(vstr, '/');
979 if (pyb_config_main == 0) {
980 vstr_add_str(vstr, "main.py");
981 } else {
982 vstr_add_str(vstr, qstr_str(pyb_config_main));
983 }
984 if (!do_file(vstr_str(vstr))) {
985 flash_error(3);
986 }
987 vstr_free(vstr);
988 }
989
Damien00ff04f2013-10-19 14:40:54 +0100990 //printf("init;al=%u\n", m_get_total_bytes_allocated()); // 1600, due to qstr_init
991 //sys_tick_delay_ms(1000);
992
Damiened656052013-10-13 00:42:20 +0100993 // Python!
Damien4b6e85c2013-10-21 09:56:56 +0100994 if (0) {
Damiened656052013-10-13 00:42:20 +0100995 //const char *pysrc = "def f():\n x=x+1\nprint(42)\n";
996 const char *pysrc =
997 // impl01.py
998 /*
999 "x = 0\n"
1000 "while x < 400:\n"
1001 " y = 0\n"
1002 " while y < 400:\n"
1003 " z = 0\n"
1004 " while z < 400:\n"
1005 " z = z + 1\n"
1006 " y = y + 1\n"
1007 " x = x + 1\n";
1008 */
1009 // impl02.py
Damien152568b2013-10-16 00:46:39 +01001010 /*
Damiened656052013-10-13 00:42:20 +01001011 "#@micropython.native\n"
1012 "def f():\n"
1013 " x = 0\n"
1014 " while x < 400:\n"
1015 " y = 0\n"
1016 " while y < 400:\n"
1017 " z = 0\n"
1018 " while z < 400:\n"
1019 " z = z + 1\n"
1020 " y = y + 1\n"
1021 " x = x + 1\n"
1022 "f()\n";
Damien152568b2013-10-16 00:46:39 +01001023 */
Damien0c5827f2013-10-22 21:13:36 +01001024 /*
Damiened656052013-10-13 00:42:20 +01001025 "print('in python!')\n"
1026 "x = 0\n"
1027 "while x < 4:\n"
1028 " pyb_led(True)\n"
1029 " pyb_delay(201)\n"
1030 " pyb_led(False)\n"
1031 " pyb_delay(201)\n"
Damienfa2162b2013-10-20 17:42:00 +01001032 " x += 1\n"
Damiened656052013-10-13 00:42:20 +01001033 "print('press me!')\n"
1034 "while True:\n"
1035 " pyb_led(pyb_sw())\n";
Damien0c5827f2013-10-22 21:13:36 +01001036 */
Damiened656052013-10-13 00:42:20 +01001037 /*
1038 // impl16.py
1039 "@micropython.asm_thumb\n"
1040 "def delay(r0):\n"
1041 " b(loop_entry)\n"
1042 " label(loop1)\n"
1043 " movw(r1, 55999)\n"
1044 " label(loop2)\n"
1045 " subs(r1, r1, 1)\n"
1046 " cmp(r1, 0)\n"
1047 " bgt(loop2)\n"
1048 " subs(r0, r0, 1)\n"
1049 " label(loop_entry)\n"
1050 " cmp(r0, 0)\n"
1051 " bgt(loop1)\n"
1052 "print('in python!')\n"
1053 "@micropython.native\n"
1054 "def flash(n):\n"
1055 " x = 0\n"
1056 " while x < n:\n"
1057 " pyb_led(True)\n"
1058 " delay(249)\n"
1059 " pyb_led(False)\n"
1060 " delay(249)\n"
1061 " x = x + 1\n"
1062 "flash(20)\n";
1063 */
Damien152568b2013-10-16 00:46:39 +01001064 // impl18.py
1065 /*
1066 "# basic exceptions\n"
1067 "x = 1\n"
1068 "try:\n"
1069 " x.a()\n"
1070 "except:\n"
1071 " print(x)\n";
1072 */
1073 // impl19.py
1074 "# for loop\n"
1075 "def f():\n"
1076 " for x in range(400):\n"
1077 " for y in range(400):\n"
1078 " for z in range(400):\n"
1079 " pass\n"
1080 "f()\n";
Damiened656052013-10-13 00:42:20 +01001081
Damiend99b0522013-12-21 18:17:45 +00001082 mp_lexer_str_buf_t mp_lexer_str_buf;
1083 mp_lexer_t *lex = mp_lexer_new_from_str_len("<stdin>", pysrc, strlen(pysrc), false, &mp_lexer_str_buf);
Damiened656052013-10-13 00:42:20 +01001084
Damienfa2162b2013-10-20 17:42:00 +01001085 // nalloc=1740;6340;6836 -> 140;4600;496 bytes for lexer, parser, compiler
1086 printf("lex; al=%u\n", m_get_total_bytes_allocated());
1087 sys_tick_delay_ms(1000);
Damiend99b0522013-12-21 18:17:45 +00001088 mp_parse_node_t pn = mp_parse(lex, MP_PARSE_FILE_INPUT);
1089 mp_lexer_free(lex);
1090 if (pn != MP_PARSE_NODE_NULL) {
Damiened656052013-10-13 00:42:20 +01001091 printf("pars;al=%u\n", m_get_total_bytes_allocated());
Damien00ff04f2013-10-19 14:40:54 +01001092 sys_tick_delay_ms(1000);
Damiened656052013-10-13 00:42:20 +01001093 //parse_node_show(pn, 0);
Damien George1fb03172014-01-03 14:22:03 +00001094 mp_obj_t module_fun = mp_compile(pn, false);
Damiened656052013-10-13 00:42:20 +01001095 printf("comp;al=%u\n", m_get_total_bytes_allocated());
Damien00ff04f2013-10-19 14:40:54 +01001096 sys_tick_delay_ms(1000);
Damiened656052013-10-13 00:42:20 +01001097
Damien George1fb03172014-01-03 14:22:03 +00001098 if (module_fun == mp_const_none) {
Damienfa2162b2013-10-20 17:42:00 +01001099 printf("compile error\n");
1100 } else {
Damiened656052013-10-13 00:42:20 +01001101 // execute it!
1102
Damien152568b2013-10-16 00:46:39 +01001103 // flash once
Damien995b8aa2013-10-18 23:44:05 +01001104 led_state(PYB_LED_G1, 1);
Damien00ff04f2013-10-19 14:40:54 +01001105 sys_tick_delay_ms(100);
Damien995b8aa2013-10-18 23:44:05 +01001106 led_state(PYB_LED_G1, 0);
Damiened656052013-10-13 00:42:20 +01001107
Damien152568b2013-10-16 00:46:39 +01001108 nlr_buf_t nlr;
1109 if (nlr_push(&nlr) == 0) {
Damiend99b0522013-12-21 18:17:45 +00001110 mp_obj_t ret = rt_call_function_0(module_fun);
Damien152568b2013-10-16 00:46:39 +01001111 printf("done! got: ");
Damiend99b0522013-12-21 18:17:45 +00001112 mp_obj_print(ret);
Damien152568b2013-10-16 00:46:39 +01001113 printf("\n");
1114 nlr_pop();
1115 } else {
1116 // uncaught exception
1117 printf("exception: ");
Damiend99b0522013-12-21 18:17:45 +00001118 mp_obj_print((mp_obj_t)nlr.ret_val);
Damien152568b2013-10-16 00:46:39 +01001119 printf("\n");
1120 }
1121
1122 // flash once
Damien995b8aa2013-10-18 23:44:05 +01001123 led_state(PYB_LED_G1, 1);
Damien00ff04f2013-10-19 14:40:54 +01001124 sys_tick_delay_ms(100);
Damien995b8aa2013-10-18 23:44:05 +01001125 led_state(PYB_LED_G1, 0);
Damien152568b2013-10-16 00:46:39 +01001126
Damien00ff04f2013-10-19 14:40:54 +01001127 sys_tick_delay_ms(1000);
Damiened656052013-10-13 00:42:20 +01001128 printf("nalloc=%u\n", m_get_total_bytes_allocated());
Damien00ff04f2013-10-19 14:40:54 +01001129 sys_tick_delay_ms(1000);
Damiened656052013-10-13 00:42:20 +01001130 }
1131 }
1132 }
Damiened656052013-10-13 00:42:20 +01001133
Damien58a1b4c2013-10-25 20:53:54 +01001134 // HID example
1135 if (0) {
1136 uint8_t data[4];
1137 data[0] = 0;
1138 data[1] = 1;
1139 data[2] = -2;
1140 data[3] = 0;
1141 for (;;) {
Damien George823877b2014-01-05 14:04:55 +00001142 if (switch_get()) {
Damien58a1b4c2013-10-25 20:53:54 +01001143 data[0] = 0x01; // 0x04 is middle, 0x02 is right
1144 } else {
1145 data[0] = 0x00;
1146 }
Damien George28708622014-01-02 21:30:26 +00001147 mma_start(0x4c /* MMA_ADDR */, 1);
Damien58a1b4c2013-10-25 20:53:54 +01001148 mma_send_byte(0);
Damien George28708622014-01-02 21:30:26 +00001149 mma_restart(0x4c /* MMA_ADDR */, 0);
Damien58a1b4c2013-10-25 20:53:54 +01001150 for (int i = 0; i <= 1; i++) {
1151 int v = mma_read_ack() & 0x3f;
1152 if (v & 0x20) {
1153 v |= ~0x1f;
1154 }
1155 data[1 + i] = v;
1156 }
1157 mma_read_nack();
1158 usb_hid_send_report(data);
1159 sys_tick_delay_ms(15);
1160 }
1161 }
1162
Damien065f8a52013-12-05 20:38:23 +00001163 // wifi
Damiend6b4c662013-12-06 00:41:33 +00001164 //pyb_wlan_init();
1165 //pyb_wlan_start();
Damien065f8a52013-12-05 20:38:23 +00001166
Damien4b6e85c2013-10-21 09:56:56 +01001167 do_repl();
1168
Damiened656052013-10-13 00:42:20 +01001169 // benchmark C version of impl02.py
1170 if (0) {
Damien995b8aa2013-10-18 23:44:05 +01001171 led_state(PYB_LED_G1, 1);
Damien00ff04f2013-10-19 14:40:54 +01001172 sys_tick_delay_ms(100);
Damien995b8aa2013-10-18 23:44:05 +01001173 led_state(PYB_LED_G1, 0);
Damiened656052013-10-13 00:42:20 +01001174 impl02_c_version();
Damien995b8aa2013-10-18 23:44:05 +01001175 led_state(PYB_LED_G1, 1);
Damien00ff04f2013-10-19 14:40:54 +01001176 sys_tick_delay_ms(100);
Damien995b8aa2013-10-18 23:44:05 +01001177 led_state(PYB_LED_G1, 0);
Damiened656052013-10-13 00:42:20 +01001178 }
1179
Damiened656052013-10-13 00:42:20 +01001180 // SD card testing
Damien8c3da5c2013-12-17 18:36:19 +00001181 if (0) {
Damien7ee80ba2013-10-24 00:22:27 +01001182 extern void sdio_init(void);
Damien8c3da5c2013-12-17 18:36:19 +00001183 sdio_init();
Damiened656052013-10-13 00:42:20 +01001184 }
1185
Damien94186c82013-10-23 00:02:06 +01001186 printf("PYB: sync filesystems\n");
1187 pyb_sync();
1188
1189 printf("PYB: soft reboot\n");
Damienbd8e1102013-11-06 23:04:33 +00001190
1191 first_soft_reset = false;
Damiene9f1e502013-10-22 23:09:25 +01001192 goto soft_reset;
Damiened656052013-10-13 00:42:20 +01001193}
Damienfecee2b2013-11-02 16:41:51 +00001194
1195double __aeabi_f2d(float x) {
1196 // TODO
1197 return 0.0;
1198}
Damien0e496732013-11-03 14:53:34 +00001199
1200float __aeabi_d2f(double x) {
1201 // TODO
1202 return 0.0;
1203}
1204
1205double sqrt(double x) {
1206 // TODO
1207 return 0.0;
1208}
Damien39c6c592013-11-09 20:15:48 +00001209
1210machine_float_t machine_sqrt(machine_float_t x) {
1211 // TODO
1212 return x;
1213}