Skip to content

Commit 273c4c1

Browse files
committed
ports/rp2: Add start/len support to rp2.Flash().
Allow support for partitioned flash on RP2. Signed-off-by: Phil Howard <phil@gadgetoid.com>
1 parent 5852fd7 commit 273c4c1

File tree

1 file changed

+48
-17
lines changed

1 file changed

+48
-17
lines changed

ports/rp2/rp2_flash.c

Lines changed: 48 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -48,14 +48,14 @@ static_assert(MICROPY_HW_FLASH_STORAGE_BASE + MICROPY_HW_FLASH_STORAGE_BYTES <=
4848

4949
typedef struct _rp2_flash_obj_t {
5050
mp_obj_base_t base;
51-
uint32_t flash_base;
52-
uint32_t flash_size;
51+
uint32_t start;
52+
uint32_t len;
5353
} rp2_flash_obj_t;
5454

5555
STATIC rp2_flash_obj_t rp2_flash_obj = {
5656
.base = { &rp2_flash_type },
57-
.flash_base = MICROPY_HW_FLASH_STORAGE_BASE,
58-
.flash_size = MICROPY_HW_FLASH_STORAGE_BYTES,
57+
.start = MICROPY_HW_FLASH_STORAGE_BASE,
58+
.len = MICROPY_HW_FLASH_STORAGE_BYTES,
5959
};
6060

6161
// Tag the flash drive in the binary as readable/writable (but not reformatable)
@@ -70,16 +70,47 @@ bi_decl(bi_block_device(
7070
BINARY_INFO_BLOCK_DEV_FLAG_PT_UNKNOWN));
7171

7272
STATIC mp_obj_t rp2_flash_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) {
73-
// Check args.
74-
mp_arg_check_num(n_args, n_kw, 0, 0, false);
73+
// Parse arguments
74+
enum { ARG_start, ARG_len };
75+
static const mp_arg_t allowed_args[] = {
76+
{ MP_QSTR_start, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
77+
{ MP_QSTR_len, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = -1} },
78+
};
79+
mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)];
80+
mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args);
81+
82+
if (args[ARG_start].u_int == -1 && args[ARG_len].u_int == -1) {
83+
#ifndef NDEBUG
84+
extern char __flash_binary_end;
85+
assert((uintptr_t)&__flash_binary_end - XIP_BASE <= MICROPY_HW_FLASH_STORAGE_BASE);
86+
#endif
87+
88+
// Default singleton object that accesses entire flash, including virtual partition table
89+
return MP_OBJ_FROM_PTR(&rp2_flash_obj);
90+
}
91+
92+
rp2_flash_obj_t *self = mp_obj_malloc(rp2_flash_obj_t, &rp2_flash_type);
93+
94+
uint32_t bl_len = MICROPY_HW_FLASH_STORAGE_BYTES;
95+
96+
mp_int_t start = args[ARG_start].u_int;
97+
if (start == -1) {
98+
start = 0;
99+
} else if (!(0 <= start && start < bl_len && start % BLOCK_SIZE_BYTES == 0)) {
100+
mp_raise_ValueError(NULL);
101+
}
102+
103+
mp_int_t len = args[ARG_len].u_int;
104+
if (len == -1) {
105+
len = MICROPY_HW_FLASH_STORAGE_BYTES;
106+
} else if (!(0 < len && start + len <= bl_len && len % BLOCK_SIZE_BYTES == 0)) {
107+
mp_raise_ValueError(NULL);
108+
}
75109

76-
#ifndef NDEBUG
77-
extern char __flash_binary_end;
78-
assert((uintptr_t)&__flash_binary_end - XIP_BASE <= MICROPY_HW_FLASH_STORAGE_BASE);
79-
#endif
110+
self->start = MICROPY_HW_FLASH_STORAGE_BASE + start;
111+
self->len = len;
80112

81-
// Return singleton object.
82-
return MP_OBJ_FROM_PTR(&rp2_flash_obj);
113+
return MP_OBJ_FROM_PTR(self);
83114
}
84115

85116
STATIC mp_obj_t rp2_flash_readblocks(size_t n_args, const mp_obj_t *args) {
@@ -90,7 +121,7 @@ STATIC mp_obj_t rp2_flash_readblocks(size_t n_args, const mp_obj_t *args) {
90121
if (n_args == 4) {
91122
offset += mp_obj_get_int(args[3]);
92123
}
93-
memcpy(bufinfo.buf, (void *)(XIP_BASE + self->flash_base + offset), bufinfo.len);
124+
memcpy(bufinfo.buf, (void *)(XIP_BASE + self->start + offset), bufinfo.len);
94125
return mp_const_none;
95126
}
96127
STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(rp2_flash_readblocks_obj, 3, 4, rp2_flash_readblocks);
@@ -103,7 +134,7 @@ STATIC mp_obj_t rp2_flash_writeblocks(size_t n_args, const mp_obj_t *args) {
103134
if (n_args == 3) {
104135
// Flash erase/program must run in an atomic section because the XIP bit gets disabled.
105136
mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION();
106-
flash_range_erase(self->flash_base + offset, bufinfo.len);
137+
flash_range_erase(self->start + offset, bufinfo.len);
107138
MICROPY_END_ATOMIC_SECTION(atomic_state);
108139
MICROPY_EVENT_POLL_HOOK
109140
// TODO check return value
@@ -112,7 +143,7 @@ STATIC mp_obj_t rp2_flash_writeblocks(size_t n_args, const mp_obj_t *args) {
112143
}
113144
// Flash erase/program must run in an atomic section because the XIP bit gets disabled.
114145
mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION();
115-
flash_range_program(self->flash_base + offset, bufinfo.buf, bufinfo.len);
146+
flash_range_program(self->start + offset, bufinfo.buf, bufinfo.len);
116147
MICROPY_END_ATOMIC_SECTION(atomic_state);
117148
MICROPY_EVENT_POLL_HOOK
118149
// TODO check return value
@@ -131,14 +162,14 @@ STATIC mp_obj_t rp2_flash_ioctl(mp_obj_t self_in, mp_obj_t cmd_in, mp_obj_t arg_
131162
case MP_BLOCKDEV_IOCTL_SYNC:
132163
return MP_OBJ_NEW_SMALL_INT(0);
133164
case MP_BLOCKDEV_IOCTL_BLOCK_COUNT:
134-
return MP_OBJ_NEW_SMALL_INT(self->flash_size / BLOCK_SIZE_BYTES);
165+
return MP_OBJ_NEW_SMALL_INT(self->len / BLOCK_SIZE_BYTES);
135166
case MP_BLOCKDEV_IOCTL_BLOCK_SIZE:
136167
return MP_OBJ_NEW_SMALL_INT(BLOCK_SIZE_BYTES);
137168
case MP_BLOCKDEV_IOCTL_BLOCK_ERASE: {
138169
uint32_t offset = mp_obj_get_int(arg_in) * BLOCK_SIZE_BYTES;
139170
// Flash erase/program must run in an atomic section because the XIP bit gets disabled.
140171
mp_uint_t atomic_state = MICROPY_BEGIN_ATOMIC_SECTION();
141-
flash_range_erase(self->flash_base + offset, BLOCK_SIZE_BYTES);
172+
flash_range_erase(self->start + offset, BLOCK_SIZE_BYTES);
142173
MICROPY_END_ATOMIC_SECTION(atomic_state);
143174
// TODO check return value
144175
return MP_OBJ_NEW_SMALL_INT(0);

0 commit comments

Comments
 (0)