STATIC mp_obj_t mp_builtin_repr(mp_obj_t o_in) { vstr_t *vstr = vstr_new(); mp_obj_print_helper((void (*)(void *env, const char *fmt, ...))vstr_printf, vstr, o_in, PRINT_REPR); mp_obj_t s = mp_obj_new_str((byte*)vstr->buf, vstr->len, false); vstr_free(vstr); return s; }
mp_obj_t str_format(uint n_args, const mp_obj_t *args) { assert(MP_OBJ_IS_STR(args[0])); GET_STR_DATA_LEN(args[0], str, len); int arg_i = 1; vstr_t *vstr = vstr_new(); for (const byte *top = str + len; str < top; str++) { if (*str == '{') { str++; if (str < top && *str == '{') { vstr_add_char(vstr, '{'); } else { while (str < top && *str != '}') str++; if (arg_i >= n_args) { nlr_jump(mp_obj_new_exception_msg(MP_QSTR_IndexError, "tuple index out of range")); } // TODO: may be PRINT_REPR depending on formatting code mp_obj_print_helper((void (*)(void*, const char*, ...))vstr_printf, vstr, args[arg_i], PRINT_STR); arg_i++; } } else { vstr_add_char(vstr, *str); } } mp_obj_t s = mp_obj_new_str((byte*)vstr->buf, vstr->len, false); vstr_free(vstr); return s; }
STATIC mp_obj_t stringio_close(mp_obj_t self_in) { mp_obj_stringio_t *self = MP_OBJ_TO_PTR(self_in); #if MICROPY_CPYTHON_COMPAT vstr_free(self->vstr); self->vstr = NULL; #else vstr_clear(self->vstr); self->vstr->alloc = 0; self->vstr->len = 0; self->pos = 0; #endif return mp_const_none; }
STATIC mp_obj_t stream_readall(mp_obj_t self_in) { struct _mp_obj_base_t *o = (struct _mp_obj_base_t *)self_in; if (o->type->stream_p == NULL || o->type->stream_p->read == NULL) { // CPython: io.UnsupportedOperation, OSError subclass nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Operation not supported")); } int total_size = 0; vstr_t *vstr = vstr_new_size(DEFAULT_BUFFER_SIZE); char *buf = vstr_str(vstr); char *p = buf; int error; int current_read = DEFAULT_BUFFER_SIZE; while (true) { mp_int_t out_sz = o->type->stream_p->read(self_in, p, current_read, &error); if (out_sz == -1) { if (is_nonblocking_error(error)) { // With non-blocking streams, we read as much as we can. // If we read nothing, return None, just like read(). // Otherwise, return data read so far. if (total_size == 0) { return mp_const_none; } break; } nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "[Errno %d]", error)); } if (out_sz == 0) { break; } total_size += out_sz; if (out_sz < current_read) { current_read -= out_sz; p += out_sz; } else { current_read = DEFAULT_BUFFER_SIZE; p = vstr_extend(vstr, current_read); if (p == NULL) { // TODO nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError/*&mp_type_RuntimeError*/, "Out of memory")); } } } mp_obj_t s = mp_obj_new_str_of_type(STREAM_CONTENT_TYPE(o->type->stream_p), (byte*)vstr->buf, total_size); vstr_free(vstr); return s; }
// Unbuffered, inefficient implementation of readline() for raw I/O files. STATIC mp_obj_t stream_unbuffered_readline(uint n_args, const mp_obj_t *args) { struct _mp_obj_base_t *o = (struct _mp_obj_base_t *)args[0]; if (o->type->stream_p == NULL || o->type->stream_p->read == NULL) { // CPython: io.UnsupportedOperation, OSError subclass nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Operation not supported")); } mp_int_t max_size = -1; if (n_args > 1) { max_size = MP_OBJ_SMALL_INT_VALUE(args[1]); } vstr_t *vstr; if (max_size != -1) { vstr = vstr_new_size(max_size); } else { vstr = vstr_new(); } int error; while (max_size == -1 || max_size-- != 0) { char *p = vstr_add_len(vstr, 1); if (p == NULL) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_MemoryError, "out of memory")); } mp_int_t out_sz = o->type->stream_p->read(o, p, 1, &error); if (out_sz == -1) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, "[Errno %d]", error)); } if (out_sz == 0) { // Back out previously added byte // TODO: This is a bit hacky, does it supported by vstr API contract? // Consider, what's better - read a char and get OutOfMemory (so read // char is lost), or allocate first as we do. vstr_add_len(vstr, -1); break; } if (*p == '\n') { break; } } // TODO need a string creation API that doesn't copy the given data mp_obj_t ret = mp_obj_new_str_of_type(STREAM_CONTENT_TYPE(o->type->stream_p), (byte*)vstr->buf, vstr->len); vstr_free(vstr); return ret; }
STATIC mp_obj_t str_make_new(mp_obj_t type_in, mp_uint_t n_args, mp_uint_t n_kw, const mp_obj_t *args) { #if MICROPY_CPYTHON_COMPAT if (n_kw != 0) { mp_arg_error_unimpl_kw(); } #endif switch (n_args) { case 0: return MP_OBJ_NEW_QSTR(MP_QSTR_); case 1: { vstr_t *vstr = vstr_new(); mp_obj_print_helper((void (*)(void*, const char*, ...))vstr_printf, vstr, args[0], PRINT_STR); mp_obj_t s = mp_obj_new_str(vstr->buf, vstr->len, false); vstr_free(vstr); return s; } case 2: case 3: { // TODO: validate 2nd/3rd args if (MP_OBJ_IS_TYPE(args[0], &mp_type_bytes)) { GET_STR_DATA_LEN(args[0], str_data, str_len); GET_STR_HASH(args[0], str_hash); mp_obj_str_t *o = mp_obj_new_str_of_type(&mp_type_str, NULL, str_len); o->data = str_data; o->hash = str_hash; return o; } else { mp_buffer_info_t bufinfo; mp_get_buffer_raise(args[0], &bufinfo, MP_BUFFER_READ); return mp_obj_new_str(bufinfo.buf, bufinfo.len, false); } } default: nlr_raise(mp_obj_new_exception_msg(&mp_type_TypeError, "str takes at most 3 arguments")); } }
mp_obj_t mp_obj_new_exception_msg_varg(const mp_obj_type_t *exc_type, const char *fmt, ...) { // check that the given type is an exception type assert(exc_type->make_new == mp_obj_exception_make_new); // make exception object mp_obj_exception_t *o = m_new_obj_var_maybe(mp_obj_exception_t, mp_obj_t, 0); if (o == NULL) { // Couldn't allocate heap memory; use local data instead. // Unfortunately, we won't be able to format the string... o = &mp_emergency_exception_obj; o->base.type = exc_type; o->traceback = MP_OBJ_NULL; o->args = mp_const_empty_tuple; } else { o->base.type = exc_type; o->traceback = MP_OBJ_NULL; o->args = mp_obj_new_tuple(1, NULL); if (fmt == NULL) { // no message assert(0); } else { // render exception message and store as .args[0] // TODO: optimize bufferbloat vstr_t *vstr = vstr_new(); va_list ap; va_start(ap, fmt); vstr_vprintf(vstr, fmt, ap); va_end(ap); o->args->items[0] = mp_obj_new_str((byte*)vstr->buf, vstr->len, false); vstr_free(vstr); } } return o; }
mp_obj_t mp_obj_new_exception_msg_varg(const mp_obj_type_t *exc_type, const char *fmt, ...) { // check that the given type is an exception type assert(exc_type->make_new == mp_obj_exception_make_new); // make exception object mp_obj_exception_t *o = m_new_obj_var_maybe(mp_obj_exception_t, mp_obj_t, 0); if (o == NULL) { // Couldn't allocate heap memory; use local data instead. // Unfortunately, we won't be able to format the string... o = &mp_emergency_exception_obj; o->base.type = exc_type; o->traceback = MP_OBJ_NULL; o->args = mp_const_empty_tuple; #if MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF // If the user has provided a buffer, then we try to create a tuple // of length 1, which has a string object and the string data. if (mp_emergency_exception_buf_size > (sizeof(mp_obj_tuple_t) + sizeof(mp_obj_str_t) + sizeof(mp_obj_t))) { mp_obj_tuple_t *tuple = (mp_obj_tuple_t *)mp_emergency_exception_buf; mp_obj_str_t *str = (mp_obj_str_t *)&tuple->items[1]; tuple->base.type = &mp_type_tuple; tuple->len = 1; tuple->items[0] = str; byte *str_data = (byte *)&str[1]; uint max_len = mp_emergency_exception_buf + mp_emergency_exception_buf_size - str_data; va_list ap; va_start(ap, fmt); str->len = vsnprintf((char *)str_data, max_len, fmt, ap); va_end(ap); str->base.type = &mp_type_str; str->hash = qstr_compute_hash(str_data, str->len); str->data = str_data; o->args = tuple; uint offset = &str_data[str->len] - mp_emergency_exception_buf; offset += sizeof(void *) - 1; offset &= ~(sizeof(void *) - 1); if ((mp_emergency_exception_buf_size - offset) > (sizeof(mp_obj_list_t) + sizeof(mp_obj_t) * 3)) { // We have room to store some traceback. mp_obj_list_t *list = (mp_obj_list_t *)((byte *)mp_emergency_exception_buf + offset); list->base.type = &mp_type_list; list->items = (mp_obj_t)&list[1]; list->alloc = (mp_emergency_exception_buf + mp_emergency_exception_buf_size - (byte *)list->items) / sizeof(list->items[0]); list->len = 0; o->traceback = list; } } #endif // MICROPY_ENABLE_EMERGENCY_EXCEPTION_BUF } else { o->base.type = exc_type; o->traceback = MP_OBJ_NULL; o->args = mp_obj_new_tuple(1, NULL); if (fmt == NULL) { // no message assert(0); } else { // render exception message and store as .args[0] // TODO: optimize bufferbloat vstr_t *vstr = vstr_new(); va_list ap; va_start(ap, fmt); vstr_vprintf(vstr, fmt, ap); va_end(ap); o->args->items[0] = mp_obj_new_str(vstr->buf, vstr->len, false); vstr_free(vstr); } } return o; }
// Unbuffered, inefficient implementation of readline() for raw I/O files. STATIC mp_obj_t stream_unbuffered_readline(uint n_args, const mp_obj_t *args) { struct _mp_obj_base_t *o = (struct _mp_obj_base_t *)args[0]; if (o->type->stream_p == NULL || o->type->stream_p->read == NULL) { // CPython: io.UnsupportedOperation, OSError subclass nlr_raise(mp_obj_new_exception_msg(&mp_type_OSError, "Operation not supported")); } mp_int_t max_size = -1; if (n_args > 1) { max_size = MP_OBJ_SMALL_INT_VALUE(args[1]); } vstr_t *vstr; if (max_size != -1) { vstr = vstr_new_size(max_size); } else { vstr = vstr_new(); } int error; while (max_size == -1 || max_size-- != 0) { char *p = vstr_add_len(vstr, 1); if (p == NULL) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_MemoryError, "out of memory")); } mp_uint_t out_sz = o->type->stream_p->read(o, p, 1, &error); if (out_sz == MP_STREAM_ERROR) { if (is_nonblocking_error(error)) { if (vstr->len == 1) { // We just incremented it, but otherwise we read nothing // and immediately got EAGAIN. This is case is not well // specified in // https://docs.python.org/3/library/io.html#io.IOBase.readline // unlike similar case for read(). But we follow the latter's // behavior - return None. vstr_free(vstr); return mp_const_none; } else { goto done; } } nlr_raise(mp_obj_new_exception_arg1(&mp_type_OSError, MP_OBJ_NEW_SMALL_INT(error))); } if (out_sz == 0) { done: // Back out previously added byte // Consider, what's better - read a char and get OutOfMemory (so read // char is lost), or allocate first as we do. vstr_cut_tail_bytes(vstr, 1); break; } if (*p == '\n') { break; } } // TODO need a string creation API that doesn't copy the given data mp_obj_t ret = mp_obj_new_str_of_type(STREAM_CONTENT_TYPE(o->type->stream_p), (byte*)vstr->buf, vstr->len); vstr_free(vstr); return ret; }
STATIC mp_obj_t stringio_close(mp_obj_t self_in) { mp_obj_stringio_t *self = self_in; vstr_free(self->vstr); self->vstr = NULL; return mp_const_none; }
int main(void) { // TODO disable JTAG // update the SystemCoreClock variable SystemCoreClockUpdate(); // set interrupt priority config to use all 4 bits for pre-empting NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4); // enable the CCM RAM and the GPIO's RCC->AHB1ENR |= RCC_AHB1ENR_CCMDATARAMEN | RCC_AHB1ENR_GPIOAEN | RCC_AHB1ENR_GPIOBEN | RCC_AHB1ENR_GPIOCEN | RCC_AHB1ENR_GPIODEN; #if MICROPY_HW_HAS_SDCARD { // configure SDIO pins to be high to start with (apparently makes it more robust) // FIXME this is not making them high, it just makes them outputs... GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_25MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIOC, &GPIO_InitStructure); // Configure PD.02 CMD line GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; GPIO_Init(GPIOD, &GPIO_InitStructure); } #endif #if defined(NETDUINO_PLUS_2) { GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_25MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; #if MICROPY_HW_HAS_SDCARD // Turn on the power enable for the sdcard (PB1) GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; GPIO_Init(GPIOB, &GPIO_InitStructure); GPIO_WriteBit(GPIOB, GPIO_Pin_1, Bit_SET); #endif // Turn on the power for the 5V on the expansion header (PB2) GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; GPIO_Init(GPIOB, &GPIO_InitStructure); GPIO_WriteBit(GPIOB, GPIO_Pin_2, Bit_SET); } #endif // basic sub-system init sys_tick_init(); pendsv_init(); led_init(); #if MICROPY_HW_ENABLE_RTC rtc_init(); #endif // turn on LED to indicate bootup led_state(PYB_LED_G1, 1); // more sub-system init #if MICROPY_HW_HAS_SDCARD sdcard_init(); #endif storage_init(); // uncomment these 2 lines if you want REPL on USART_6 (or another usart) as well as on USB VCP //pyb_usart_global_debug = PYB_USART_YA; //usart_init(pyb_usart_global_debug, 115200); int first_soft_reset = true; soft_reset: // GC init gc_init(&_heap_start, &_heap_end); // Micro Python init qstr_init(); mp_init(); mp_obj_list_init(mp_sys_path, 0); mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR_0_colon__slash_)); mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR_0_colon__slash_lib)); mp_obj_list_init(mp_sys_argv, 0); exti_init(); #if MICROPY_HW_HAS_SWITCH switch_init(); #endif #if MICROPY_HW_HAS_LCD // LCD init (just creates class, init hardware by calling LCD()) lcd_init(); #endif #if MICROPY_HW_ENABLE_SERVO // servo servo_init(); #endif #if MICROPY_HW_ENABLE_TIMER // timer timer_init(); #endif #if MICROPY_HW_ENABLE_RNG // RNG RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_RNG, ENABLE); RNG_Cmd(ENABLE); #endif pin_map_init(); // add some functions to the builtin Python namespace mp_store_name(MP_QSTR_help, mp_make_function_n(0, pyb_help)); mp_store_name(MP_QSTR_open, mp_make_function_n(2, pyb_io_open)); // load the pyb module mp_module_register(MP_QSTR_pyb, (mp_obj_t)&pyb_module); // check if user switch held (initiates reset of filesystem) bool reset_filesystem = false; #if MICROPY_HW_HAS_SWITCH if (switch_get()) { reset_filesystem = true; for (int i = 0; i < 50; i++) { if (!switch_get()) { reset_filesystem = false; break; } sys_tick_delay_ms(10); } } #endif // local filesystem init { // try to mount the flash FRESULT res = f_mount(&fatfs0, "0:", 1); if (!reset_filesystem && res == FR_OK) { // mount sucessful } else if (reset_filesystem || res == FR_NO_FILESYSTEM) { // no filesystem, so create a fresh one // TODO doesn't seem to work correctly when reset_filesystem is true... // LED on to indicate creation of LFS led_state(PYB_LED_R2, 1); uint32_t stc = sys_tick_counter; res = f_mkfs("0:", 0, 0); if (res == FR_OK) { // success creating fresh LFS } else { __fatal_error("could not create LFS"); } // create src directory res = f_mkdir("0:/src"); // ignore result from mkdir // create empty main.py FIL fp; f_open(&fp, "0:/src/main.py", FA_WRITE | FA_CREATE_ALWAYS); UINT n; f_write(&fp, fresh_main_py, sizeof(fresh_main_py) - 1 /* don't count null terminator */, &n); // TODO check we could write n bytes f_close(&fp); // keep LED on for at least 200ms sys_tick_wait_at_least(stc, 200); led_state(PYB_LED_R2, 0); } else { __fatal_error("could not access LFS"); } } // make sure we have a /boot.py { FILINFO fno; FRESULT res = f_stat("0:/boot.py", &fno); if (res == FR_OK) { if (fno.fattrib & AM_DIR) { // exists as a directory // TODO handle this case // see http://elm-chan.org/fsw/ff/img/app2.c for a "rm -rf" implementation } else { // exists as a file, good! } } else { // doesn't exist, create fresh file // LED on to indicate creation of boot.py led_state(PYB_LED_R2, 1); uint32_t stc = sys_tick_counter; FIL fp; f_open(&fp, "0:/boot.py", FA_WRITE | FA_CREATE_ALWAYS); UINT n; f_write(&fp, fresh_boot_py, sizeof(fresh_boot_py) - 1 /* don't count null terminator */, &n); // TODO check we could write n bytes f_close(&fp); // keep LED on for at least 200ms sys_tick_wait_at_least(stc, 200); led_state(PYB_LED_R2, 0); } } // run /boot.py if (!pyexec_file("0:/boot.py")) { flash_error(4); } if (first_soft_reset) { #if MICROPY_HW_HAS_MMA7660 // MMA accel: init and reset address to zero accel_init(); #endif } // turn boot-up LED off led_state(PYB_LED_G1, 0); #if MICROPY_HW_HAS_SDCARD // if an SD card is present then mount it on 1:/ if (sdcard_is_present()) { FRESULT res = f_mount(&fatfs1, "1:", 1); if (res != FR_OK) { printf("[SD] could not mount SD card\n"); } else { if (first_soft_reset) { // use SD card as medium for the USB MSD usbd_storage_select_medium(USBD_STORAGE_MEDIUM_SDCARD); } } } #endif #ifdef USE_HOST_MODE // USB host pyb_usb_host_init(); #elif defined(USE_DEVICE_MODE) // USB device pyb_usb_dev_init(PYB_USB_DEV_VCP_MSC); #endif // run main script { vstr_t *vstr = vstr_new(); vstr_add_str(vstr, "0:/"); if (pyb_config_source_dir == MP_OBJ_NULL) { vstr_add_str(vstr, "src"); } else { vstr_add_str(vstr, mp_obj_str_get_str(pyb_config_source_dir)); } vstr_add_char(vstr, '/'); if (pyb_config_main == MP_OBJ_NULL) { vstr_add_str(vstr, "main.py"); } else { vstr_add_str(vstr, mp_obj_str_get_str(pyb_config_main)); } if (!pyexec_file(vstr_str(vstr))) { flash_error(3); } vstr_free(vstr); } #if MICROPY_HW_HAS_MMA7660 // HID example if (0) { uint8_t data[4]; data[0] = 0; data[1] = 1; data[2] = -2; data[3] = 0; for (;;) { #if MICROPY_HW_HAS_SWITCH if (switch_get()) { data[0] = 0x01; // 0x04 is middle, 0x02 is right } else { data[0] = 0x00; } #else data[0] = 0x00; #endif accel_start(0x4c /* ACCEL_ADDR */, 1); accel_send_byte(0); accel_restart(0x4c /* ACCEL_ADDR */, 0); for (int i = 0; i <= 1; i++) { int v = accel_read_ack() & 0x3f; if (v & 0x20) { v |= ~0x1f; } data[1 + i] = v; } accel_read_nack(); usb_hid_send_report(data); sys_tick_delay_ms(15); } } #endif #if MICROPY_HW_HAS_WLAN // wifi pyb_wlan_init(); pyb_wlan_start(); #endif pyexec_repl(); printf("PYB: sync filesystems\n"); storage_flush(); printf("PYB: soft reboot\n"); first_soft_reset = false; goto soft_reset; }
int main(void) { // TODO disable JTAG /* STM32F4xx HAL library initialization: - Configure the Flash prefetch, instruction and Data caches - Configure the Systick to generate an interrupt each 1 msec - Set NVIC Group Priority to 4 - Global MSP (MCU Support Package) initialization */ HAL_Init(); // set the system clock to be HSE SystemClock_Config(); // enable GPIO clocks __GPIOA_CLK_ENABLE(); __GPIOB_CLK_ENABLE(); __GPIOC_CLK_ENABLE(); __GPIOD_CLK_ENABLE(); // enable the CCM RAM __CCMDATARAMEN_CLK_ENABLE(); #if 0 #if defined(NETDUINO_PLUS_2) { GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_25MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; #if MICROPY_HW_HAS_SDCARD // Turn on the power enable for the sdcard (PB1) GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; GPIO_Init(GPIOB, &GPIO_InitStructure); GPIO_WriteBit(GPIOB, GPIO_Pin_1, Bit_SET); #endif // Turn on the power for the 5V on the expansion header (PB2) GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; GPIO_Init(GPIOB, &GPIO_InitStructure); GPIO_WriteBit(GPIOB, GPIO_Pin_2, Bit_SET); } #endif #endif // basic sub-system init pendsv_init(); timer_tim3_init(); led_init(); switch_init0(); int first_soft_reset = true; soft_reset: // check if user switch held to select the reset mode led_state(1, 0); led_state(2, 1); led_state(3, 0); led_state(4, 0); uint reset_mode = 1; #if MICROPY_HW_HAS_SWITCH if (switch_get()) { for (uint i = 0; i < 3000; i++) { if (!switch_get()) { break; } HAL_Delay(20); if (i % 30 == 29) { if (++reset_mode > 3) { reset_mode = 1; } led_state(2, reset_mode & 1); led_state(3, reset_mode & 2); led_state(4, reset_mode & 4); } } // flash the selected reset mode for (uint i = 0; i < 6; i++) { led_state(2, 0); led_state(3, 0); led_state(4, 0); HAL_Delay(50); led_state(2, reset_mode & 1); led_state(3, reset_mode & 2); led_state(4, reset_mode & 4); HAL_Delay(50); } HAL_Delay(400); } #endif #if MICROPY_HW_ENABLE_RTC if (first_soft_reset) { rtc_init(); } #endif // more sub-system init #if MICROPY_HW_HAS_SDCARD if (first_soft_reset) { sdcard_init(); } #endif if (first_soft_reset) { storage_init(); } // GC init gc_init(&_heap_start, &_heap_end); // Change #if 0 to #if 1 if you want REPL on USART_6 (or another usart) // as well as on USB VCP #if 0 pyb_usart_global_debug = pyb_Usart(MP_OBJ_NEW_SMALL_INT(PYB_USART_YA), MP_OBJ_NEW_SMALL_INT(115200)); #else pyb_usart_global_debug = NULL; #endif // Micro Python init qstr_init(); mp_init(); mp_obj_list_init(mp_sys_path, 0); mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR_0_colon__slash_)); mp_obj_list_append(mp_sys_path, MP_OBJ_NEW_QSTR(MP_QSTR_0_colon__slash_lib)); mp_obj_list_init(mp_sys_argv, 0); readline_init(); exti_init(); #if MICROPY_HW_HAS_SWITCH // must come after exti_init switch_init(); #endif #if MICROPY_HW_HAS_LCD // LCD init (just creates class, init hardware by calling LCD()) lcd_init(); #endif pin_map_init(); // local filesystem init { // try to mount the flash FRESULT res = f_mount(&fatfs0, "0:", 1); if (reset_mode == 3 || res == FR_NO_FILESYSTEM) { // no filesystem, or asked to reset it, so create a fresh one // LED on to indicate creation of LFS led_state(PYB_LED_R2, 1); uint32_t start_tick = HAL_GetTick(); res = f_mkfs("0:", 0, 0); if (res == FR_OK) { // success creating fresh LFS } else { __fatal_error("could not create LFS"); } // create empty main.py FIL fp; f_open(&fp, "0:/main.py", FA_WRITE | FA_CREATE_ALWAYS); UINT n; f_write(&fp, fresh_main_py, sizeof(fresh_main_py) - 1 /* don't count null terminator */, &n); // TODO check we could write n bytes f_close(&fp); // create .inf driver file f_open(&fp, "0:/pybcdc.inf", FA_WRITE | FA_CREATE_ALWAYS); f_write(&fp, fresh_pybcdc_inf, sizeof(fresh_pybcdc_inf) - 1 /* don't count null terminator */, &n); f_close(&fp); // keep LED on for at least 200ms sys_tick_wait_at_least(start_tick, 200); led_state(PYB_LED_R2, 0); } else if (res == FR_OK) { // mount sucessful } else { __fatal_error("could not access LFS"); } } // make sure we have a 0:/boot.py { FILINFO fno; #if _USE_LFN fno.lfname = NULL; fno.lfsize = 0; #endif FRESULT res = f_stat("0:/boot.py", &fno); if (res == FR_OK) { if (fno.fattrib & AM_DIR) { // exists as a directory // TODO handle this case // see http://elm-chan.org/fsw/ff/img/app2.c for a "rm -rf" implementation } else { // exists as a file, good! } } else { // doesn't exist, create fresh file // LED on to indicate creation of boot.py led_state(PYB_LED_R2, 1); uint32_t start_tick = HAL_GetTick(); FIL fp; f_open(&fp, "0:/boot.py", FA_WRITE | FA_CREATE_ALWAYS); UINT n; f_write(&fp, fresh_boot_py, sizeof(fresh_boot_py) - 1 /* don't count null terminator */, &n); // TODO check we could write n bytes f_close(&fp); // keep LED on for at least 200ms sys_tick_wait_at_least(start_tick, 200); led_state(PYB_LED_R2, 0); } } // root device defaults to internal flash filesystem uint root_device = 0; #if defined(USE_DEVICE_MODE) usb_storage_medium_t usb_medium = USB_STORAGE_MEDIUM_FLASH; #endif #if MICROPY_HW_HAS_SDCARD // if an SD card is present then mount it on 1:/ if (reset_mode == 1 && sdcard_is_present()) { FRESULT res = f_mount(&fatfs1, "1:", 1); if (res != FR_OK) { printf("[SD] could not mount SD card\n"); } else { // use SD card as root device root_device = 1; if (first_soft_reset) { // use SD card as medium for the USB MSD #if defined(USE_DEVICE_MODE) usb_medium = USB_STORAGE_MEDIUM_SDCARD; #endif } } } #else // Get rid of compiler warning if no SDCARD is configured. (void)first_soft_reset; #endif // run <root>:/boot.py, if it exists if (reset_mode == 1) { const char *boot_file; if (root_device == 0) { boot_file = "0:/boot.py"; } else { boot_file = "1:/boot.py"; } FRESULT res = f_stat(boot_file, NULL); if (res == FR_OK) { if (!pyexec_file(boot_file)) { flash_error(4); } } } // turn boot-up LEDs off led_state(2, 0); led_state(3, 0); led_state(4, 0); #if defined(USE_HOST_MODE) // USB host pyb_usb_host_init(); #elif defined(USE_DEVICE_MODE) // USB device if (reset_mode == 1) { usb_device_mode_t usb_mode = USB_DEVICE_MODE_CDC_MSC; if (pyb_config_usb_mode != MP_OBJ_NULL) { if (strcmp(mp_obj_str_get_str(pyb_config_usb_mode), "CDC+HID") == 0) { usb_mode = USB_DEVICE_MODE_CDC_HID; } } pyb_usb_dev_init(usb_mode, usb_medium); } else { pyb_usb_dev_init(USB_DEVICE_MODE_CDC_MSC, usb_medium); } #endif #if MICROPY_HW_ENABLE_RNG // RNG rng_init(); #endif #if MICROPY_HW_ENABLE_TIMER // timer //timer_init(); #endif // I2C i2c_init(); #if MICROPY_HW_HAS_MMA7660 // MMA accel: init and reset accel_init(); #endif #if MICROPY_HW_ENABLE_SERVO // servo servo_init(); #endif #if MICROPY_HW_ENABLE_DAC // DAC dac_init(); #endif // now that everything is initialised, run main script if (reset_mode == 1 && pyexec_mode_kind == PYEXEC_MODE_FRIENDLY_REPL) { vstr_t *vstr = vstr_new(); vstr_printf(vstr, "%d:/", root_device); if (pyb_config_main == MP_OBJ_NULL) { vstr_add_str(vstr, "main.py"); } else { vstr_add_str(vstr, mp_obj_str_get_str(pyb_config_main)); } FRESULT res = f_stat(vstr_str(vstr), NULL); if (res == FR_OK) { if (!pyexec_file(vstr_str(vstr))) { flash_error(3); } } vstr_free(vstr); } #if 0 #if MICROPY_HW_HAS_WLAN // wifi pyb_wlan_init(); pyb_wlan_start(); #endif #endif // enter REPL // REPL mode can change, or it can request a soft reset for (;;) { if (pyexec_mode_kind == PYEXEC_MODE_RAW_REPL) { if (pyexec_raw_repl() != 0) { break; } } else { if (pyexec_friendly_repl() != 0) { break; } } } printf("PYB: sync filesystems\n"); storage_flush(); printf("PYB: soft reboot\n"); first_soft_reset = false; goto soft_reset; }