Skip to content

Commit ee3469b

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

File tree

2 files changed

+239
-0
lines changed

2 files changed

+239
-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: 236 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,236 @@
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+
35+
#include "metal/alloc.h"
36+
#include "metal/errno.h"
37+
#include "metal/io.h"
38+
#include "metal/sys.h"
39+
#include "metal/device.h"
40+
#include "metal/utilities.h"
41+
#include "openamp/remoteproc.h"
42+
#include "openamp/remoteproc_loader.h"
43+
44+
#include "lib/oofatfs/ff.h"
45+
#include "lib/oofatfs/diskio.h"
46+
47+
#include "extmod/vfs.h"
48+
#include "extmod/vfs_fat.h"
49+
50+
#define debug_printf(...) mp_printf(&mp_plat_print, __VA_ARGS__)
51+
52+
#define FILE_BUF_SIZE (512)
53+
54+
typedef struct filestore {
55+
FIL fp;
56+
uint8_t buf[FILE_BUF_SIZE];
57+
} filestore_t;
58+
59+
static FATFS *lookup_path(const TCHAR **path) {
60+
mp_vfs_mount_t *fs = mp_vfs_lookup_path(*path, path);
61+
if (fs == MP_VFS_NONE || fs == MP_VFS_ROOT) {
62+
return NULL;
63+
}
64+
// here we assume that the mounted device is FATFS
65+
return &((fs_user_mount_t *)MP_OBJ_TO_PTR(fs->obj))->fatfs;
66+
}
67+
68+
static int store_open(void *store, const char *path, const void **image_data) {
69+
debug_printf("store_open(): %s\n", path);
70+
71+
filestore_t *fstore = store;
72+
73+
FATFS *fs = lookup_path(&path);
74+
if (fs == NULL) {
75+
return -EINVAL;
76+
}
77+
78+
FRESULT res = f_open(fs, &fstore->fp, path, FA_READ);
79+
if (res != FR_OK) {
80+
return -EINVAL;
81+
}
82+
83+
UINT n;
84+
res = f_read(&fstore->fp, fstore->buf, FILE_BUF_SIZE, &n);
85+
if (res != FR_OK || n != FILE_BUF_SIZE) {
86+
return -EINVAL;
87+
}
88+
*image_data = fstore->buf;
89+
90+
return FILE_BUF_SIZE;
91+
}
92+
93+
static void store_close(void *store) {
94+
debug_printf("store_close()\n");
95+
filestore_t *fstore = store;
96+
f_close(&fstore->fp);
97+
metal_free_memory(store);
98+
}
99+
100+
static int store_load(void *store, size_t offset, size_t size,
101+
const void **data, metal_phys_addr_t pa,
102+
struct metal_io_region *io,
103+
char is_blocking) {
104+
105+
filestore_t *fstore = store;
106+
FRESULT res = f_lseek(&fstore->fp, offset);
107+
if (res != FR_OK) {
108+
return -EINVAL;
109+
}
110+
111+
if (pa == METAL_BAD_PHYS) {
112+
*data = fstore->buf;
113+
size = size > FILE_BUF_SIZE ? FILE_BUF_SIZE : size;
114+
debug_printf("store_load(): pa 0x%lx offset %u size %u \n", (uint32_t)pa, offset, size);
115+
} else {
116+
void *va = metal_io_phys_to_virt(io, pa);
117+
if (va == NULL) {
118+
return -EINVAL;
119+
}
120+
*data = va;
121+
debug_printf("store_load(): pa 0x%lx va 0x%p offset %u size %u \n", (uint32_t)pa, va, offset, size);
122+
}
123+
124+
UINT nread;
125+
res = f_read(&fstore->fp, (void *)*data, size, &nread);
126+
if (res != FR_OK) {
127+
return -EINVAL;
128+
}
129+
130+
return nread;
131+
}
132+
133+
const struct image_store_ops mp_store_ops = {
134+
.open = store_open,
135+
.close = store_close,
136+
.load = store_load,
137+
.features = SUPPORT_SEEK,
138+
};
139+
140+
static struct remoteproc *rproc_init(struct remoteproc *rproc,
141+
const struct remoteproc_ops *ops, void *arg) {
142+
debug_printf("rproc_init()\n");
143+
rproc = rproc;
144+
rproc->ops = ops;
145+
rproc->priv = metal_allocate_memory(sizeof(filestore_t));
146+
metal_list_init(&rproc->mems);
147+
rproc->state = RPROC_READY; // RPROC_OFFLINE to call config
148+
return rproc;
149+
}
150+
151+
static void *rproc_mmap(struct remoteproc *rproc, metal_phys_addr_t *pa,
152+
metal_phys_addr_t *da, size_t size, unsigned int attribute,
153+
struct metal_io_region **io) {
154+
debug_printf("rproc_mmap(): pa 0x%p da 0x%p io 0x%p size %u\n", *pa, *da, *io, size);
155+
156+
struct remoteproc_mem *mem;
157+
metal_phys_addr_t lpa = *pa;
158+
metal_phys_addr_t lda = *da;
159+
160+
if (lda == METAL_BAD_PHYS) {
161+
return NULL;
162+
}
163+
164+
if (lpa == METAL_BAD_PHYS) {
165+
lpa = lda;
166+
}
167+
168+
mem = metal_allocate_memory(sizeof(*mem));
169+
if (!mem) {
170+
return NULL;
171+
}
172+
173+
*io = metal_allocate_memory(sizeof(struct metal_io_region));
174+
if (!*io) {
175+
metal_free_memory(mem);
176+
return NULL;
177+
}
178+
179+
remoteproc_init_mem(mem, NULL, lpa, lda, size, *io);
180+
181+
metal_io_init(*io, (void *)mem->da, &mem->pa, size,
182+
sizeof(metal_phys_addr_t) << 3, attribute, NULL);
183+
184+
remoteproc_add_mem(rproc, mem);
185+
*pa = lpa;
186+
*da = lda;
187+
return metal_io_phys_to_virt(*io, mem->pa);
188+
}
189+
190+
static int rproc_start(struct remoteproc *rproc) {
191+
debug_printf("rproc_start()\n");
192+
if (RCC->GCR & RCC_GCR_BOOT_C2) {
193+
// CM4 core is already booted.
194+
debug_printf("rproc_start(): CM4 core is already booted.\n");
195+
return -1;
196+
}
197+
198+
// Flush M7 cache.
199+
struct metal_list *node;
200+
metal_list_for_each(&rproc->mems, node) {
201+
struct remoteproc_mem *mem;
202+
mem = metal_container_of(node, struct remoteproc_mem, node);
203+
SCB_CleanDCache_by_Addr((uint32_t *)mem->pa, mem->size);
204+
}
205+
206+
HAL_PWREx_HoldCore(PWR_CORE_CPU2);
207+
HAL_SYSCFG_CM4BootAddConfig(SYSCFG_BOOT_ADDR0, (uint32_t)rproc->bootaddr);
208+
HAL_RCCEx_EnableBootCore(RCC_BOOT_C2);
209+
return 0;
210+
}
211+
212+
static int rproc_stop(struct remoteproc *rproc) {
213+
debug_printf("rproc_stop()\n");
214+
(void)rproc;
215+
return 0;
216+
}
217+
218+
static void rproc_remove(struct remoteproc *rproc) {
219+
debug_printf("rproc_remove()\n");
220+
(void)rproc;
221+
}
222+
223+
static int rproc_shutdown(struct remoteproc *rproc) {
224+
debug_printf("rproc_shutdown()\n");
225+
(void)rproc;
226+
return 0;
227+
}
228+
229+
const struct remoteproc_ops mp_rproc_ops = {
230+
.init = rproc_init,
231+
.mmap = rproc_mmap,
232+
.start = rproc_start,
233+
.stop = rproc_stop,
234+
.remove = rproc_remove,
235+
.shutdown = rproc_shutdown,
236+
};

0 commit comments

Comments
 (0)