diff options
29 files changed, 427 insertions, 144 deletions
diff --git a/py/builtin.c b/py/builtin.c index 5911fa634..5e2015452 100644 --- a/py/builtin.c +++ b/py/builtin.c @@ -6,6 +6,7 @@ #include "mpconfig.h" #include "qstr.h" #include "obj.h" +#include "objstr.h" #include "runtime0.h" #include "runtime.h" #include "builtin.h" @@ -125,6 +126,13 @@ STATIC mp_obj_t mp_builtin_any(mp_obj_t o_in) { MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_any_obj, mp_builtin_any); +STATIC mp_obj_t mp_builtin_bin(mp_obj_t o_in) { + mp_obj_t args[] = { MP_OBJ_NEW_QSTR(MP_QSTR__brace_open__colon__hash_b_brace_close_), o_in }; + return mp_obj_str_format(sizeof(args) / sizeof(args[0]), args); +} + +MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_bin_obj, mp_builtin_bin); + STATIC mp_obj_t mp_builtin_callable(mp_obj_t o_in) { if (mp_obj_is_callable(o_in)) { return mp_const_true; @@ -299,6 +307,12 @@ STATIC mp_obj_t mp_builtin_next(mp_obj_t o) { MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_next_obj, mp_builtin_next); +STATIC mp_obj_t mp_builtin_oct(mp_obj_t o_in) { + return mp_binary_op(MP_BINARY_OP_MODULO, MP_OBJ_NEW_QSTR(MP_QSTR__percent__hash_o), o_in); +} + +MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_oct_obj, mp_builtin_oct); + STATIC mp_obj_t mp_builtin_ord(mp_obj_t o_in) { uint len; const char *str = mp_obj_str_get_data(o_in, &len); diff --git a/py/builtin.h b/py/builtin.h index 51a74a310..36b9f3881 100644 --- a/py/builtin.h +++ b/py/builtin.h @@ -6,6 +6,7 @@ MP_DECLARE_CONST_FUN_OBJ(mp_builtin___repl_print___obj); MP_DECLARE_CONST_FUN_OBJ(mp_builtin_abs_obj); MP_DECLARE_CONST_FUN_OBJ(mp_builtin_all_obj); MP_DECLARE_CONST_FUN_OBJ(mp_builtin_any_obj); +MP_DECLARE_CONST_FUN_OBJ(mp_builtin_bin_obj); MP_DECLARE_CONST_FUN_OBJ(mp_builtin_callable_obj); MP_DECLARE_CONST_FUN_OBJ(mp_builtin_chr_obj); MP_DECLARE_CONST_FUN_OBJ(mp_builtin_dir_obj); @@ -26,6 +27,7 @@ MP_DECLARE_CONST_FUN_OBJ(mp_builtin_locals_obj); MP_DECLARE_CONST_FUN_OBJ(mp_builtin_max_obj); MP_DECLARE_CONST_FUN_OBJ(mp_builtin_min_obj); MP_DECLARE_CONST_FUN_OBJ(mp_builtin_next_obj); +MP_DECLARE_CONST_FUN_OBJ(mp_builtin_oct_obj); MP_DECLARE_CONST_FUN_OBJ(mp_builtin_ord_obj); MP_DECLARE_CONST_FUN_OBJ(mp_builtin_pow_obj); MP_DECLARE_CONST_FUN_OBJ(mp_builtin_print_obj); diff --git a/py/builtintables.c b/py/builtintables.c index 6cf12dffa..6bdae2400 100644 --- a/py/builtintables.c +++ b/py/builtintables.c @@ -51,6 +51,7 @@ STATIC const mp_map_elem_t mp_builtin_object_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_abs), (mp_obj_t)&mp_builtin_abs_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_all), (mp_obj_t)&mp_builtin_all_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_any), (mp_obj_t)&mp_builtin_any_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_bin), (mp_obj_t)&mp_builtin_bin_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_callable), (mp_obj_t)&mp_builtin_callable_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_chr), (mp_obj_t)&mp_builtin_chr_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_dir), (mp_obj_t)&mp_builtin_dir_obj }, @@ -70,6 +71,7 @@ STATIC const mp_map_elem_t mp_builtin_object_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_max), (mp_obj_t)&mp_builtin_max_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_min), (mp_obj_t)&mp_builtin_min_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_next), (mp_obj_t)&mp_builtin_next_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_oct), (mp_obj_t)&mp_builtin_oct_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_ord), (mp_obj_t)&mp_builtin_ord_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_pow), (mp_obj_t)&mp_builtin_pow_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_print), (mp_obj_t)&mp_builtin_print_obj }, diff --git a/py/makeqstrdata.py b/py/makeqstrdata.py index 8620af567..afde77205 100644 --- a/py/makeqstrdata.py +++ b/py/makeqstrdata.py @@ -18,6 +18,8 @@ codepoint2name[ord(':')] = 'colon' codepoint2name[ord('/')] = 'slash' codepoint2name[ord('%')] = 'percent' codepoint2name[ord('#')] = 'hash' +codepoint2name[ord('{')] = 'brace_open' +codepoint2name[ord('}')] = 'brace_close' # this must match the equivalent function in qstr.c def compute_hash(qstr): @@ -320,7 +320,7 @@ uint mp_get_index(const mp_obj_type_t *type, machine_uint_t len, mp_obj_t index, // may return MP_OBJ_NULL mp_obj_t mp_obj_len_maybe(mp_obj_t o_in) { - if (MP_OBJ_IS_STR(o_in)) { + if (MP_OBJ_IS_STR(o_in) || MP_OBJ_IS_TYPE(o_in, &mp_type_bytes)) { return MP_OBJ_NEW_SMALL_INT((machine_int_t)mp_obj_str_get_len(o_in)); } else { mp_obj_type_t *type = mp_obj_get_type(o_in); diff --git a/py/objstr.c b/py/objstr.c index fc1e1c569..7de42b6e9 100644 --- a/py/objstr.c +++ b/py/objstr.c @@ -579,7 +579,7 @@ static mp_obj_t arg_as_int(mp_obj_t arg) { return arg; } -mp_obj_t str_format(uint n_args, const mp_obj_t *args) { +mp_obj_t mp_obj_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); @@ -1346,7 +1346,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(str_join_obj, str_join); STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_split_obj, 1, 3, str_split); STATIC MP_DEFINE_CONST_FUN_OBJ_2(str_startswith_obj, str_startswith); STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_strip_obj, 1, 2, str_strip); -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR(str_format_obj, 1, str_format); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR(str_format_obj, 1, mp_obj_str_format); STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_replace_obj, 3, 4, str_replace); STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(str_count_obj, 2, 4, str_count); STATIC MP_DEFINE_CONST_FUN_OBJ_2(str_partition_obj, str_partition); @@ -1485,7 +1485,8 @@ uint mp_obj_str_get_hash(mp_obj_t self_in) { } uint mp_obj_str_get_len(mp_obj_t self_in) { - if (MP_OBJ_IS_STR(self_in)) { + // TODO This has a double check for the type, one in obj.c and one here + if (MP_OBJ_IS_STR(self_in) || MP_OBJ_IS_TYPE(self_in, &mp_type_bytes)) { GET_STR_LEN(self_in, l); return l; } else { diff --git a/py/objstr.h b/py/objstr.h index a32ba53b1..800568de8 100644 --- a/py/objstr.h +++ b/py/objstr.h @@ -8,3 +8,5 @@ typedef struct _mp_obj_str_t { } mp_obj_str_t; #define MP_DEFINE_STR_OBJ(obj_name, str) mp_obj_str_t obj_name = {{&mp_type_str}, 0, sizeof(str) - 1, (const byte*)str}; + +mp_obj_t mp_obj_str_format(uint n_args, const mp_obj_t *args); diff --git a/py/qstrdefs.h b/py/qstrdefs.h index d18882f69..20c4db75f 100644 --- a/py/qstrdefs.h +++ b/py/qstrdefs.h @@ -83,6 +83,8 @@ Q(all) Q(any) Q(args) Q(array) +Q(bin) +Q({:#b}) Q(bool) Q(bytearray) Q(bytes) @@ -122,6 +124,8 @@ Q(max) Q(min) Q(namedtuple) Q(next) +Q(oct) +Q(%#o) Q(open) Q(ord) Q(path) diff --git a/stmhal/Makefile b/stmhal/Makefile index 978918994..f0d132520 100644 --- a/stmhal/Makefile +++ b/stmhal/Makefile @@ -210,6 +210,14 @@ PREFIX_FILE = boards/stm32f4xx-prefix.c GEN_PINS_SRC = $(BUILD)/pins_$(BOARD).c GEN_PINS_HDR = $(BUILD)/pins.h +INSERT_USB_IDS = ../tools/insert-usb-ids.py +FILE2H = ../tools/file2h.py + +USB_IDS_FILE = usbd_desc_cdc_msc.c +CDCINF_TEMPLATE = pybcdc.inf_template +GEN_CDCINF_FILE = $(BUILD)/pybcdc.inf +GEN_CDCINF_HEADER = $(BUILD)/pybcdc_inf.h + # Making OBJ use an order-only depenedency on the generated pins.h file # has the side effect of making the pins.h file before we actually compile # any of the objects. The normal dependency generation will deal with the @@ -217,6 +225,8 @@ GEN_PINS_HDR = $(BUILD)/pins.h # which source files might need it. $(OBJ): | $(BUILD)/pins.h +$(BUILD)/main.o: $(GEN_CDCINF_HEADER) + # Use a pattern rule here so that make will only call make-pins.py once to make # both pins_$(BOARD).c and pins.h $(BUILD)/%_$(BOARD).c $(BUILD)/%.h: boards/$(BOARD)/%.csv $(MAKE_PINS) $(AF_FILE) $(PREFIX_FILE) @@ -226,4 +236,12 @@ $(BUILD)/%_$(BOARD).c $(BUILD)/%.h: boards/$(BOARD)/%.csv $(MAKE_PINS) $(AF_FILE $(BUILD)/pins_$(BOARD).o: $(BUILD)/pins_$(BOARD).c $(call compile_c) +$(GEN_CDCINF_HEADER): $(GEN_CDCINF_FILE) $(FILE2H) + $(ECHO) "Create $@" + $(Q)$(PYTHON) $(FILE2H) $< > $@ + +$(GEN_CDCINF_FILE): $(CDCINF_TEMPLATE) $(INSERT_USB_IDS) $(USB_IDS_FILE) + $(ECHO) "Create $@" + $(Q)$(PYTHON) $(INSERT_USB_IDS) $(USB_IDS_FILE) $< > $@ + include ../py/mkrules.mk diff --git a/stmhal/adc.c b/stmhal/adc.c index 8a1c23c4f..dafa3f7bc 100644 --- a/stmhal/adc.c +++ b/stmhal/adc.c @@ -11,6 +11,7 @@ #include "adc.h" #include "pin.h" #include "build/pins.h" +#include "timer.h" // Usage Model: // @@ -162,8 +163,39 @@ STATIC mp_obj_t adc_read(mp_obj_t self_in) { STATIC MP_DEFINE_CONST_FUN_OBJ_1(adc_read_obj, adc_read); +STATIC mp_obj_t adc_read_timed(mp_obj_t self_in, mp_obj_t buf_in, mp_obj_t freq_in) { + pyb_obj_adc_t *self = self_in; + + buffer_info_t bufinfo; + mp_get_buffer_raise(buf_in, &bufinfo); + + // Init TIM6 at the required frequency (in Hz) + timer_tim6_init(mp_obj_get_int(freq_in)); + + // Start timer + HAL_TIM_Base_Start(&TIM6_Handle); + + // This uses the timer in polling mode to do the sampling + // TODO use DMA + for (uint i = 0; i < bufinfo.len; i++) { + // Wait for the timer to trigger + while (__HAL_TIM_GET_FLAG(&TIM6_Handle, TIM_FLAG_UPDATE) == RESET) { + } + __HAL_TIM_CLEAR_FLAG(&TIM6_Handle, TIM_FLAG_UPDATE); + ((byte*)bufinfo.buf)[i] = adc_read_channel(&self->handle) >> 4; + } + + // Stop timer + HAL_TIM_Base_Stop(&TIM6_Handle); + + return mp_obj_new_int(bufinfo.len); +} + +STATIC MP_DEFINE_CONST_FUN_OBJ_3(adc_read_timed_obj, adc_read_timed); + STATIC const mp_map_elem_t adc_locals_dict_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_read), (mp_obj_t)&adc_read_obj}, + { MP_OBJ_NEW_QSTR(MP_QSTR_read_timed), (mp_obj_t)&adc_read_timed_obj}, }; STATIC MP_DEFINE_CONST_DICT(adc_locals_dict, adc_locals_dict_table); diff --git a/stmhal/dac.c b/stmhal/dac.c index 5e809412e..c018a4046 100644 --- a/stmhal/dac.c +++ b/stmhal/dac.c @@ -10,9 +10,9 @@ #include "parse.h" #include "obj.h" #include "runtime.h" +#include "timer.h" #include "dac.h" -TIM_HandleTypeDef TIM6_Handle; STATIC DAC_HandleTypeDef DAC_Handle; void dac_init(void) { @@ -22,19 +22,8 @@ void dac_init(void) { } STATIC void TIM6_Config(uint freq) { - // TIM6 clock enable - __TIM6_CLK_ENABLE(); - - // Compute the prescaler value so TIM6 triggers at freq-Hz - uint16_t period = (uint16_t) ((SystemCoreClock / 2) / freq) - 1; - - // time base clock configuration - TIM6_Handle.Instance = TIM6; - TIM6_Handle.Init.Period = period; - TIM6_Handle.Init.Prescaler = 0; // timer runs at SystemCoreClock / 2 - TIM6_Handle.Init.ClockDivision = 0; // unused for TIM6 - TIM6_Handle.Init.CounterMode = TIM_COUNTERMODE_UP; // unused for TIM6 - HAL_TIM_Base_Init(&TIM6_Handle); + // Init TIM6 at the required frequency (in Hz) + timer_tim6_init(freq); // TIM6 TRGO selection TIM_MasterConfigTypeDef config; @@ -203,17 +192,14 @@ mp_obj_t pyb_dac_dma(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) { DAC_Init(self->dac_channel, &DAC_InitStructure); */ - if (self->state != 3) { - DAC_ChannelConfTypeDef config; - config.DAC_Trigger = DAC_TRIGGER_T6_TRGO; - config.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE; - HAL_DAC_ConfigChannel(&DAC_Handle, &config, self->dac_channel); - self->state = 3; - } - // DMA1_Stream[67] channel7 configuration DMA_HandleTypeDef DMA_Handle; DMA_Handle.Instance = self->dma_stream; + + // Need to deinit DMA first + DMA_Handle.State = HAL_DMA_STATE_READY; + HAL_DMA_DeInit(&DMA_Handle); + DMA_Handle.Init.Channel = DMA_CHANNEL_7; DMA_Handle.Init.Direction = DMA_MEMORY_TO_PERIPH; DMA_Handle.Init.PeriphInc = DMA_PINC_DISABLE; @@ -231,6 +217,18 @@ mp_obj_t pyb_dac_dma(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) { __HAL_LINKDMA(&DAC_Handle, DMA_Handle1, DMA_Handle); + DAC_Handle.Instance = DAC; + DAC_Handle.State = HAL_DAC_STATE_RESET; + HAL_DAC_Init(&DAC_Handle); + + if (self->state != 3) { + DAC_ChannelConfTypeDef config; + config.DAC_Trigger = DAC_TRIGGER_T6_TRGO; + config.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE; + HAL_DAC_ConfigChannel(&DAC_Handle, &config, self->dac_channel); + self->state = 3; + } + HAL_DAC_Start_DMA(&DAC_Handle, self->dac_channel, (uint32_t*)bufinfo.buf, bufinfo.len, DAC_ALIGN_8B_R); /* diff --git a/stmhal/i2c.c b/stmhal/i2c.c index 65bc3600e..780d4fb49 100644 --- a/stmhal/i2c.c +++ b/stmhal/i2c.c @@ -98,14 +98,13 @@ STATIC mp_obj_t pyb_i2c_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const return (mp_obj_t)i2c_obj; } +// Check if an I2C device responds to the given address. STATIC mp_obj_t pyb_i2c_is_ready(mp_obj_t self_in, mp_obj_t i2c_addr_o) { pyb_i2c_obj_t *self = self_in; machine_uint_t i2c_addr = mp_obj_get_int(i2c_addr_o) << 1; - //printf("IsDeviceReady\n"); for (int i = 0; i < 10; i++) { HAL_StatusTypeDef status = HAL_I2C_IsDeviceReady(self->i2c_handle, i2c_addr, 10, 200); - //printf(" got %d\n", status); if (status == HAL_OK) { return mp_const_true; } @@ -116,6 +115,69 @@ STATIC mp_obj_t pyb_i2c_is_ready(mp_obj_t self_in, mp_obj_t i2c_addr_o) { STATIC MP_DEFINE_CONST_FUN_OBJ_2(pyb_i2c_is_ready_obj, pyb_i2c_is_ready); +// Scan all I2C addresses from 0x01 to 0x7f and return a list of those that respond. +STATIC mp_obj_t pyb_i2c_scan(mp_obj_t self_in) { + pyb_i2c_obj_t *self = self_in; + + mp_obj_t list = mp_obj_new_list(0, NULL); + + for (uint addr = 1; addr <= 127; addr++) { + for (int i = 0; i < 10; i++) { + HAL_StatusTypeDef status = HAL_I2C_IsDeviceReady(self->i2c_handle, addr << 1, 10, 200); + if (status == HAL_OK) { + mp_obj_list_append(list, mp_obj_new_int(addr)); + break; + } + } + } + + return list; +} + +STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_i2c_scan_obj, pyb_i2c_scan); + +STATIC mp_obj_t pyb_i2c_read(mp_obj_t self_in, mp_obj_t i2c_addr_in, mp_obj_t n_in) { + pyb_i2c_obj_t *self = self_in; + machine_uint_t i2c_addr = mp_obj_get_int(i2c_addr_in) << 1; + machine_uint_t n = mp_obj_get_int(n_in); + + byte *data; + mp_obj_t o = mp_obj_str_builder_start(&mp_type_bytes, n, &data); + HAL_StatusTypeDef status = HAL_I2C_Master_Receive(self->i2c_handle, i2c_addr, data, n, 500); + + if (status != HAL_OK) { + // TODO really need a HardwareError object, or something + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_Exception, "HAL_I2C_Master_Receive failed with code %d", status)); + } + + return mp_obj_str_builder_end(o); +} + +STATIC MP_DEFINE_CONST_FUN_OBJ_3(pyb_i2c_read_obj, pyb_i2c_read); + +STATIC mp_obj_t pyb_i2c_write(mp_obj_t self_in, mp_obj_t i2c_addr_in, mp_obj_t data_in) { + pyb_i2c_obj_t *self = self_in; + machine_uint_t i2c_addr = mp_obj_get_int(i2c_addr_in) << 1; + HAL_StatusTypeDef status; + if (MP_OBJ_IS_INT(data_in)) { + uint8_t data[1] = {mp_obj_get_int(data_in)}; + status = HAL_I2C_Master_Transmit(self->i2c_handle, i2c_addr, data, 1, 500); + } else { + buffer_info_t bufinfo; + mp_get_buffer_raise(data_in, &bufinfo); + status = HAL_I2C_Master_Transmit(self->i2c_handle, i2c_addr, bufinfo.buf, bufinfo.len, 500); + } + + if (status != HAL_OK) { + // TODO really need a HardwareError object, or something + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_Exception, "HAL_I2C_Master_Transmit failed with code %d", status)); + } + + return mp_const_none; +} + +STATIC MP_DEFINE_CONST_FUN_OBJ_3(pyb_i2c_write_obj, pyb_i2c_write); + STATIC mp_obj_t pyb_i2c_mem_read(uint n_args, const mp_obj_t *args) { pyb_i2c_obj_t *self = args[0]; machine_uint_t i2c_addr = mp_obj_get_int(args[1]) << 1; @@ -166,6 +228,9 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(pyb_i2c_mem_write_obj, 4, 4, pyb_i2c_ STATIC const mp_map_elem_t pyb_i2c_locals_dict_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_is_ready), (mp_obj_t)&pyb_i2c_is_ready_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_scan), (mp_obj_t)&pyb_i2c_scan_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_read), (mp_obj_t)&pyb_i2c_read_obj }, + { MP_OBJ_NEW_QSTR(MP_QSTR_write), (mp_obj_t)&pyb_i2c_write_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_mem_read), (mp_obj_t)&pyb_i2c_mem_read_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_mem_write), (mp_obj_t)&pyb_i2c_mem_write_obj }, }; diff --git a/stmhal/main.c b/stmhal/main.c index 2f40f140a..c5633fb68 100644 --- a/stmhal/main.c +++ b/stmhal/main.c @@ -134,7 +134,22 @@ static const char fresh_main_py[] = ; static const char fresh_pybcdc_inf[] = -#include "pybcdc.h" +#include "build/pybcdc_inf.h" +; + +static const char fresh_readme_txt[] = +"This is a Micro Python board\r\n" +"\r\n" +"You can get started right away by writing your Python code in 'main.py'.\r\n" +"\r\n" +"For a serial prompt:\r\n" +" - Windows: you need to go to 'Device manager', right click on the unknown device,\r\n" +" then update the driver software, using the 'pybcdc.inf' file found on this drive.\r\n" +" Then use a terminal program like Hyperterminal or putty.\r\n" +" - Mac OS X: use the command: screen /dev/tty.usbmodem*\r\n" +" - Linux: use the command: screen /dev/ttyACM0\r\n" +"\r\n" +"Please visit http://micropython.org/help/ for further help.\r\n" ; int main(void) { @@ -254,8 +269,15 @@ soft_reset: // 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)); + { + mp_obj_t args[2] = { + MP_OBJ_NEW_SMALL_INT(PYB_USART_6), + MP_OBJ_NEW_SMALL_INT(115200), + }; + pyb_usart_global_debug = pyb_usart_type.make_new((mp_obj_t)&pyb_usart_type, + sizeof(args) / sizeof(args[0]), + 0, args); + } #else pyb_usart_global_debug = NULL; #endif @@ -315,6 +337,11 @@ soft_reset: f_write(&fp, fresh_pybcdc_inf, sizeof(fresh_pybcdc_inf) - 1 /* don't count null terminator */, &n); f_close(&fp); + // create readme file + f_open(&fp, "0:/README.txt", FA_WRITE | FA_CREATE_ALWAYS); + f_write(&fp, fresh_readme_txt, sizeof(fresh_readme_txt) - 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); diff --git a/stmhal/pybcdc.h b/stmhal/pybcdc.h deleted file mode 100644 index 44685a05b..000000000 --- a/stmhal/pybcdc.h +++ /dev/null @@ -1,92 +0,0 @@ -"; Windows USB CDC ACM Setup File\r\n" -"; Based on INF files which were:\r\n" -"; Copyright (c) 2000 Microsoft Corporation\r\n" -"; Copyright (C) 2007 Microchip Technology Inc.\r\n" -"; Likely to be covered by the MLPL as found at:\r\n" -"; <http://msdn.microsoft.com/en-us/cc300389.aspx#MLPL>.\r\n" -"\r\n" -"[Version]\r\n" -"Signature=\"$Windows NT$\"\r\n" -"Class=Ports\r\n" -"ClassGuid={4D36E978-E325-11CE-BFC1-08002BE10318}\r\n" -"Provider=%MFGNAME%\r\n" -"LayoutFile=layout.inf\r\n" -"DriverVer=03/11/2010,5.1.2600.3\r\n" -"\r\n" -"[Manufacturer]\r\n" -"%MFGNAME%=DeviceList, NTamd64\r\n" -"\r\n" -"[DestinationDirs]\r\n" -"DefaultDestDir=12\r\n" -"\r\n" -";---------------------------------------------------------------------\r\n" -"; Windows 2000/XP/Server2003/Vista/Server2008/7 - 32bit Sections\r\n" -"\r\n" -"[DriverInstall.nt]\r\n" -"include=mdmcpq.inf\r\n" -"CopyFiles=DriverCopyFiles.nt\r\n" -"AddReg=DriverInstall.nt.AddReg\r\n" -"\r\n" -"[DriverCopyFiles.nt]\r\n" -"usbser.sys,,,0x20\r\n" -"\r\n" -"[DriverInstall.nt.AddReg]\r\n" -"HKR,,DevLoader,,*ntkern\r\n" -"HKR,,NTMPDriver,,usbser.sys\r\n" -"HKR,,EnumPropPages32,,\"MsPorts.dll,SerialPortPropPageProvider\"\r\n" -"\r\n" -"[DriverInstall.nt.Services]\r\n" -"AddService=usbser, 0x00000002, DriverService.nt\r\n" -"\r\n" -"[DriverService.nt]\r\n" -"DisplayName=%SERVICE%\r\n" -"ServiceType=1\r\n" -"StartType=3\r\n" -"ErrorControl=1\r\n" -"ServiceBinary=%12%\\usbser.sys\r\n" -"\r\n" -";---------------------------------------------------------------------\r\n" -"; Windows XP/Server2003/Vista/Server2008/7 - 64bit Sections\r\n" -"\r\n" -"[DriverInstall.NTamd64]\r\n" -"include=mdmcpq.inf\r\n" -"CopyFiles=DriverCopyFiles.NTamd64\r\n" -"AddReg=DriverInstall.NTamd64.AddReg\r\n" -"\r\n" -"[DriverCopyFiles.NTamd64]\r\n" -"usbser.sys,,,0x20\r\n" -"\r\n" -"[DriverInstall.NTamd64.AddReg]\r\n" -"HKR,,DevLoader,,*ntkern\r\n" -"HKR,,NTMPDriver,,usbser.sys\r\n" -"HKR,,EnumPropPages32,,\"MsPorts.dll,SerialPortPropPageProvider\"\r\n" -"\r\n" -"[DriverInstall.NTamd64.Services]\r\n" -"AddService=usbser, 0x00000002, DriverService.NTamd64\r\n" -"\r\n" -"[DriverService.NTamd64]\r\n" -"DisplayName=%SERVICE%\r\n" -"ServiceType=1\r\n" -"StartType=3\r\n" -"ErrorControl=1\r\n" -"ServiceBinary=%12%\\usbser.sys\r\n" -"\r\n" -";---------------------------------------------------------------------\r\n" -"; Vendor and Product ID Definitions\r\n" -"\r\n" -"[SourceDisksFiles]\r\n" -"[SourceDisksNames]\r\n" -"[DeviceList]\r\n" -"%DESCRIPTION%=DriverInstall, USB\\VID_0483&PID_5740&MI_00, USB\\VID_0483&PID_5740&MI_01\r\n" -"\r\n" -"[DeviceList.NTamd64]\r\n" -"%DESCRIPTION%=DriverInstall, USB\\VID_0483&PID_5740&MI_00, USB\\VID_0483&PID_5740&MI_01\r\n" -"\r\n" -";---------------------------------------------------------------------\r\n" -"; String Definitions\r\n" -"\r\n" -"[Strings]\r\n" -"MFGFILENAME=\"pybcdc\"\r\n" -"MFGNAME=\"Micro Python\"\r\n" -"DESCRIPTION=\"Pyboard USB Comm Port\"\r\n" -"SERVICE=\"USB Serial Driver\"\r\n" diff --git a/stmhal/pybcdc.inf b/stmhal/pybcdc.inf_template index eb04b65ce..87cd1467b 100755..100644 --- a/stmhal/pybcdc.inf +++ b/stmhal/pybcdc.inf_template @@ -77,10 +77,10 @@ ServiceBinary=%12%\usbser.sys [SourceDisksFiles]
[SourceDisksNames]
[DeviceList]
-%DESCRIPTION%=DriverInstall, USB\VID_0483&PID_5740&MI_00, USB\VID_0483&PID_5740&MI_01
+%DESCRIPTION%=DriverInstall, USB\VID_${USB_VID}&PID_${USB_PID}&MI_00, USB\VID_${USB_VID}&PID_${USB_PID}&MI_01
[DeviceList.NTamd64]
-%DESCRIPTION%=DriverInstall, USB\VID_0483&PID_5740&MI_00, USB\VID_0483&PID_5740&MI_01
+%DESCRIPTION%=DriverInstall, USB\VID_${USB_VID}&PID_${USB_PID}&MI_00, USB\VID_${USB_VID}&PID_${USB_PID}&MI_01
;---------------------------------------------------------------------
; String Definitions
diff --git a/stmhal/qstrdefsport.h b/stmhal/qstrdefsport.h index 0dd8c2b61..68b91c3d8 100644 --- a/stmhal/qstrdefsport.h +++ b/stmhal/qstrdefsport.h @@ -82,6 +82,7 @@ Q(MODE_EVT_RISING_FALLING) // for I2C object Q(I2C) Q(is_ready) +Q(scan) Q(mem_read) Q(mem_write) @@ -96,6 +97,7 @@ Q(filtered_xyz) // for ADC object Q(ADC) Q(ADC_all) +Q(read_timed) Q(read_channel) Q(read_core_temp) Q(read_core_vbat) diff --git a/stmhal/timer.c b/stmhal/timer.c index 1e77f0fea..5ea605039 100644 --- a/stmhal/timer.c +++ b/stmhal/timer.c @@ -27,6 +27,7 @@ TIM_HandleTypeDef TIM3_Handle; TIM_HandleTypeDef TIM5_Handle; +TIM_HandleTypeDef TIM6_Handle; // TIM3 is set-up for the USB CDC interface void timer_tim3_init(void) { @@ -57,6 +58,7 @@ void timer_tim3_deinit(void) { */ // TIM5 is set-up for the servo controller +// This function inits but does not start the timer void timer_tim5_init(void) { // TIM5 clock enable __TIM5_CLK_ENABLE(); @@ -74,6 +76,31 @@ void timer_tim5_init(void) { HAL_TIM_PWM_Init(&TIM5_Handle); } +// Init TIM6 with a counter-overflow at the given frequency (given in Hz) +// TIM6 is used by the DAC and ADC for auto sampling at a given frequency +// This function inits but does not start the timer +void timer_tim6_init(uint freq) { + // TIM6 clock enable + __TIM6_CLK_ENABLE(); + + // Timer runs at SystemCoreClock / 2 + // Compute the prescaler value so TIM6 triggers at freq-Hz + uint32_t period = (SystemCoreClock / 2) / freq; + uint32_t prescaler = 1; + while (period > 0xffff) { + period >>= 1; + prescaler <<= 1; + } + + // Time base clock configuration + TIM6_Handle.Instance = TIM6; + TIM6_Handle.Init.Period = period - 1; + TIM6_Handle.Init.Prescaler = prescaler - 1; + TIM6_Handle.Init.ClockDivision = 0; // unused for TIM6 + TIM6_Handle.Init.CounterMode = TIM_COUNTERMODE_UP; // unused for TIM6 + HAL_TIM_Base_Init(&TIM6_Handle); +} + // Interrupt dispatch void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if (htim == &TIM3_Handle) { diff --git a/stmhal/timer.h b/stmhal/timer.h index 317b39b3f..06e19bcc8 100644 --- a/stmhal/timer.h +++ b/stmhal/timer.h @@ -5,6 +5,8 @@ extern TIM_HandleTypeDef TIM3_Handle; extern TIM_HandleTypeDef TIM5_Handle; +extern TIM_HandleTypeDef TIM6_Handle; void timer_tim3_init(void); void timer_tim5_init(void); +void timer_tim6_init(uint freq); diff --git a/stmhal/usbd_msc_storage.c b/stmhal/usbd_msc_storage.c index f3ecd023d..0225a2a23 100644 --- a/stmhal/usbd_msc_storage.c +++ b/stmhal/usbd_msc_storage.c @@ -35,6 +35,11 @@ #include "diskio.h" #include "sdcard.h" +// These are needed to support removal of the medium, so that the USB drive +// can be unmounted, and won't be remounted automatically. +static uint8_t flash_removed = 0; +static uint8_t sdcard_removed = 0; + /******************************************************************************/ // Callback functions for when the internal flash is the mass storage device @@ -83,6 +88,9 @@ int8_t FLASH_STORAGE_GetCapacity(uint8_t lun, uint32_t *block_num, uint16_t *blo * @retval Status */ int8_t FLASH_STORAGE_IsReady(uint8_t lun) { + if (flash_removed) { + return -1; + } return 0; } @@ -95,6 +103,12 @@ int8_t FLASH_STORAGE_IsWriteProtected(uint8_t lun) { return 0; } +// Remove the lun +int8_t FLASH_STORAGE_StopUnit(uint8_t lun) { + flash_removed = 1; + return 0; +} + /** * @brief Read data from the medium * @param lun : logical unit number @@ -150,6 +164,7 @@ const USBD_StorageTypeDef USBD_FLASH_STORAGE_fops = { FLASH_STORAGE_GetCapacity, FLASH_STORAGE_IsReady, FLASH_STORAGE_IsWriteProtected, + FLASH_STORAGE_StopUnit, FLASH_STORAGE_Read, FLASH_STORAGE_Write, FLASH_STORAGE_GetMaxLun, @@ -236,6 +251,9 @@ int8_t SDCARD_STORAGE_GetCapacity(uint8_t lun, uint32_t *block_num, uint16_t *bl * @retval Status */ int8_t SDCARD_STORAGE_IsReady(uint8_t lun) { + if (sdcard_removed) { + return -1; + } /* #ifndef USE_STM3210C_EVAL @@ -271,6 +289,12 @@ int8_t SDCARD_STORAGE_IsWriteProtected(uint8_t lun) { return 0; } +// Remove the lun +int8_t SDCARD_STORAGE_StopUnit(uint8_t lun) { + sdcard_removed = 1; + return 0; +} + /** * @brief Read data from the medium * @param lun : logical unit number @@ -315,6 +339,7 @@ const USBD_StorageTypeDef USBD_SDCARD_STORAGE_fops = { SDCARD_STORAGE_GetCapacity, SDCARD_STORAGE_IsReady, SDCARD_STORAGE_IsWriteProtected, + SDCARD_STORAGE_StopUnit, SDCARD_STORAGE_Read, SDCARD_STORAGE_Write, SDCARD_STORAGE_GetMaxLun, diff --git a/stmhal/usbdev/class/cdc_msc_hid/inc/usbd_cdc_msc_hid.h b/stmhal/usbdev/class/cdc_msc_hid/inc/usbd_cdc_msc_hid.h index 8423ad775..934399493 100644 --- a/stmhal/usbdev/class/cdc_msc_hid/inc/usbd_cdc_msc_hid.h +++ b/stmhal/usbdev/class/cdc_msc_hid/inc/usbd_cdc_msc_hid.h @@ -53,6 +53,7 @@ typedef struct _USBD_STORAGE { int8_t (* GetCapacity) (uint8_t lun, uint32_t *block_num, uint16_t *block_size); int8_t (* IsReady) (uint8_t lun); int8_t (* IsWriteProtected) (uint8_t lun); + int8_t (* StopUnit)(uint8_t lun); int8_t (* Read) (uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len); int8_t (* Write)(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len); int8_t (* GetMaxLun)(void); diff --git a/stmhal/usbdev/class/cdc_msc_hid/src/usbd_cdc_msc_hid.c b/stmhal/usbdev/class/cdc_msc_hid/src/usbd_cdc_msc_hid.c index 6cb15ba21..6dc0af0e6 100644 --- a/stmhal/usbdev/class/cdc_msc_hid/src/usbd_cdc_msc_hid.c +++ b/stmhal/usbdev/class/cdc_msc_hid/src/usbd_cdc_msc_hid.c @@ -583,11 +583,18 @@ static uint8_t USBD_CDC_MSC_HID_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTyp /* printf("SU: %x %x %x %x\n", req->bmRequest, req->bRequest, req->wValue, req->wIndex); + This is what we get when MSC is IFACE=0 and CDC is IFACE=1,2: SU: 21 22 0 1 -- USB_REQ_TYPE_CLASS | USB_REQ_RECIPIENT_INTERFACE; CDC_SET_CONTROL_LINE_STATE SU: 21 20 0 1 -- USB_REQ_TYPE_CLASS | USB_REQ_RECIPIENT_INTERFACE; CDC_SET_LINE_CODING SU: a1 fe 0 0 -- 0x80 | USB_REQ_TYPE_CLASS | USB_REQ_RECIPIENT_INTERFACE; BOT_GET_MAX_LUN; 0; 0 SU: 21 22 3 1 -- USB_REQ_TYPE_CLASS | USB_REQ_RECIPIENT_INTERFACE; CDC_SET_CONTROL_LINE_STATE + + On a Mac OS X, with MSC then CDC: + SU: a1 fe 0 0 + SU: 21 22 2 1 + SU: 21 22 3 1 + SU: 21 20 0 1 */ switch (req->bmRequest & USB_REQ_TYPE_MASK) { @@ -723,6 +730,11 @@ static uint8_t USBD_CDC_MSC_HID_Setup(USBD_HandleTypeDef *pdev, USBD_SetupReqTyp return USBD_OK; } +/* unused +static uint8_t EP0_TxSent(USBD_HandleTypeDef *pdev) { +} +*/ + static uint8_t USBD_CDC_MSC_HID_EP0_RxReady(USBD_HandleTypeDef *pdev) { if((CDC_fops != NULL) && (CDC_ClassData.CmdOpCode != 0xFF)) { CDC_fops->Control(CDC_ClassData.CmdOpCode, (uint8_t *)CDC_ClassData.data, CDC_ClassData.CmdLength); @@ -902,8 +914,8 @@ USBD_ClassTypeDef USBD_CDC_MSC_HID = { USBD_CDC_MSC_HID_DataIn, USBD_CDC_MSC_HID_DataOut, NULL, // SOF - NULL, - NULL, + NULL, // IsoINIncomplete + NULL, // IsoOUTIncomplete USBD_CDC_MSC_HID_GetCfgDesc, USBD_CDC_MSC_HID_GetCfgDesc, USBD_CDC_MSC_HID_GetCfgDesc, diff --git a/stmhal/usbdev/class/cdc_msc_hid/src/usbd_msc_scsi.c b/stmhal/usbdev/class/cdc_msc_hid/src/usbd_msc_scsi.c index af3818d37..b00d1ae2c 100644 --- a/stmhal/usbdev/class/cdc_msc_hid/src/usbd_msc_scsi.c +++ b/stmhal/usbdev/class/cdc_msc_hid/src/usbd_msc_scsi.c @@ -86,6 +86,7 @@ static int8_t SCSI_ReadFormatCapacity(USBD_HandleTypeDef *pdev, uint8_t lun, ui static int8_t SCSI_ReadCapacity10(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params);
static int8_t SCSI_RequestSense (USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params);
static int8_t SCSI_StartStopUnit(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params);
+static int8_t SCSI_AllowMediumRemoval(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params);
static int8_t SCSI_ModeSense6 (USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params);
static int8_t SCSI_ModeSense10 (USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params);
static int8_t SCSI_Write10(USBD_HandleTypeDef *pdev, uint8_t lun , uint8_t *params);
@@ -122,6 +123,11 @@ int8_t SCSI_ProcessCmd(USBD_HandleTypeDef *pdev, uint8_t lun,
uint8_t *params)
{
+ /*
+ if (params[0] != SCSI_READ10 && params[0] != SCSI_WRITE10) {
+ printf("SCSI_ProcessCmd(lun=%d, params=%x, %x)\n", lun, params[0], params[1]);
+ }
+ */
switch (params[0])
{
@@ -137,7 +143,7 @@ int8_t SCSI_ProcessCmd(USBD_HandleTypeDef *pdev, return SCSI_StartStopUnit(pdev, lun, params);
case SCSI_ALLOW_MEDIUM_REMOVAL:
- return SCSI_StartStopUnit(pdev, lun, params);
+ return SCSI_AllowMediumRemoval(pdev, lun, params);
case SCSI_MODE_SENSE6:
return SCSI_ModeSense6 (pdev, lun, params);
@@ -442,6 +448,30 @@ static int8_t SCSI_StartStopUnit(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t {
USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData;
hmsc->bot_data_length = 0;
+
+ // On Mac OS X, when the device is ejected a SCSI_START_STOP_UNIT command is sent.
+ // params[1]==0 means stop, param[1]==1 seems to be something else (happens after the
+ // device is plugged in and mounted for some time, probably a keep alive).
+ // If we get a stop, we must really stop the device so that the Mac does not
+ // automatically remount it.
+ if (params[1] == 0) {
+ ((USBD_StorageTypeDef *)pdev->pUserData)->StopUnit(lun);
+ }
+
+ return 0;
+}
+
+/**
+* @brief SCSI_AllowMediumRemoval
+* Process Allow Medium Removal command
+* @param lun: Logical unit number
+* @param params: Command parameters
+* @retval status
+*/
+static int8_t SCSI_AllowMediumRemoval(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *params)
+{
+ USBD_MSC_BOT_HandleTypeDef *hmsc = pdev->pClassData;
+ hmsc->bot_data_length = 0;
return 0;
}
diff --git a/tests/basics/builtin-bin.py b/tests/basics/builtin-bin.py new file mode 100644 index 000000000..f6b6079de --- /dev/null +++ b/tests/basics/builtin-bin.py @@ -0,0 +1,12 @@ +# test builtin bin function + +print(bin(1)) +print(bin(-1)) +print(bin(15)) +print(bin(-15)) + +print(bin(12345)) +print(bin(0b10101)) + +print(bin(12345678901234567890)) +print(bin(0b10101010101010101010)) diff --git a/tests/basics/builtin-hex.py b/tests/basics/builtin-hex.py new file mode 100644 index 000000000..7d1c98a7a --- /dev/null +++ b/tests/basics/builtin-hex.py @@ -0,0 +1,12 @@ +# test builtin hex function + +print(hex(1)) +print(hex(-1)) +print(hex(15)) +print(hex(-15)) + +print(hex(12345)) +print(hex(0x12345)) + +print(hex(12345678901234567890)) +print(hex(0x12345678901234567890)) diff --git a/tests/basics/builtin-oct.py b/tests/basics/builtin-oct.py new file mode 100644 index 000000000..d8ba8e434 --- /dev/null +++ b/tests/basics/builtin-oct.py @@ -0,0 +1,12 @@ +# test builtin oct function + +print(oct(1)) +print(oct(-1)) +print(oct(15)) +print(oct(-15)) + +print(oct(12345)) +print(oct(0o12345)) + +print(oct(12345678901234567890)) +print(oct(0o12345670123456701234)) diff --git a/tests/basics/memoryerror.py b/tests/basics/memoryerror.py index e9aa97d85..b4be420c3 100644 --- a/tests/basics/memoryerror.py +++ b/tests/basics/memoryerror.py @@ -1,11 +1,6 @@ -# this test for MemoryError can be difficult to reproduce -# on different machine configurations (notably Travis CI) -# so we disable it -# TODO is there a way of testing that we are on Travis CI? -if False: - l = list(range(10000)) - try: - 100000000 * l - except MemoryError: - print('MemoryError') - print(len(l), l[0], l[-1]) +l = list(range(10000)) +try: + 100000000 * l +except MemoryError: + print('MemoryError') +print(len(l), l[0], l[-1]) diff --git a/tests/run-tests b/tests/run-tests index 554f5134c..bd6e50bbd 100755 --- a/tests/run-tests +++ b/tests/run-tests @@ -15,6 +15,9 @@ else: CPYTHON3 = os.getenv('MICROPY_CPYTHON3', 'python3') MP_PY = '../unix/micropython' +# Set of tests that we shouldn't run under Travis CI +skip_travis_tests = set(['basics/memoryerror.py']) + def rm_f(fname): if os.path.exists(fname): os.remove(fname) @@ -36,8 +39,12 @@ if test_on_pyboard: pyb = pyboard.Pyboard('/dev/ttyACM0') pyb.enter_raw_repl() +running_under_travis = os.environ.get('TRAVIS', 'false') == 'true' + for test_file in tests: - test_name = os.path.splitext(os.path.basename(test_file))[0] + if running_under_travis and test_file in skip_travis_tests: + print("skip ", test_file) + continue # run CPython try: @@ -64,15 +71,20 @@ for test_file in tests: testcase_count += len(output_expected.splitlines()) + test_basename = os.path.basename(test_file) + test_name = os.path.splitext(test_basename)[0] + filename_expected = test_basename + ".exp" + filename_mupy = test_basename + ".out" + if output_expected == output_mupy: print("pass ", test_file) passed_count += 1 - rm_f(os.path.basename(test_file + ".exp")) - rm_f(os.path.basename(test_file + ".out")) + rm_f(filename_expected) + rm_f(filename_mupy) else: - with open(os.path.basename(test_file + ".exp"), "w") as f: + with open(filename_expected, "w") as f: f.write(str(output_expected, "ascii")) - with open(os.path.basename(test_file + ".out"), "w") as f: + with open(filename_mupy, "w") as f: f.write(str(output_mupy, "ascii")) print("FAIL ", test_file) failed_tests.append(test_name) diff --git a/tools/file2h.py b/tools/file2h.py new file mode 100644 index 000000000..2a04ae22b --- /dev/null +++ b/tools/file2h.py @@ -0,0 +1,30 @@ +# Reads in a text file, and performs the necessary escapes so that it +# can be #included as a static string like: +# static const char string_from_textfile[] = +# #include "build/textfile.h" +# ; +# This script simply prints the escaped string straight to stdout + +from __future__ import print_function + +import sys + +# Can either be set explicitly, or left blank to auto-detect +# Except auto-detect doesn't work because the file has been passed +# through Python text processing, which makes all EOL a \n +line_end = '\\r\\n' + +if __name__ == "__main__": + filename = sys.argv[1] + for line in open(filename, 'r').readlines(): + if not line_end: + for ending in ('\r\n', '\r', '\n'): + if line.endswith(ending): + line_end = ending.replace('\r', '\\r').replace('\n', '\\n') + break + if not line_end: + raise Exception("Couldn't auto-detect line-ending of %s" % filename) + line = line.rstrip('\r\n') + line = line.replace('\\', '\\\\') + line = line.replace('"', '\\"') + print('"%s%s"' % (line, line_end)) diff --git a/tools/insert-usb-ids.py b/tools/insert-usb-ids.py new file mode 100644 index 000000000..42303da8b --- /dev/null +++ b/tools/insert-usb-ids.py @@ -0,0 +1,36 @@ +# Reads the USB VID and PID from the file specifed by sys.arg[1] and then +# inserts those values into the template file specified by sys.argv[2], +# printing the result to stdout + +from __future__ import print_function + +import sys +import re +import string + +def parse_usb_ids(filename): + rv = dict() + if filename == 'usbd_desc_cdc_msc.c': + for line in open(filename).readlines(): + line = line.rstrip('\r\n') + match = re.match('^#define\s+(\w+)\s+0x([0-9A-Fa-f]+)$', line) + if match: + if match.group(1) == 'USBD_VID': + rv['USB_VID'] = match.group(2) + elif match.group(1) == 'USBD_PID': + rv['USB_PID'] = match.group(2) + if 'USB_VID' in rv and 'USB_PID' in rv: + break + else: + raise Exception("Don't (yet) know how to parse USB IDs from %s" % filename) + for k in ('USB_PID', 'USB_VID'): + if k not in rv: + raise Exception("Unable to parse %s from %s" % (k, filename)) + return rv + +if __name__ == "__main__": + usb_ids_file = sys.argv[1] + template_file = sys.argv[2] + replacements = parse_usb_ids(usb_ids_file) + for line in open(template_file, 'r').readlines(): + print(string.Template(line).safe_substitute(replacements), end='') |
