Skip to content

Commit bb7f27c

Browse files
committed
ports/stm32: Add OpenAMP's remoteproc port.
Signed-off-by: iabdalkader <i.abdalkader@gmail.com>
1 parent 1d5bb91 commit bb7f27c

File tree

2 files changed

+249
-0
lines changed

2 files changed

+249
-0
lines changed

ports/stm32/Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -495,6 +495,9 @@ endif # MICROPY_PY_BLUETOOTH
495495

496496
ifeq ($(MICROPY_PY_OPENAMP),1)
497497
SRC_C += metal/metal_port.c
498+
ifeq ($(MICROPY_PY_REMOTEPROC),1)
499+
SRC_C += mprprocport.c
500+
endif
498501
endif
499502

500503
# SRC_O should be placed first to work around this LTO bug with binutils <2.35:

ports/stm32/mprprocport.c

Lines changed: 246 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,246 @@
1+
/*
2+
* This file is part of the MicroPython project, http://micropython.org/
3+
*
4+
* The MIT License (MIT)
5+
*
6+
* Copyright (c) 2023 Arduino SA
7+
*
8+
* Permission is hereby granted, free of charge, to any person obtaining a copy
9+
* of this software and associated documentation files (the "Software"), to deal
10+
* in the Software without restriction, including without limitation the rights
11+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
* copies of the Software, and to permit persons to whom the Software is
13+
* furnished to do so, subject to the following conditions:
14+
*
15+
* The above copyright notice and this permission notice shall be included in
16+
* all copies or substantial portions of the Software.
17+
*
18+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
* THE SOFTWARE.
25+
*
26+
* modremoteproc stm32 port.
27+
*/
28+
#include <stdio.h>
29+
#include <stdint.h>
30+
31+
#include "py/obj.h"
32+
#include "py/runtime.h"
33+
#include "py/gc.h"
34+
#include "py/stream.h"
35+
#include "extmod/vfs.h"
36+
37+
#include "metal/alloc.h"
38+
#include "metal/errno.h"
39+
#include "metal/io.h"
40+
#include "metal/sys.h"
41+
#include "metal/device.h"
42+
#include "metal/utilities.h"
43+
#include "openamp/remoteproc.h"
44+
#include "openamp/remoteproc_loader.h"
45+
46+
#define debug_printf(...) // mp_printf(&mp_plat_print, __VA_ARGS__)
47+
48+
#define FILE_STORE_BUF_SIZE (1024)
49+
50+
typedef struct filestore {
51+
size_t len;
52+
uint8_t *buf;
53+
mp_obj_t file;
54+
} filestore_t;
55+
56+
static int store_open(void *store, const char *path, const void **image_data) {
57+
debug_printf("store_open(): %s\n", path);
58+
59+
mp_obj_t args[2] = {
60+
mp_obj_new_str(path, strlen(path)),
61+
MP_OBJ_NEW_QSTR(MP_QSTR_rb),
62+
};
63+
64+
filestore_t *fstore = store;
65+
fstore->file = mp_vfs_open(MP_ARRAY_SIZE(args), args, (mp_map_t *)&mp_const_empty_map);
66+
67+
int error = 0;
68+
mp_uint_t bytes = mp_stream_read_exactly(fstore->file, fstore->buf, FILE_STORE_BUF_SIZE, &error);
69+
if (error != 0 || bytes != FILE_STORE_BUF_SIZE) {
70+
return -EINVAL;
71+
}
72+
*image_data = fstore->buf;
73+
return bytes;
74+
}
75+
76+
static void store_close(void *store) {
77+
debug_printf("store_close()\n");
78+
filestore_t *fstore = store;
79+
mp_stream_close(fstore->file);
80+
metal_free_memory(fstore->buf);
81+
metal_free_memory(fstore);
82+
}
83+
84+
static int store_load(void *store, size_t offset, size_t size,
85+
const void **data, metal_phys_addr_t pa,
86+
struct metal_io_region *io,
87+
char is_blocking) {
88+
89+
int error = 0;
90+
filestore_t *fstore = store;
91+
92+
if (mp_stream_seek(fstore->file, offset, MP_SEEK_SET, &error) == -1) {
93+
return -EINVAL;
94+
}
95+
96+
if (pa == METAL_BAD_PHYS) {
97+
if (size > fstore->len) {
98+
// Note tracked allocs don't support realloc.
99+
fstore->len = size;
100+
fstore->buf = metal_allocate_memory(size);
101+
debug_printf("store_load() realloc to %lu\n", fstore->len);
102+
}
103+
*data = fstore->buf;
104+
debug_printf("store_load(): pa 0x%lx offset %u size %u \n", (uint32_t)pa, offset, size);
105+
} else {
106+
void *va = metal_io_phys_to_virt(io, pa);
107+
if (va == NULL) {
108+
return -EINVAL;
109+
}
110+
*data = va;
111+
debug_printf("store_load(): pa 0x%lx va 0x%p offset %u size %u \n", (uint32_t)pa, va, offset, size);
112+
}
113+
114+
mp_uint_t bytes = mp_stream_read_exactly(fstore->file, (void *)*data, size, &error);
115+
if (bytes != size || error != 0) {
116+
return -EINVAL;
117+
}
118+
119+
return bytes;
120+
}
121+
122+
const struct image_store_ops mp_store_ops = {
123+
.open = store_open,
124+
.close = store_close,
125+
.load = store_load,
126+
.features = SUPPORT_SEEK,
127+
};
128+
129+
static struct remoteproc *rproc_init(struct remoteproc *rproc,
130+
const struct remoteproc_ops *ops, void *arg) {
131+
debug_printf("rproc_init()\n");
132+
133+
rproc = rproc;
134+
rproc->ops = ops;
135+
// Allocate filestore struct.
136+
filestore_t *filestore = metal_allocate_memory(sizeof(filestore_t));
137+
filestore->len = FILE_STORE_BUF_SIZE;
138+
filestore->buf = metal_allocate_memory(FILE_STORE_BUF_SIZE);
139+
// Store in rproc's private data.
140+
rproc->priv = filestore;
141+
metal_list_init(&rproc->mems);
142+
// Set RPROC_OFFLINE to make rproc_config get called.
143+
rproc->state = RPROC_READY;
144+
return rproc;
145+
}
146+
147+
static void *rproc_mmap(struct remoteproc *rproc, metal_phys_addr_t *pa,
148+
metal_phys_addr_t *da, size_t size, unsigned int attribute,
149+
struct metal_io_region **io) {
150+
debug_printf("rproc_mmap(): pa 0x%p da 0x%p io 0x%p size %u\n", *pa, *da, *io, size);
151+
152+
struct remoteproc_mem *mem;
153+
metal_phys_addr_t lpa = *pa;
154+
metal_phys_addr_t lda = *da;
155+
156+
if (lda == METAL_BAD_PHYS) {
157+
return NULL;
158+
}
159+
160+
if (lpa == METAL_BAD_PHYS) {
161+
lpa = lda;
162+
}
163+
164+
mem = metal_allocate_memory(sizeof(*mem));
165+
if (!mem) {
166+
return NULL;
167+
}
168+
169+
*io = metal_allocate_memory(sizeof(struct metal_io_region));
170+
if (!*io) {
171+
metal_free_memory(mem);
172+
return NULL;
173+
}
174+
175+
remoteproc_init_mem(mem, NULL, lpa, lda, size, *io);
176+
177+
metal_io_init(*io, (void *)mem->da, &mem->pa, size,
178+
sizeof(metal_phys_addr_t) << 3, attribute, NULL);
179+
180+
remoteproc_add_mem(rproc, mem);
181+
*pa = lpa;
182+
*da = lda;
183+
return metal_io_phys_to_virt(*io, mem->pa);
184+
}
185+
186+
static int rproc_start(struct remoteproc *rproc) {
187+
debug_printf("rproc_start()\n");
188+
if (RCC->GCR & RCC_GCR_BOOT_C2) {
189+
// CM4 core is already booted.
190+
debug_printf("rproc_start(): CM4 core is already booted.\n");
191+
return -1;
192+
}
193+
194+
// Flush M7 cache.
195+
struct metal_list *node;
196+
metal_list_for_each(&rproc->mems, node) {
197+
struct remoteproc_mem *mem;
198+
mem = metal_container_of(node, struct remoteproc_mem, node);
199+
SCB_CleanDCache_by_Addr((uint32_t *)mem->pa, mem->size);
200+
}
201+
202+
HAL_SYSCFG_CM4BootAddConfig(SYSCFG_BOOT_ADDR0, (uint32_t)rproc->bootaddr);
203+
HAL_RCCEx_EnableBootCore(RCC_BOOT_C2);
204+
return 0;
205+
}
206+
207+
static int rproc_stop(struct remoteproc *rproc) {
208+
debug_printf("rproc_stop()\n");
209+
if (rproc->state == RPROC_RUNNING) {
210+
// There's no straightforward way to reset or shut down
211+
// the remote processor, so a full system reset is needed.
212+
NVIC_SystemReset();
213+
}
214+
return 0;
215+
}
216+
217+
static int rproc_config(struct remoteproc *rproc, void *data) {
218+
debug_printf("rproc_config()\n");
219+
(void)rproc;
220+
return 0;
221+
}
222+
223+
static void rproc_remove(struct remoteproc *rproc) {
224+
debug_printf("rproc_remove()\n");
225+
(void)rproc;
226+
}
227+
228+
static int rproc_shutdown(struct remoteproc *rproc) {
229+
debug_printf("rproc_shutdown()\n");
230+
if (rproc->state == RPROC_RUNNING) {
231+
// There's no straightforward way to reset or shut down
232+
// the remote processor, so a full system reset is needed.
233+
NVIC_SystemReset();
234+
}
235+
return 0;
236+
}
237+
238+
const struct remoteproc_ops mp_rproc_ops = {
239+
.init = rproc_init,
240+
.mmap = rproc_mmap,
241+
.start = rproc_start,
242+
.stop = rproc_stop,
243+
.config = rproc_config,
244+
.remove = rproc_remove,
245+
.shutdown = rproc_shutdown,
246+
};

0 commit comments

Comments
 (0)