|
47 | 47 | //| import memorymap
|
48 | 48 | //| rtc_slow_mem = memorymap.AddressRange(start=0x50000000, length=0x2000)
|
49 | 49 | //| rtc_slow_mem[0:3] = b"\xcc\x10\x00"
|
| 50 | +//| |
| 51 | +//| Example I/O register usage on RP2040:: |
| 52 | +//| |
| 53 | +//| import binascii |
| 54 | +//| import board |
| 55 | +//| import digitalio |
| 56 | +//| import memorymap |
| 57 | +//| |
| 58 | +//| def rp2040_set_pad_drive(p, d): |
| 59 | +//| pads_bank0 = memorymap.AddressRange(start=0x4001C000, length=0x4000) |
| 60 | +//| pad_ctrl = int.from_bytes(pads_bank0[p*4+4:p*4+8], "little") |
| 61 | +//| # Pad control register is updated using an MP-safe atomic XOR |
| 62 | +//| pad_ctrl ^= (d << 4) |
| 63 | +//| pad_ctrl &= 0x00000030 |
| 64 | +//| pads_bank0[p*4+0x3004:p*4+0x3008] = pad_ctrl.to_bytes(4, "little") |
| 65 | +//| |
| 66 | +//| def rp2040_get_pad_drive(p): |
| 67 | +//| pads_bank0 = memorymap.AddressRange(start=0x4001C000, length=0x4000) |
| 68 | +//| pad_ctrl = int.from_bytes(pads_bank0[p*4+4:p*4+8], "little") |
| 69 | +//| return (pad_ctrl >> 4) & 0x3 |
| 70 | +//| |
| 71 | +//| # set GPIO16 pad drive strength to 12 mA |
| 72 | +//| rp2040_set_pad_drive(16, 3) |
| 73 | +//| |
| 74 | +//| # print GPIO16 pad drive strength |
| 75 | +//| print(rp2040_get_pad_drive(16)) |
50 | 76 | //| """
|
51 | 77 |
|
52 | 78 | //| def __init__(self, *, start, length) -> None:
|
53 | 79 | //| """Constructs an address range starting at ``start`` and ending at
|
54 |
| -//| ``start + length - 1``. An exception will be raised if any of the |
| 80 | +//| ``start + length``. An exception will be raised if any of the |
55 | 81 | //| addresses are invalid or protected."""
|
56 | 82 | //| ...
|
57 | 83 | 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) {
|
58 | 84 | enum { ARG_start, ARG_length };
|
59 | 85 | static const mp_arg_t allowed_args[] = {
|
60 |
| - { MP_QSTR_start, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_UINT }, |
| 86 | + { MP_QSTR_start, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_OBJ }, |
61 | 87 | { MP_QSTR_length, MP_ARG_KW_ONLY | MP_ARG_REQUIRED | MP_ARG_INT },
|
62 | 88 | };
|
63 | 89 | mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
|
64 | 90 | mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
|
65 | 91 |
|
66 |
| - size_t start = args[ARG_start].u_uint; |
| 92 | + // Argument start is a pointer into the address map, so we validate it here because a |
| 93 | + // signed int argument will overflow if it is in the upper half of the map. |
| 94 | + size_t start; |
| 95 | + if (mp_obj_is_small_int(args[ARG_start].u_obj)) { |
| 96 | + start = MP_OBJ_SMALL_INT_VALUE(args[ARG_start].u_obj); |
| 97 | + } else if (mp_obj_is_type(args[ARG_start].u_obj, &mp_type_int)) { |
| 98 | + start = mp_obj_int_get_uint_checked(args[ARG_start].u_obj); |
| 99 | + } else { |
| 100 | + mp_raise_TypeError(translate("start must be an int")); |
| 101 | + } |
67 | 102 | size_t length =
|
68 | 103 | mp_arg_validate_int_min(args[ARG_length].u_int, 1, MP_QSTR_length);
|
69 | 104 | // Check for address range wrap here as this can break port-specific code due to size_t overflow.
|
|
0 commit comments