2021-04-21 06:57 AM
Hi,
iam trying to get a full understanding of remoteproc and its resource tabel. In the paper i read i understood it that the resource table is used to give the information about the vrings location to the master and the slave. The master parses the ressource table during starting. When i had a look at my code i saw that the adresse of the vrings are set to -1 (attached picture). So iam confused about it really works. Does the master knows the location from the device tree and give it through the slave? And how does the master knows where it has to load the elf-File from the M4, also from the device tree? In the linker script i saw that the regions of the memorys are define but i guess never really used in the code.
2021-04-23 12:23 AM
Hello,
All Information is contained in the elf file and the device tree.
1) The elf file contains the address and the size of the memory section to load, you can have this information with following command
$> readelf -S ./STM32CubeIDE/CM4/Debug/OpenAMP_TTY_echo_CM4.elf
There are 27 section headers, starting at offset 0x294430:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .isr_vector PROGBITS 00000000 010000 000298 00 A 0 0 1
[ 2] .text PROGBITS 10000000 020000 006f2c 00 AX 0 0 16
[ 3] .startup_copro_fw.Reset_Handler PROGBITS 10006f2c 026f2c 000050 00 AX 0 0 4
[ 4] .rodata PROGBITS 10006f7c 026f7c 0005cc 00 A 0 0 4
[ 5] .ARM.extab PROGBITS 10007548 0301c4 000000 00 W 0 0 1
[ 6] .ARM PROGBITS 10007548 0301c4 000000 00 W 0 0 1
[ 7] .preinit_array PREINIT_ARRAY 10007548 0301c4 000000 04 WA 0 0 1
[ 8] .init_array INIT_ARRAY 10007548 027548 000004 04 WA 0 0 4
[ 9] .fini_array FINI_ARRAY 1000754c 02754c 000004 04 WA 0 0 4
[10] .data PROGBITS 10020000 030000 000138 00 WA 0 0 4
[11] .resource_table PROGBITS 10020138 030138 00008c 00 A 0 0 4
[12] .bss NOBITS 100201c4 0301c4 000de8 00 WA 0 0 4
[13] ._user_heap_stack NOBITS 10020fac 0301c4 000604 00 WA 0 0 1
[...]
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
L (link order), O (extra OS processing required), G (group), T (TLS),
C (compressed), x (unknown), o (OS specific), E (exclude),
y (purecode), p (processor specific)
In this example the resource table is loaded at address 0x10020138.
This is the way the Linux remoteproc find the resource table address.
If the firmware is loaded by U-boot or OP-TEE, the resource table address is retrieved from a backup register written by the loading component.
Something important is that the resource table is read only for the Cortex-M4, only the Cortex-A7 should update it.
2) resource table initialization for RPMsg/virtio communication
The addresses of the Vrings and RPMsg buffers areas are allocated by the Linux thanks to information provided in the device tree memory regions. These addresses are computed by the Linux kernel remoteproc core for the vrings and by the rpmsg virtio bus for the RPMsg buffers.
reserved-memory {
#address-cells = <1>;
#size-cells = <1>;
ranges;
mcuram2: mcuram2@10000000 {
compatible = "shared-dma-pool";
reg = <0x10000000 0x40000>;
no-map;
};
vdev0vring0: vdev0vring0@10040000 {
compatible = "shared-dma-pool";
reg = <0x10040000 0x1000>;
no-map;
};
vdev0vring1: vdev0vring1@10041000 {
compatible = "shared-dma-pool";
reg = <0x10041000 0x1000>;
no-map;
};
vdev0buffer: vdev0buffer@10042000 {
compatible = "shared-dma-pool";
reg = <0x10042000 0x4000>;
no-map;
};
mcu_rsc_table: mcu_rsc_table@10048000 {
compatible = "shared-dma-pool";
reg = <0x10048000 0x8000>;
no-map;
};
mcuram: mcuram@30000000 {
compatible = "shared-dma-pool";
reg = <0x30000000 0x40000>;
no-map;
};
retram: retram@38000000 {
compatible = "shared-dma-pool";
reg = <0x38000000 0x10000>;
no-map;
};
};
vdev0vring0 is the memory region used to store the vring[0]
vdev0vring1 is the memory region used to store the vring[1]
vdev0buffer is the memory region used to store the Rpmsg/virtio buffers.
Other memory regions define the regions for the firmware code and data.
The -1 in the resource table means that the cortex-M4 doesn't impose an address. It's recommended for the stm32mp1 Socs not to change this value, and to use the memory region to update the addresses.
When the Linux kernel is ready to communicate ( resource table is updated), it sets the status field in the fw_rsc_vdev resource table structure. This informs the Cortex-M4 that the Vrings structures have been initialized and that the RPMsg communication can start.
If you want to go deep in the Linux remoteproc framework knowledge, i suggest you that you enable dynamic trace in kernel to help you to parse the source code:
echo -n 'file stm32_rproc.c +p' > /sys/kernel/debug/dynamic_debug/control
echo -n 'file stm32-ipcc.c +p' > /sys/kernel/debug/dynamic_debug/control
echo -n 'file remoteproc*.c +p' > /sys/kernel/debug/dynamic_debug/control
echo -n 'file virtio_rpmsg_bus.c +p' > /sys/kernel/debug/dynamic_debug/control
echo -n 'file virtio_ring.c +p' > /sys/kernel/debug/dynamic_debug/control