diff --git a/py/builtin.c b/py/builtin.c index 2e0627fa5..93e91072c 100644 --- a/py/builtin.c +++ b/py/builtin.c @@ -375,28 +375,6 @@ STATIC mp_obj_t mp_builtin_sorted(uint n_args, const mp_obj_t *args, mp_map_t *k MP_DEFINE_CONST_FUN_OBJ_KW(mp_builtin_sorted_obj, 1, mp_builtin_sorted); -STATIC mp_obj_t mp_builtin_str(mp_obj_t o_in) { - vstr_t *vstr = vstr_new(); - mp_obj_print_helper((void (*)(void*, const char*, ...))vstr_printf, vstr, o_in, PRINT_STR); - mp_obj_t s = mp_obj_new_str((byte*)vstr->buf, vstr->len, false); - vstr_free(vstr); - return s; -} - -MP_DEFINE_CONST_FUN_OBJ_1(mp_builtin_str_obj, mp_builtin_str); - -// TODO: This should be type, this is just quick CPython compat hack -STATIC mp_obj_t mp_builtin_bytes(uint n_args, const mp_obj_t *args) { - if (!MP_OBJ_IS_QSTR(args[0]) && !MP_OBJ_IS_TYPE(args[0], &str_type)) { - assert(0); - } - // Currently, MicroPython strings are mix between CPython byte and unicode - // strings. So, conversion is null so far. - return args[0]; -} - -MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(mp_builtin_bytes_obj, 1, 3, mp_builtin_bytes); - STATIC mp_obj_t mp_builtin_id(mp_obj_t o_in) { return mp_obj_new_int((machine_int_t)o_in); } diff --git a/py/builtinmath.c b/py/builtinmath.c index fd1368ce3..59af5a021 100644 --- a/py/builtinmath.c +++ b/py/builtinmath.c @@ -46,9 +46,9 @@ MATH_FUN_1(fabs, fabs) MATH_FUN_1(floor, floor) //TODO: delegate to x.__floor__() if x is not a float MATH_FUN_2(fmod, fmod) //MATH_FUN_1(frexp, frexp) -MATH_FUN_1(isfinite, isfinite) -MATH_FUN_1(isinf, isinf) -MATH_FUN_1(isnan, isnan) +//MATH_FUN_1(isfinite, isfinite) +//MATH_FUN_1(isinf, isinf) +//MATH_FUN_1(isnan, isnan) MATH_FUN_1(trunc, trunc) //TODO: factorial, fsum, frexp, ldexp, modf @@ -83,9 +83,9 @@ STATIC const mp_map_elem_t mp_module_math_globals_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_floor), (mp_obj_t)&mp_math_floor_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_fmod), (mp_obj_t)&mp_math_fmod_obj }, //{ MP_OBJ_NEW_QSTR(MP_QSTR_frexp), (mp_obj_t)&mp_math_frexp_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_isfinite), (mp_obj_t)&mp_math_isfinite_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_isinf), (mp_obj_t)&mp_math_isinf_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_isnan), (mp_obj_t)&mp_math_isnan_obj }, + //{ MP_OBJ_NEW_QSTR(MP_QSTR_isfinite), (mp_obj_t)&mp_math_isfinite_obj }, + //{ MP_OBJ_NEW_QSTR(MP_QSTR_isinf), (mp_obj_t)&mp_math_isinf_obj }, + //{ MP_OBJ_NEW_QSTR(MP_QSTR_isnan), (mp_obj_t)&mp_math_isnan_obj }, { MP_OBJ_NEW_QSTR(MP_QSTR_trunc), (mp_obj_t)&mp_math_trunc_obj }, }; diff --git a/py/objcomplex.c b/py/objcomplex.c index 65957cbf6..2ba522615 100644 --- a/py/objcomplex.c +++ b/py/objcomplex.c @@ -6,6 +6,7 @@ #include "mpconfig.h" #include "qstr.h" #include "obj.h" +#include "parsenum.h" #include "runtime0.h" #include "map.h" @@ -36,15 +37,20 @@ STATIC mp_obj_t complex_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const return mp_obj_new_complex(0, 0); case 1: - // TODO allow string as first arg and parse it - if (MP_OBJ_IS_TYPE(args[0], &mp_type_complex)) { + if (MP_OBJ_IS_STR(args[0])) { + // a string, parse it + uint l; + const char *s = mp_obj_str_get_data(args[0], &l); + return mp_parse_num_decimal(s, l, true, true); + } else if (MP_OBJ_IS_TYPE(args[0], &mp_type_complex)) { + // a complex, just return it return args[0]; } else { + // something else, try to cast it to a complex return mp_obj_new_complex(mp_obj_get_float(args[0]), 0); } - case 2: - { + case 2: { mp_float_t real, imag; if (MP_OBJ_IS_TYPE(args[0], &mp_type_complex)) { mp_obj_complex_get(args[0], &real, &imag); diff --git a/py/objfloat.c b/py/objfloat.c index 704b3d599..c4567c4a3 100644 --- a/py/objfloat.c +++ b/py/objfloat.c @@ -39,10 +39,12 @@ STATIC mp_obj_t float_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const m // a string, parse it uint l; const char *s = mp_obj_str_get_data(args[0], &l); - return mp_parse_num_decimal(s, l); + return mp_parse_num_decimal(s, l, false, false); } else if (MP_OBJ_IS_TYPE(args[0], &mp_type_float)) { + // a float, just return it return args[0]; } else { + // something else, try to cast it to a float return mp_obj_new_float(mp_obj_get_float(args[0])); } diff --git a/py/objstr.c b/py/objstr.c index d660bf952..35a948700 100644 --- a/py/objstr.c +++ b/py/objstr.c @@ -14,9 +14,11 @@ typedef struct _mp_obj_str_t { mp_obj_base_t base; machine_uint_t hash : 16; // XXX here we assume the hash size is 16 bits (it is at the moment; see qstr.c) machine_uint_t len : 16; // len == number of bytes used in data, alloc = len + 1 because (at the moment) we also append a null byte - byte data[]; + const byte *data; } mp_obj_str_t; +const mp_obj_t mp_const_empty_bytes; + // use this macro to extract the string hash #define GET_STR_HASH(str_obj_in, str_hash) uint str_hash; if (MP_OBJ_IS_QSTR(str_obj_in)) { str_hash = qstr_hash(MP_OBJ_QSTR_VALUE(str_obj_in)); } else { str_hash = ((mp_obj_str_t*)str_obj_in)->hash; } @@ -28,6 +30,7 @@ typedef struct _mp_obj_str_t { STATIC mp_obj_t mp_obj_new_str_iterator(mp_obj_t str); STATIC mp_obj_t mp_obj_new_bytes_iterator(mp_obj_t str); +STATIC mp_obj_t str_new(const mp_obj_type_t *type, const byte* data, uint len); /******************************************************************************/ /* str */ @@ -78,6 +81,109 @@ STATIC void str_print(void (*print)(void *env, const char *fmt, ...), void *env, } } +STATIC mp_obj_t str_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) { + 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((byte*)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], &bytes_type)) { + nlr_jump(mp_obj_new_exception_msg(&mp_type_TypeError, "bytes expected")); + } + GET_STR_DATA_LEN(args[0], str_data, str_len); + GET_STR_HASH(args[0], str_hash); + mp_obj_str_t *o = str_new(&str_type, NULL, str_len); + o->data = str_data; + o->hash = str_hash; + return o; + } + + default: + nlr_jump(mp_obj_new_exception_msg(&mp_type_TypeError, "str takes at most 3 arguments")); + } +} + +STATIC mp_obj_t bytes_make_new(mp_obj_t type_in, uint n_args, uint n_kw, const mp_obj_t *args) { + if (n_args == 0) { + return mp_const_empty_bytes; + } + + if (MP_OBJ_IS_STR(args[0])) { + if (n_args < 2 || n_args > 3) { + goto wrong_args; + } + GET_STR_DATA_LEN(args[0], str_data, str_len); + GET_STR_HASH(args[0], str_hash); + mp_obj_str_t *o = str_new(&bytes_type, NULL, str_len); + o->data = str_data; + o->hash = str_hash; + return o; + } + + if (n_args > 1) { + goto wrong_args; + } + + if (MP_OBJ_IS_SMALL_INT(args[0])) { + uint len = MP_OBJ_SMALL_INT_VALUE(args[0]); + byte *data; + + mp_obj_t o = mp_obj_str_builder_start(&bytes_type, len, &data); + memset(data, 0, len); + return mp_obj_str_builder_end(o); + } + + int len; + byte *data; + vstr_t *vstr = NULL; + mp_obj_t o = NULL; + // Try to create array of exact len if initializer len is known + mp_obj_t len_in = mp_obj_len_maybe(args[0]); + if (len_in == MP_OBJ_NULL) { + len = -1; + vstr = vstr_new(); + } else { + len = MP_OBJ_SMALL_INT_VALUE(len_in); + o = mp_obj_str_builder_start(&bytes_type, len, &data); + } + + mp_obj_t iterable = rt_getiter(args[0]); + mp_obj_t item; + while ((item = rt_iternext(iterable)) != mp_const_stop_iteration) { + if (len == -1) { + vstr_add_char(vstr, MP_OBJ_SMALL_INT_VALUE(item)); + } else { + *data++ = MP_OBJ_SMALL_INT_VALUE(item); + } + } + + if (len == -1) { + vstr_shrink(vstr); + // TODO: Optimize, borrow buffer from vstr + len = vstr_len(vstr); + o = mp_obj_str_builder_start(&bytes_type, len, &data); + memcpy(data, vstr_str(vstr), len); + vstr_free(vstr); + } + + return mp_obj_str_builder_end(o); + +wrong_args: + nlr_jump(mp_obj_new_exception_msg(&mp_type_TypeError, "wrong number of arguments")); +} + // like strstr but with specified length and allows \0 bytes // TODO replace with something more efficient/standard STATIC const byte *find_subbytes(const byte *haystack, uint hlen, const byte *needle, uint nlen) { @@ -520,6 +626,62 @@ STATIC mp_obj_t str_count(uint n_args, const mp_obj_t *args) { return MP_OBJ_NEW_SMALL_INT(num_occurrences); } +STATIC mp_obj_t str_partitioner(mp_obj_t self_in, mp_obj_t arg, machine_int_t direction) { + assert(MP_OBJ_IS_STR(self_in)); + if (!MP_OBJ_IS_STR(arg)) { + nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_TypeError, + "Can't convert '%s' object to str implicitly", mp_obj_get_type_str(arg))); + } + + GET_STR_DATA_LEN(self_in, str, str_len); + GET_STR_DATA_LEN(arg, sep, sep_len); + + if (sep_len == 0) { + nlr_jump(mp_obj_new_exception_msg(&mp_type_ValueError, "empty separator")); + } + + mp_obj_t result[] = {MP_OBJ_NEW_QSTR(MP_QSTR_), MP_OBJ_NEW_QSTR(MP_QSTR_), MP_OBJ_NEW_QSTR(MP_QSTR_)}; + + if (direction > 0) { + result[0] = self_in; + } else { + result[2] = self_in; + } + + if (str_len >= sep_len) { + machine_uint_t str_index, str_index_end; + if (direction > 0) { + str_index = 0; + str_index_end = str_len - sep_len; + } else { + str_index = str_len - sep_len; + str_index_end = 0; + } + for (;;) { + if (memcmp(&str[str_index], sep, sep_len) == 0) { + result[0] = mp_obj_new_str(str, str_index, false); + result[1] = arg; + result[2] = mp_obj_new_str(str + str_index + sep_len, str_len - str_index - sep_len, false); + break; + } + if (str_index == str_index_end) { + break; + } + str_index += direction; + } + } + + return mp_obj_new_tuple(3, result); +} + +STATIC mp_obj_t str_partition(mp_obj_t self_in, mp_obj_t arg) { + return str_partitioner(self_in, arg, 1); +} + +STATIC mp_obj_t str_rpartition(mp_obj_t self_in, mp_obj_t arg) { + return str_partitioner(self_in, arg, -1); +} + STATIC machine_int_t str_get_buffer(mp_obj_t self_in, buffer_info_t *bufinfo, int flags) { if (flags == BUFFER_READ) { GET_STR_DATA_LEN(self_in, str_data, str_len); @@ -542,6 +704,8 @@ 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_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); +STATIC MP_DEFINE_CONST_FUN_OBJ_2(str_rpartition_obj, str_rpartition); STATIC const mp_method_t str_type_methods[] = { { "find", &str_find_obj }, @@ -552,6 +716,8 @@ STATIC const mp_method_t str_type_methods[] = { { "format", &str_format_obj }, { "replace", &str_replace_obj }, { "count", &str_count_obj }, + { "partition", &str_partition_obj }, + { "rpartition", &str_rpartition_obj }, { NULL, NULL }, // end-of-list sentinel }; @@ -559,6 +725,7 @@ const mp_obj_type_t str_type = { { &mp_type_type }, .name = MP_QSTR_str, .print = str_print, + .make_new = str_make_new, .binary_op = str_binary_op, .getiter = mp_obj_new_str_iterator, .methods = str_type_methods, @@ -570,34 +737,45 @@ const mp_obj_type_t bytes_type = { { &mp_type_type }, .name = MP_QSTR_bytes, .print = str_print, + .make_new = bytes_make_new, .binary_op = str_binary_op, .getiter = mp_obj_new_bytes_iterator, .methods = str_type_methods, }; +// the zero-length bytes +STATIC const mp_obj_str_t empty_bytes_obj = {{&bytes_type}, 0, 0, NULL}; +const mp_obj_t mp_const_empty_bytes = (mp_obj_t)&empty_bytes_obj; + mp_obj_t mp_obj_str_builder_start(const mp_obj_type_t *type, uint len, byte **data) { - mp_obj_str_t *o = m_new_obj_var(mp_obj_str_t, byte, len + 1); + mp_obj_str_t *o = m_new_obj(mp_obj_str_t); o->base.type = type; o->len = len; - *data = o->data; + byte *p = m_new(byte, len + 1); + o->data = p; + *data = p; return o; } mp_obj_t mp_obj_str_builder_end(mp_obj_t o_in) { - assert(MP_OBJ_IS_STR(o_in)); mp_obj_str_t *o = o_in; o->hash = qstr_compute_hash(o->data, o->len); - o->data[o->len] = '\0'; // for now we add null for compatibility with C ASCIIZ strings + byte *p = (byte*)o->data; + p[o->len] = '\0'; // for now we add null for compatibility with C ASCIIZ strings return o; } STATIC mp_obj_t str_new(const mp_obj_type_t *type, const byte* data, uint len) { - mp_obj_str_t *o = m_new_obj_var(mp_obj_str_t, byte, len + 1); + mp_obj_str_t *o = m_new_obj(mp_obj_str_t); o->base.type = type; - o->hash = qstr_compute_hash(data, len); o->len = len; - memcpy(o->data, data, len * sizeof(byte)); - o->data[len] = '\0'; // for now we add null for compatibility with C ASCIIZ strings + if (data) { + o->hash = qstr_compute_hash(data, len); + byte *p = m_new(byte, len + 1); + o->data = p; + memcpy(p, data, len * sizeof(byte)); + p[len] = '\0'; // for now we add null for compatibility with C ASCIIZ strings + } return o; } diff --git a/py/parsenum.c b/py/parsenum.c index c9cef5fcd..7be53897a 100644 --- a/py/parsenum.c +++ b/py/parsenum.c @@ -9,139 +9,217 @@ #include "parsenumbase.h" #include "parsenum.h" -#if defined(UNIX) - -#include -#include +#if MICROPY_ENABLE_FLOAT +#include +#endif mp_obj_t mp_parse_num_integer(const char *restrict str, uint len, int base) { - // TODO at the moment we ignore len; we should honour it! - // TODO detect integer overflow and return bignum - - int c, neg = 0; - const char *p = str; - char *num; - long found; + const char *restrict top = str + len; + bool neg = false; // check radix base if ((base != 0 && base < 2) || base > 36) { nlr_jump(mp_obj_new_exception_msg(&mp_type_ValueError, "ValueError: int() arg 2 must be >=2 and <= 36")); } - // skip surrounded whitespace - while (isspace((c = *(p++)))); - if (c == 0) { - goto value_error; - } - // preced sign - if (c == '+' || c == '-') { - neg = - (c == '-'); - } else { - p--; + + // skip leading space + for (; str < top && unichar_isspace(*str); str++) { } - len -= p - str; - int skip = mp_parse_num_base(p, len, &base); - p += skip; - len -= skip; - - errno = 0; - found = strtol(p, &num, base); - if (errno) { - goto value_error; - } else if (found && *(num) == 0) { - goto done; - } else if (found || num != p) { - goto check_tail_space; - } else { - goto value_error; - } - -check_tail_space: - if (*(num) != 0) { - while (isspace((c = *(num++)))); - if (c != 0) { - goto value_error; + // parse optional sign + if (str < top) { + if (*str == '+') { + str++; + } else if (*str == '-') { + str++; + neg = true; } } -done: - return MP_OBJ_NEW_SMALL_INT((found ^ neg) - neg); + // parse optional base prefix + str += mp_parse_num_base(str, top - str, &base); + + // string should be an integer number + machine_int_t int_val = 0; + const char *restrict str_val_start = str; + for (; str < top; str++) { + machine_int_t old_val = int_val; + int dig = *str; + if (unichar_isdigit(dig) && dig - '0' < base) { + // 0-9 digit + int_val = base * int_val + dig - '0'; + } else if (base == 16) { + dig |= 0x20; + if ('a' <= dig && dig <= 'f') { + // a-f hex digit + int_val = base * int_val + dig - 'a' + 10; + } else { + // unknown character + break; + } + } else { + // unknown character + break; + } + if (int_val < old_val) { + // If new value became less than previous, it's overflow + goto overflow; + } else if ((old_val ^ int_val) & WORD_MSBIT_HIGH) { + // If signed number changed sign - it's overflow + goto overflow; + } + } + + // check we parsed something + if (str == str_val_start) { + goto value_error; + } + + // negate value if needed + if (neg) { + int_val = -int_val; + } + + // skip trailing space + for (; str < top && unichar_isspace(*str); str++) { + } + + // check we reached the end of the string + if (str != top) { + goto value_error; + } + + // return the object + return MP_OBJ_NEW_SMALL_INT(int_val); value_error: nlr_jump(mp_obj_new_exception_msg_varg(&mp_type_ValueError, "invalid literal for int() with base %d: '%s'", base, str)); + +overflow: + // TODO reparse using bignum + nlr_jump(mp_obj_new_exception_msg(&mp_type_ValueError, "overflow parsing integer")); } -#else /* defined(UNIX) */ - -mp_obj_t mp_parse_num_integer(const char *restrict str, uint len, int base) { - // TODO port strtol to stm - return MP_OBJ_NEW_SMALL_INT(0); -} - -#endif /* defined(UNIX) */ - #define PARSE_DEC_IN_INTG (1) #define PARSE_DEC_IN_FRAC (2) #define PARSE_DEC_IN_EXP (3) -mp_obj_t mp_parse_num_decimal(const char *str, uint len) { +mp_obj_t mp_parse_num_decimal(const char *str, uint len, bool allow_imag, bool force_complex) { #if MICROPY_ENABLE_FLOAT - int in = PARSE_DEC_IN_INTG; - mp_float_t dec_val = 0; - bool exp_neg = false; - int exp_val = 0; - int exp_extra = 0; - bool imag = false; const char *top = str + len; - for (; str < top; str++) { - int dig = *str; - if ('0' <= dig && dig <= '9') { - dig -= '0'; - if (in == PARSE_DEC_IN_EXP) { - exp_val = 10 * exp_val + dig; - } else { - dec_val = 10 * dec_val + dig; - if (in == PARSE_DEC_IN_FRAC) { - exp_extra -= 1; - } - } - } else if (in == PARSE_DEC_IN_INTG && dig == '.') { - in = PARSE_DEC_IN_FRAC; - } else if (in != PARSE_DEC_IN_EXP && (dig == 'E' || dig == 'e')) { - in = PARSE_DEC_IN_EXP; - if (str[1] == '+') { - str++; - } else if (str[1] == '-') { - str++; - exp_neg = true; - } - } else if (dig == 'J' || dig == 'j') { + mp_float_t dec_val = 0; + bool dec_neg = false; + bool imag = false; + + // skip leading space + for (; str < top && unichar_isspace(*str); str++) { + } + + // parse optional sign + if (str < top) { + if (*str == '+') { str++; - imag = true; - break; - } else { - // unknown character - break; + } else if (*str == '-') { + str++; + dec_neg = true; } } - if (*str != 0) { + + // determine what the string is + if (str < top && (str[0] | 0x20) == 'i') { + // string starts with 'i', should be 'inf' or 'infinity' (case insensitive) + if (str + 2 < top && (str[1] | 0x20) == 'n' && (str[2] | 0x20) == 'f') { + // inf + str += 3; + dec_val = INFINITY; + if (str + 4 < top && (str[0] | 0x20) == 'i' && (str[1] | 0x20) == 'n' && (str[2] | 0x20) == 'i' && (str[3] | 0x20) == 't' && (str[4] | 0x20) == 'y') { + // infinity + str += 5; + } + } + } else if (str < top && (str[0] | 0x20) == 'n') { + // string starts with 'n', should be 'nan' (case insensitive) + if (str + 2 < top && (str[1] | 0x20) == 'a' && (str[2] | 0x20) == 'n') { + // NaN + str += 3; + dec_val = MICROPY_FLOAT_C_FUN(nan)(""); + } + } else { + // string should be a decimal number + int in = PARSE_DEC_IN_INTG; + bool exp_neg = false; + int exp_val = 0; + int exp_extra = 0; + for (; str < top; str++) { + int dig = *str; + if ('0' <= dig && dig <= '9') { + dig -= '0'; + if (in == PARSE_DEC_IN_EXP) { + exp_val = 10 * exp_val + dig; + } else { + dec_val = 10 * dec_val + dig; + if (in == PARSE_DEC_IN_FRAC) { + exp_extra -= 1; + } + } + } else if (in == PARSE_DEC_IN_INTG && dig == '.') { + in = PARSE_DEC_IN_FRAC; + } else if (in != PARSE_DEC_IN_EXP && ((dig | 0x20) == 'e')) { + in = PARSE_DEC_IN_EXP; + if (str[1] == '+') { + str++; + } else if (str[1] == '-') { + str++; + exp_neg = true; + } + } else if (allow_imag && (dig | 0x20) == 'j') { + str++; + imag = true; + break; + } else { + // unknown character + break; + } + } + + // work out the exponent + if (exp_neg) { + exp_val = -exp_val; + } + exp_val += exp_extra; + + // apply the exponent + for (; exp_val > 0; exp_val--) { + dec_val *= 10; + } + for (; exp_val < 0; exp_val++) { + dec_val *= 0.1; + } + } + + // negate value if needed + if (dec_neg) { + dec_val = -dec_val; + } + + // skip trailing space + for (; str < top && unichar_isspace(*str); str++) { + } + + // check we reached the end of the string + if (str != top) { nlr_jump(mp_obj_new_exception_msg(&mp_type_SyntaxError, "invalid syntax for number")); } - if (exp_neg) { - exp_val = -exp_val; - } - exp_val += exp_extra; - for (; exp_val > 0; exp_val--) { - dec_val *= 10; - } - for (; exp_val < 0; exp_val++) { - dec_val *= 0.1; - } + + // return the object if (imag) { return mp_obj_new_complex(0, dec_val); + } else if (force_complex) { + return mp_obj_new_complex(dec_val, 0); } else { return mp_obj_new_float(dec_val); } + #else nlr_jump(mp_obj_new_exception_msg(&mp_type_SyntaxError, "decimal numbers not supported")); #endif diff --git a/py/parsenum.h b/py/parsenum.h index 5a2e42da5..97578423c 100644 --- a/py/parsenum.h +++ b/py/parsenum.h @@ -1,2 +1,2 @@ mp_obj_t mp_parse_num_integer(const char *restrict str, uint len, int base); -mp_obj_t mp_parse_num_decimal(const char *str, uint len); +mp_obj_t mp_parse_num_decimal(const char *str, uint len, bool allow_imag, bool force_complex); diff --git a/py/runtime.c b/py/runtime.c index b57a74fa3..68edf5456 100644 --- a/py/runtime.c +++ b/py/runtime.c @@ -89,6 +89,7 @@ STATIC const mp_builtin_elem_t builtin_table[] = { // built-in types { MP_QSTR_bool, (mp_obj_t)&bool_type }, + { MP_QSTR_bytes, (mp_obj_t)&bytes_type }, #if MICROPY_ENABLE_FLOAT { MP_QSTR_complex, (mp_obj_t)&mp_type_complex }, #endif @@ -102,6 +103,7 @@ STATIC const mp_builtin_elem_t builtin_table[] = { { MP_QSTR_list, (mp_obj_t)&list_type }, { MP_QSTR_map, (mp_obj_t)&map_type }, { MP_QSTR_set, (mp_obj_t)&set_type }, + { MP_QSTR_str, (mp_obj_t)&str_type }, { MP_QSTR_super, (mp_obj_t)&super_type }, { MP_QSTR_tuple, (mp_obj_t)&tuple_type }, { MP_QSTR_type, (mp_obj_t)&mp_type_type }, @@ -114,7 +116,6 @@ STATIC const mp_builtin_elem_t builtin_table[] = { { MP_QSTR_abs, (mp_obj_t)&mp_builtin_abs_obj }, { MP_QSTR_all, (mp_obj_t)&mp_builtin_all_obj }, { MP_QSTR_any, (mp_obj_t)&mp_builtin_any_obj }, - { MP_QSTR_bytes, (mp_obj_t)&mp_builtin_bytes_obj }, { MP_QSTR_callable, (mp_obj_t)&mp_builtin_callable_obj }, { MP_QSTR_chr, (mp_obj_t)&mp_builtin_chr_obj }, { MP_QSTR_dir, (mp_obj_t)&mp_builtin_dir_obj }, @@ -137,7 +138,6 @@ STATIC const mp_builtin_elem_t builtin_table[] = { { MP_QSTR_repr, (mp_obj_t)&mp_builtin_repr_obj }, { MP_QSTR_sorted, (mp_obj_t)&mp_builtin_sorted_obj }, { MP_QSTR_sum, (mp_obj_t)&mp_builtin_sum_obj }, - { MP_QSTR_str, (mp_obj_t)&mp_builtin_str_obj }, { MP_QSTR_bytearray, (mp_obj_t)&mp_builtin_bytearray_obj }, // built-in exceptions @@ -376,7 +376,7 @@ mp_obj_t rt_load_const_dec(qstr qstr) { DEBUG_OP_printf("load '%s'\n", qstr_str(qstr)); uint len; const byte* data = qstr_data(qstr, &len); - return mp_parse_num_decimal((const char*)data, len); + return mp_parse_num_decimal((const char*)data, len, true, false); } mp_obj_t rt_load_const_str(qstr qstr) { diff --git a/py/showbc.c b/py/showbc.c index bc81086c7..9bdf811d9 100644 --- a/py/showbc.c +++ b/py/showbc.c @@ -394,6 +394,10 @@ void mp_byte_code_print(const byte *ip, int len) { printf("YIELD_VALUE"); break; + case MP_BC_YIELD_FROM: + printf("YIELD_FROM"); + break; + case MP_BC_IMPORT_NAME: DECODE_QSTR; printf("IMPORT_NAME %s", qstr_str(qstr)); diff --git a/stm/math.c b/stm/math.c index 8e2c6fc75..0809a3f2c 100644 --- a/stm/math.c +++ b/stm/math.c @@ -44,6 +44,10 @@ float acosf(float x) { return 0.0; } float asinf(float x) { return 0.0; } float atanf(float x) { return 0.0; } float atan2f(float x, float y) { return 0.0; } +float ceilf(float x) { return 0.0; } +float floorf(float x) { return 0.0; } +float truncf(float x) { return 0.0; } +float fmodf(float x, float y) { return 0.0; } /*****************************************************************************/ // from musl-0.9.15 libm.h diff --git a/stmhal/Makefile b/stmhal/Makefile index 9f3e365a1..86791607a 100644 --- a/stmhal/Makefile +++ b/stmhal/Makefile @@ -21,7 +21,7 @@ INC += -I$(PY_SRC) INC += -I$(CMSIS_DIR)/inc INC += -I$(CMSIS_DIR)/devinc INC += -I$(HAL_DIR)/inc -INC += -I$(USBDEV_DIR)/core/inc -I$(USBDEV_DIR)/class/cdc/inc +INC += -I$(USBDEV_DIR)/core/inc -I$(USBDEV_DIR)/class/cdc/inc -I$(USBDEV_DIR)/class/msc/inc #INC += -I$(USBHOST_DIR) INC += -I$(FATFS_DIR)/src #INC += -I$(CC3K_DIR) @@ -56,8 +56,10 @@ SRC_C = \ stm32f4xx_it.c \ stm32f4xx_hal_msp.c \ usbd_conf.c \ - usbd_desc.c \ + usbd_desc_vcp.c \ usbd_cdc_interface.c \ + usbd_desc_msc.c \ + usbd_msc_storage.c \ pendsv.c \ systick.c \ led.c \ @@ -84,9 +86,9 @@ SRC_C = \ sdcard.c \ diskio.c \ lcd.c \ + accel.c \ # servo.c \ -# accel.c \ # timer.c \ # audio.c \ # i2c.c \ @@ -104,6 +106,7 @@ SRC_HAL = $(addprefix $(HAL_DIR)/src/,\ stm32f4xx_hal_flash.c \ stm32f4xx_hal_flash_ex.c \ stm32f4xx_hal_gpio.c \ + stm32f4xx_hal_i2c.c \ stm32f4xx_hal_pcd.c \ stm32f4xx_hal_rcc.c \ stm32f4xx_hal_rcc_ex.c \ @@ -122,6 +125,10 @@ SRC_USBDEV = $(addprefix $(USBDEV_DIR)/,\ core/src/usbd_ctlreq.c \ core/src/usbd_ioreq.c \ class/cdc/src/usbd_cdc.c \ + class/msc/src/usbd_msc.c \ + class/msc/src/usbd_msc_bot.c \ + class/msc/src/usbd_msc_scsi.c \ + class/msc/src/usbd_msc_data.c \ ) # usbd_core.c \ diff --git a/stmhal/accel.c b/stmhal/accel.c new file mode 100644 index 000000000..f380242bf --- /dev/null +++ b/stmhal/accel.c @@ -0,0 +1,137 @@ +#include +#include + +#include + +#include "misc.h" +#include "mpconfig.h" +#include "qstr.h" +#include "obj.h" +#include "runtime.h" +#include "accel.h" + +#define MMA_ADDR (0x98) +#define MMA_REG_MODE (7) + +STATIC I2C_HandleTypeDef I2cHandle; + +void accel_init(void) { + GPIO_InitTypeDef GPIO_InitStructure; + + // PB5 is connected to AVDD; pull high to enable MMA accel device + GPIOB->BSRRH = GPIO_PIN_5; // turn off AVDD + GPIO_InitStructure.Pin = GPIO_PIN_5; + GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStructure.Speed = GPIO_SPEED_LOW; + GPIO_InitStructure.Pull = GPIO_NOPULL; + HAL_GPIO_Init(GPIOB, &GPIO_InitStructure); + + // wait 20ms, then turn on AVDD, then wait 20ms again + HAL_Delay(20); + GPIOB->BSRRL = GPIO_PIN_5; + HAL_Delay(20); + + // PB6=SCL, PB7=SDA + GPIO_InitStructure.Pin = GPIO_PIN_6 | GPIO_PIN_7; + GPIO_InitStructure.Mode = GPIO_MODE_AF_OD; + GPIO_InitStructure.Speed = GPIO_SPEED_FAST; + GPIO_InitStructure.Pull = GPIO_NOPULL; // have external pull-up resistors on both lines + GPIO_InitStructure.Alternate = GPIO_AF4_I2C1; + HAL_GPIO_Init(GPIOB, &GPIO_InitStructure); + + // enable the I2C1 clock + __I2C1_CLK_ENABLE(); + + // set up the I2C1 device + memset(&I2cHandle, 0, sizeof(I2C_HandleTypeDef)); + I2cHandle.Instance = I2C1; + I2cHandle.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; + I2cHandle.Init.ClockSpeed = 400000; + I2cHandle.Init.DualAddressMode = I2C_DUALADDRESS_DISABLED; + I2cHandle.Init.DutyCycle = I2C_DUTYCYCLE_16_9; + I2cHandle.Init.GeneralCallMode = I2C_GENERALCALL_DISABLED; + I2cHandle.Init.NoStretchMode = I2C_NOSTRETCH_DISABLED; + I2cHandle.Init.OwnAddress1 = 0xfe; // unused + I2cHandle.Init.OwnAddress2 = 0xfe; // unused + + if (HAL_I2C_Init(&I2cHandle) != HAL_OK) { + // init error + printf("accel_init: HAL_I2C_Init failed\n"); + return; + } + + HAL_StatusTypeDef status; + + //printf("IsDeviceReady\n"); + for (int i = 0; i < 10; i++) { + status = HAL_I2C_IsDeviceReady(&I2cHandle, MMA_ADDR, 10, 200); + //printf(" got %d\n", status); + if (status == HAL_OK) { + break; + } + } + + //printf("MemWrite\n"); + uint8_t data[1]; + data[0] = 1; // active mode + status = HAL_I2C_Mem_Write(&I2cHandle, MMA_ADDR, MMA_REG_MODE, I2C_MEMADD_SIZE_8BIT, data, 1, 200); + //printf(" got %d\n", status); +} + +/******************************************************************************/ +/* Micro Python bindings */ + +int accel_buf[12]; + +mp_obj_t pyb_accel_read(void) { + for (int i = 0; i <= 6; i += 3) { + accel_buf[0 + i] = accel_buf[0 + i + 3]; + accel_buf[1 + i] = accel_buf[1 + i + 3]; + accel_buf[2 + i] = accel_buf[2 + i + 3]; + } + + uint8_t data_[4]; + HAL_I2C_Mem_Read(&I2cHandle, MMA_ADDR, 0, I2C_MEMADD_SIZE_8BIT, data_, 4, 200); + accel_buf[9] = data_[0] & 0x3f; if (accel_buf[9] & 0x20) accel_buf[9] |= ~0x1f; + accel_buf[10] = data_[1] & 0x3f; if (accel_buf[10] & 0x20) accel_buf[10] |= ~0x1f; + accel_buf[11] = data_[2] & 0x3f; if (accel_buf[11] & 0x20) accel_buf[11] |= ~0x1f; + int jolt_info = data_[3]; + + mp_obj_t data[4]; + data[0] = mp_obj_new_int(accel_buf[0] + accel_buf[3] + accel_buf[6] + accel_buf[9]); + data[1] = mp_obj_new_int(accel_buf[1] + accel_buf[4] + accel_buf[7] + accel_buf[10]); + data[2] = mp_obj_new_int(accel_buf[2] + accel_buf[5] + accel_buf[8] + accel_buf[11]); + data[3] = mp_obj_new_int(jolt_info); + + return rt_build_tuple(4, data); +} + +MP_DEFINE_CONST_FUN_OBJ_0(pyb_accel_read_obj, pyb_accel_read); + +/* +mp_obj_t pyb_accel_read_all(void) { + mp_obj_t data[11]; + accel_start(MMA_ADDR, 1); + accel_send_byte(0); + accel_restart(MMA_ADDR, 0); + for (int i = 0; i <= 9; i++) { + data[i] = mp_obj_new_int(accel_read_ack()); + } + data[10] = mp_obj_new_int(accel_read_nack()); + + return rt_build_tuple(11, data); +} + +MP_DEFINE_CONST_FUN_OBJ_0(pyb_accel_read_all_obj, pyb_accel_read_all); + +mp_obj_t pyb_accel_write_mode(mp_obj_t o_int, mp_obj_t o_mode) { + accel_start(MMA_ADDR, 1); + accel_send_byte(6); // start at int + accel_send_byte(mp_obj_get_int(o_int)); + accel_send_byte(mp_obj_get_int(o_mode)); + accel_stop(); + return mp_const_none; +} + +MP_DEFINE_CONST_FUN_OBJ_2(pyb_accel_write_mode_obj, pyb_accel_write_mode); +*/ diff --git a/stmhal/accel.h b/stmhal/accel.h new file mode 100644 index 000000000..c2320f1a4 --- /dev/null +++ b/stmhal/accel.h @@ -0,0 +1,11 @@ +void accel_init(void); +void accel_restart(uint8_t addr, int write); +void accel_start(uint8_t addr, int write); +void accel_send_byte(uint8_t data); +uint8_t accel_read_ack(void); +uint8_t accel_read_nack(void); +void accel_stop(void); + +MP_DECLARE_CONST_FUN_OBJ(pyb_accel_read_obj); +MP_DECLARE_CONST_FUN_OBJ(pyb_accel_read_all_obj); +MP_DECLARE_CONST_FUN_OBJ(pyb_accel_write_mode_obj); diff --git a/stmhal/import.c b/stmhal/import.c index f2fd3b3de..c977dcf2e 100644 --- a/stmhal/import.c +++ b/stmhal/import.c @@ -1,16 +1,18 @@ +#include #include #include "misc.h" #include "mpconfig.h" #include "qstr.h" #include "lexer.h" -#if 0 #include "ff.h" -#endif mp_import_stat_t mp_import_stat(const char *path) { -#if 0 FILINFO fno; +#if _USE_LFN + fno.lfname = NULL; + fno.lfsize = 0; +#endif FRESULT res = f_stat(path, &fno); if (res == FR_OK) { if ((fno.fattrib & AM_DIR) != 0) { @@ -19,6 +21,5 @@ mp_import_stat_t mp_import_stat(const char *path) { return MP_IMPORT_STAT_FILE; } } -#endif return MP_IMPORT_STAT_NO_EXIST; } diff --git a/stmhal/led.c b/stmhal/led.c index 677c151b3..80c1e145f 100644 --- a/stmhal/led.c +++ b/stmhal/led.c @@ -73,6 +73,14 @@ void led_toggle(pyb_led_t led) { } } +void led_debug(int n, int delay) { + led_state(1, n & 1); + led_state(2, n & 2); + led_state(3, n & 4); + led_state(4, n & 8); + HAL_Delay(delay); +} + /******************************************************************************/ /* Micro Python bindings */ diff --git a/stmhal/led.h b/stmhal/led.h index 44c68d4eb..b3762271c 100644 --- a/stmhal/led.h +++ b/stmhal/led.h @@ -19,5 +19,6 @@ typedef enum { void led_init(void); void led_state(pyb_led_t led, int state); void led_toggle(pyb_led_t led); +void led_debug(int value, int delay); MP_DECLARE_CONST_FUN_OBJ(pyb_Led_obj); diff --git a/stmhal/main.c b/stmhal/main.c index d77733429..d92ccdd5b 100644 --- a/stmhal/main.c +++ b/stmhal/main.c @@ -33,9 +33,9 @@ #include "sdcard.h" #include "ff.h" #include "lcd.h" +#include "accel.h" #if 0 #include "servo.h" -#include "accel.h" #include "timer.h" #include "pybwlan.h" #include "pin.h" @@ -170,22 +170,6 @@ int main(void) { // enable the CCM RAM __CCMDATARAMEN_CLK_ENABLE(); - // some test code to flash LEDs - led_init(); - - led_state(0, 1); - led_state(1, 0); - led_state(2, 1); - -#if 0 - for (;;) { - HAL_Delay(500); - led_state(1, 1); - HAL_Delay(500); - led_state(1, 0); - } -#endif - #if 0 #if defined(NETDUINO_PLUS_2) { @@ -348,6 +332,11 @@ soft_reset: // make sure we have a /boot.py { FILINFO fno; +#if _USE_LFN + fno.lfname = NULL; + fno.lfsize = 0; +#endif + led_debug(0, 500); FRESULT res = f_stat("0:/boot.py", &fno); if (res == FR_OK) { if (fno.fattrib & AM_DIR) { @@ -382,18 +371,13 @@ soft_reset: flash_error(4); } - if (first_soft_reset) { -#if 0 -#if MICROPY_HW_HAS_MMA7660 - // MMA accel: init and reset address to zero - accel_init(); -#endif -#endif - } - // turn boot-up LED off led_state(PYB_LED_GREEN, 0); +#if defined(USE_DEVICE_MODE) + usbd_storage_medium_kind_t usbd_medium_kind = USBD_STORAGE_MEDIUM_FLASH; +#endif + #if MICROPY_HW_HAS_SDCARD // if an SD card is present then mount it on 1:/ if (sdcard_is_present()) { @@ -403,8 +387,8 @@ soft_reset: } else { if (first_soft_reset) { // use SD card as medium for the USB MSD -#if 0 - usbd_storage_select_medium(USBD_STORAGE_MEDIUM_SDCARD); +#if defined(USE_DEVICE_MODE) + usbd_medium_kind = USBD_STORAGE_MEDIUM_SDCARD; #endif } } @@ -416,7 +400,12 @@ soft_reset: pyb_usb_host_init(); #elif defined(USE_DEVICE_MODE) // USB device - pyb_usb_dev_init(PYB_USB_DEV_VCP_MSC); + pyb_usb_dev_init(USBD_DEVICE_MSC, usbd_medium_kind); +#endif + +#if MICROPY_HW_HAS_MMA7660 + // MMA accel: init and reset + accel_init(); #endif // run main script diff --git a/stmhal/math.c b/stmhal/math.c index 8e2c6fc75..0809a3f2c 100644 --- a/stmhal/math.c +++ b/stmhal/math.c @@ -44,6 +44,10 @@ float acosf(float x) { return 0.0; } float asinf(float x) { return 0.0; } float atanf(float x) { return 0.0; } float atan2f(float x, float y) { return 0.0; } +float ceilf(float x) { return 0.0; } +float floorf(float x) { return 0.0; } +float truncf(float x) { return 0.0; } +float fmodf(float x, float y) { return 0.0; } /*****************************************************************************/ // from musl-0.9.15 libm.h diff --git a/stmhal/pybmodule.c b/stmhal/pybmodule.c index b6b269b06..3db23dc6d 100644 --- a/stmhal/pybmodule.c +++ b/stmhal/pybmodule.c @@ -21,10 +21,10 @@ #include "usart.h" #include "storage.h" #include "sdcard.h" +#include "accel.h" #if 0 #include "servo.h" #include "usb.h" -#include "accel.h" #include "i2c.h" #include "adc.h" #include "audio.h" @@ -256,13 +256,13 @@ STATIC const mp_map_elem_t pyb_module_globals_table[] = { { MP_OBJ_NEW_QSTR(MP_QSTR_SD), (mp_obj_t)&pyb_sdcard_obj }, #endif -#if 0 #if MICROPY_HW_HAS_MMA7660 { MP_OBJ_NEW_QSTR(MP_QSTR_accel), (mp_obj_t)&pyb_accel_read_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_accel_read), (mp_obj_t)&pyb_accel_read_all_obj }, - { MP_OBJ_NEW_QSTR(MP_QSTR_accel_mode), (mp_obj_t)&pyb_accel_write_mode_obj }, + //{ MP_OBJ_NEW_QSTR(MP_QSTR_accel_read), (mp_obj_t)&pyb_accel_read_all_obj }, + //{ MP_OBJ_NEW_QSTR(MP_QSTR_accel_mode), (mp_obj_t)&pyb_accel_write_mode_obj }, #endif +#if 0 { MP_OBJ_NEW_QSTR(MP_QSTR_hid), (mp_obj_t)&pyb_hid_send_report_obj }, #endif { MP_OBJ_NEW_QSTR(MP_QSTR_Led), (mp_obj_t)&pyb_Led_obj }, diff --git a/stmhal/usb.c b/stmhal/usb.c index 5cf7b5f32..c14a5ad68 100644 --- a/stmhal/usb.c +++ b/stmhal/usb.c @@ -1,21 +1,16 @@ #include -/* -#include "usb_core.h" -#include "usbd_cdc_core.h" -#include "usbd_pyb_core.h" -#include "usbd_usr.h" -*/ #include "usbd_core.h" #include "usbd_desc.h" #include "usbd_cdc.h" #include "usbd_cdc_interface.h" +#include "usbd_msc.h" +#include "usbd_msc_storage.h" #include "misc.h" #include "mpconfig.h" #include "qstr.h" #include "obj.h" -//#include "pendsv.h" #include "usb.h" #ifdef USE_DEVICE_MODE @@ -26,12 +21,12 @@ static int dev_is_enabled = 0; uint32_t APP_dev_is_connected = 0; /* used by usbd_cdc_vcp */ mp_obj_t mp_const_vcp_interrupt = MP_OBJ_NULL; -void pyb_usb_dev_init(int usb_dev_type) { +void pyb_usb_dev_init(usbd_device_kind_t device_kind, usbd_storage_medium_kind_t medium_kind) { #ifdef USE_DEVICE_MODE if (!dev_is_enabled) { // only init USB once in the device's power-lifetime - switch (usb_dev_type) { - case PYB_USB_DEV_VCP_MSC: + switch (device_kind) { + case USBD_DEVICE_CDC: // XXX USBD_CDC_Init (called by one of these functions below) uses malloc, // so the memory is invalid after a soft reset (which resets the GC). USBD_Init(&hUSBDDevice, &VCP_Desc, 0); @@ -41,7 +36,20 @@ void pyb_usb_dev_init(int usb_dev_type) { //USBD_Init(&USB_OTG_Core, USB_OTG_FS_CORE_ID, &USR_desc, &USBD_PYB_cb, &USR_cb); break; - case PYB_USB_DEV_HID: + case USBD_DEVICE_MSC: + // XXX USBD_CDC_Init (called by one of these functions below) uses malloc, + // so the memory is invalid after a soft reset (which resets the GC). + USBD_Init(&hUSBDDevice, &MSC_Desc, 0); + USBD_RegisterClass(&hUSBDDevice, &USBD_MSC); + if (medium_kind == USBD_STORAGE_MEDIUM_FLASH) { + USBD_MSC_RegisterStorage(&hUSBDDevice, (USBD_StorageTypeDef*)&USBD_FLASH_STORAGE_fops); + } else { + USBD_MSC_RegisterStorage(&hUSBDDevice, (USBD_StorageTypeDef*)&USBD_SDCARD_STORAGE_fops); + } + USBD_Start(&hUSBDDevice); + break; + + case USBD_DEVICE_HID: //USBD_Init(&USB_OTG_Core, USB_OTG_FS_CORE_ID, &USR_desc, &USBD_PYB_HID_cb, &USR_cb); // TODO break; diff --git a/stmhal/usb.h b/stmhal/usb.h index 3e6bdccec..bb6283c89 100644 --- a/stmhal/usb.h +++ b/stmhal/usb.h @@ -4,10 +4,18 @@ #define VCP_CHAR_CTRL_C (3) #define VCP_CHAR_CTRL_D (4) -#define PYB_USB_DEV_VCP_MSC (0) -#define PYB_USB_DEV_HID (1) +typedef enum { + USBD_DEVICE_CDC, + USBD_DEVICE_MSC, + USBD_DEVICE_HID, +} usbd_device_kind_t; -void pyb_usb_dev_init(int usb_dev_type); +typedef enum { + USBD_STORAGE_MEDIUM_FLASH, + USBD_STORAGE_MEDIUM_SDCARD, +} usbd_storage_medium_kind_t; + +void pyb_usb_dev_init(usbd_device_kind_t device_kind, usbd_storage_medium_kind_t medium_kind); bool usb_vcp_is_enabled(void); bool usb_vcp_is_connected(void); void usb_vcp_set_interrupt_char(int c); diff --git a/stmhal/usbd_conf.h b/stmhal/usbd_conf.h index 8c02ad0ec..cc3ad73f9 100644 --- a/stmhal/usbd_conf.h +++ b/stmhal/usbd_conf.h @@ -48,6 +48,9 @@ #define USBD_SELF_POWERED 0 #define USBD_DEBUG_LEVEL 0 +// for MSC device +#define MSC_MEDIA_PACKET 8192 + /* Exported macro ------------------------------------------------------------*/ /* Memory management macros */ #define USBD_malloc gc_alloc diff --git a/stmhal/usbd_desc.h b/stmhal/usbd_desc.h index 8b2d8f103..a54e427e3 100644 --- a/stmhal/usbd_desc.h +++ b/stmhal/usbd_desc.h @@ -1,43 +1,2 @@ -/** - ****************************************************************************** - * @file USB_Device/CDC_Standalone/Inc/usbd_desc.h - * @author MCD Application Team - * @version V1.0.1 - * @date 26-February-2014 - * @brief Header for usbd_desc.c module - ****************************************************************************** - * @attention - * - *

© COPYRIGHT(c) 2014 STMicroelectronics

- * - * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); - * You may not use this file except in compliance with the License. - * You may obtain a copy of the License at: - * - * http://www.st.com/software_license_agreement_liberty_v2 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - ****************************************************************************** - */ - -/* Define to prevent recursive inclusion -------------------------------------*/ -#ifndef __USBD_DESC_H -#define __USBD_DESC_H - -/* Includes ------------------------------------------------------------------*/ -#include "usbd_def.h" - -/* Exported types ------------------------------------------------------------*/ -/* Exported constants --------------------------------------------------------*/ -/* Exported macro ------------------------------------------------------------*/ -/* Exported functions ------------------------------------------------------- */ -extern USBD_DescriptorsTypeDef VCP_Desc; - -#endif /* __USBD_DESC_H */ - -/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ +extern USBD_DescriptorsTypeDef VCP_Desc; +extern USBD_DescriptorsTypeDef MSC_Desc; diff --git a/stmhal/usbd_desc_msc.c b/stmhal/usbd_desc_msc.c new file mode 100644 index 000000000..7d0911e82 --- /dev/null +++ b/stmhal/usbd_desc_msc.c @@ -0,0 +1,227 @@ +/** + ****************************************************************************** + * @file USB_Device/MSC_Standalone/Src/usbd_desc.c + * @author MCD Application Team + * @version V1.0.1 + * @date 26-February-2014 + * @brief This file provides the USBD descriptors and string formating method. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT(c) 2014 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ****************************************************************************** + */ + +/* Includes ------------------------------------------------------------------*/ +#include "usbd_core.h" +#include "usbd_desc.h" +#include "usbd_conf.h" + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +#define USBD_VID 0x0483 +#define USBD_PID 0x5720 +#define USBD_LANGID_STRING 0x409 +#define USBD_MANUFACTURER_STRING "STMicroelectronics" +#define USBD_PRODUCT_HS_STRING "Mass Storage in HS Mode" +#define USBD_SERIALNUMBER_HS_STRING "00000000001A" +#define USBD_PRODUCT_FS_STRING "Mass Storage in FS Mode" +#define USBD_SERIALNUMBER_FS_STRING "00000000001B" +#define USBD_CONFIGURATION_HS_STRING "MSC Config" +#define USBD_INTERFACE_HS_STRING "MSC Interface" +#define USBD_CONFIGURATION_FS_STRING "MSC Config" +#define USBD_INTERFACE_FS_STRING "MSC Interface" + +/* Private macro -------------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +uint8_t *USBD_MSC_DeviceDescriptor(USBD_SpeedTypeDef speed, uint16_t *length); +uint8_t *USBD_MSC_LangIDStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length); +uint8_t *USBD_MSC_ManufacturerStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length); +uint8_t *USBD_MSC_ProductStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length); +uint8_t *USBD_MSC_SerialStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length); +uint8_t *USBD_MSC_ConfigStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length); +uint8_t *USBD_MSC_InterfaceStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length); +#ifdef USB_SUPPORT_USER_STRING_DESC +uint8_t *USBD_MSC_USRStringDesc(USBD_SpeedTypeDef speed, uint8_t idx, uint16_t *length); +#endif /* USB_SUPPORT_USER_STRING_DESC */ + +/* Private variables ---------------------------------------------------------*/ +USBD_DescriptorsTypeDef MSC_Desc = { + USBD_MSC_DeviceDescriptor, + USBD_MSC_LangIDStrDescriptor, + USBD_MSC_ManufacturerStrDescriptor, + USBD_MSC_ProductStrDescriptor, + USBD_MSC_SerialStrDescriptor, + USBD_MSC_ConfigStrDescriptor, + USBD_MSC_InterfaceStrDescriptor, +}; + +/* USB Standard Device Descriptor */ +#if defined ( __ICCARM__ ) /*!< IAR Compiler */ + #pragma data_alignment=4 +#endif +__ALIGN_BEGIN static uint8_t USBD_DeviceDesc[USB_LEN_DEV_DESC] __ALIGN_END = { + 0x12, /* bLength */ + USB_DESC_TYPE_DEVICE, /* bDescriptorType */ + 0x00, /* bcdUSB */ + 0x02, + 0x00, /* bDeviceClass */ + 0x00, /* bDeviceSubClass */ + 0x00, /* bDeviceProtocol */ + USB_MAX_EP0_SIZE, /* bMaxPacketSize */ + LOBYTE(USBD_VID), /* idVendor */ + HIBYTE(USBD_VID), /* idVendor */ + LOBYTE(USBD_PID), /* idVendor */ + HIBYTE(USBD_PID), /* idVendor */ + 0x00, /* bcdDevice rel. 2.00 */ + 0x02, + USBD_IDX_MFC_STR, /* Index of manufacturer string */ + USBD_IDX_PRODUCT_STR, /* Index of product string */ + USBD_IDX_SERIAL_STR, /* Index of serial number string */ + USBD_MAX_NUM_CONFIGURATION /* bNumConfigurations */ +}; /* USB_DeviceDescriptor */ + +/* USB Standard Device Descriptor */ +#if defined ( __ICCARM__ ) /*!< IAR Compiler */ + #pragma data_alignment=4 +#endif +__ALIGN_BEGIN static uint8_t USBD_LangIDDesc[USB_LEN_LANGID_STR_DESC] __ALIGN_END = { + USB_LEN_LANGID_STR_DESC, + USB_DESC_TYPE_STRING, + LOBYTE(USBD_LANGID_STRING), + HIBYTE(USBD_LANGID_STRING), +}; + +#if defined ( __ICCARM__ ) /*!< IAR Compiler */ + #pragma data_alignment=4 +#endif +__ALIGN_BEGIN static uint8_t USBD_StrDesc[USBD_MAX_STR_DESC_SIZ] __ALIGN_END; + +/* Private functions ---------------------------------------------------------*/ + +/** + * @brief Returns the device descriptor. + * @param speed: Current device speed + * @param length: Pointer to data length variable + * @retval Pointer to descriptor buffer + */ +uint8_t *USBD_MSC_DeviceDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) +{ + *length = sizeof(USBD_DeviceDesc); + return USBD_DeviceDesc; +} + +/** + * @brief Returns the LangID string descriptor. + * @param speed: Current device speed + * @param length: Pointer to data length variable + * @retval Pointer to descriptor buffer + */ +uint8_t *USBD_MSC_LangIDStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) +{ + *length = sizeof(USBD_LangIDDesc); + return USBD_LangIDDesc; +} + +/** + * @brief Returns the product string descriptor. + * @param speed: Current device speed + * @param length: Pointer to data length variable + * @retval Pointer to descriptor buffer + */ +uint8_t *USBD_MSC_ProductStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) +{ + if(speed == 0) + { + USBD_GetString((uint8_t *)(uint8_t *)USBD_PRODUCT_HS_STRING, USBD_StrDesc, length); + } + else + { + USBD_GetString((uint8_t *)(uint8_t *)USBD_PRODUCT_FS_STRING, USBD_StrDesc, length); + } + return USBD_StrDesc; +} + +/** + * @brief Returns the manufacturer string descriptor. + * @param speed: Current device speed + * @param length: Pointer to data length variable + * @retval Pointer to descriptor buffer + */ +uint8_t *USBD_MSC_ManufacturerStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) +{ + USBD_GetString((uint8_t *)(uint8_t *)USBD_MANUFACTURER_STRING, USBD_StrDesc, length); + return USBD_StrDesc; +} + +/** + * @brief Returns the serial number string descriptor. + * @param speed: Current device speed + * @param length: Pointer to data length variable + * @retval Pointer to descriptor buffer + */ +uint8_t *USBD_MSC_SerialStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) +{ + if(speed == USBD_SPEED_HIGH) + { + USBD_GetString((uint8_t *)(uint8_t *)USBD_SERIALNUMBER_HS_STRING, USBD_StrDesc, length); + } + else + { + USBD_GetString((uint8_t *)(uint8_t *)USBD_SERIALNUMBER_FS_STRING, USBD_StrDesc, length); + } + return USBD_StrDesc; +} + +/** + * @brief Returns the configuration string descriptor. + * @param speed: Current device speed + * @param length: Pointer to data length variable + * @retval Pointer to descriptor buffer + */ +uint8_t *USBD_MSC_ConfigStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) +{ + if(speed == USBD_SPEED_HIGH) + { + USBD_GetString((uint8_t *)(uint8_t *)USBD_CONFIGURATION_HS_STRING, USBD_StrDesc, length); + } + else + { + USBD_GetString((uint8_t *)(uint8_t *)USBD_CONFIGURATION_FS_STRING, USBD_StrDesc, length); + } + return USBD_StrDesc; +} + +/** + * @brief Returns the interface string descriptor. + * @param speed: Current device speed + * @param length: Pointer to data length variable + * @retval Pointer to descriptor buffer + */ +uint8_t *USBD_MSC_InterfaceStrDescriptor(USBD_SpeedTypeDef speed, uint16_t *length) +{ + if(speed == 0) + { + USBD_GetString((uint8_t *)(uint8_t *)USBD_INTERFACE_HS_STRING, USBD_StrDesc, length); + } + else + { + USBD_GetString((uint8_t *)(uint8_t *)USBD_INTERFACE_FS_STRING, USBD_StrDesc, length); + } + return USBD_StrDesc; +} + +/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ diff --git a/stmhal/usbd_desc.c b/stmhal/usbd_desc_vcp.c similarity index 94% rename from stmhal/usbd_desc.c rename to stmhal/usbd_desc_vcp.c index ca9ea487d..edcb4b343 100644 --- a/stmhal/usbd_desc.c +++ b/stmhal/usbd_desc_vcp.c @@ -73,7 +73,7 @@ USBD_DescriptorsTypeDef VCP_Desc = { #if defined ( __ICCARM__ ) /*!< IAR Compiler */ #pragma data_alignment=4 #endif -__ALIGN_BEGIN uint8_t hUSBDDeviceDesc[USB_LEN_DEV_DESC] __ALIGN_END = { +__ALIGN_BEGIN static uint8_t hUSBDDeviceDesc[USB_LEN_DEV_DESC] __ALIGN_END = { 0x12, /* bLength */ USB_DESC_TYPE_DEVICE, /* bDescriptorType */ 0x00, /* bcdUSB */ @@ -98,7 +98,7 @@ __ALIGN_BEGIN uint8_t hUSBDDeviceDesc[USB_LEN_DEV_DESC] __ALIGN_END = { #if defined ( __ICCARM__ ) /*!< IAR Compiler */ #pragma data_alignment=4 #endif -__ALIGN_BEGIN uint8_t USBD_LangIDDesc[USB_LEN_LANGID_STR_DESC] __ALIGN_END = { +__ALIGN_BEGIN static uint8_t USBD_LangIDDesc[USB_LEN_LANGID_STR_DESC] __ALIGN_END = { USB_LEN_LANGID_STR_DESC, USB_DESC_TYPE_STRING, LOBYTE(USBD_LANGID_STRING), @@ -108,7 +108,7 @@ __ALIGN_BEGIN uint8_t USBD_LangIDDesc[USB_LEN_LANGID_STR_DESC] __ALIGN_END = { #if defined ( __ICCARM__ ) /*!< IAR Compiler */ #pragma data_alignment=4 #endif -__ALIGN_BEGIN uint8_t USBD_StrDesc[USBD_MAX_STR_DESC_SIZ] __ALIGN_END; +__ALIGN_BEGIN static uint8_t USBD_StrDesc[USBD_MAX_STR_DESC_SIZ] __ALIGN_END; /* Private functions ---------------------------------------------------------*/ diff --git a/stmhal/usbd_msc_storage.c b/stmhal/usbd_msc_storage.c new file mode 100644 index 000000000..e5c75e27c --- /dev/null +++ b/stmhal/usbd_msc_storage.c @@ -0,0 +1,320 @@ +/** + ****************************************************************************** + * @file usbd_storage_msd.c + * @author MCD application Team + * @version V1.1.0 + * @date 19-March-2012 + * @brief This file provides the disk operations functions. + ****************************************************************************** + * @attention + * + *

