blob: c49fa42ff9a8c82673a003197db225519ea4641a [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"
Dave Hylands9b7b9472014-01-07 09:49:42 -080022#include "lexerfatfs.h"
Damiend99b0522013-12-21 18:17:45 +000023#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"
mux35912852014-01-14 19:57:51 +020043#include "adc.h"
Damien065f8a52013-12-05 20:38:23 +000044
45int errno;
Damiened656052013-10-13 00:42:20 +010046
Damien3f69aca2013-10-21 23:46:04 +010047extern uint32_t _heap_start;
48
Damien8fe84132013-11-30 15:06:24 +000049static FATFS fatfs0;
50
Damien94186c82013-10-23 00:02:06 +010051void flash_error(int n) {
52 for (int i = 0; i < n; i++) {
53 led_state(PYB_LED_R1, 1);
54 led_state(PYB_LED_R2, 0);
55 sys_tick_delay_ms(250);
56 led_state(PYB_LED_R1, 0);
57 led_state(PYB_LED_R2, 1);
58 sys_tick_delay_ms(250);
59 }
60 led_state(PYB_LED_R2, 0);
61}
62
Damien0f654512013-10-23 20:39:20 +010063static void impl02_c_version(void) {
Damiened656052013-10-13 00:42:20 +010064 int x = 0;
65 while (x < 400) {
66 int y = 0;
67 while (y < 400) {
68 volatile int z = 0;
69 while (z < 400) {
70 z = z + 1;
71 }
72 y = y + 1;
73 }
74 x = x + 1;
75 }
76}
77
Damiened656052013-10-13 00:42:20 +010078void __fatal_error(const char *msg) {
79 lcd_print_strn("\nFATAL ERROR:\n", 14);
80 lcd_print_strn(msg, strlen(msg));
Damiened656052013-10-13 00:42:20 +010081 for (;;) {
Damien94186c82013-10-23 00:02:06 +010082 flash_error(1);
Damiened656052013-10-13 00:42:20 +010083 }
84}
85
Damien94186c82013-10-23 00:02:06 +010086static qstr pyb_config_source_dir = 0;
87static qstr pyb_config_main = 0;
88
Damiend99b0522013-12-21 18:17:45 +000089mp_obj_t pyb_source_dir(mp_obj_t source_dir) {
90 pyb_config_source_dir = mp_obj_get_qstr(source_dir);
91 return mp_const_none;
Damiene9f1e502013-10-22 23:09:25 +010092}
93
Damiend99b0522013-12-21 18:17:45 +000094mp_obj_t pyb_main(mp_obj_t main) {
95 pyb_config_main = mp_obj_get_qstr(main);
96 return mp_const_none;
Damien94186c82013-10-23 00:02:06 +010097}
98
99// sync all file systems
Damiend99b0522013-12-21 18:17:45 +0000100mp_obj_t pyb_sync(void) {
Damien94186c82013-10-23 00:02:06 +0100101 storage_flush();
Damiend99b0522013-12-21 18:17:45 +0000102 return mp_const_none;
Damiene9f1e502013-10-22 23:09:25 +0100103}
Damiened656052013-10-13 00:42:20 +0100104
Damiend99b0522013-12-21 18:17:45 +0000105mp_obj_t pyb_delay(mp_obj_t count) {
106 sys_tick_delay_ms(mp_obj_get_int(count));
107 return mp_const_none;
Damiened656052013-10-13 00:42:20 +0100108}
109
Damiend99b0522013-12-21 18:17:45 +0000110mp_obj_t pyb_led(mp_obj_t state) {
Damien995b8aa2013-10-18 23:44:05 +0100111 led_state(PYB_LED_G1, rt_is_true(state));
Damiened656052013-10-13 00:42:20 +0100112 return state;
113}
114
Damien4a175e12013-10-17 22:50:21 +0100115/*
Damien152568b2013-10-16 00:46:39 +0100116void g(uint i) {
117 printf("g:%d\n", i);
118 if (i & 1) {
119 nlr_jump((void*)(42 + i));
120 }
121}
Damien0f654512013-10-23 20:39:20 +0100122void f(void) {
Damien152568b2013-10-16 00:46:39 +0100123 nlr_buf_t nlr;
124 int i;
125 for (i = 0; i < 4; i++) {
126 printf("f:loop:%d:%p\n", i, &nlr);
127 if (nlr_push(&nlr) == 0) {
128 // normal
129 //printf("a:%p:%p %p %p %u\n", &nlr, nlr.ip, nlr.sp, nlr.prev, nlr.ret_val);
130 g(i);
131 printf("f:lp:%d:nrm\n", i);
132 nlr_pop();
133 } else {
134 // nlr
135 //printf("b:%p:%p %p %p %u\n", &nlr, nlr.ip, nlr.sp, nlr.prev, nlr.ret_val);
136 printf("f:lp:%d:nlr:%d\n", i, (int)nlr.ret_val);
137 }
138 }
139}
Damien0f654512013-10-23 20:39:20 +0100140void nlr_test(void) {
Damien152568b2013-10-16 00:46:39 +0100141 f(1);
142}
Damien4a175e12013-10-17 22:50:21 +0100143*/
144
Damien0f654512013-10-23 20:39:20 +0100145void fatality(void) {
Damien00ff04f2013-10-19 14:40:54 +0100146 led_state(PYB_LED_R1, 1);
147 led_state(PYB_LED_G1, 1);
148 led_state(PYB_LED_R2, 1);
149 led_state(PYB_LED_G2, 1);
150}
Damiened656052013-10-13 00:42:20 +0100151
Damienafe12bc2013-10-19 18:13:48 +0100152static const char fresh_boot_py[] =
Damien00ff04f2013-10-19 14:40:54 +0100153"# boot.py -- run on boot-up\n"
154"# can run arbitrary Python, but best to keep it minimal\n"
155"\n"
156"pyb.source_dir('/src')\n"
157"pyb.main('main.py')\n"
158"#pyb.usb_usr('VCP')\n"
159"#pyb.usb_msd(True, 'dual partition')\n"
160"#pyb.flush_cache(False)\n"
161"#pyb.error_log('error.txt')\n"
162;
Damiened656052013-10-13 00:42:20 +0100163
Damien8c3da5c2013-12-17 18:36:19 +0000164static const char fresh_main_py[] =
165"# main.py -- put your code here!\n"
166;
167
168static const char *help_text =
169"Welcome to Micro Python!\n\n"
170"This is a *very* early version of Micro Python and has minimal functionality.\n\n"
171"Specific commands for the board:\n"
172" pyb.info() -- print some general information\n"
173" pyb.gc() -- run the garbage collector\n"
174" pyb.delay(<n>) -- wait for n milliseconds\n"
175" pyb.Led(<n>) -- create Led object for LED n (n=1,2)\n"
176" Led methods: on(), off()\n"
177" pyb.Servo(<n>) -- create Servo object for servo n (n=1,2,3,4)\n"
178" Servo methods: angle(<x>)\n"
179" pyb.switch() -- return True/False if switch pressed or not\n"
180" pyb.accel() -- get accelerometer values\n"
181" pyb.rand() -- get a 16-bit random number\n"
182;
183
184// get some help about available functions
Damiend99b0522013-12-21 18:17:45 +0000185static mp_obj_t pyb_help(void) {
Damien8c3da5c2013-12-17 18:36:19 +0000186 printf("%s", help_text);
Damiend99b0522013-12-21 18:17:45 +0000187 return mp_const_none;
Damien8c3da5c2013-12-17 18:36:19 +0000188}
189
Damien00ff04f2013-10-19 14:40:54 +0100190// get lots of info about the board
Damiend99b0522013-12-21 18:17:45 +0000191static mp_obj_t pyb_info(void) {
Damien8c3da5c2013-12-17 18:36:19 +0000192 // get and print unique id; 96 bits
193 {
194 byte *id = (byte*)0x1fff7a10;
195 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]);
196 }
197
Damiened656052013-10-13 00:42:20 +0100198 // get and print clock speeds
199 // SYSCLK=168MHz, HCLK=168MHz, PCLK1=42MHz, PCLK2=84MHz
Damiened656052013-10-13 00:42:20 +0100200 {
201 RCC_ClocksTypeDef rcc_clocks;
202 RCC_GetClocksFreq(&rcc_clocks);
Damien00ff04f2013-10-19 14:40:54 +0100203 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 +0100204 }
205
Damien995b8aa2013-10-18 23:44:05 +0100206 // to print info about memory
Damien00ff04f2013-10-19 14:40:54 +0100207 {
Damien4a175e12013-10-17 22:50:21 +0100208 extern void *_sidata;
209 extern void *_sdata;
210 extern void *_edata;
211 extern void *_sbss;
212 extern void *_ebss;
213 extern void *_estack;
214 extern void *_etext;
Damien00ff04f2013-10-19 14:40:54 +0100215 printf("_sidata=%p\n", &_sidata);
216 printf("_sdata=%p\n", &_sdata);
217 printf("_edata=%p\n", &_edata);
218 printf("_sbss=%p\n", &_sbss);
219 printf("_ebss=%p\n", &_ebss);
220 printf("_estack=%p\n", &_estack);
221 printf("_etext=%p\n", &_etext);
222 printf("_heap_start=%p\n", &_heap_start);
223 }
224
Damien94186c82013-10-23 00:02:06 +0100225 // GC info
226 {
227 gc_info_t info;
228 gc_info(&info);
229 printf("GC:\n");
230 printf(" %lu total\n", info.total);
231 printf(" %lu : %lu\n", info.used, info.free);
232 printf(" 1=%lu 2=%lu m=%lu\n", info.num_1block, info.num_2block, info.max_block);
233 }
234
Damien00ff04f2013-10-19 14:40:54 +0100235 // free space on flash
236 {
237 DWORD nclst;
238 FATFS *fatfs;
239 f_getfree("0:", &nclst, &fatfs);
Damien94186c82013-10-23 00:02:06 +0100240 printf("LFS free: %u bytes\n", (uint)(nclst * fatfs->csize * 512));
Damien00ff04f2013-10-19 14:40:54 +0100241 }
Damien00ff04f2013-10-19 14:40:54 +0100242
Damiend99b0522013-12-21 18:17:45 +0000243 return mp_const_none;
Damien4b6e85c2013-10-21 09:56:56 +0100244}
245
Damienb73085d2013-12-20 11:45:06 +0000246// SD card test
Damiend99b0522013-12-21 18:17:45 +0000247static mp_obj_t pyb_sd_test(void) {
Damienb73085d2013-12-20 11:45:06 +0000248 extern void sdio_init(void);
249 sdio_init();
Damiend99b0522013-12-21 18:17:45 +0000250 return mp_const_none;
Damienb73085d2013-12-20 11:45:06 +0000251}
252
Damien52851552013-12-11 00:40:15 +0000253static void SYSCLKConfig_STOP(void) {
254 /* After wake-up from STOP reconfigure the system clock */
255 /* Enable HSE */
256 RCC_HSEConfig(RCC_HSE_ON);
257
258 /* Wait till HSE is ready */
259 while (RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET) {
260 }
261
262 /* Enable PLL */
263 RCC_PLLCmd(ENABLE);
264
265 /* Wait till PLL is ready */
266 while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET) {
267 }
268
269 /* Select PLL as system clock source */
270 RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
271
272 /* Wait till PLL is used as system clock source */
273 while (RCC_GetSYSCLKSource() != 0x08) {
274 }
275}
276
Damiend99b0522013-12-21 18:17:45 +0000277static mp_obj_t pyb_stop(void) {
Damien52851552013-12-11 00:40:15 +0000278 PWR_EnterSTANDBYMode();
279 //PWR_FlashPowerDownCmd(ENABLE); don't know what the logic is with this
280
281 /* Enter Stop Mode */
282 PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI);
283
284 /* Configures system clock after wake-up from STOP: enable HSE, PLL and select
285 * PLL as system clock source (HSE and PLL are disabled in STOP mode) */
286 SYSCLKConfig_STOP();
287
288 //PWR_FlashPowerDownCmd(DISABLE);
289
Damiend99b0522013-12-21 18:17:45 +0000290 return mp_const_none;
Damien52851552013-12-11 00:40:15 +0000291}
292
Damiend99b0522013-12-21 18:17:45 +0000293static mp_obj_t pyb_standby(void) {
Damien52851552013-12-11 00:40:15 +0000294 PWR_EnterSTANDBYMode();
Damiend99b0522013-12-21 18:17:45 +0000295 return mp_const_none;
Damien52851552013-12-11 00:40:15 +0000296}
297
Damien9281cd62013-10-26 02:29:02 +0100298char *strdup(const char *str) {
299 uint32_t len = strlen(str);
300 char *s2 = m_new(char, len + 1);
301 memcpy(s2, str, len);
302 s2[len] = 0;
303 return s2;
304}
305
306#define READLINE_HIST_SIZE (8)
307
308static const char *readline_hist[READLINE_HIST_SIZE] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
309
Damien8f7491a2013-10-26 18:01:48 +0100310void stdout_tx_str(const char *str) {
Damien George328708e2014-01-13 00:20:06 +0000311 if (pyb_usart_global_debug != PYB_USART_NONE) {
312 usart_tx_str(pyb_usart_global_debug, str);
313 }
Damien8f7491a2013-10-26 18:01:48 +0100314 usb_vcp_send_str(str);
315}
316
Damiene9f1e502013-10-22 23:09:25 +0100317int readline(vstr_t *line, const char *prompt) {
Damien8f7491a2013-10-26 18:01:48 +0100318 stdout_tx_str(prompt);
Damiene9f1e502013-10-22 23:09:25 +0100319 int len = vstr_len(line);
Damien9281cd62013-10-26 02:29:02 +0100320 int escape = 0;
321 int hist_num = 0;
Damiene9f1e502013-10-22 23:09:25 +0100322 for (;;) {
Damien8f7491a2013-10-26 18:01:48 +0100323 char c;
324 for (;;) {
325 if (usb_vcp_rx_any() != 0) {
326 c = usb_vcp_rx_get();
327 break;
Damien George328708e2014-01-13 00:20:06 +0000328 } else if (pyb_usart_global_debug != PYB_USART_NONE && usart_rx_any(pyb_usart_global_debug)) {
329 c = usart_rx_char(pyb_usart_global_debug);
Damien8f7491a2013-10-26 18:01:48 +0100330 break;
Damien George328708e2014-01-13 00:20:06 +0000331 }
Damien9281cd62013-10-26 02:29:02 +0100332 sys_tick_delay_ms(1);
Damien52851552013-12-11 00:40:15 +0000333 if (storage_needs_flush()) {
334 storage_flush();
335 }
Damiene9f1e502013-10-22 23:09:25 +0100336 }
Damien9281cd62013-10-26 02:29:02 +0100337 if (escape == 0) {
338 if (c == 4 && vstr_len(line) == len) {
339 return 0;
340 } else if (c == '\r') {
Damien8f7491a2013-10-26 18:01:48 +0100341 stdout_tx_str("\r\n");
Damien9281cd62013-10-26 02:29:02 +0100342 for (int i = READLINE_HIST_SIZE - 1; i > 0; i--) {
343 readline_hist[i] = readline_hist[i - 1];
344 }
345 readline_hist[0] = strdup(vstr_str(line));
346 return 1;
347 } else if (c == 27) {
348 escape = true;
349 } else if (c == 127) {
350 if (vstr_len(line) > len) {
351 vstr_cut_tail(line, 1);
Damien8f7491a2013-10-26 18:01:48 +0100352 stdout_tx_str("\b \b");
Damien9281cd62013-10-26 02:29:02 +0100353 }
354 } else if (32 <= c && c <= 126) {
355 vstr_add_char(line, c);
Damien8f7491a2013-10-26 18:01:48 +0100356 stdout_tx_str(line->buf + line->len - 1);
Damiene9f1e502013-10-22 23:09:25 +0100357 }
Damien9281cd62013-10-26 02:29:02 +0100358 } else if (escape == 1) {
359 if (c == '[') {
360 escape = 2;
361 } else {
362 escape = 0;
363 }
364 } else if (escape == 2) {
365 escape = 0;
366 if (c == 'A') {
367 // up arrow
368 if (hist_num < READLINE_HIST_SIZE && readline_hist[hist_num] != NULL) {
369 // erase line
370 for (int i = line->len - len; i > 0; i--) {
Damien8f7491a2013-10-26 18:01:48 +0100371 stdout_tx_str("\b \b");
Damien9281cd62013-10-26 02:29:02 +0100372 }
373 // set line to history
374 line->len = len;
375 vstr_add_str(line, readline_hist[hist_num]);
376 // draw line
Damien8f7491a2013-10-26 18:01:48 +0100377 stdout_tx_str(readline_hist[hist_num]);
Damien9281cd62013-10-26 02:29:02 +0100378 // increase hist num
379 hist_num += 1;
380 }
381 }
382 } else {
383 escape = 0;
Damiene9f1e502013-10-22 23:09:25 +0100384 }
Damien9281cd62013-10-26 02:29:02 +0100385 sys_tick_delay_ms(10);
Damiene9f1e502013-10-22 23:09:25 +0100386 }
387}
388
Damien0f654512013-10-23 20:39:20 +0100389void do_repl(void) {
Damien George28708622014-01-02 21:30:26 +0000390 stdout_tx_str("Micro Python build <git hash> on 2/1/2014; PYBv3 with STM32F405RG\r\n");
Damien8c3da5c2013-12-17 18:36:19 +0000391 stdout_tx_str("Type \"help()\" for more information.\r\n");
Damiene9f1e502013-10-22 23:09:25 +0100392
393 vstr_t line;
Paul Sokolovsky5d2499c2014-01-13 23:15:23 +0200394 vstr_init(&line, 32);
Damien4b6e85c2013-10-21 09:56:56 +0100395
396 for (;;) {
Damiene9f1e502013-10-22 23:09:25 +0100397 vstr_reset(&line);
398 int ret = readline(&line, ">>> ");
399 if (ret == 0) {
Damien4b6e85c2013-10-21 09:56:56 +0100400 // EOF
Damiene9f1e502013-10-22 23:09:25 +0100401 break;
Damien4b6e85c2013-10-21 09:56:56 +0100402 }
Damiene9f1e502013-10-22 23:09:25 +0100403
404 if (vstr_len(&line) == 0) {
405 continue;
406 }
407
Damiend99b0522013-12-21 18:17:45 +0000408 if (mp_repl_is_compound_stmt(vstr_str(&line))) {
Damien4b6e85c2013-10-21 09:56:56 +0100409 for (;;) {
Damiene9f1e502013-10-22 23:09:25 +0100410 vstr_add_char(&line, '\n');
411 int len = vstr_len(&line);
412 int ret = readline(&line, "... ");
413 if (ret == 0 || vstr_len(&line) == len) {
414 // done entering compound statement
Damien4b6e85c2013-10-21 09:56:56 +0100415 break;
416 }
Damien4b6e85c2013-10-21 09:56:56 +0100417 }
418 }
Damien4b6e85c2013-10-21 09:56:56 +0100419
Damien George9193f892014-01-08 15:28:26 +0000420 mp_lexer_t *lex = mp_lexer_new_from_str_len("<stdin>", vstr_str(&line), vstr_len(&line), 0);
Damien George9528cd62014-01-15 21:23:31 +0000421 qstr parse_exc_id;
422 const char *parse_exc_msg;
423 mp_parse_node_t pn = mp_parse(lex, MP_PARSE_SINGLE_INPUT, &parse_exc_id, &parse_exc_msg);
Damien George08335002014-01-18 23:24:36 +0000424 qstr source_name = mp_lexer_source_name(lex);
Damien4b6e85c2013-10-21 09:56:56 +0100425
Damien George9528cd62014-01-15 21:23:31 +0000426 if (pn == MP_PARSE_NODE_NULL) {
427 // parse error
428 mp_lexer_show_error_pythonic_prefix(lex);
429 printf("%s: %s\n", qstr_str(parse_exc_id), parse_exc_msg);
430 mp_lexer_free(lex);
431 } else {
432 // parse okay
433 mp_lexer_free(lex);
Damien George08335002014-01-18 23:24:36 +0000434 mp_obj_t module_fun = mp_compile(pn, source_name, true);
Damien George1fb03172014-01-03 14:22:03 +0000435 if (module_fun != mp_const_none) {
436 nlr_buf_t nlr;
437 uint32_t start = sys_tick_counter;
438 if (nlr_push(&nlr) == 0) {
439 rt_call_function_0(module_fun);
440 nlr_pop();
441 // optional timing
442 if (0) {
443 uint32_t ticks = sys_tick_counter - start; // TODO implement a function that does this properly
444 printf("(took %lu ms)\n", ticks);
Damien4b6e85c2013-10-21 09:56:56 +0100445 }
Damien George1fb03172014-01-03 14:22:03 +0000446 } else {
447 // uncaught exception
Paul Sokolovsky76d982e2014-01-13 19:19:16 +0200448 mp_obj_print((mp_obj_t)nlr.ret_val, PRINT_REPR);
Damien George1fb03172014-01-03 14:22:03 +0000449 printf("\n");
Damien4b6e85c2013-10-21 09:56:56 +0100450 }
451 }
452 }
453 }
Damiene9f1e502013-10-22 23:09:25 +0100454
Damien8f7491a2013-10-26 18:01:48 +0100455 stdout_tx_str("\r\n");
Damien94186c82013-10-23 00:02:06 +0100456}
457
458bool do_file(const char *filename) {
Damien George8161a102014-01-16 22:09:13 +0000459 mp_lexer_t *lex = mp_lexer_new_from_file(filename);
Damien94186c82013-10-23 00:02:06 +0100460
461 if (lex == NULL) {
462 printf("could not open file '%s' for reading\n", filename);
463 return false;
464 }
465
Damien George9528cd62014-01-15 21:23:31 +0000466 qstr parse_exc_id;
467 const char *parse_exc_msg;
468 mp_parse_node_t pn = mp_parse(lex, MP_PARSE_FILE_INPUT, &parse_exc_id, &parse_exc_msg);
Damien George08335002014-01-18 23:24:36 +0000469 qstr source_name = mp_lexer_source_name(lex);
Damien94186c82013-10-23 00:02:06 +0100470
Damiend99b0522013-12-21 18:17:45 +0000471 if (pn == MP_PARSE_NODE_NULL) {
Damien George9528cd62014-01-15 21:23:31 +0000472 // parse error
473 mp_lexer_show_error_pythonic_prefix(lex);
474 printf("%s: %s\n", qstr_str(parse_exc_id), parse_exc_msg);
475 mp_lexer_free(lex);
Damien94186c82013-10-23 00:02:06 +0100476 return false;
477 }
478
Damien George9528cd62014-01-15 21:23:31 +0000479 mp_lexer_free(lex);
480
Damien George08335002014-01-18 23:24:36 +0000481 mp_obj_t module_fun = mp_compile(pn, source_name, false);
Damiend99b0522013-12-21 18:17:45 +0000482 if (module_fun == mp_const_none) {
Damien94186c82013-10-23 00:02:06 +0100483 return false;
484 }
485
486 nlr_buf_t nlr;
487 if (nlr_push(&nlr) == 0) {
488 rt_call_function_0(module_fun);
489 nlr_pop();
490 return true;
491 } else {
492 // uncaught exception
Paul Sokolovsky76d982e2014-01-13 19:19:16 +0200493 mp_obj_print((mp_obj_t)nlr.ret_val, PRINT_REPR);
Damien94186c82013-10-23 00:02:06 +0100494 printf("\n");
495 return false;
496 }
Damien4b6e85c2013-10-21 09:56:56 +0100497}
498
Damien0c5827f2013-10-22 21:13:36 +0100499#define RAM_START (0x20000000) // fixed for chip
500#define HEAP_END (0x2001c000) // tunable
501#define RAM_END (0x20020000) // fixed for chip
502
503void gc_helper_get_regs_and_clean_stack(machine_uint_t *regs, machine_uint_t heap_end);
504
Damien0f654512013-10-23 20:39:20 +0100505void gc_collect(void) {
Damien0c5827f2013-10-22 21:13:36 +0100506 uint32_t start = sys_tick_counter;
Damien3f69aca2013-10-21 23:46:04 +0100507 gc_collect_start();
Damien0c5827f2013-10-22 21:13:36 +0100508 gc_collect_root((void**)RAM_START, (((uint32_t)&_heap_start) - RAM_START) / 4);
509 machine_uint_t regs[10];
510 gc_helper_get_regs_and_clean_stack(regs, HEAP_END);
511 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 +0100512 gc_collect_end();
Damien0c5827f2013-10-22 21:13:36 +0100513 uint32_t ticks = sys_tick_counter - start; // TODO implement a function that does this properly
Damien8c3da5c2013-12-17 18:36:19 +0000514
515 if (0) {
516 // print GC info
517 gc_info_t info;
518 gc_info(&info);
519 printf("GC@%lu %lums\n", start, ticks);
520 printf(" %lu total\n", info.total);
521 printf(" %lu : %lu\n", info.used, info.free);
522 printf(" 1=%lu 2=%lu m=%lu\n", info.num_1block, info.num_2block, info.max_block);
523 }
Damien0c5827f2013-10-22 21:13:36 +0100524}
525
Damiend99b0522013-12-21 18:17:45 +0000526mp_obj_t pyb_gc(void) {
Damien0c5827f2013-10-22 21:13:36 +0100527 gc_collect();
Damiend99b0522013-12-21 18:17:45 +0000528 return mp_const_none;
Damien0c70f882013-11-03 18:30:57 +0000529}
530
Damien George28708622014-01-02 21:30:26 +0000531mp_obj_t pyb_gpio(int n_args, mp_obj_t *args) {
532 //assert(1 <= n_args && n_args <= 2);
Damien6f08f8c2013-10-23 22:17:26 +0100533
Damien George28708622014-01-02 21:30:26 +0000534 const char *pin_name = qstr_str(mp_obj_get_qstr(args[0]));
535 GPIO_TypeDef *port;
536 switch (pin_name[0]) {
537 case 'A': case 'a': port = GPIOA; break;
538 case 'B': case 'b': port = GPIOB; break;
539 case 'C': case 'c': port = GPIOC; break;
540 default: goto pin_error;
Damien8fe84132013-11-30 15:06:24 +0000541 }
Damien George28708622014-01-02 21:30:26 +0000542 uint pin_num = 0;
543 for (const char *s = pin_name + 1; *s; s++) {
544 if (!('0' <= *s && *s <= '9')) {
545 goto pin_error;
Damien6f08f8c2013-10-23 22:17:26 +0100546 }
Damien George28708622014-01-02 21:30:26 +0000547 pin_num = 10 * pin_num + *s - '0';
Damien6f08f8c2013-10-23 22:17:26 +0100548 }
Damien George28708622014-01-02 21:30:26 +0000549 if (!(0 <= pin_num && pin_num <= 15)) {
550 goto pin_error;
551 }
Damien8fe84132013-11-30 15:06:24 +0000552
Damien George28708622014-01-02 21:30:26 +0000553 if (n_args == 1) {
554 // get pin
555 if ((port->IDR & (1 << pin_num)) != (uint32_t)Bit_RESET) {
556 return MP_OBJ_NEW_SMALL_INT(1);
557 } else {
558 return MP_OBJ_NEW_SMALL_INT(0);
559 }
560 } else {
561 // set pin
562 if (rt_is_true(args[1])) {
563 // set pin high
564 port->BSRRL = 1 << pin_num;
565 } else {
566 // set pin low
567 port->BSRRH = 1 << pin_num;
568 }
569 return mp_const_none;
570 }
Damien8fe84132013-11-30 15:06:24 +0000571
Damien George28708622014-01-02 21:30:26 +0000572pin_error:
Damien Georgeeb7bfcb2014-01-04 15:57:35 +0000573 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 +0100574}
575
Damien George28708622014-01-02 21:30:26 +0000576MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_gpio_obj, 1, 2, pyb_gpio);
577
Damiend99b0522013-12-21 18:17:45 +0000578mp_obj_t pyb_hid_send_report(mp_obj_t arg) {
579 mp_obj_t *items = mp_obj_get_array_fixed_n(arg, 4);
Damien58a1b4c2013-10-25 20:53:54 +0100580 uint8_t data[4];
Damiend99b0522013-12-21 18:17:45 +0000581 data[0] = mp_obj_get_int(items[0]);
582 data[1] = mp_obj_get_int(items[1]);
583 data[2] = mp_obj_get_int(items[2]);
584 data[3] = mp_obj_get_int(items[3]);
Damien58a1b4c2013-10-25 20:53:54 +0100585 usb_hid_send_report(data);
Damiend99b0522013-12-21 18:17:45 +0000586 return mp_const_none;
Damien58a1b4c2013-10-25 20:53:54 +0100587}
588
Damien81289412013-10-26 02:06:37 +0100589static void rtc_init(void) {
mux5df3d472014-01-08 11:26:18 +0200590 uint32_t rtc_clksrc;
591 uint32_t timeout =10000;
592
Damien81289412013-10-26 02:06:37 +0100593 /* Enable the PWR clock */
594 RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
595
596 /* Allow access to RTC */
597 PWR_BackupAccessCmd(ENABLE);
598
599 /* Enable the LSE OSC */
600 RCC_LSEConfig(RCC_LSE_ON);
601
602 /* Wait till LSE is ready */
mux5df3d472014-01-08 11:26:18 +0200603 while((RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET) && (--timeout > 0)) {
604 }
605
606 /* If LSE timed out, use LSI instead */
607 if (timeout == 0) {
608 /* Enable the LSI OSC */
609 RCC_LSICmd(ENABLE);
610
611 /* Wait till LSI is ready */
612 while(RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET) {
613 }
614
615 /* Use LSI as the RTC Clock Source */
616 rtc_clksrc = RCC_RTCCLKSource_LSI;
617 } else {
618 /* Use LSE as the RTC Clock Source */
619 rtc_clksrc = RCC_RTCCLKSource_LSE;
Damien81289412013-10-26 02:06:37 +0100620 }
621
622 /* Select the RTC Clock Source */
mux5df3d472014-01-08 11:26:18 +0200623 RCC_RTCCLKConfig(rtc_clksrc);
624
625 /* Note: LSI is around (32KHz), these dividers should work either way */
Damien81289412013-10-26 02:06:37 +0100626 /* ck_spre(1Hz) = RTCCLK(LSE) /(uwAsynchPrediv + 1)*(uwSynchPrediv + 1)*/
627 uint32_t uwSynchPrediv = 0xFF;
628 uint32_t uwAsynchPrediv = 0x7F;
629
630 /* Enable the RTC Clock */
631 RCC_RTCCLKCmd(ENABLE);
632
633 /* Wait for RTC APB registers synchronisation */
634 RTC_WaitForSynchro();
635
636 /* Configure the RTC data register and RTC prescaler */
637 RTC_InitTypeDef RTC_InitStructure;
638 RTC_InitStructure.RTC_AsynchPrediv = uwAsynchPrediv;
639 RTC_InitStructure.RTC_SynchPrediv = uwSynchPrediv;
640 RTC_InitStructure.RTC_HourFormat = RTC_HourFormat_24;
641 RTC_Init(&RTC_InitStructure);
642
643 // Set the date (BCD)
644 RTC_DateTypeDef RTC_DateStructure;
645 RTC_DateStructure.RTC_Year = 0x13;
646 RTC_DateStructure.RTC_Month = RTC_Month_October;
647 RTC_DateStructure.RTC_Date = 0x26;
648 RTC_DateStructure.RTC_WeekDay = RTC_Weekday_Saturday;
649 RTC_SetDate(RTC_Format_BCD, &RTC_DateStructure);
650
651 // Set the time (BCD)
652 RTC_TimeTypeDef RTC_TimeStructure;
653 RTC_TimeStructure.RTC_H12 = RTC_H12_AM;
654 RTC_TimeStructure.RTC_Hours = 0x01;
655 RTC_TimeStructure.RTC_Minutes = 0x53;
656 RTC_TimeStructure.RTC_Seconds = 0x00;
657 RTC_SetTime(RTC_Format_BCD, &RTC_TimeStructure);
658
659 // Indicator for the RTC configuration
660 //RTC_WriteBackupRegister(RTC_BKP_DR0, 0x32F2);
661}
662
Damiend99b0522013-12-21 18:17:45 +0000663mp_obj_t pyb_rtc_read(void) {
Damien81289412013-10-26 02:06:37 +0100664 RTC_TimeTypeDef RTC_TimeStructure;
665 RTC_GetTime(RTC_Format_BIN, &RTC_TimeStructure);
666 printf("%02d:%02d:%02d\n", RTC_TimeStructure.RTC_Hours, RTC_TimeStructure.RTC_Minutes, RTC_TimeStructure.RTC_Seconds);
Damiend99b0522013-12-21 18:17:45 +0000667 return mp_const_none;
Damien81289412013-10-26 02:06:37 +0100668}
669
Damiend99b0522013-12-21 18:17:45 +0000670typedef struct _pyb_file_obj_t {
671 mp_obj_base_t base;
672 FIL fp;
673} pyb_file_obj_t;
674
Paul Sokolovsky76d982e2014-01-13 19:19:16 +0200675void file_obj_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in, mp_print_kind_t kind) {
Damiend99b0522013-12-21 18:17:45 +0000676 printf("<file %p>", self_in);
Damien0e496732013-11-03 14:53:34 +0000677}
678
Damiend99b0522013-12-21 18:17:45 +0000679mp_obj_t file_obj_read(mp_obj_t self_in, mp_obj_t arg) {
680 pyb_file_obj_t *self = self_in;
681 int n = mp_obj_get_int(arg);
Damien0e496732013-11-03 14:53:34 +0000682 char *buf = m_new(char, n + 1);
683 UINT n_out;
Damiend99b0522013-12-21 18:17:45 +0000684 f_read(&self->fp, buf, n, &n_out);
Damien0e496732013-11-03 14:53:34 +0000685 buf[n_out] = 0;
Damien732407f2013-12-29 19:33:23 +0000686 return mp_obj_new_str(qstr_from_str_take(buf, n + 1));
Damien0e496732013-11-03 14:53:34 +0000687}
688
Damiend99b0522013-12-21 18:17:45 +0000689mp_obj_t file_obj_write(mp_obj_t self_in, mp_obj_t arg) {
690 pyb_file_obj_t *self = self_in;
691 const char *s = qstr_str(mp_obj_get_qstr(arg));
Damien0e496732013-11-03 14:53:34 +0000692 UINT n_out;
Damiend99b0522013-12-21 18:17:45 +0000693 FRESULT res = f_write(&self->fp, s, strlen(s), &n_out);
Damien0e496732013-11-03 14:53:34 +0000694 if (res != FR_OK) {
695 printf("File error: could not write to file; error code %d\n", res);
696 } else if (n_out != strlen(s)) {
697 printf("File error: could not write all data to file; wrote %d / %d bytes\n", n_out, strlen(s));
698 }
Damiend99b0522013-12-21 18:17:45 +0000699 return mp_const_none;
Damien0e496732013-11-03 14:53:34 +0000700}
701
Damiend99b0522013-12-21 18:17:45 +0000702mp_obj_t file_obj_close(mp_obj_t self_in) {
703 pyb_file_obj_t *self = self_in;
704 f_close(&self->fp);
705 return mp_const_none;
Damien0e496732013-11-03 14:53:34 +0000706}
707
Damiend99b0522013-12-21 18:17:45 +0000708static MP_DEFINE_CONST_FUN_OBJ_2(file_obj_read_obj, file_obj_read);
709static MP_DEFINE_CONST_FUN_OBJ_2(file_obj_write_obj, file_obj_write);
710static MP_DEFINE_CONST_FUN_OBJ_1(file_obj_close_obj, file_obj_close);
711
Damien0e496732013-11-03 14:53:34 +0000712// TODO gc hook to close the file if not already closed
Damiend99b0522013-12-21 18:17:45 +0000713
Damien George97209d32014-01-07 15:58:30 +0000714static const mp_method_t file_methods[] = {
715 { "read", &file_obj_read_obj },
716 { "write", &file_obj_write_obj },
717 { "close", &file_obj_close_obj },
718 {NULL, NULL},
719};
720
Damiend99b0522013-12-21 18:17:45 +0000721static const mp_obj_type_t file_obj_type = {
722 { &mp_const_type },
Damien0e496732013-11-03 14:53:34 +0000723 "File",
Damien George97209d32014-01-07 15:58:30 +0000724 .print = file_obj_print,
725 .methods = file_methods,
Damien0e496732013-11-03 14:53:34 +0000726};
727
Damiend99b0522013-12-21 18:17:45 +0000728mp_obj_t pyb_io_open(mp_obj_t o_filename, mp_obj_t o_mode) {
729 const char *filename = qstr_str(mp_obj_get_qstr(o_filename));
730 const char *mode = qstr_str(mp_obj_get_qstr(o_mode));
731 pyb_file_obj_t *self = m_new_obj(pyb_file_obj_t);
732 self->base.type = &file_obj_type;
Damien0e496732013-11-03 14:53:34 +0000733 if (mode[0] == 'r') {
734 // open for reading
Damiend99b0522013-12-21 18:17:45 +0000735 FRESULT res = f_open(&self->fp, filename, FA_READ);
Damien0e496732013-11-03 14:53:34 +0000736 if (res != FR_OK) {
737 printf("FileNotFoundError: [Errno 2] No such file or directory: '%s'\n", filename);
Damiend99b0522013-12-21 18:17:45 +0000738 return mp_const_none;
Damien0e496732013-11-03 14:53:34 +0000739 }
740 } else if (mode[0] == 'w') {
741 // open for writing, truncate the file first
Damiend99b0522013-12-21 18:17:45 +0000742 FRESULT res = f_open(&self->fp, filename, FA_WRITE | FA_CREATE_ALWAYS);
Damien0e496732013-11-03 14:53:34 +0000743 if (res != FR_OK) {
744 printf("?FileError: could not create file: '%s'\n", filename);
Damiend99b0522013-12-21 18:17:45 +0000745 return mp_const_none;
Damien0e496732013-11-03 14:53:34 +0000746 }
747 } else {
748 printf("ValueError: invalid mode: '%s'\n", mode);
Damiend99b0522013-12-21 18:17:45 +0000749 return mp_const_none;
Damien0e496732013-11-03 14:53:34 +0000750 }
Damiend99b0522013-12-21 18:17:45 +0000751 return self;
Damien0e496732013-11-03 14:53:34 +0000752}
753
Damiend99b0522013-12-21 18:17:45 +0000754mp_obj_t pyb_rng_get(void) {
755 return mp_obj_new_int(RNG_GetRandomNumber() >> 16);
Damien39c6c592013-11-09 20:15:48 +0000756}
757
Damien0f654512013-10-23 20:39:20 +0100758int main(void) {
Damien00ff04f2013-10-19 14:40:54 +0100759 // TODO disable JTAG
760
Damiend6b4c662013-12-06 00:41:33 +0000761 // update the SystemCoreClock variable
762 SystemCoreClockUpdate();
763
Damienafe12bc2013-10-19 18:13:48 +0100764 // set interrupt priority config to use all 4 bits for pre-empting
765 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
766
767 // enable the CCM RAM and the GPIO's
768 RCC->AHB1ENR |= RCC_AHB1ENR_CCMDATARAMEN | RCC_AHB1ENR_GPIOAEN | RCC_AHB1ENR_GPIOBEN | RCC_AHB1ENR_GPIOCEN;
769
Damien5892f472013-10-26 18:02:46 +0100770 // configure SDIO pins to be high to start with (apparently makes it more robust)
Damien7ee80ba2013-10-24 00:22:27 +0100771 {
772 GPIO_InitTypeDef GPIO_InitStructure;
773 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12;
774 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_25MHz;
775 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
776 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
777 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
778 GPIO_Init(GPIOC, &GPIO_InitStructure);
779
780 // Configure PD.02 CMD line
781 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
782 GPIO_Init(GPIOD, &GPIO_InitStructure);
783 }
784
Damien00ff04f2013-10-19 14:40:54 +0100785 // basic sub-system init
786 sys_tick_init();
Damien00ff04f2013-10-19 14:40:54 +0100787 led_init();
Damien81289412013-10-26 02:06:37 +0100788 rtc_init();
Damien00ff04f2013-10-19 14:40:54 +0100789
790 // turn on LED to indicate bootup
791 led_state(PYB_LED_G1, 1);
792
793 // more sub-system init
Damien George823877b2014-01-05 14:04:55 +0000794 switch_init();
Damien00ff04f2013-10-19 14:40:54 +0100795 storage_init();
Damien065f8a52013-12-05 20:38:23 +0000796
Damien George328708e2014-01-13 00:20:06 +0000797 // uncomment these 2 lines if you want REPL on USART_6 (or another usart) as well as on USB VCP
798 //pyb_usart_global_debug = PYB_USART_6;
799 //usart_init(pyb_usart_global_debug, 115200);
Damien00ff04f2013-10-19 14:40:54 +0100800
Damienbd8e1102013-11-06 23:04:33 +0000801 int first_soft_reset = true;
802
Damiene9f1e502013-10-22 23:09:25 +0100803soft_reset:
804
Damien3f69aca2013-10-21 23:46:04 +0100805 // GC init
Damien0c5827f2013-10-22 21:13:36 +0100806 gc_init(&_heap_start, (void*)HEAP_END);
Damien3f69aca2013-10-21 23:46:04 +0100807
Damiene9f1e502013-10-22 23:09:25 +0100808 // Micro Python init
Damienafe12bc2013-10-19 18:13:48 +0100809 qstr_init();
810 rt_init();
Damien00ff04f2013-10-19 14:40:54 +0100811
Damien39c6c592013-11-09 20:15:48 +0000812 // LCD init
Damien8fe84132013-11-30 15:06:24 +0000813 //lcd_init(); disabled while servos on PA0 PA1
Damien39c6c592013-11-09 20:15:48 +0000814
Damien0f654512013-10-23 20:39:20 +0100815 // servo
816 servo_init();
817
Damien1c62d042013-11-04 23:05:48 +0000818 // audio
Damien52851552013-12-11 00:40:15 +0000819 //audio_init();
Damien1c62d042013-11-04 23:05:48 +0000820
Damienbd8e1102013-11-06 23:04:33 +0000821 // timer
822 timer_init();
823
Damien39c6c592013-11-09 20:15:48 +0000824 // RNG
Damien8c3da5c2013-12-17 18:36:19 +0000825 if (1) {
Damien39c6c592013-11-09 20:15:48 +0000826 RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_RNG, ENABLE);
827 RNG_Cmd(ENABLE);
828 }
829
Damienf48cf672013-10-21 10:42:06 +0100830 // add some functions to the python namespace
Damiene9f1e502013-10-22 23:09:25 +0100831 {
Damien Georgef62d33a2014-01-13 19:50:05 +0000832 rt_store_name(qstr_from_str_static("help"), rt_make_function_n(0, pyb_help));
Damien8c3da5c2013-12-17 18:36:19 +0000833
Damien George28708622014-01-02 21:30:26 +0000834 mp_obj_t m = mp_obj_new_module(qstr_from_str_static("pyb"));
Damien Georgef62d33a2014-01-13 19:50:05 +0000835 rt_store_attr(m, qstr_from_str_static("info"), rt_make_function_n(0, pyb_info));
836 rt_store_attr(m, qstr_from_str_static("sd_test"), rt_make_function_n(0, pyb_sd_test));
837 rt_store_attr(m, qstr_from_str_static("stop"), rt_make_function_n(0, pyb_stop));
838 rt_store_attr(m, qstr_from_str_static("standby"), rt_make_function_n(0, pyb_standby));
839 rt_store_attr(m, qstr_from_str_static("source_dir"), rt_make_function_n(1, pyb_source_dir));
840 rt_store_attr(m, qstr_from_str_static("main"), rt_make_function_n(1, pyb_main));
841 rt_store_attr(m, qstr_from_str_static("sync"), rt_make_function_n(0, pyb_sync));
842 rt_store_attr(m, qstr_from_str_static("gc"), rt_make_function_n(0, pyb_gc));
843 rt_store_attr(m, qstr_from_str_static("delay"), rt_make_function_n(1, pyb_delay));
844 rt_store_attr(m, qstr_from_str_static("led"), rt_make_function_n(1, pyb_led));
Damien George823877b2014-01-05 14:04:55 +0000845 rt_store_attr(m, qstr_from_str_static("switch"), (mp_obj_t)&pyb_switch_obj);
Damien Georgef62d33a2014-01-13 19:50:05 +0000846 rt_store_attr(m, qstr_from_str_static("servo"), rt_make_function_n(2, pyb_servo_set));
847 rt_store_attr(m, qstr_from_str_static("pwm"), rt_make_function_n(2, pyb_pwm_set));
Damien George28708622014-01-02 21:30:26 +0000848 rt_store_attr(m, qstr_from_str_static("accel"), (mp_obj_t)&pyb_mma_read_obj);
849 rt_store_attr(m, qstr_from_str_static("mma_read"), (mp_obj_t)&pyb_mma_read_all_obj);
850 rt_store_attr(m, qstr_from_str_static("mma_mode"), (mp_obj_t)&pyb_mma_write_mode_obj);
Damien Georgef62d33a2014-01-13 19:50:05 +0000851 rt_store_attr(m, qstr_from_str_static("hid"), rt_make_function_n(1, pyb_hid_send_report));
852 rt_store_attr(m, qstr_from_str_static("time"), rt_make_function_n(0, pyb_rtc_read));
853 rt_store_attr(m, qstr_from_str_static("rand"), rt_make_function_n(0, pyb_rng_get));
854 rt_store_attr(m, qstr_from_str_static("Led"), rt_make_function_n(1, pyb_Led));
855 rt_store_attr(m, qstr_from_str_static("Servo"), rt_make_function_n(1, pyb_Servo));
856 rt_store_attr(m, qstr_from_str_static("I2C"), rt_make_function_n(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);
Damien Georgef62d33a2014-01-13 19:50:05 +0000858 rt_store_attr(m, qstr_from_str_static("Usart"), rt_make_function_n(2, pyb_Usart));
mux35912852014-01-14 19:57:51 +0200859 rt_store_attr(m, qstr_from_str_static("ADC"), rt_make_function_n(1, pyb_ADC));
Damiene9f1e502013-10-22 23:09:25 +0100860 rt_store_name(qstr_from_str_static("pyb"), m);
Damien0e496732013-11-03 14:53:34 +0000861
Damien Georgef62d33a2014-01-13 19:50:05 +0000862 rt_store_name(qstr_from_str_static("open"), rt_make_function_n(2, pyb_io_open));
Damiene9f1e502013-10-22 23:09:25 +0100863 }
Damienf48cf672013-10-21 10:42:06 +0100864
Damiene9f1e502013-10-22 23:09:25 +0100865 // print a message to the LCD
866 lcd_print_str(" micro py board\n");
Damien00ff04f2013-10-19 14:40:54 +0100867
Damiend6b4c662013-12-06 00:41:33 +0000868 // check if user switch held (initiates reset of filesystem)
869 bool reset_filesystem = false;
Damien George823877b2014-01-05 14:04:55 +0000870 if (switch_get()) {
Damiend6b4c662013-12-06 00:41:33 +0000871 reset_filesystem = true;
872 for (int i = 0; i < 50; i++) {
Damien George823877b2014-01-05 14:04:55 +0000873 if (!switch_get()) {
Damiend6b4c662013-12-06 00:41:33 +0000874 reset_filesystem = false;
875 break;
876 }
877 sys_tick_delay_ms(10);
878 }
879 }
880
Damien00ff04f2013-10-19 14:40:54 +0100881 // local filesystem init
882 {
883 // try to mount the flash
884 FRESULT res = f_mount(&fatfs0, "0:", 1);
Damiend6b4c662013-12-06 00:41:33 +0000885 if (!reset_filesystem && res == FR_OK) {
Damien00ff04f2013-10-19 14:40:54 +0100886 // mount sucessful
Damiend6b4c662013-12-06 00:41:33 +0000887 } else if (reset_filesystem || res == FR_NO_FILESYSTEM) {
Damien00ff04f2013-10-19 14:40:54 +0100888 // no filesystem, so create a fresh one
Damiend6b4c662013-12-06 00:41:33 +0000889 // TODO doesn't seem to work correctly when reset_filesystem is true...
Damien00ff04f2013-10-19 14:40:54 +0100890
891 // LED on to indicate creation of LFS
892 led_state(PYB_LED_R2, 1);
893 uint32_t stc = sys_tick_counter;
894
895 res = f_mkfs("0:", 0, 0);
896 if (res == FR_OK) {
897 // success creating fresh LFS
898 } else {
899 __fatal_error("could not create LFS");
900 }
901
Damien8c3da5c2013-12-17 18:36:19 +0000902 // create src directory
903 res = f_mkdir("0:/src");
904 // ignore result from mkdir
905
906 // create empty main.py
907 FIL fp;
908 f_open(&fp, "0:/src/main.py", FA_WRITE | FA_CREATE_ALWAYS);
909 UINT n;
910 f_write(&fp, fresh_main_py, sizeof(fresh_main_py) - 1 /* don't count null terminator */, &n);
911 // TODO check we could write n bytes
912 f_close(&fp);
913
Damienafe12bc2013-10-19 18:13:48 +0100914 // keep LED on for at least 200ms
915 sys_tick_wait_at_least(stc, 200);
Damien00ff04f2013-10-19 14:40:54 +0100916 led_state(PYB_LED_R2, 0);
917 } else {
918 __fatal_error("could not access LFS");
Damien4a175e12013-10-17 22:50:21 +0100919 }
Damien00ff04f2013-10-19 14:40:54 +0100920 }
921
922 // make sure we have a /boot.py
923 {
924 FILINFO fno;
925 FRESULT res = f_stat("0:/boot.py", &fno);
926 if (res == FR_OK) {
927 if (fno.fattrib & AM_DIR) {
928 // exists as a directory
929 // TODO handle this case
930 // see http://elm-chan.org/fsw/ff/img/app2.c for a "rm -rf" implementation
931 } else {
932 // exists as a file, good!
933 }
934 } else {
935 // doesn't exist, create fresh file
936
937 // LED on to indicate creation of boot.py
938 led_state(PYB_LED_R2, 1);
939 uint32_t stc = sys_tick_counter;
940
941 FIL fp;
942 f_open(&fp, "0:/boot.py", FA_WRITE | FA_CREATE_ALWAYS);
943 UINT n;
Damiene9f1e502013-10-22 23:09:25 +0100944 f_write(&fp, fresh_boot_py, sizeof(fresh_boot_py) - 1 /* don't count null terminator */, &n);
Damien00ff04f2013-10-19 14:40:54 +0100945 // TODO check we could write n bytes
946 f_close(&fp);
947
Damienafe12bc2013-10-19 18:13:48 +0100948 // keep LED on for at least 200ms
949 sys_tick_wait_at_least(stc, 200);
Damien00ff04f2013-10-19 14:40:54 +0100950 led_state(PYB_LED_R2, 0);
951 }
952 }
953
Damien94186c82013-10-23 00:02:06 +0100954 // run /boot.py
955 if (!do_file("0:/boot.py")) {
956 flash_error(4);
957 }
958
Damiene9f1e502013-10-22 23:09:25 +0100959 // USB
960 usb_init();
961
Damien George328708e2014-01-13 00:20:06 +0000962 // USB host; not working!
963 //pyb_usbh_init();
964
Damien6f08f8c2013-10-23 22:17:26 +0100965 // MMA
Damienbd8e1102013-11-06 23:04:33 +0000966 if (first_soft_reset) {
Damien6f08f8c2013-10-23 22:17:26 +0100967 // init and reset address to zero
968 mma_init();
Damien6f08f8c2013-10-23 22:17:26 +0100969 }
970
Damien00ff04f2013-10-19 14:40:54 +0100971 // turn boot-up LED off
972 led_state(PYB_LED_G1, 0);
973
Damien94186c82013-10-23 00:02:06 +0100974 // run main script
975 {
976 vstr_t *vstr = vstr_new();
977 vstr_add_str(vstr, "0:/");
978 if (pyb_config_source_dir == 0) {
979 vstr_add_str(vstr, "src");
980 } else {
981 vstr_add_str(vstr, qstr_str(pyb_config_source_dir));
982 }
983 vstr_add_char(vstr, '/');
984 if (pyb_config_main == 0) {
985 vstr_add_str(vstr, "main.py");
986 } else {
987 vstr_add_str(vstr, qstr_str(pyb_config_main));
988 }
989 if (!do_file(vstr_str(vstr))) {
990 flash_error(3);
991 }
992 vstr_free(vstr);
993 }
994
Damien00ff04f2013-10-19 14:40:54 +0100995 //printf("init;al=%u\n", m_get_total_bytes_allocated()); // 1600, due to qstr_init
996 //sys_tick_delay_ms(1000);
997
Damiened656052013-10-13 00:42:20 +0100998 // Python!
Damien4b6e85c2013-10-21 09:56:56 +0100999 if (0) {
Damiened656052013-10-13 00:42:20 +01001000 //const char *pysrc = "def f():\n x=x+1\nprint(42)\n";
1001 const char *pysrc =
1002 // impl01.py
1003 /*
1004 "x = 0\n"
1005 "while x < 400:\n"
1006 " y = 0\n"
1007 " while y < 400:\n"
1008 " z = 0\n"
1009 " while z < 400:\n"
1010 " z = z + 1\n"
1011 " y = y + 1\n"
1012 " x = x + 1\n";
1013 */
1014 // impl02.py
Damien152568b2013-10-16 00:46:39 +01001015 /*
Damiened656052013-10-13 00:42:20 +01001016 "#@micropython.native\n"
1017 "def f():\n"
1018 " x = 0\n"
1019 " while x < 400:\n"
1020 " y = 0\n"
1021 " while y < 400:\n"
1022 " z = 0\n"
1023 " while z < 400:\n"
1024 " z = z + 1\n"
1025 " y = y + 1\n"
1026 " x = x + 1\n"
1027 "f()\n";
Damien152568b2013-10-16 00:46:39 +01001028 */
Damien0c5827f2013-10-22 21:13:36 +01001029 /*
Damiened656052013-10-13 00:42:20 +01001030 "print('in python!')\n"
1031 "x = 0\n"
1032 "while x < 4:\n"
1033 " pyb_led(True)\n"
1034 " pyb_delay(201)\n"
1035 " pyb_led(False)\n"
1036 " pyb_delay(201)\n"
Damienfa2162b2013-10-20 17:42:00 +01001037 " x += 1\n"
Damiened656052013-10-13 00:42:20 +01001038 "print('press me!')\n"
1039 "while True:\n"
1040 " pyb_led(pyb_sw())\n";
Damien0c5827f2013-10-22 21:13:36 +01001041 */
Damiened656052013-10-13 00:42:20 +01001042 /*
1043 // impl16.py
1044 "@micropython.asm_thumb\n"
1045 "def delay(r0):\n"
1046 " b(loop_entry)\n"
1047 " label(loop1)\n"
1048 " movw(r1, 55999)\n"
1049 " label(loop2)\n"
1050 " subs(r1, r1, 1)\n"
1051 " cmp(r1, 0)\n"
1052 " bgt(loop2)\n"
1053 " subs(r0, r0, 1)\n"
1054 " label(loop_entry)\n"
1055 " cmp(r0, 0)\n"
1056 " bgt(loop1)\n"
1057 "print('in python!')\n"
1058 "@micropython.native\n"
1059 "def flash(n):\n"
1060 " x = 0\n"
1061 " while x < n:\n"
1062 " pyb_led(True)\n"
1063 " delay(249)\n"
1064 " pyb_led(False)\n"
1065 " delay(249)\n"
1066 " x = x + 1\n"
1067 "flash(20)\n";
1068 */
Damien152568b2013-10-16 00:46:39 +01001069 // impl18.py
1070 /*
1071 "# basic exceptions\n"
1072 "x = 1\n"
1073 "try:\n"
1074 " x.a()\n"
1075 "except:\n"
1076 " print(x)\n";
1077 */
1078 // impl19.py
1079 "# for loop\n"
1080 "def f():\n"
1081 " for x in range(400):\n"
1082 " for y in range(400):\n"
1083 " for z in range(400):\n"
1084 " pass\n"
1085 "f()\n";
Damiened656052013-10-13 00:42:20 +01001086
Damien George9193f892014-01-08 15:28:26 +00001087 mp_lexer_t *lex = mp_lexer_new_from_str_len("<stdin>", pysrc, strlen(pysrc), 0);
Damiened656052013-10-13 00:42:20 +01001088
Damienfa2162b2013-10-20 17:42:00 +01001089 // nalloc=1740;6340;6836 -> 140;4600;496 bytes for lexer, parser, compiler
1090 printf("lex; al=%u\n", m_get_total_bytes_allocated());
1091 sys_tick_delay_ms(1000);
Damien George9528cd62014-01-15 21:23:31 +00001092 qstr parse_exc_id;
1093 const char *parse_exc_msg;
1094 mp_parse_node_t pn = mp_parse(lex, MP_PARSE_FILE_INPUT, &parse_exc_id, &parse_exc_msg);
Damiend99b0522013-12-21 18:17:45 +00001095 mp_lexer_free(lex);
1096 if (pn != MP_PARSE_NODE_NULL) {
Damiened656052013-10-13 00:42:20 +01001097 printf("pars;al=%u\n", m_get_total_bytes_allocated());
Damien00ff04f2013-10-19 14:40:54 +01001098 sys_tick_delay_ms(1000);
Damiened656052013-10-13 00:42:20 +01001099 //parse_node_show(pn, 0);
Damien George08335002014-01-18 23:24:36 +00001100 mp_obj_t module_fun = mp_compile(pn, 0, false);
Damiened656052013-10-13 00:42:20 +01001101 printf("comp;al=%u\n", m_get_total_bytes_allocated());
Damien00ff04f2013-10-19 14:40:54 +01001102 sys_tick_delay_ms(1000);
Damiened656052013-10-13 00:42:20 +01001103
Damien George1fb03172014-01-03 14:22:03 +00001104 if (module_fun == mp_const_none) {
Damienfa2162b2013-10-20 17:42:00 +01001105 printf("compile error\n");
1106 } else {
Damiened656052013-10-13 00:42:20 +01001107 // execute it!
1108
Damien152568b2013-10-16 00:46:39 +01001109 // flash once
Damien995b8aa2013-10-18 23:44:05 +01001110 led_state(PYB_LED_G1, 1);
Damien00ff04f2013-10-19 14:40:54 +01001111 sys_tick_delay_ms(100);
Damien995b8aa2013-10-18 23:44:05 +01001112 led_state(PYB_LED_G1, 0);
Damiened656052013-10-13 00:42:20 +01001113
Damien152568b2013-10-16 00:46:39 +01001114 nlr_buf_t nlr;
1115 if (nlr_push(&nlr) == 0) {
Damiend99b0522013-12-21 18:17:45 +00001116 mp_obj_t ret = rt_call_function_0(module_fun);
Damien152568b2013-10-16 00:46:39 +01001117 printf("done! got: ");
Paul Sokolovsky76d982e2014-01-13 19:19:16 +02001118 mp_obj_print(ret, PRINT_REPR);
Damien152568b2013-10-16 00:46:39 +01001119 printf("\n");
1120 nlr_pop();
1121 } else {
1122 // uncaught exception
1123 printf("exception: ");
Paul Sokolovsky76d982e2014-01-13 19:19:16 +02001124 mp_obj_print((mp_obj_t)nlr.ret_val, PRINT_REPR);
Damien152568b2013-10-16 00:46:39 +01001125 printf("\n");
1126 }
1127
1128 // flash once
Damien995b8aa2013-10-18 23:44:05 +01001129 led_state(PYB_LED_G1, 1);
Damien00ff04f2013-10-19 14:40:54 +01001130 sys_tick_delay_ms(100);
Damien995b8aa2013-10-18 23:44:05 +01001131 led_state(PYB_LED_G1, 0);
Damien152568b2013-10-16 00:46:39 +01001132
Damien00ff04f2013-10-19 14:40:54 +01001133 sys_tick_delay_ms(1000);
Damiened656052013-10-13 00:42:20 +01001134 printf("nalloc=%u\n", m_get_total_bytes_allocated());
Damien00ff04f2013-10-19 14:40:54 +01001135 sys_tick_delay_ms(1000);
Damiened656052013-10-13 00:42:20 +01001136 }
1137 }
1138 }
Damiened656052013-10-13 00:42:20 +01001139
Damien58a1b4c2013-10-25 20:53:54 +01001140 // HID example
1141 if (0) {
1142 uint8_t data[4];
1143 data[0] = 0;
1144 data[1] = 1;
1145 data[2] = -2;
1146 data[3] = 0;
1147 for (;;) {
Damien George823877b2014-01-05 14:04:55 +00001148 if (switch_get()) {
Damien58a1b4c2013-10-25 20:53:54 +01001149 data[0] = 0x01; // 0x04 is middle, 0x02 is right
1150 } else {
1151 data[0] = 0x00;
1152 }
Damien George28708622014-01-02 21:30:26 +00001153 mma_start(0x4c /* MMA_ADDR */, 1);
Damien58a1b4c2013-10-25 20:53:54 +01001154 mma_send_byte(0);
Damien George28708622014-01-02 21:30:26 +00001155 mma_restart(0x4c /* MMA_ADDR */, 0);
Damien58a1b4c2013-10-25 20:53:54 +01001156 for (int i = 0; i <= 1; i++) {
1157 int v = mma_read_ack() & 0x3f;
1158 if (v & 0x20) {
1159 v |= ~0x1f;
1160 }
1161 data[1 + i] = v;
1162 }
1163 mma_read_nack();
1164 usb_hid_send_report(data);
1165 sys_tick_delay_ms(15);
1166 }
1167 }
1168
Damien065f8a52013-12-05 20:38:23 +00001169 // wifi
Damiend6b4c662013-12-06 00:41:33 +00001170 //pyb_wlan_init();
1171 //pyb_wlan_start();
Damien065f8a52013-12-05 20:38:23 +00001172
Damien4b6e85c2013-10-21 09:56:56 +01001173 do_repl();
1174
Damiened656052013-10-13 00:42:20 +01001175 // benchmark C version of impl02.py
1176 if (0) {
Damien995b8aa2013-10-18 23:44:05 +01001177 led_state(PYB_LED_G1, 1);
Damien00ff04f2013-10-19 14:40:54 +01001178 sys_tick_delay_ms(100);
Damien995b8aa2013-10-18 23:44:05 +01001179 led_state(PYB_LED_G1, 0);
Damiened656052013-10-13 00:42:20 +01001180 impl02_c_version();
Damien995b8aa2013-10-18 23:44:05 +01001181 led_state(PYB_LED_G1, 1);
Damien00ff04f2013-10-19 14:40:54 +01001182 sys_tick_delay_ms(100);
Damien995b8aa2013-10-18 23:44:05 +01001183 led_state(PYB_LED_G1, 0);
Damiened656052013-10-13 00:42:20 +01001184 }
1185
Damiened656052013-10-13 00:42:20 +01001186 // SD card testing
Damien8c3da5c2013-12-17 18:36:19 +00001187 if (0) {
Damien7ee80ba2013-10-24 00:22:27 +01001188 extern void sdio_init(void);
Damien8c3da5c2013-12-17 18:36:19 +00001189 sdio_init();
Damiened656052013-10-13 00:42:20 +01001190 }
1191
Damien94186c82013-10-23 00:02:06 +01001192 printf("PYB: sync filesystems\n");
1193 pyb_sync();
1194
1195 printf("PYB: soft reboot\n");
Damienbd8e1102013-11-06 23:04:33 +00001196
1197 first_soft_reset = false;
Damiene9f1e502013-10-22 23:09:25 +01001198 goto soft_reset;
Damiened656052013-10-13 00:42:20 +01001199}
Damienfecee2b2013-11-02 16:41:51 +00001200
Damien George0367ad62014-01-14 23:48:11 +00001201/* now supplied by libgcc library
Damienfecee2b2013-11-02 16:41:51 +00001202double __aeabi_f2d(float x) {
1203 // TODO
1204 return 0.0;
1205}
Damien0e496732013-11-03 14:53:34 +00001206
1207float __aeabi_d2f(double x) {
1208 // TODO
1209 return 0.0;
1210}
Damien George0367ad62014-01-14 23:48:11 +00001211*/
Damien0e496732013-11-03 14:53:34 +00001212
1213double sqrt(double x) {
1214 // TODO
1215 return 0.0;
1216}
Damien39c6c592013-11-09 20:15:48 +00001217
1218machine_float_t machine_sqrt(machine_float_t x) {
1219 // TODO
1220 return x;
1221}