blob: b7ae8aacca4c9f01fbf53eeb12a58a9950243632 [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"
Damien065f8a52013-12-05 20:38:23 +000042
43int errno;
Damiened656052013-10-13 00:42:20 +010044
Damien3f69aca2013-10-21 23:46:04 +010045extern uint32_t _heap_start;
46
Damien8fe84132013-11-30 15:06:24 +000047static FATFS fatfs0;
48
Damien94186c82013-10-23 00:02:06 +010049void flash_error(int n) {
50 for (int i = 0; i < n; i++) {
51 led_state(PYB_LED_R1, 1);
52 led_state(PYB_LED_R2, 0);
53 sys_tick_delay_ms(250);
54 led_state(PYB_LED_R1, 0);
55 led_state(PYB_LED_R2, 1);
56 sys_tick_delay_ms(250);
57 }
58 led_state(PYB_LED_R2, 0);
59}
60
Damien0f654512013-10-23 20:39:20 +010061static void impl02_c_version(void) {
Damiened656052013-10-13 00:42:20 +010062 int x = 0;
63 while (x < 400) {
64 int y = 0;
65 while (y < 400) {
66 volatile int z = 0;
67 while (z < 400) {
68 z = z + 1;
69 }
70 y = y + 1;
71 }
72 x = x + 1;
73 }
74}
75
Damiened656052013-10-13 00:42:20 +010076#define PYB_USRSW_PORT (GPIOA)
Damien00ff04f2013-10-19 14:40:54 +010077#define PYB_USRSW_PIN (GPIO_Pin_13)
Damiened656052013-10-13 00:42:20 +010078
Damien0f654512013-10-23 20:39:20 +010079void sw_init(void) {
Damiened656052013-10-13 00:42:20 +010080 // make it an input with pull-up
Damien00ff04f2013-10-19 14:40:54 +010081 GPIO_InitTypeDef GPIO_InitStructure;
82 GPIO_InitStructure.GPIO_Pin = PYB_USRSW_PIN;
83 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
84 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
85 GPIO_Init(PYB_USRSW_PORT, &GPIO_InitStructure);
Damien52851552013-12-11 00:40:15 +000086
87 // the rest does the EXTI interrupt
88
89 /* Enable SYSCFG clock */
90 RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
91
92 /* Connect EXTI Line13 to PA13 pin */
93 SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource13);
94
95 /* Configure EXTI Line13, rising edge */
96 EXTI_InitTypeDef EXTI_InitStructure;
97 EXTI_InitStructure.EXTI_Line = EXTI_Line13;
98 EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
99 EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
100 EXTI_InitStructure.EXTI_LineCmd = ENABLE;
101 EXTI_Init(&EXTI_InitStructure);
102
103 /* Enable and set EXTI15_10 Interrupt to the lowest priority */
104 NVIC_InitTypeDef NVIC_InitStructure;
105 NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;
106 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0F;
107 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0F;
108 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
109 NVIC_Init(&NVIC_InitStructure);
Damiened656052013-10-13 00:42:20 +0100110}
111
Damien0f654512013-10-23 20:39:20 +0100112int sw_get(void) {
Damien00ff04f2013-10-19 14:40:54 +0100113 if (PYB_USRSW_PORT->IDR & PYB_USRSW_PIN) {
Damiened656052013-10-13 00:42:20 +0100114 // pulled high, so switch is not pressed
115 return 0;
116 } else {
117 // pulled low, so switch is pressed
118 return 1;
119 }
120}
121
Damiened656052013-10-13 00:42:20 +0100122void __fatal_error(const char *msg) {
123 lcd_print_strn("\nFATAL ERROR:\n", 14);
124 lcd_print_strn(msg, strlen(msg));
Damiened656052013-10-13 00:42:20 +0100125 for (;;) {
Damien94186c82013-10-23 00:02:06 +0100126 flash_error(1);
Damiened656052013-10-13 00:42:20 +0100127 }
128}
129
Damien94186c82013-10-23 00:02:06 +0100130static qstr pyb_config_source_dir = 0;
131static qstr pyb_config_main = 0;
132
Damiend99b0522013-12-21 18:17:45 +0000133mp_obj_t pyb_source_dir(mp_obj_t source_dir) {
134 pyb_config_source_dir = mp_obj_get_qstr(source_dir);
135 return mp_const_none;
Damiene9f1e502013-10-22 23:09:25 +0100136}
137
Damiend99b0522013-12-21 18:17:45 +0000138mp_obj_t pyb_main(mp_obj_t main) {
139 pyb_config_main = mp_obj_get_qstr(main);
140 return mp_const_none;
Damien94186c82013-10-23 00:02:06 +0100141}
142
143// sync all file systems
Damiend99b0522013-12-21 18:17:45 +0000144mp_obj_t pyb_sync(void) {
Damien94186c82013-10-23 00:02:06 +0100145 storage_flush();
Damiend99b0522013-12-21 18:17:45 +0000146 return mp_const_none;
Damiene9f1e502013-10-22 23:09:25 +0100147}
Damiened656052013-10-13 00:42:20 +0100148
Damiend99b0522013-12-21 18:17:45 +0000149mp_obj_t pyb_delay(mp_obj_t count) {
150 sys_tick_delay_ms(mp_obj_get_int(count));
151 return mp_const_none;
Damiened656052013-10-13 00:42:20 +0100152}
153
Damiend99b0522013-12-21 18:17:45 +0000154mp_obj_t pyb_led(mp_obj_t state) {
Damien995b8aa2013-10-18 23:44:05 +0100155 led_state(PYB_LED_G1, rt_is_true(state));
Damiened656052013-10-13 00:42:20 +0100156 return state;
157}
158
Damiend99b0522013-12-21 18:17:45 +0000159mp_obj_t pyb_sw(void) {
Damiened656052013-10-13 00:42:20 +0100160 if (sw_get()) {
Damiend99b0522013-12-21 18:17:45 +0000161 return mp_const_true;
Damiened656052013-10-13 00:42:20 +0100162 } else {
Damiend99b0522013-12-21 18:17:45 +0000163 return mp_const_false;
Damiened656052013-10-13 00:42:20 +0100164 }
165}
Damiened656052013-10-13 00:42:20 +0100166
Damien4a175e12013-10-17 22:50:21 +0100167/*
Damien152568b2013-10-16 00:46:39 +0100168void g(uint i) {
169 printf("g:%d\n", i);
170 if (i & 1) {
171 nlr_jump((void*)(42 + i));
172 }
173}
Damien0f654512013-10-23 20:39:20 +0100174void f(void) {
Damien152568b2013-10-16 00:46:39 +0100175 nlr_buf_t nlr;
176 int i;
177 for (i = 0; i < 4; i++) {
178 printf("f:loop:%d:%p\n", i, &nlr);
179 if (nlr_push(&nlr) == 0) {
180 // normal
181 //printf("a:%p:%p %p %p %u\n", &nlr, nlr.ip, nlr.sp, nlr.prev, nlr.ret_val);
182 g(i);
183 printf("f:lp:%d:nrm\n", i);
184 nlr_pop();
185 } else {
186 // nlr
187 //printf("b:%p:%p %p %p %u\n", &nlr, nlr.ip, nlr.sp, nlr.prev, nlr.ret_val);
188 printf("f:lp:%d:nlr:%d\n", i, (int)nlr.ret_val);
189 }
190 }
191}
Damien0f654512013-10-23 20:39:20 +0100192void nlr_test(void) {
Damien152568b2013-10-16 00:46:39 +0100193 f(1);
194}
Damien4a175e12013-10-17 22:50:21 +0100195*/
196
Damien0f654512013-10-23 20:39:20 +0100197void fatality(void) {
Damien00ff04f2013-10-19 14:40:54 +0100198 led_state(PYB_LED_R1, 1);
199 led_state(PYB_LED_G1, 1);
200 led_state(PYB_LED_R2, 1);
201 led_state(PYB_LED_G2, 1);
202}
Damiened656052013-10-13 00:42:20 +0100203
Damienafe12bc2013-10-19 18:13:48 +0100204static const char fresh_boot_py[] =
Damien00ff04f2013-10-19 14:40:54 +0100205"# boot.py -- run on boot-up\n"
206"# can run arbitrary Python, but best to keep it minimal\n"
207"\n"
208"pyb.source_dir('/src')\n"
209"pyb.main('main.py')\n"
210"#pyb.usb_usr('VCP')\n"
211"#pyb.usb_msd(True, 'dual partition')\n"
212"#pyb.flush_cache(False)\n"
213"#pyb.error_log('error.txt')\n"
214;
Damiened656052013-10-13 00:42:20 +0100215
Damien8c3da5c2013-12-17 18:36:19 +0000216static const char fresh_main_py[] =
217"# main.py -- put your code here!\n"
218;
219
220static const char *help_text =
221"Welcome to Micro Python!\n\n"
222"This is a *very* early version of Micro Python and has minimal functionality.\n\n"
223"Specific commands for the board:\n"
224" pyb.info() -- print some general information\n"
225" pyb.gc() -- run the garbage collector\n"
226" pyb.delay(<n>) -- wait for n milliseconds\n"
227" pyb.Led(<n>) -- create Led object for LED n (n=1,2)\n"
228" Led methods: on(), off()\n"
229" pyb.Servo(<n>) -- create Servo object for servo n (n=1,2,3,4)\n"
230" Servo methods: angle(<x>)\n"
231" pyb.switch() -- return True/False if switch pressed or not\n"
232" pyb.accel() -- get accelerometer values\n"
233" pyb.rand() -- get a 16-bit random number\n"
234;
235
236// get some help about available functions
Damiend99b0522013-12-21 18:17:45 +0000237static mp_obj_t pyb_help(void) {
Damien8c3da5c2013-12-17 18:36:19 +0000238 printf("%s", help_text);
Damiend99b0522013-12-21 18:17:45 +0000239 return mp_const_none;
Damien8c3da5c2013-12-17 18:36:19 +0000240}
241
Damien00ff04f2013-10-19 14:40:54 +0100242// get lots of info about the board
Damiend99b0522013-12-21 18:17:45 +0000243static mp_obj_t pyb_info(void) {
Damien8c3da5c2013-12-17 18:36:19 +0000244 // get and print unique id; 96 bits
245 {
246 byte *id = (byte*)0x1fff7a10;
247 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]);
248 }
249
Damiened656052013-10-13 00:42:20 +0100250 // get and print clock speeds
251 // SYSCLK=168MHz, HCLK=168MHz, PCLK1=42MHz, PCLK2=84MHz
Damiened656052013-10-13 00:42:20 +0100252 {
253 RCC_ClocksTypeDef rcc_clocks;
254 RCC_GetClocksFreq(&rcc_clocks);
Damien00ff04f2013-10-19 14:40:54 +0100255 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 +0100256 }
257
Damien995b8aa2013-10-18 23:44:05 +0100258 // to print info about memory
Damien00ff04f2013-10-19 14:40:54 +0100259 {
Damien4a175e12013-10-17 22:50:21 +0100260 extern void *_sidata;
261 extern void *_sdata;
262 extern void *_edata;
263 extern void *_sbss;
264 extern void *_ebss;
265 extern void *_estack;
266 extern void *_etext;
Damien00ff04f2013-10-19 14:40:54 +0100267 printf("_sidata=%p\n", &_sidata);
268 printf("_sdata=%p\n", &_sdata);
269 printf("_edata=%p\n", &_edata);
270 printf("_sbss=%p\n", &_sbss);
271 printf("_ebss=%p\n", &_ebss);
272 printf("_estack=%p\n", &_estack);
273 printf("_etext=%p\n", &_etext);
274 printf("_heap_start=%p\n", &_heap_start);
275 }
276
Damien94186c82013-10-23 00:02:06 +0100277 // GC info
278 {
279 gc_info_t info;
280 gc_info(&info);
281 printf("GC:\n");
282 printf(" %lu total\n", info.total);
283 printf(" %lu : %lu\n", info.used, info.free);
284 printf(" 1=%lu 2=%lu m=%lu\n", info.num_1block, info.num_2block, info.max_block);
285 }
286
Damien00ff04f2013-10-19 14:40:54 +0100287 // free space on flash
288 {
289 DWORD nclst;
290 FATFS *fatfs;
291 f_getfree("0:", &nclst, &fatfs);
Damien94186c82013-10-23 00:02:06 +0100292 printf("LFS free: %u bytes\n", (uint)(nclst * fatfs->csize * 512));
Damien00ff04f2013-10-19 14:40:54 +0100293 }
Damien00ff04f2013-10-19 14:40:54 +0100294
Damiend99b0522013-12-21 18:17:45 +0000295 return mp_const_none;
Damien4b6e85c2013-10-21 09:56:56 +0100296}
297
Damienb73085d2013-12-20 11:45:06 +0000298// SD card test
Damiend99b0522013-12-21 18:17:45 +0000299static mp_obj_t pyb_sd_test(void) {
Damienb73085d2013-12-20 11:45:06 +0000300 extern void sdio_init(void);
301 sdio_init();
Damiend99b0522013-12-21 18:17:45 +0000302 return mp_const_none;
Damienb73085d2013-12-20 11:45:06 +0000303}
304
Damien52851552013-12-11 00:40:15 +0000305static void SYSCLKConfig_STOP(void) {
306 /* After wake-up from STOP reconfigure the system clock */
307 /* Enable HSE */
308 RCC_HSEConfig(RCC_HSE_ON);
309
310 /* Wait till HSE is ready */
311 while (RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET) {
312 }
313
314 /* Enable PLL */
315 RCC_PLLCmd(ENABLE);
316
317 /* Wait till PLL is ready */
318 while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET) {
319 }
320
321 /* Select PLL as system clock source */
322 RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
323
324 /* Wait till PLL is used as system clock source */
325 while (RCC_GetSYSCLKSource() != 0x08) {
326 }
327}
328
Damiend99b0522013-12-21 18:17:45 +0000329static mp_obj_t pyb_stop(void) {
Damien52851552013-12-11 00:40:15 +0000330 PWR_EnterSTANDBYMode();
331 //PWR_FlashPowerDownCmd(ENABLE); don't know what the logic is with this
332
333 /* Enter Stop Mode */
334 PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI);
335
336 /* Configures system clock after wake-up from STOP: enable HSE, PLL and select
337 * PLL as system clock source (HSE and PLL are disabled in STOP mode) */
338 SYSCLKConfig_STOP();
339
340 //PWR_FlashPowerDownCmd(DISABLE);
341
Damiend99b0522013-12-21 18:17:45 +0000342 return mp_const_none;
Damien52851552013-12-11 00:40:15 +0000343}
344
Damiend99b0522013-12-21 18:17:45 +0000345static mp_obj_t pyb_standby(void) {
Damien52851552013-12-11 00:40:15 +0000346 PWR_EnterSTANDBYMode();
Damiend99b0522013-12-21 18:17:45 +0000347 return mp_const_none;
Damien52851552013-12-11 00:40:15 +0000348}
349
Damiend99b0522013-12-21 18:17:45 +0000350mp_obj_t pyb_usart_send(mp_obj_t data) {
351 usart_tx_char(mp_obj_get_int(data));
352 return mp_const_none;
Damien8f7491a2013-10-26 18:01:48 +0100353}
354
Damiend99b0522013-12-21 18:17:45 +0000355mp_obj_t pyb_usart_receive(void) {
356 return mp_obj_new_int(usart_rx_char());
Damien8f7491a2013-10-26 18:01:48 +0100357}
358
Damiend99b0522013-12-21 18:17:45 +0000359mp_obj_t pyb_usart_status(void) {
Damien8f7491a2013-10-26 18:01:48 +0100360 if (usart_rx_any()) {
Damiend99b0522013-12-21 18:17:45 +0000361 return mp_const_true;
Damien8f7491a2013-10-26 18:01:48 +0100362 } else {
Damiend99b0522013-12-21 18:17:45 +0000363 return mp_const_false;
Damien8f7491a2013-10-26 18:01:48 +0100364 }
365}
366
Damien9281cd62013-10-26 02:29:02 +0100367char *strdup(const char *str) {
368 uint32_t len = strlen(str);
369 char *s2 = m_new(char, len + 1);
370 memcpy(s2, str, len);
371 s2[len] = 0;
372 return s2;
373}
374
375#define READLINE_HIST_SIZE (8)
376
377static const char *readline_hist[READLINE_HIST_SIZE] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
378
Damien8f7491a2013-10-26 18:01:48 +0100379void stdout_tx_str(const char *str) {
380 usart_tx_str(str);
381 usb_vcp_send_str(str);
382}
383
Damiene9f1e502013-10-22 23:09:25 +0100384int readline(vstr_t *line, const char *prompt) {
Damien8f7491a2013-10-26 18:01:48 +0100385 stdout_tx_str(prompt);
Damiene9f1e502013-10-22 23:09:25 +0100386 int len = vstr_len(line);
Damien9281cd62013-10-26 02:29:02 +0100387 int escape = 0;
388 int hist_num = 0;
Damiene9f1e502013-10-22 23:09:25 +0100389 for (;;) {
Damien8f7491a2013-10-26 18:01:48 +0100390 char c;
391 for (;;) {
392 if (usb_vcp_rx_any() != 0) {
393 c = usb_vcp_rx_get();
394 break;
395 } else if (usart_rx_any()) {
396 c = usart_rx_char();
397 break;
398 }
Damien9281cd62013-10-26 02:29:02 +0100399 sys_tick_delay_ms(1);
Damien52851552013-12-11 00:40:15 +0000400 if (storage_needs_flush()) {
401 storage_flush();
402 }
Damiene9f1e502013-10-22 23:09:25 +0100403 }
Damien9281cd62013-10-26 02:29:02 +0100404 if (escape == 0) {
405 if (c == 4 && vstr_len(line) == len) {
406 return 0;
407 } else if (c == '\r') {
Damien8f7491a2013-10-26 18:01:48 +0100408 stdout_tx_str("\r\n");
Damien9281cd62013-10-26 02:29:02 +0100409 for (int i = READLINE_HIST_SIZE - 1; i > 0; i--) {
410 readline_hist[i] = readline_hist[i - 1];
411 }
412 readline_hist[0] = strdup(vstr_str(line));
413 return 1;
414 } else if (c == 27) {
415 escape = true;
416 } else if (c == 127) {
417 if (vstr_len(line) > len) {
418 vstr_cut_tail(line, 1);
Damien8f7491a2013-10-26 18:01:48 +0100419 stdout_tx_str("\b \b");
Damien9281cd62013-10-26 02:29:02 +0100420 }
421 } else if (32 <= c && c <= 126) {
422 vstr_add_char(line, c);
Damien8f7491a2013-10-26 18:01:48 +0100423 stdout_tx_str(line->buf + line->len - 1);
Damiene9f1e502013-10-22 23:09:25 +0100424 }
Damien9281cd62013-10-26 02:29:02 +0100425 } else if (escape == 1) {
426 if (c == '[') {
427 escape = 2;
428 } else {
429 escape = 0;
430 }
431 } else if (escape == 2) {
432 escape = 0;
433 if (c == 'A') {
434 // up arrow
435 if (hist_num < READLINE_HIST_SIZE && readline_hist[hist_num] != NULL) {
436 // erase line
437 for (int i = line->len - len; i > 0; i--) {
Damien8f7491a2013-10-26 18:01:48 +0100438 stdout_tx_str("\b \b");
Damien9281cd62013-10-26 02:29:02 +0100439 }
440 // set line to history
441 line->len = len;
442 vstr_add_str(line, readline_hist[hist_num]);
443 // draw line
Damien8f7491a2013-10-26 18:01:48 +0100444 stdout_tx_str(readline_hist[hist_num]);
Damien9281cd62013-10-26 02:29:02 +0100445 // increase hist num
446 hist_num += 1;
447 }
448 }
449 } else {
450 escape = 0;
Damiene9f1e502013-10-22 23:09:25 +0100451 }
Damien9281cd62013-10-26 02:29:02 +0100452 sys_tick_delay_ms(10);
Damiene9f1e502013-10-22 23:09:25 +0100453 }
454}
455
Damien0f654512013-10-23 20:39:20 +0100456void do_repl(void) {
Damien George28708622014-01-02 21:30:26 +0000457 stdout_tx_str("Micro Python build <git hash> on 2/1/2014; PYBv3 with STM32F405RG\r\n");
Damien8c3da5c2013-12-17 18:36:19 +0000458 stdout_tx_str("Type \"help()\" for more information.\r\n");
Damiene9f1e502013-10-22 23:09:25 +0100459
460 vstr_t line;
461 vstr_init(&line);
Damien4b6e85c2013-10-21 09:56:56 +0100462
463 for (;;) {
Damiene9f1e502013-10-22 23:09:25 +0100464 vstr_reset(&line);
465 int ret = readline(&line, ">>> ");
466 if (ret == 0) {
Damien4b6e85c2013-10-21 09:56:56 +0100467 // EOF
Damiene9f1e502013-10-22 23:09:25 +0100468 break;
Damien4b6e85c2013-10-21 09:56:56 +0100469 }
Damiene9f1e502013-10-22 23:09:25 +0100470
471 if (vstr_len(&line) == 0) {
472 continue;
473 }
474
Damiend99b0522013-12-21 18:17:45 +0000475 if (mp_repl_is_compound_stmt(vstr_str(&line))) {
Damien4b6e85c2013-10-21 09:56:56 +0100476 for (;;) {
Damiene9f1e502013-10-22 23:09:25 +0100477 vstr_add_char(&line, '\n');
478 int len = vstr_len(&line);
479 int ret = readline(&line, "... ");
480 if (ret == 0 || vstr_len(&line) == len) {
481 // done entering compound statement
Damien4b6e85c2013-10-21 09:56:56 +0100482 break;
483 }
Damien4b6e85c2013-10-21 09:56:56 +0100484 }
485 }
Damien4b6e85c2013-10-21 09:56:56 +0100486
Damiend99b0522013-12-21 18:17:45 +0000487 mp_lexer_str_buf_t sb;
488 mp_lexer_t *lex = mp_lexer_new_from_str_len("<stdin>", vstr_str(&line), vstr_len(&line), false, &sb);
489 mp_parse_node_t pn = mp_parse(lex, MP_PARSE_SINGLE_INPUT);
490 mp_lexer_free(lex);
Damien4b6e85c2013-10-21 09:56:56 +0100491
Damiend99b0522013-12-21 18:17:45 +0000492 if (pn != MP_PARSE_NODE_NULL) {
Damien George1fb03172014-01-03 14:22:03 +0000493 mp_obj_t module_fun = mp_compile(pn, true);
494 if (module_fun != mp_const_none) {
495 nlr_buf_t nlr;
496 uint32_t start = sys_tick_counter;
497 if (nlr_push(&nlr) == 0) {
498 rt_call_function_0(module_fun);
499 nlr_pop();
500 // optional timing
501 if (0) {
502 uint32_t ticks = sys_tick_counter - start; // TODO implement a function that does this properly
503 printf("(took %lu ms)\n", ticks);
Damien4b6e85c2013-10-21 09:56:56 +0100504 }
Damien George1fb03172014-01-03 14:22:03 +0000505 } else {
506 // uncaught exception
507 mp_obj_print((mp_obj_t)nlr.ret_val);
508 printf("\n");
Damien4b6e85c2013-10-21 09:56:56 +0100509 }
510 }
511 }
512 }
Damiene9f1e502013-10-22 23:09:25 +0100513
Damien8f7491a2013-10-26 18:01:48 +0100514 stdout_tx_str("\r\n");
Damien94186c82013-10-23 00:02:06 +0100515}
516
517bool do_file(const char *filename) {
Damiend99b0522013-12-21 18:17:45 +0000518 mp_lexer_file_buf_t fb;
519 mp_lexer_t *lex = mp_lexer_new_from_file(filename, &fb);
Damien94186c82013-10-23 00:02:06 +0100520
521 if (lex == NULL) {
522 printf("could not open file '%s' for reading\n", filename);
523 return false;
524 }
525
Damiend99b0522013-12-21 18:17:45 +0000526 mp_parse_node_t pn = mp_parse(lex, MP_PARSE_FILE_INPUT);
527 mp_lexer_free(lex);
Damien94186c82013-10-23 00:02:06 +0100528
Damiend99b0522013-12-21 18:17:45 +0000529 if (pn == MP_PARSE_NODE_NULL) {
Damien94186c82013-10-23 00:02:06 +0100530 return false;
531 }
532
Damien George1fb03172014-01-03 14:22:03 +0000533 mp_obj_t module_fun = mp_compile(pn, false);
Damiend99b0522013-12-21 18:17:45 +0000534 if (module_fun == mp_const_none) {
Damien94186c82013-10-23 00:02:06 +0100535 return false;
536 }
537
538 nlr_buf_t nlr;
539 if (nlr_push(&nlr) == 0) {
540 rt_call_function_0(module_fun);
541 nlr_pop();
542 return true;
543 } else {
544 // uncaught exception
Damiend99b0522013-12-21 18:17:45 +0000545 mp_obj_print((mp_obj_t)nlr.ret_val);
Damien94186c82013-10-23 00:02:06 +0100546 printf("\n");
547 return false;
548 }
Damien4b6e85c2013-10-21 09:56:56 +0100549}
550
Damien0c5827f2013-10-22 21:13:36 +0100551#define RAM_START (0x20000000) // fixed for chip
552#define HEAP_END (0x2001c000) // tunable
553#define RAM_END (0x20020000) // fixed for chip
554
555void gc_helper_get_regs_and_clean_stack(machine_uint_t *regs, machine_uint_t heap_end);
556
Damien0f654512013-10-23 20:39:20 +0100557void gc_collect(void) {
Damien0c5827f2013-10-22 21:13:36 +0100558 uint32_t start = sys_tick_counter;
Damien3f69aca2013-10-21 23:46:04 +0100559 gc_collect_start();
Damien0c5827f2013-10-22 21:13:36 +0100560 gc_collect_root((void**)RAM_START, (((uint32_t)&_heap_start) - RAM_START) / 4);
561 machine_uint_t regs[10];
562 gc_helper_get_regs_and_clean_stack(regs, HEAP_END);
563 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 +0100564 gc_collect_end();
Damien0c5827f2013-10-22 21:13:36 +0100565 uint32_t ticks = sys_tick_counter - start; // TODO implement a function that does this properly
Damien8c3da5c2013-12-17 18:36:19 +0000566
567 if (0) {
568 // print GC info
569 gc_info_t info;
570 gc_info(&info);
571 printf("GC@%lu %lums\n", start, ticks);
572 printf(" %lu total\n", info.total);
573 printf(" %lu : %lu\n", info.used, info.free);
574 printf(" 1=%lu 2=%lu m=%lu\n", info.num_1block, info.num_2block, info.max_block);
575 }
Damien0c5827f2013-10-22 21:13:36 +0100576}
577
Damiend99b0522013-12-21 18:17:45 +0000578mp_obj_t pyb_gc(void) {
Damien0c5827f2013-10-22 21:13:36 +0100579 gc_collect();
Damiend99b0522013-12-21 18:17:45 +0000580 return mp_const_none;
Damien0c70f882013-11-03 18:30:57 +0000581}
582
Damien George28708622014-01-02 21:30:26 +0000583mp_obj_t pyb_gpio(int n_args, mp_obj_t *args) {
584 //assert(1 <= n_args && n_args <= 2);
Damien6f08f8c2013-10-23 22:17:26 +0100585
Damien George28708622014-01-02 21:30:26 +0000586 const char *pin_name = qstr_str(mp_obj_get_qstr(args[0]));
587 GPIO_TypeDef *port;
588 switch (pin_name[0]) {
589 case 'A': case 'a': port = GPIOA; break;
590 case 'B': case 'b': port = GPIOB; break;
591 case 'C': case 'c': port = GPIOC; break;
592 default: goto pin_error;
Damien8fe84132013-11-30 15:06:24 +0000593 }
Damien George28708622014-01-02 21:30:26 +0000594 uint pin_num = 0;
595 for (const char *s = pin_name + 1; *s; s++) {
596 if (!('0' <= *s && *s <= '9')) {
597 goto pin_error;
Damien6f08f8c2013-10-23 22:17:26 +0100598 }
Damien George28708622014-01-02 21:30:26 +0000599 pin_num = 10 * pin_num + *s - '0';
Damien6f08f8c2013-10-23 22:17:26 +0100600 }
Damien George28708622014-01-02 21:30:26 +0000601 if (!(0 <= pin_num && pin_num <= 15)) {
602 goto pin_error;
603 }
Damien8fe84132013-11-30 15:06:24 +0000604
Damien George28708622014-01-02 21:30:26 +0000605 if (n_args == 1) {
606 // get pin
607 if ((port->IDR & (1 << pin_num)) != (uint32_t)Bit_RESET) {
608 return MP_OBJ_NEW_SMALL_INT(1);
609 } else {
610 return MP_OBJ_NEW_SMALL_INT(0);
611 }
612 } else {
613 // set pin
614 if (rt_is_true(args[1])) {
615 // set pin high
616 port->BSRRL = 1 << pin_num;
617 } else {
618 // set pin low
619 port->BSRRH = 1 << pin_num;
620 }
621 return mp_const_none;
622 }
Damien8fe84132013-11-30 15:06:24 +0000623
Damien George28708622014-01-02 21:30:26 +0000624pin_error:
Damien Georgeeb7bfcb2014-01-04 15:57:35 +0000625 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 +0100626}
627
Damien George28708622014-01-02 21:30:26 +0000628MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_gpio_obj, 1, 2, pyb_gpio);
629
Damiend99b0522013-12-21 18:17:45 +0000630mp_obj_t pyb_hid_send_report(mp_obj_t arg) {
631 mp_obj_t *items = mp_obj_get_array_fixed_n(arg, 4);
Damien58a1b4c2013-10-25 20:53:54 +0100632 uint8_t data[4];
Damiend99b0522013-12-21 18:17:45 +0000633 data[0] = mp_obj_get_int(items[0]);
634 data[1] = mp_obj_get_int(items[1]);
635 data[2] = mp_obj_get_int(items[2]);
636 data[3] = mp_obj_get_int(items[3]);
Damien58a1b4c2013-10-25 20:53:54 +0100637 usb_hid_send_report(data);
Damiend99b0522013-12-21 18:17:45 +0000638 return mp_const_none;
Damien58a1b4c2013-10-25 20:53:54 +0100639}
640
Damien81289412013-10-26 02:06:37 +0100641static void rtc_init(void) {
642 /* Enable the PWR clock */
643 RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
644
645 /* Allow access to RTC */
646 PWR_BackupAccessCmd(ENABLE);
647
648 /* Enable the LSE OSC */
649 RCC_LSEConfig(RCC_LSE_ON);
650
651 /* Wait till LSE is ready */
652 while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET) {
653 }
654
655 /* Select the RTC Clock Source */
656 RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
657 /* ck_spre(1Hz) = RTCCLK(LSE) /(uwAsynchPrediv + 1)*(uwSynchPrediv + 1)*/
658 uint32_t uwSynchPrediv = 0xFF;
659 uint32_t uwAsynchPrediv = 0x7F;
660
661 /* Enable the RTC Clock */
662 RCC_RTCCLKCmd(ENABLE);
663
664 /* Wait for RTC APB registers synchronisation */
665 RTC_WaitForSynchro();
666
667 /* Configure the RTC data register and RTC prescaler */
668 RTC_InitTypeDef RTC_InitStructure;
669 RTC_InitStructure.RTC_AsynchPrediv = uwAsynchPrediv;
670 RTC_InitStructure.RTC_SynchPrediv = uwSynchPrediv;
671 RTC_InitStructure.RTC_HourFormat = RTC_HourFormat_24;
672 RTC_Init(&RTC_InitStructure);
673
674 // Set the date (BCD)
675 RTC_DateTypeDef RTC_DateStructure;
676 RTC_DateStructure.RTC_Year = 0x13;
677 RTC_DateStructure.RTC_Month = RTC_Month_October;
678 RTC_DateStructure.RTC_Date = 0x26;
679 RTC_DateStructure.RTC_WeekDay = RTC_Weekday_Saturday;
680 RTC_SetDate(RTC_Format_BCD, &RTC_DateStructure);
681
682 // Set the time (BCD)
683 RTC_TimeTypeDef RTC_TimeStructure;
684 RTC_TimeStructure.RTC_H12 = RTC_H12_AM;
685 RTC_TimeStructure.RTC_Hours = 0x01;
686 RTC_TimeStructure.RTC_Minutes = 0x53;
687 RTC_TimeStructure.RTC_Seconds = 0x00;
688 RTC_SetTime(RTC_Format_BCD, &RTC_TimeStructure);
689
690 // Indicator for the RTC configuration
691 //RTC_WriteBackupRegister(RTC_BKP_DR0, 0x32F2);
692}
693
Damiend99b0522013-12-21 18:17:45 +0000694mp_obj_t pyb_rtc_read(void) {
Damien81289412013-10-26 02:06:37 +0100695 RTC_TimeTypeDef RTC_TimeStructure;
696 RTC_GetTime(RTC_Format_BIN, &RTC_TimeStructure);
697 printf("%02d:%02d:%02d\n", RTC_TimeStructure.RTC_Hours, RTC_TimeStructure.RTC_Minutes, RTC_TimeStructure.RTC_Seconds);
Damiend99b0522013-12-21 18:17:45 +0000698 return mp_const_none;
Damien81289412013-10-26 02:06:37 +0100699}
700
Damiend99b0522013-12-21 18:17:45 +0000701typedef struct _pyb_file_obj_t {
702 mp_obj_base_t base;
703 FIL fp;
704} pyb_file_obj_t;
705
706void file_obj_print(void (*print)(void *env, const char *fmt, ...), void *env, mp_obj_t self_in) {
707 printf("<file %p>", self_in);
Damien0e496732013-11-03 14:53:34 +0000708}
709
Damiend99b0522013-12-21 18:17:45 +0000710mp_obj_t file_obj_read(mp_obj_t self_in, mp_obj_t arg) {
711 pyb_file_obj_t *self = self_in;
712 int n = mp_obj_get_int(arg);
Damien0e496732013-11-03 14:53:34 +0000713 char *buf = m_new(char, n + 1);
714 UINT n_out;
Damiend99b0522013-12-21 18:17:45 +0000715 f_read(&self->fp, buf, n, &n_out);
Damien0e496732013-11-03 14:53:34 +0000716 buf[n_out] = 0;
Damien732407f2013-12-29 19:33:23 +0000717 return mp_obj_new_str(qstr_from_str_take(buf, n + 1));
Damien0e496732013-11-03 14:53:34 +0000718}
719
Damiend99b0522013-12-21 18:17:45 +0000720mp_obj_t file_obj_write(mp_obj_t self_in, mp_obj_t arg) {
721 pyb_file_obj_t *self = self_in;
722 const char *s = qstr_str(mp_obj_get_qstr(arg));
Damien0e496732013-11-03 14:53:34 +0000723 UINT n_out;
Damiend99b0522013-12-21 18:17:45 +0000724 FRESULT res = f_write(&self->fp, s, strlen(s), &n_out);
Damien0e496732013-11-03 14:53:34 +0000725 if (res != FR_OK) {
726 printf("File error: could not write to file; error code %d\n", res);
727 } else if (n_out != strlen(s)) {
728 printf("File error: could not write all data to file; wrote %d / %d bytes\n", n_out, strlen(s));
729 }
Damiend99b0522013-12-21 18:17:45 +0000730 return mp_const_none;
Damien0e496732013-11-03 14:53:34 +0000731}
732
Damiend99b0522013-12-21 18:17:45 +0000733mp_obj_t file_obj_close(mp_obj_t self_in) {
734 pyb_file_obj_t *self = self_in;
735 f_close(&self->fp);
736 return mp_const_none;
Damien0e496732013-11-03 14:53:34 +0000737}
738
Damiend99b0522013-12-21 18:17:45 +0000739static MP_DEFINE_CONST_FUN_OBJ_2(file_obj_read_obj, file_obj_read);
740static MP_DEFINE_CONST_FUN_OBJ_2(file_obj_write_obj, file_obj_write);
741static MP_DEFINE_CONST_FUN_OBJ_1(file_obj_close_obj, file_obj_close);
742
Damien0e496732013-11-03 14:53:34 +0000743// TODO gc hook to close the file if not already closed
Damiend99b0522013-12-21 18:17:45 +0000744
745static const mp_obj_type_t file_obj_type = {
746 { &mp_const_type },
Damien0e496732013-11-03 14:53:34 +0000747 "File",
Damiend99b0522013-12-21 18:17:45 +0000748 file_obj_print, // print
749 NULL, // call_n
750 NULL, // unary_op
751 NULL, // binary_op
752 NULL, // getiter
753 NULL, // iternext
754 { // method list
755 { "read", &file_obj_read_obj },
756 { "write", &file_obj_write_obj },
757 { "close", &file_obj_close_obj },
758 {NULL, NULL},
Damien0e496732013-11-03 14:53:34 +0000759 }
760};
761
Damiend99b0522013-12-21 18:17:45 +0000762mp_obj_t pyb_io_open(mp_obj_t o_filename, mp_obj_t o_mode) {
763 const char *filename = qstr_str(mp_obj_get_qstr(o_filename));
764 const char *mode = qstr_str(mp_obj_get_qstr(o_mode));
765 pyb_file_obj_t *self = m_new_obj(pyb_file_obj_t);
766 self->base.type = &file_obj_type;
Damien0e496732013-11-03 14:53:34 +0000767 if (mode[0] == 'r') {
768 // open for reading
Damiend99b0522013-12-21 18:17:45 +0000769 FRESULT res = f_open(&self->fp, filename, FA_READ);
Damien0e496732013-11-03 14:53:34 +0000770 if (res != FR_OK) {
771 printf("FileNotFoundError: [Errno 2] No such file or directory: '%s'\n", filename);
Damiend99b0522013-12-21 18:17:45 +0000772 return mp_const_none;
Damien0e496732013-11-03 14:53:34 +0000773 }
774 } else if (mode[0] == 'w') {
775 // open for writing, truncate the file first
Damiend99b0522013-12-21 18:17:45 +0000776 FRESULT res = f_open(&self->fp, filename, FA_WRITE | FA_CREATE_ALWAYS);
Damien0e496732013-11-03 14:53:34 +0000777 if (res != FR_OK) {
778 printf("?FileError: could not create file: '%s'\n", filename);
Damiend99b0522013-12-21 18:17:45 +0000779 return mp_const_none;
Damien0e496732013-11-03 14:53:34 +0000780 }
781 } else {
782 printf("ValueError: invalid mode: '%s'\n", mode);
Damiend99b0522013-12-21 18:17:45 +0000783 return mp_const_none;
Damien0e496732013-11-03 14:53:34 +0000784 }
Damiend99b0522013-12-21 18:17:45 +0000785 return self;
Damien0e496732013-11-03 14:53:34 +0000786}
787
Damiend99b0522013-12-21 18:17:45 +0000788mp_obj_t pyb_rng_get(void) {
789 return mp_obj_new_int(RNG_GetRandomNumber() >> 16);
Damien39c6c592013-11-09 20:15:48 +0000790}
791
Damien0f654512013-10-23 20:39:20 +0100792int main(void) {
Damien00ff04f2013-10-19 14:40:54 +0100793 // TODO disable JTAG
794
Damiend6b4c662013-12-06 00:41:33 +0000795 // update the SystemCoreClock variable
796 SystemCoreClockUpdate();
797
Damienafe12bc2013-10-19 18:13:48 +0100798 // set interrupt priority config to use all 4 bits for pre-empting
799 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
800
801 // enable the CCM RAM and the GPIO's
802 RCC->AHB1ENR |= RCC_AHB1ENR_CCMDATARAMEN | RCC_AHB1ENR_GPIOAEN | RCC_AHB1ENR_GPIOBEN | RCC_AHB1ENR_GPIOCEN;
803
Damien5892f472013-10-26 18:02:46 +0100804 // configure SDIO pins to be high to start with (apparently makes it more robust)
Damien7ee80ba2013-10-24 00:22:27 +0100805 {
806 GPIO_InitTypeDef GPIO_InitStructure;
807 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12;
808 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_25MHz;
809 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
810 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
811 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
812 GPIO_Init(GPIOC, &GPIO_InitStructure);
813
814 // Configure PD.02 CMD line
815 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
816 GPIO_Init(GPIOD, &GPIO_InitStructure);
817 }
818
Damien00ff04f2013-10-19 14:40:54 +0100819 // basic sub-system init
820 sys_tick_init();
Damien00ff04f2013-10-19 14:40:54 +0100821 led_init();
Damien81289412013-10-26 02:06:37 +0100822 rtc_init();
Damien00ff04f2013-10-19 14:40:54 +0100823
824 // turn on LED to indicate bootup
825 led_state(PYB_LED_G1, 1);
826
827 // more sub-system init
828 sw_init();
Damien00ff04f2013-10-19 14:40:54 +0100829 storage_init();
Damien065f8a52013-12-05 20:38:23 +0000830
831 //usart_init(); disabled while wi-fi is enabled
Damien00ff04f2013-10-19 14:40:54 +0100832
Damienbd8e1102013-11-06 23:04:33 +0000833 int first_soft_reset = true;
834
Damiene9f1e502013-10-22 23:09:25 +0100835soft_reset:
836
Damien3f69aca2013-10-21 23:46:04 +0100837 // GC init
Damien0c5827f2013-10-22 21:13:36 +0100838 gc_init(&_heap_start, (void*)HEAP_END);
Damien3f69aca2013-10-21 23:46:04 +0100839
Damiene9f1e502013-10-22 23:09:25 +0100840 // Micro Python init
Damienafe12bc2013-10-19 18:13:48 +0100841 qstr_init();
842 rt_init();
Damien00ff04f2013-10-19 14:40:54 +0100843
Damien39c6c592013-11-09 20:15:48 +0000844 // LCD init
Damien8fe84132013-11-30 15:06:24 +0000845 //lcd_init(); disabled while servos on PA0 PA1
Damien39c6c592013-11-09 20:15:48 +0000846
Damien0f654512013-10-23 20:39:20 +0100847 // servo
848 servo_init();
849
Damien1c62d042013-11-04 23:05:48 +0000850 // audio
Damien52851552013-12-11 00:40:15 +0000851 //audio_init();
Damien1c62d042013-11-04 23:05:48 +0000852
Damienbd8e1102013-11-06 23:04:33 +0000853 // timer
854 timer_init();
855
Damien39c6c592013-11-09 20:15:48 +0000856 // RNG
Damien8c3da5c2013-12-17 18:36:19 +0000857 if (1) {
Damien39c6c592013-11-09 20:15:48 +0000858 RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_RNG, ENABLE);
859 RNG_Cmd(ENABLE);
860 }
861
Damienf48cf672013-10-21 10:42:06 +0100862 // add some functions to the python namespace
Damiene9f1e502013-10-22 23:09:25 +0100863 {
Damien8c3da5c2013-12-17 18:36:19 +0000864 rt_store_name(qstr_from_str_static("help"), rt_make_function_0(pyb_help));
865
Damien George28708622014-01-02 21:30:26 +0000866 mp_obj_t m = mp_obj_new_module(qstr_from_str_static("pyb"));
Damiene9f1e502013-10-22 23:09:25 +0100867 rt_store_attr(m, qstr_from_str_static("info"), rt_make_function_0(pyb_info));
Damienb73085d2013-12-20 11:45:06 +0000868 rt_store_attr(m, qstr_from_str_static("sd_test"), rt_make_function_0(pyb_sd_test));
Damien52851552013-12-11 00:40:15 +0000869 rt_store_attr(m, qstr_from_str_static("stop"), rt_make_function_0(pyb_stop));
870 rt_store_attr(m, qstr_from_str_static("standby"), rt_make_function_0(pyb_standby));
Damiene9f1e502013-10-22 23:09:25 +0100871 rt_store_attr(m, qstr_from_str_static("source_dir"), rt_make_function_1(pyb_source_dir));
872 rt_store_attr(m, qstr_from_str_static("main"), rt_make_function_1(pyb_main));
Damien94186c82013-10-23 00:02:06 +0100873 rt_store_attr(m, qstr_from_str_static("sync"), rt_make_function_0(pyb_sync));
Damiene9f1e502013-10-22 23:09:25 +0100874 rt_store_attr(m, qstr_from_str_static("gc"), rt_make_function_0(pyb_gc));
875 rt_store_attr(m, qstr_from_str_static("delay"), rt_make_function_1(pyb_delay));
876 rt_store_attr(m, qstr_from_str_static("led"), rt_make_function_1(pyb_led));
Damien8c3da5c2013-12-17 18:36:19 +0000877 rt_store_attr(m, qstr_from_str_static("switch"), rt_make_function_0(pyb_sw));
Damien8fe84132013-11-30 15:06:24 +0000878 rt_store_attr(m, qstr_from_str_static("servo"), rt_make_function_2(pyb_servo_set));
Damien0c70f882013-11-03 18:30:57 +0000879 rt_store_attr(m, qstr_from_str_static("pwm"), rt_make_function_2(pyb_pwm_set));
Damien George28708622014-01-02 21:30:26 +0000880 rt_store_attr(m, qstr_from_str_static("accel"), (mp_obj_t)&pyb_mma_read_obj);
881 rt_store_attr(m, qstr_from_str_static("mma_read"), (mp_obj_t)&pyb_mma_read_all_obj);
882 rt_store_attr(m, qstr_from_str_static("mma_mode"), (mp_obj_t)&pyb_mma_write_mode_obj);
Damien58a1b4c2013-10-25 20:53:54 +0100883 rt_store_attr(m, qstr_from_str_static("hid"), rt_make_function_1(pyb_hid_send_report));
Damien81289412013-10-26 02:06:37 +0100884 rt_store_attr(m, qstr_from_str_static("time"), rt_make_function_0(pyb_rtc_read));
Damien8f7491a2013-10-26 18:01:48 +0100885 rt_store_attr(m, qstr_from_str_static("uout"), rt_make_function_1(pyb_usart_send));
886 rt_store_attr(m, qstr_from_str_static("uin"), rt_make_function_0(pyb_usart_receive));
887 rt_store_attr(m, qstr_from_str_static("ustat"), rt_make_function_0(pyb_usart_status));
Damien8c3da5c2013-12-17 18:36:19 +0000888 rt_store_attr(m, qstr_from_str_static("rand"), rt_make_function_0(pyb_rng_get));
Damiend6b4c662013-12-06 00:41:33 +0000889 rt_store_attr(m, qstr_from_str_static("Led"), rt_make_function_1(pyb_Led));
Damien52851552013-12-11 00:40:15 +0000890 rt_store_attr(m, qstr_from_str_static("Servo"), rt_make_function_1(pyb_Servo));
Hagen Kaye07590c22013-12-28 20:22:12 -0500891 rt_store_attr(m, qstr_from_str_static("I2C"), rt_make_function_2(pyb_I2C));
Damien George28708622014-01-02 21:30:26 +0000892 rt_store_attr(m, qstr_from_str_static("gpio"), (mp_obj_t)&pyb_gpio_obj);
Damiene9f1e502013-10-22 23:09:25 +0100893 rt_store_name(qstr_from_str_static("pyb"), m);
Damien0e496732013-11-03 14:53:34 +0000894
895 rt_store_name(qstr_from_str_static("open"), rt_make_function_2(pyb_io_open));
Damiene9f1e502013-10-22 23:09:25 +0100896 }
Damienf48cf672013-10-21 10:42:06 +0100897
Damiene9f1e502013-10-22 23:09:25 +0100898 // print a message to the LCD
899 lcd_print_str(" micro py board\n");
Damien00ff04f2013-10-19 14:40:54 +0100900
Damiend6b4c662013-12-06 00:41:33 +0000901 // check if user switch held (initiates reset of filesystem)
902 bool reset_filesystem = false;
903 if (sw_get()) {
904 reset_filesystem = true;
905 for (int i = 0; i < 50; i++) {
906 if (!sw_get()) {
907 reset_filesystem = false;
908 break;
909 }
910 sys_tick_delay_ms(10);
911 }
912 }
913
Damien00ff04f2013-10-19 14:40:54 +0100914 // local filesystem init
915 {
916 // try to mount the flash
917 FRESULT res = f_mount(&fatfs0, "0:", 1);
Damiend6b4c662013-12-06 00:41:33 +0000918 if (!reset_filesystem && res == FR_OK) {
Damien00ff04f2013-10-19 14:40:54 +0100919 // mount sucessful
Damiend6b4c662013-12-06 00:41:33 +0000920 } else if (reset_filesystem || res == FR_NO_FILESYSTEM) {
Damien00ff04f2013-10-19 14:40:54 +0100921 // no filesystem, so create a fresh one
Damiend6b4c662013-12-06 00:41:33 +0000922 // TODO doesn't seem to work correctly when reset_filesystem is true...
Damien00ff04f2013-10-19 14:40:54 +0100923
924 // LED on to indicate creation of LFS
925 led_state(PYB_LED_R2, 1);
926 uint32_t stc = sys_tick_counter;
927
928 res = f_mkfs("0:", 0, 0);
929 if (res == FR_OK) {
930 // success creating fresh LFS
931 } else {
932 __fatal_error("could not create LFS");
933 }
934
Damien8c3da5c2013-12-17 18:36:19 +0000935 // create src directory
936 res = f_mkdir("0:/src");
937 // ignore result from mkdir
938
939 // create empty main.py
940 FIL fp;
941 f_open(&fp, "0:/src/main.py", FA_WRITE | FA_CREATE_ALWAYS);
942 UINT n;
943 f_write(&fp, fresh_main_py, sizeof(fresh_main_py) - 1 /* don't count null terminator */, &n);
944 // TODO check we could write n bytes
945 f_close(&fp);
946
Damienafe12bc2013-10-19 18:13:48 +0100947 // keep LED on for at least 200ms
948 sys_tick_wait_at_least(stc, 200);
Damien00ff04f2013-10-19 14:40:54 +0100949 led_state(PYB_LED_R2, 0);
950 } else {
951 __fatal_error("could not access LFS");
Damien4a175e12013-10-17 22:50:21 +0100952 }
Damien00ff04f2013-10-19 14:40:54 +0100953 }
954
955 // make sure we have a /boot.py
956 {
957 FILINFO fno;
958 FRESULT res = f_stat("0:/boot.py", &fno);
959 if (res == FR_OK) {
960 if (fno.fattrib & AM_DIR) {
961 // exists as a directory
962 // TODO handle this case
963 // see http://elm-chan.org/fsw/ff/img/app2.c for a "rm -rf" implementation
964 } else {
965 // exists as a file, good!
966 }
967 } else {
968 // doesn't exist, create fresh file
969
970 // LED on to indicate creation of boot.py
971 led_state(PYB_LED_R2, 1);
972 uint32_t stc = sys_tick_counter;
973
974 FIL fp;
975 f_open(&fp, "0:/boot.py", FA_WRITE | FA_CREATE_ALWAYS);
976 UINT n;
Damiene9f1e502013-10-22 23:09:25 +0100977 f_write(&fp, fresh_boot_py, sizeof(fresh_boot_py) - 1 /* don't count null terminator */, &n);
Damien00ff04f2013-10-19 14:40:54 +0100978 // TODO check we could write n bytes
979 f_close(&fp);
980
Damienafe12bc2013-10-19 18:13:48 +0100981 // keep LED on for at least 200ms
982 sys_tick_wait_at_least(stc, 200);
Damien00ff04f2013-10-19 14:40:54 +0100983 led_state(PYB_LED_R2, 0);
984 }
985 }
986
Damien94186c82013-10-23 00:02:06 +0100987 // run /boot.py
988 if (!do_file("0:/boot.py")) {
989 flash_error(4);
990 }
991
Damiene9f1e502013-10-22 23:09:25 +0100992 // USB
993 usb_init();
994
Damien6f08f8c2013-10-23 22:17:26 +0100995 // MMA
Damienbd8e1102013-11-06 23:04:33 +0000996 if (first_soft_reset) {
Damien6f08f8c2013-10-23 22:17:26 +0100997 // init and reset address to zero
998 mma_init();
Damien6f08f8c2013-10-23 22:17:26 +0100999 }
1000
Damien00ff04f2013-10-19 14:40:54 +01001001 // turn boot-up LED off
1002 led_state(PYB_LED_G1, 0);
1003
Damien94186c82013-10-23 00:02:06 +01001004 // run main script
1005 {
1006 vstr_t *vstr = vstr_new();
1007 vstr_add_str(vstr, "0:/");
1008 if (pyb_config_source_dir == 0) {
1009 vstr_add_str(vstr, "src");
1010 } else {
1011 vstr_add_str(vstr, qstr_str(pyb_config_source_dir));
1012 }
1013 vstr_add_char(vstr, '/');
1014 if (pyb_config_main == 0) {
1015 vstr_add_str(vstr, "main.py");
1016 } else {
1017 vstr_add_str(vstr, qstr_str(pyb_config_main));
1018 }
1019 if (!do_file(vstr_str(vstr))) {
1020 flash_error(3);
1021 }
1022 vstr_free(vstr);
1023 }
1024
Damien00ff04f2013-10-19 14:40:54 +01001025 //printf("init;al=%u\n", m_get_total_bytes_allocated()); // 1600, due to qstr_init
1026 //sys_tick_delay_ms(1000);
1027
Damiened656052013-10-13 00:42:20 +01001028 // Python!
Damien4b6e85c2013-10-21 09:56:56 +01001029 if (0) {
Damiened656052013-10-13 00:42:20 +01001030 //const char *pysrc = "def f():\n x=x+1\nprint(42)\n";
1031 const char *pysrc =
1032 // impl01.py
1033 /*
1034 "x = 0\n"
1035 "while x < 400:\n"
1036 " y = 0\n"
1037 " while y < 400:\n"
1038 " z = 0\n"
1039 " while z < 400:\n"
1040 " z = z + 1\n"
1041 " y = y + 1\n"
1042 " x = x + 1\n";
1043 */
1044 // impl02.py
Damien152568b2013-10-16 00:46:39 +01001045 /*
Damiened656052013-10-13 00:42:20 +01001046 "#@micropython.native\n"
1047 "def f():\n"
1048 " x = 0\n"
1049 " while x < 400:\n"
1050 " y = 0\n"
1051 " while y < 400:\n"
1052 " z = 0\n"
1053 " while z < 400:\n"
1054 " z = z + 1\n"
1055 " y = y + 1\n"
1056 " x = x + 1\n"
1057 "f()\n";
Damien152568b2013-10-16 00:46:39 +01001058 */
Damien0c5827f2013-10-22 21:13:36 +01001059 /*
Damiened656052013-10-13 00:42:20 +01001060 "print('in python!')\n"
1061 "x = 0\n"
1062 "while x < 4:\n"
1063 " pyb_led(True)\n"
1064 " pyb_delay(201)\n"
1065 " pyb_led(False)\n"
1066 " pyb_delay(201)\n"
Damienfa2162b2013-10-20 17:42:00 +01001067 " x += 1\n"
Damiened656052013-10-13 00:42:20 +01001068 "print('press me!')\n"
1069 "while True:\n"
1070 " pyb_led(pyb_sw())\n";
Damien0c5827f2013-10-22 21:13:36 +01001071 */
Damiened656052013-10-13 00:42:20 +01001072 /*
1073 // impl16.py
1074 "@micropython.asm_thumb\n"
1075 "def delay(r0):\n"
1076 " b(loop_entry)\n"
1077 " label(loop1)\n"
1078 " movw(r1, 55999)\n"
1079 " label(loop2)\n"
1080 " subs(r1, r1, 1)\n"
1081 " cmp(r1, 0)\n"
1082 " bgt(loop2)\n"
1083 " subs(r0, r0, 1)\n"
1084 " label(loop_entry)\n"
1085 " cmp(r0, 0)\n"
1086 " bgt(loop1)\n"
1087 "print('in python!')\n"
1088 "@micropython.native\n"
1089 "def flash(n):\n"
1090 " x = 0\n"
1091 " while x < n:\n"
1092 " pyb_led(True)\n"
1093 " delay(249)\n"
1094 " pyb_led(False)\n"
1095 " delay(249)\n"
1096 " x = x + 1\n"
1097 "flash(20)\n";
1098 */
Damien152568b2013-10-16 00:46:39 +01001099 // impl18.py
1100 /*
1101 "# basic exceptions\n"
1102 "x = 1\n"
1103 "try:\n"
1104 " x.a()\n"
1105 "except:\n"
1106 " print(x)\n";
1107 */
1108 // impl19.py
1109 "# for loop\n"
1110 "def f():\n"
1111 " for x in range(400):\n"
1112 " for y in range(400):\n"
1113 " for z in range(400):\n"
1114 " pass\n"
1115 "f()\n";
Damiened656052013-10-13 00:42:20 +01001116
Damiend99b0522013-12-21 18:17:45 +00001117 mp_lexer_str_buf_t mp_lexer_str_buf;
1118 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 +01001119
Damienfa2162b2013-10-20 17:42:00 +01001120 // nalloc=1740;6340;6836 -> 140;4600;496 bytes for lexer, parser, compiler
1121 printf("lex; al=%u\n", m_get_total_bytes_allocated());
1122 sys_tick_delay_ms(1000);
Damiend99b0522013-12-21 18:17:45 +00001123 mp_parse_node_t pn = mp_parse(lex, MP_PARSE_FILE_INPUT);
1124 mp_lexer_free(lex);
1125 if (pn != MP_PARSE_NODE_NULL) {
Damiened656052013-10-13 00:42:20 +01001126 printf("pars;al=%u\n", m_get_total_bytes_allocated());
Damien00ff04f2013-10-19 14:40:54 +01001127 sys_tick_delay_ms(1000);
Damiened656052013-10-13 00:42:20 +01001128 //parse_node_show(pn, 0);
Damien George1fb03172014-01-03 14:22:03 +00001129 mp_obj_t module_fun = mp_compile(pn, false);
Damiened656052013-10-13 00:42:20 +01001130 printf("comp;al=%u\n", m_get_total_bytes_allocated());
Damien00ff04f2013-10-19 14:40:54 +01001131 sys_tick_delay_ms(1000);
Damiened656052013-10-13 00:42:20 +01001132
Damien George1fb03172014-01-03 14:22:03 +00001133 if (module_fun == mp_const_none) {
Damienfa2162b2013-10-20 17:42:00 +01001134 printf("compile error\n");
1135 } else {
Damiened656052013-10-13 00:42:20 +01001136 // execute it!
1137
Damien152568b2013-10-16 00:46:39 +01001138 // flash once
Damien995b8aa2013-10-18 23:44:05 +01001139 led_state(PYB_LED_G1, 1);
Damien00ff04f2013-10-19 14:40:54 +01001140 sys_tick_delay_ms(100);
Damien995b8aa2013-10-18 23:44:05 +01001141 led_state(PYB_LED_G1, 0);
Damiened656052013-10-13 00:42:20 +01001142
Damien152568b2013-10-16 00:46:39 +01001143 nlr_buf_t nlr;
1144 if (nlr_push(&nlr) == 0) {
Damiend99b0522013-12-21 18:17:45 +00001145 mp_obj_t ret = rt_call_function_0(module_fun);
Damien152568b2013-10-16 00:46:39 +01001146 printf("done! got: ");
Damiend99b0522013-12-21 18:17:45 +00001147 mp_obj_print(ret);
Damien152568b2013-10-16 00:46:39 +01001148 printf("\n");
1149 nlr_pop();
1150 } else {
1151 // uncaught exception
1152 printf("exception: ");
Damiend99b0522013-12-21 18:17:45 +00001153 mp_obj_print((mp_obj_t)nlr.ret_val);
Damien152568b2013-10-16 00:46:39 +01001154 printf("\n");
1155 }
1156
1157 // flash once
Damien995b8aa2013-10-18 23:44:05 +01001158 led_state(PYB_LED_G1, 1);
Damien00ff04f2013-10-19 14:40:54 +01001159 sys_tick_delay_ms(100);
Damien995b8aa2013-10-18 23:44:05 +01001160 led_state(PYB_LED_G1, 0);
Damien152568b2013-10-16 00:46:39 +01001161
Damien00ff04f2013-10-19 14:40:54 +01001162 sys_tick_delay_ms(1000);
Damiened656052013-10-13 00:42:20 +01001163 printf("nalloc=%u\n", m_get_total_bytes_allocated());
Damien00ff04f2013-10-19 14:40:54 +01001164 sys_tick_delay_ms(1000);
Damiened656052013-10-13 00:42:20 +01001165 }
1166 }
1167 }
Damiened656052013-10-13 00:42:20 +01001168
Damien58a1b4c2013-10-25 20:53:54 +01001169 // HID example
1170 if (0) {
1171 uint8_t data[4];
1172 data[0] = 0;
1173 data[1] = 1;
1174 data[2] = -2;
1175 data[3] = 0;
1176 for (;;) {
1177 if (sw_get()) {
1178 data[0] = 0x01; // 0x04 is middle, 0x02 is right
1179 } else {
1180 data[0] = 0x00;
1181 }
Damien George28708622014-01-02 21:30:26 +00001182 mma_start(0x4c /* MMA_ADDR */, 1);
Damien58a1b4c2013-10-25 20:53:54 +01001183 mma_send_byte(0);
Damien George28708622014-01-02 21:30:26 +00001184 mma_restart(0x4c /* MMA_ADDR */, 0);
Damien58a1b4c2013-10-25 20:53:54 +01001185 for (int i = 0; i <= 1; i++) {
1186 int v = mma_read_ack() & 0x3f;
1187 if (v & 0x20) {
1188 v |= ~0x1f;
1189 }
1190 data[1 + i] = v;
1191 }
1192 mma_read_nack();
1193 usb_hid_send_report(data);
1194 sys_tick_delay_ms(15);
1195 }
1196 }
1197
Damien065f8a52013-12-05 20:38:23 +00001198 // wifi
Damiend6b4c662013-12-06 00:41:33 +00001199 //pyb_wlan_init();
1200 //pyb_wlan_start();
Damien065f8a52013-12-05 20:38:23 +00001201
Damien4b6e85c2013-10-21 09:56:56 +01001202 do_repl();
1203
Damiened656052013-10-13 00:42:20 +01001204 // benchmark C version of impl02.py
1205 if (0) {
Damien995b8aa2013-10-18 23:44:05 +01001206 led_state(PYB_LED_G1, 1);
Damien00ff04f2013-10-19 14:40:54 +01001207 sys_tick_delay_ms(100);
Damien995b8aa2013-10-18 23:44:05 +01001208 led_state(PYB_LED_G1, 0);
Damiened656052013-10-13 00:42:20 +01001209 impl02_c_version();
Damien995b8aa2013-10-18 23:44:05 +01001210 led_state(PYB_LED_G1, 1);
Damien00ff04f2013-10-19 14:40:54 +01001211 sys_tick_delay_ms(100);
Damien995b8aa2013-10-18 23:44:05 +01001212 led_state(PYB_LED_G1, 0);
Damiened656052013-10-13 00:42:20 +01001213 }
1214
Damiened656052013-10-13 00:42:20 +01001215 // SD card testing
Damien8c3da5c2013-12-17 18:36:19 +00001216 if (0) {
Damien7ee80ba2013-10-24 00:22:27 +01001217 extern void sdio_init(void);
Damien8c3da5c2013-12-17 18:36:19 +00001218 sdio_init();
Damiened656052013-10-13 00:42:20 +01001219 }
1220
Damien94186c82013-10-23 00:02:06 +01001221 printf("PYB: sync filesystems\n");
1222 pyb_sync();
1223
1224 printf("PYB: soft reboot\n");
Damienbd8e1102013-11-06 23:04:33 +00001225
1226 first_soft_reset = false;
Damiene9f1e502013-10-22 23:09:25 +01001227 goto soft_reset;
Damiened656052013-10-13 00:42:20 +01001228}
Damienfecee2b2013-11-02 16:41:51 +00001229
1230double __aeabi_f2d(float x) {
1231 // TODO
1232 return 0.0;
1233}
Damien0e496732013-11-03 14:53:34 +00001234
1235float __aeabi_d2f(double x) {
1236 // TODO
1237 return 0.0;
1238}
1239
1240double sqrt(double x) {
1241 // TODO
1242 return 0.0;
1243}
Damien39c6c592013-11-09 20:15:48 +00001244
1245machine_float_t machine_sqrt(machine_float_t x) {
1246 // TODO
1247 return x;
1248}