© COPYRIGHT 2012 STMicroelectronics

+ * + * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.st.com/software_license_agreement_liberty_v2 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Heavily modified by dpgeorge for Micro Python. + * + ****************************************************************************** + */ + +#include "usbd_msc.h" +#include "usbd_msc_storage.h" + +#include "misc.h" +#include "storage.h" +#include "diskio.h" +#include "sdcard.h" + +/******************************************************************************/ +// Callback functions for when the internal flash is the mass storage device + +static const int8_t FLASH_STORAGE_Inquirydata[] = { // 36 bytes + // LUN 0 + 0x00, + 0x00, // 0x00 for a fixed drive, 0x80 for a removable drive + 0x02, + 0x02, + (STANDARD_INQUIRY_DATA_LEN - 5), + 0x00, + 0x00, + 0x00, + 'u', 'P', 'y', ' ', ' ', ' ', ' ', ' ', // Manufacturer : 8 bytes + 'm', 'i', 'c', 'r', 'o', 'S', 'D', ' ', // Product : 16 Bytes + 'F', 'l', 'a', 's', 'h', ' ', ' ', ' ', + '1', '.', '0' ,'0', // Version : 4 Bytes +}; + +/** + * @brief Initialize the storage medium + * @param lun : logical unit number + * @retval Status + */ +int8_t FLASH_STORAGE_Init(uint8_t lun) { + storage_init(); + return 0; +} + +/** + * @brief return medium capacity and block size + * @param lun : logical unit number + * @param block_num : number of physical block + * @param block_size : size of a physical block + * @retval Status + */ +int8_t FLASH_STORAGE_GetCapacity(uint8_t lun, uint32_t *block_num, uint16_t *block_size) { + *block_size = storage_get_block_size(); + *block_num = storage_get_block_count(); + return 0; +} + +/** + * @brief check whether the medium is ready + * @param lun : logical unit number + * @retval Status + */ +int8_t FLASH_STORAGE_IsReady(uint8_t lun) { + return 0; +} + +/** + * @brief check whether the medium is write-protected + * @param lun : logical unit number + * @retval Status + */ +int8_t FLASH_STORAGE_IsWriteProtected(uint8_t lun) { + return 0; +} + +/** + * @brief Read data from the medium + * @param lun : logical unit number + * @param buf : Pointer to the buffer to save data + * @param blk_addr : address of 1st block to be read + * @param blk_len : nmber of blocks to be read + * @retval Status + */ +int8_t FLASH_STORAGE_Read(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len) { + disk_read(0, buf, blk_addr, blk_len); + /* + for (int i = 0; i < blk_len; i++) { + if (!storage_read_block(buf + i * FLASH_BLOCK_SIZE, blk_addr + i)) { + return -1; + } + } + */ + return 0; +} + +/** + * @brief Write data to the medium + * @param lun : logical unit number + * @param buf : Pointer to the buffer to write from + * @param blk_addr : address of 1st block to be written + * @param blk_len : nmber of blocks to be read + * @retval Status + */ +int8_t FLASH_STORAGE_Write (uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len) { + disk_write(0, buf, blk_addr, blk_len); + /* + for (int i = 0; i < blk_len; i++) { + if (!storage_write_block(buf + i * FLASH_BLOCK_SIZE, blk_addr + i)) { + return -1; + } + } + */ + storage_flush(); // XXX hack for now so that the cache is always flushed + return 0; +} + +/** + * @brief Return number of supported logical unit + * @param None + * @retval number of logical unit + */ +int8_t FLASH_STORAGE_GetMaxLun(void) { + return 0; +} + +const USBD_StorageTypeDef USBD_FLASH_STORAGE_fops = { + FLASH_STORAGE_Init, + FLASH_STORAGE_GetCapacity, + FLASH_STORAGE_IsReady, + FLASH_STORAGE_IsWriteProtected, + FLASH_STORAGE_Read, + FLASH_STORAGE_Write, + FLASH_STORAGE_GetMaxLun, + (int8_t *)FLASH_STORAGE_Inquirydata, +}; + +/******************************************************************************/ +// Callback functions for when the SD card is the mass storage device + +static const int8_t SDCARD_STORAGE_Inquirydata[] = { // 36 bytes + // LUN 0 + 0x00, + 0x80, // 0x00 for a fixed drive, 0x80 for a removable drive + 0x02, + 0x02, + (STANDARD_INQUIRY_DATA_LEN - 5), + 0x00, + 0x00, + 0x00, + 'u', 'P', 'y', ' ', ' ', ' ', ' ', ' ', // Manufacturer : 8 bytes + 'm', 'i', 'c', 'r', 'o', 'S', 'D', ' ', // Product : 16 Bytes + 'S', 'D', ' ', 'c', 'a', 'r', 'd', ' ', + '1', '.', '0' ,'0', // Version : 4 Bytes +}; + +/** + * @brief Initialize the storage medium + * @param lun : logical unit number + * @retval Status + */ +int8_t SDCARD_STORAGE_Init(uint8_t lun) { + /* +#ifndef USE_STM3210C_EVAL + NVIC_InitTypeDef NVIC_InitStructure; + NVIC_InitStructure.NVIC_IRQChannel = SDIO_IRQn; + NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority =0; + NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; + NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; + NVIC_Init(&NVIC_InitStructure); +#endif + if( SD_Init() != 0) + { + return (-1); + } + */ + if (!sdcard_power_on()) { + return -1; + } + + return 0; + +} + +/** + * @brief return medium capacity and block size + * @param lun : logical unit number + * @param block_num : number of physical block + * @param block_size : size of a physical block + * @retval Status + */ +int8_t SDCARD_STORAGE_GetCapacity(uint8_t lun, uint32_t *block_num, uint16_t *block_size) { +/* +#ifdef USE_STM3210C_EVAL + SD_CardInfo SDCardInfo; + SD_GetCardInfo(&SDCardInfo); +#else + if(SD_GetStatus() != 0 ) { + return (-1); + } +#endif + */ + + *block_size = SDCARD_BLOCK_SIZE; + *block_num = sdcard_get_capacity_in_bytes() / SDCARD_BLOCK_SIZE; + + return 0; +} + +/** + * @brief check whether the medium is ready + * @param lun : logical unit number + * @retval Status + */ +int8_t SDCARD_STORAGE_IsReady(uint8_t lun) { + /* +#ifndef USE_STM3210C_EVAL + + static int8_t last_status = 0; + + if(last_status < 0) + { + SD_Init(); + last_status = 0; + } + + if(SD_GetStatus() != 0) + { + last_status = -1; + return (-1); + } +#else + if( SD_Init() != 0) + { + return (-1); + } +#endif +*/ + return 0; +} + +/** + * @brief check whether the medium is write-protected + * @param lun : logical unit number + * @retval Status + */ +int8_t SDCARD_STORAGE_IsWriteProtected(uint8_t lun) { + return 0; +} + +/** + * @brief Read data from the medium + * @param lun : logical unit number + * @param buf : Pointer to the buffer to save data + * @param blk_addr : address of 1st block to be read + * @param blk_len : nmber of blocks to be read + * @retval Status + */ +int8_t SDCARD_STORAGE_Read(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len) { + if (!sdcard_read_blocks(buf, blk_addr, blk_len)) { + return -1; + } + return 0; +} + +/** + * @brief Write data to the medium + * @param lun : logical unit number + * @param buf : Pointer to the buffer to write from + * @param blk_addr : address of 1st block to be written + * @param blk_len : nmber of blocks to be read + * @retval Status + */ +int8_t SDCARD_STORAGE_Write(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len) { + if (!sdcard_write_blocks(buf, blk_addr, blk_len)) { + return -1; + } + return 0; +} + +/** + * @brief Return number of supported logical unit + * @param None + * @retval number of logical unit + */ +int8_t SDCARD_STORAGE_GetMaxLun(void) { + return 0; +} + +const USBD_StorageTypeDef USBD_SDCARD_STORAGE_fops = { + SDCARD_STORAGE_Init, + SDCARD_STORAGE_GetCapacity, + SDCARD_STORAGE_IsReady, + SDCARD_STORAGE_IsWriteProtected, + SDCARD_STORAGE_Read, + SDCARD_STORAGE_Write, + SDCARD_STORAGE_GetMaxLun, + (int8_t *)SDCARD_STORAGE_Inquirydata, +}; diff --git a/stmhal/usbd_msc_storage.h b/stmhal/usbd_msc_storage.h new file mode 100644 index 000000000..7cc79ca79 --- /dev/null +++ b/stmhal/usbd_msc_storage.h @@ -0,0 +1,2 @@ +extern const USBD_StorageTypeDef USBD_FLASH_STORAGE_fops; +extern const USBD_StorageTypeDef USBD_SDCARD_STORAGE_fops; diff --git a/stmhal/usbdev/class/MSC/Inc/usbd_msc.h b/stmhal/usbdev/class/msc/inc/usbd_msc.h similarity index 100% rename from stmhal/usbdev/class/MSC/Inc/usbd_msc.h rename to stmhal/usbdev/class/msc/inc/usbd_msc.h diff --git a/stmhal/usbdev/class/MSC/Inc/usbd_msc_bot.h b/stmhal/usbdev/class/msc/inc/usbd_msc_bot.h similarity index 100% rename from stmhal/usbdev/class/MSC/Inc/usbd_msc_bot.h rename to stmhal/usbdev/class/msc/inc/usbd_msc_bot.h diff --git a/stmhal/usbdev/class/MSC/Inc/usbd_msc_data.h b/stmhal/usbdev/class/msc/inc/usbd_msc_data.h similarity index 100% rename from stmhal/usbdev/class/MSC/Inc/usbd_msc_data.h rename to stmhal/usbdev/class/msc/inc/usbd_msc_data.h diff --git a/stmhal/usbdev/class/MSC/Inc/usbd_msc_scsi.h b/stmhal/usbdev/class/msc/inc/usbd_msc_scsi.h similarity index 100% rename from stmhal/usbdev/class/MSC/Inc/usbd_msc_scsi.h rename to stmhal/usbdev/class/msc/inc/usbd_msc_scsi.h diff --git a/stmhal/usbdev/class/MSC/Inc/usbd_msc_storage_template.h b/stmhal/usbdev/class/msc/inc/usbd_msc_storage_template.h similarity index 100% rename from stmhal/usbdev/class/MSC/Inc/usbd_msc_storage_template.h rename to stmhal/usbdev/class/msc/inc/usbd_msc_storage_template.h diff --git a/stmhal/usbdev/class/MSC/Src/usbd_msc.c b/stmhal/usbdev/class/msc/src/usbd_msc.c similarity index 100% rename from stmhal/usbdev/class/MSC/Src/usbd_msc.c rename to stmhal/usbdev/class/msc/src/usbd_msc.c diff --git a/stmhal/usbdev/class/MSC/Src/usbd_msc_bot.c b/stmhal/usbdev/class/msc/src/usbd_msc_bot.c similarity index 100% rename from stmhal/usbdev/class/MSC/Src/usbd_msc_bot.c rename to stmhal/usbdev/class/msc/src/usbd_msc_bot.c diff --git a/stmhal/usbdev/class/MSC/Src/usbd_msc_data.c b/stmhal/usbdev/class/msc/src/usbd_msc_data.c similarity index 100% rename from stmhal/usbdev/class/MSC/Src/usbd_msc_data.c rename to stmhal/usbdev/class/msc/src/usbd_msc_data.c diff --git a/stmhal/usbdev/class/MSC/Src/usbd_msc_scsi.c b/stmhal/usbdev/class/msc/src/usbd_msc_scsi.c similarity index 100% rename from stmhal/usbdev/class/MSC/Src/usbd_msc_scsi.c rename to stmhal/usbdev/class/msc/src/usbd_msc_scsi.c diff --git a/stmhal/usbdev/class/MSC/Src/usbd_msc_storage_template.c b/stmhal/usbdev/class/msc/src/usbd_msc_storage_template.c similarity index 100% rename from stmhal/usbdev/class/MSC/Src/usbd_msc_storage_template.c rename to stmhal/usbdev/class/msc/src/usbd_msc_storage_template.c diff --git a/tests/basics/bytes.py b/tests/basics/bytes.py index 7d0cf22d4..a084bc399 100644 --- a/tests/basics/bytes.py +++ b/tests/basics/bytes.py @@ -4,8 +4,36 @@ print(str(a)) print(repr(a)) print(a[0], a[2]) print(a[-1]) +print(str(a, "utf-8")) +print(str(a, "utf-8", "ignore")) +try: + str(a, "utf-8", "ignore", "toomuch") +except TypeError: + print("TypeError") s = 0 for i in a: s += i print(s) + + +print(bytes("abc", "utf-8")) +print(bytes("abc", "utf-8", "replace")) +try: + bytes("abc") +except TypeError: + print("TypeError") +try: + bytes("abc", "utf-8", "replace", "toomuch") +except TypeError: + print("TypeError") + +print(bytes(3)) + +print(bytes([3, 2, 1])) +print(bytes(range(5))) + +def gen(): + for i in range(4): + yield i +print(bytes(gen())) diff --git a/tests/basics/int-long.py b/tests/basics/int-long.py index f867d8037..3567e08b2 100644 --- a/tests/basics/int-long.py +++ b/tests/basics/int-long.py @@ -37,3 +37,10 @@ a <<= 5 print(a) a >>= 1 print(a) + +# Test referential integrity of long ints +a = 0x1ffffffff +b = a +a += 1 +print(a) +print(b) diff --git a/tests/basics/math.py b/tests/basics/math-fun.py similarity index 100% rename from tests/basics/math.py rename to tests/basics/math-fun.py diff --git a/tests/basics/string_partition.py b/tests/basics/string_partition.py new file mode 100644 index 000000000..ad70d0250 --- /dev/null +++ b/tests/basics/string_partition.py @@ -0,0 +1,29 @@ +print("asdf".partition('g')) +print("asdf".partition('a')) +print("asdf".partition('s')) +print("asdf".partition('f')) +print("asdf".partition('d')) +print("asdf".partition('asd')) +print("asdf".partition('sdf')) +print("asdf".partition('as')) +print("asdf".partition('df')) +print("asdf".partition('asdf')) +print("asdf".partition('asdfa')) +print("asdf".partition('fasdf')) +print("asdf".partition('fasdfa')) +print("abba".partition('a')) +print("abba".partition('b')) + +try: + print("asdf".partition(1)) +except TypeError: + print("Raised TypeError") +else: + print("Did not raise TypeError") + +try: + print("asdf".partition('')) +except ValueError: + print("Raised ValueError") +else: + print("Did not raise ValueError") diff --git a/tests/basics/string_rpartition.py b/tests/basics/string_rpartition.py new file mode 100644 index 000000000..656121c94 --- /dev/null +++ b/tests/basics/string_rpartition.py @@ -0,0 +1,29 @@ +print("asdf".rpartition('g')) +print("asdf".rpartition('a')) +print("asdf".rpartition('s')) +print("asdf".rpartition('f')) +print("asdf".rpartition('d')) +print("asdf".rpartition('asd')) +print("asdf".rpartition('sdf')) +print("asdf".rpartition('as')) +print("asdf".rpartition('df')) +print("asdf".rpartition('asdf')) +print("asdf".rpartition('asdfa')) +print("asdf".rpartition('fasdf')) +print("asdf".rpartition('fasdfa')) +print("abba".rpartition('a')) +print("abba".rpartition('b')) + +try: + print("asdf".rpartition(1)) +except TypeError: + print("Raised TypeError") +else: + print("Did not raise TypeError") + +try: + print("asdf".rpartition('')) +except ValueError: + print("Raised ValueError") +else: + print("Did not raise ValueError")