review update, add RP2040 example

This commit is contained in:
Bob Abeles 2023-09-06 19:59:40 -07:00
parent 1648a3db1e
commit 1e178318cf
8 changed files with 47 additions and 27 deletions

View File

@ -2140,6 +2140,10 @@ msgstr ""
msgid "Unable to access unaliged IO register"
msgstr ""
#: ports/raspberrypi/common-hal/memorymap/AddressRange.c
msgid "Unable to access unaligned IO register"
msgstr ""
#: ports/atmel-samd/common-hal/audiobusio/I2SOut.c
#: ports/atmel-samd/common-hal/audioio/AudioOut.c
#: ports/raspberrypi/common-hal/audiobusio/I2SOut.c
@ -4048,6 +4052,10 @@ msgstr ""
msgid "source_bitmap must have value_count of 8"
msgstr ""
#: shared-bindings/memorymap/AddressRange.c
msgid "start must be an int"
msgstr ""
#: py/objstr.c
msgid "start/end indices"
msgstr ""

View File

@ -90,7 +90,7 @@ void common_hal_memorymap_addressrange_set_bytes(const memorymap_addressrange_ob
case IO:
if ((size_t)dest_addr & 0x03 || len & 0x03) {
// Unaligned access or unaligned length not supported by RP2 for IO registers
mp_raise_RuntimeError(translate("Unable to access unaliged IO register"));
mp_raise_RuntimeError(translate("Unable to access unaligned IO register"));
} else {
// Aligned access and length, use 32-bit writes
uint32_t *dest_addr32 = (uint32_t *)dest_addr;

View File

@ -115,8 +115,6 @@ void mp_arg_parse_all(size_t n_pos, const mp_obj_t *pos, mp_map_t *kws, size_t n
out_vals[i].u_bool = mp_obj_is_true(given_arg);
} else if ((allowed[i].flags & MP_ARG_KIND_MASK) == MP_ARG_INT) {
out_vals[i].u_int = mp_obj_get_int(given_arg);
} else if ((allowed[i].flags & MP_ARG_KIND_MASK) == MP_ARG_UINT) {
out_vals[i].u_uint = mp_obj_get_uint(given_arg);
} else {
assert((allowed[i].flags & MP_ARG_KIND_MASK) == MP_ARG_OBJ);
out_vals[i].u_obj = given_arg;

View File

@ -420,21 +420,6 @@ bool mp_obj_get_int_maybe(mp_const_obj_t arg, mp_int_t *value) {
return true;
}
mp_uint_t mp_obj_get_uint(mp_const_obj_t arg) {
if (arg == mp_const_false) {
return 0;
} else if (arg == mp_const_true) {
return 1;
} else if (mp_obj_is_small_int(arg)) {
return MP_OBJ_SMALL_INT_VALUE(arg);
} else if (mp_obj_is_type(arg, &mp_type_int)) {
return mp_obj_int_get_uint_checked(arg);
} else {
mp_obj_t res = mp_unary_op(MP_UNARY_OP_INT, (mp_obj_t)arg);
return mp_obj_int_get_uint_checked(res);
}
}
#if MICROPY_PY_BUILTINS_FLOAT
bool mp_obj_get_float_maybe(mp_obj_t arg, mp_float_t *value) {
mp_float_t val;

View File

@ -939,7 +939,6 @@ static MP_INLINE bool mp_obj_is_integer(mp_const_obj_t o) {
mp_int_t mp_obj_get_int(mp_const_obj_t arg);
mp_int_t mp_obj_get_int_truncated(mp_const_obj_t arg);
bool mp_obj_get_int_maybe(mp_const_obj_t arg, mp_int_t *value);
mp_uint_t mp_obj_get_uint(mp_const_obj_t arg);
#if MICROPY_PY_BUILTINS_FLOAT
mp_float_t mp_obj_get_float(mp_obj_t self_in);
bool mp_obj_get_float_maybe(mp_obj_t arg, mp_float_t *value);

View File

@ -438,10 +438,6 @@ mp_int_t mp_obj_int_get_checked(mp_const_obj_t self_in) {
return MP_OBJ_SMALL_INT_VALUE(self_in);
}
mp_uint_t mp_obj_int_get_uint_checked(mp_const_obj_t self_in) {
return MP_OBJ_SMALL_INT_VALUE(self_in);
}
#endif // MICROPY_LONGINT_IMPL == MICROPY_LONGINT_IMPL_NONE

View File

@ -45,7 +45,6 @@ typedef enum {
MP_ARG_BOOL = 0x001,
MP_ARG_INT = 0x002,
MP_ARG_OBJ = 0x003,
MP_ARG_UINT = 0x004,
MP_ARG_KIND_MASK = 0x0ff,
MP_ARG_REQUIRED = 0x100,
MP_ARG_KW_ONLY = 0x200,

View File

@ -47,23 +47,58 @@
//| import memorymap
//| rtc_slow_mem = memorymap.AddressRange(start=0x50000000, length=0x2000)
//| rtc_slow_mem[0:3] = b"\xcc\x10\x00"
//|
//| Example I/O register usage on RP2040::
//|
//| import binascii
//| import board
//| import digitalio
//| import memorymap
//|
//| def rp2040_set_pad_drive(p, d):
//| pads_bank0 = memorymap.AddressRange(start=0x4001C000, length=0x4000)
//| pad_ctrl = int.from_bytes(pads_bank0[p*4+4:p*4+8], "little")
//| # Pad control register is updated using an MP-safe atomic XOR
//| pad_ctrl ^= (d << 4)
//| pad_ctrl &= 0x00000030
//| pads_bank0[p*4+0x3004:p*4+0x3008] = pad_ctrl.to_bytes(4, "little")
//|
//| def rp2040_get_pad_drive(p):
//| pads_bank0 = memorymap.AddressRange(start=0x4001C000, length=0x4000)
//| pad_ctrl = int.from_bytes(pads_bank0[p*4+4:p*4+8], "little")
//| return (pad_ctrl >> 4) & 0x3
//|
//| # set GPIO16 pad drive strength to 12 mA
//| rp2040_set_pad_drive(16, 3)
//|
//| # print GPIO16 pad drive strength
//| print(rp2040_get_pad_drive(16))
//| """
//| def __init__(self, *, start, length) -> None:
//| """Constructs an address range starting at ``start`` and ending at
//| ``start + length - 1``. An exception will be raised if any of the
//| ``start + length``. An exception will be raised if any of the
//| addresses are invalid or protected."""
//| ...
STATIC mp_obj_t memorymap_addressrange_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
enum { ARG_start, ARG_length };
static const mp_arg_t allowed_args[] = {
{ MP_QSTR_start, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_UINT },
{ MP_QSTR_start, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_OBJ },
{ MP_QSTR_length, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_INT },
};
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
size_t start = args[ARG_start].u_uint;
// Argument start is a pointer into the address map, so we validate it here because a
// signed int argument will overflow if it is in the upper half of the map.
size_t start;
if (mp_obj_is_small_int(args[ARG_start].u_obj)) {
start = MP_OBJ_SMALL_INT_VALUE(args[ARG_start].u_obj);
} else if (mp_obj_is_type(args[ARG_start].u_obj, &mp_type_int)) {
start = mp_obj_int_get_uint_checked(args[ARG_start].u_obj);
} else {
mp_raise_TypeError(translate("start must be an int"));
}
size_t length =
mp_arg_validate_int_min(args[ARG_length].u_int, 1, MP_QSTR_length);
// Check for address range wrap here as this can break port-specific code due to size_t overflow.