Difference between revisions of "How to exchange large data buffers with the coprocessor - principle"

[unchecked revision] [quality revision]
(RPMsg messaging)

1 Introduction[edit]

As explained in "Exchanging_buffers_with_the_coprocessor", the RPMsg protocol may be not efficient enough to directly exchange large buffers between the Cortexes. In this case implementing it is recommended to implement the indirect buffer exchange mode is recommended:

  • allocate contiguous buffers to store the data to exchange,
  • use RPMsg to exchange references reference to these buffers with the remote processor.

This article gives an example of a mechanism that can be implemented put in place to exchange indirect buffers between a main processor and a coprocessor.

2 Architecture overview[edit]

This architecture example relies on the rpmsg_sdb linux driver.

Copro-sw-ipc-big-data.png

  • On Cortex-A:
  • The rpmsg_sdb Linux linux driver implements the service to allocate and share buffers with the Cortex-M.
  • The Linux application Application requests and memory-maps (mmap) the buffers needed to be able to access to the associated memory.
  • On Cortex-M:
  • The application Application has to implement the "rpmsg-sdb-channel" RPMsg service to manage the buffer information.
  • A DMA can be used to transfer data to/from DDR.

Refer For an example, refer to How to exchange large data buffers with the coprocessor - example for an example.

3 rpmsg_sdb driver[edit]

The RPMsg shared data buffer driver example is in charge of:

  • Allocating allocating large buffers in contiguous memory (DDR) and memory mapping mmap them (mmap) for use by an application usage.
  • implementing the RPMsg service to share buffer information (address, size) with the coprocessor.
  • Sending sending events to a Linux application Application (relying on the eventfd interface) when buffers are available (on RPMsg message reception).
Info.png This driver drivers is provided as example. It , and implements only the transfer from Cortex-M to cortex-A

3.1 Configuration[edit]

3.1.1 Kernel configuration[edit]

No kernel configuration is needed. The rpmsg_sdb Linux driver is proposed as module and can be installed using thanks to the associated Yocto recipe.

3.1.2 Device tree[edit]

No device tree device tree declaration is needed. The rpmsg_sdb driver is registered as an a RPMsg driver. it is probed when the remote processor creates the "rpmsg-sdb-channel" service .

3.1.3 Source code[edit]

The source code is available in the rpsmg-sdb-mod Yocto recipe.

3.2 How to use[edit]

3.2.1 User space interface[edit]

The rpmsg_sdb driver exposes a "/dev/rpmsg_sdb" sysfs that offers an interface to allocate and manage the shared buffers.

  • open/close: get/release file descriptor.
  int fd;
  fd= open('/dev/rpmsg_sdb');
  close(fd);

  • mmap: allocate and map memories
  void *buff0_id, *buff1_id;
 
  buff0_id = mmap(NULL, size,  PROT_READ | PROT_WRITE, 	MAP_PRIVATE, fd, 0);
  buff1_id = mmap(NULL, size,  PROT_READ | PROT_WRITE, 	MAP_PRIVATE, fd, 0);

  • RPMSG_SDB_IOCTL_SET_EFD ioctl: register event for a buffer
  typedef struct
  {
  	int bufferId, eventfd;
  } rpmsg_sdb_ioctl_set_efd;
  
  int efd[NB_BUF];
  rpmsg_sdb_ioctl_set_efd q_set_efd;

  for (i=0;i<NB_BUF;i++){
	/* Create the evenfd, and sent it to kernel driver, for notification of buffer full */
	efd[i] = eventfd(0, 0);
  }
  q_set_efd.bufferId = i;  /* i is the index of the buffer */
  q_set_efd.eventfd = efd[i];
  
  ioctl(fd, RPMSG_SDB_IOCTL_SET_EFD, buff0_id, &q_set_efd);

  • RPMSG_SDB_IOCTL_GET_DATA_SIZE ioctl : get the size of a buffer
  typedef struct
  {
  	int bufferId;
  	uint32_t size;
  } rpmsg_sdb_ioctl_get_data_size;
  
  rpmsg_sdb_ioctl_get_data_size q_get_data_size;

  ioctl(fd, RPMSG_SDB_IOCTL_GET_DATA_SIZE, buff0_id, eventfd);

p*manage event

  while (1) {
	ret = poll(fds, NB_BUF, TIMEOUT * 1000);
	if (ret < 0) {
		perror("poll()");
		break;
	} else if (ret) {
		printf("Data is available now.\n");
	} else if (ret == 0) {
		printf("No data within five seconds.\n");
		break;
	}
	for (j=0;j<NB_BUF;j++){
		if (fds[j].revents & POLLIN) {
			/* Event received for the buffer j: New data is available for buffer j */
		}
	}
}

3.2.2 RPMsg messaging[edit]

The RPMsg protocol is used for the communication with the Cortex-M:

  • Information about the on buffer allocated and mmaped is sent to the Cortex-M.
The message is structured in a string with following format: "BxAyyyyyyyyLzzzzzzzz"
  • x: buffer index (32 bits, decimal format, no leading zero),
  • yyyyyyyy: physical address of the buffer in DDR ( 32 bits, 8 -digit digits hexadecimal format, leading zero),
  • zzzzzzzz: length of the buffer (32 bits, 8 -digit digits hexadecimal format, leading zero).
  • Buffer filled event received from the Cortex-M:
When the Cortex-M4 has filled a buffer it can inform the Linux application Application by sending an a RPMsg with following string format Format : "BxLzzzzzzzz"'.
  • x: buffer index (32 bits, decimal format, no leading zero),
  • zzzzzzzz: length of the buffer (32 bits, 8 -digit digits hexadecimal format, leading zero).
On reception of this message reception the rpmsg_sdb driver sends an event to the application .



== Introduction ==
As explained in "[[Exchanging_buffers_with_the_coprocessor]]", the RPMsg  protocol may be not efficient enough to directly exchange large buffers between the Cortexes. In this case implementing it is recommended to implement the indirect buffer exchange mode is recommended:
* allocate contiguous buffers to store the data to exchange,

* use RPMsg to exchange referencesreference to these buffers with the remote processor.
This article gives an example of a mechanism that can be implemented put in place to exchange indirect buffers between a main processor and a coprocessor.

== Architecture overview ==
This architecture example relies on the rpmsg_sdb linux driver. 

[[File:copro-sw-ipc-big-data.png | |link=]]
* <u>On Cortex-A</u>: 
:* The rpmsg_sdb Linuxlinux driver implements the service to allocate and share buffers with the Cortex-M.

:* The Linux applicationApplication requests and memory-maps (mmap) the buffers needed to access to be able to access to the associated memory.
* <u>On Cortex-M</u>: 
:*The application Application has to implement the "rpmsg-sdb-channel"  RPMsg service to manage the buffer information. 
:*A DMA can be used to transfer data to/from DDR.Refer For an example, refer to [[How_to_exchange_large_data_buffers_with_the_coprocessor_-_example| How to exchange large data buffers with the coprocessor - example]] for an example.

== rpmsg_sdb driver ==
The RPMsg shared data buffer driver example is in charge of:
* Allocatingallocating large buffers in contiguous memory (DDR) and memory mapping mmap them (mmap) for use by an application usage.
* implementing the RPMsg service to share buffer information (address, size)  with the coprocessor.
* Sendingsending events to a Linux applicationApplication (relying on the [http://man7.org/linux/man-pages/man2/eventfd.2.html eventfd] interface) when buffers are available (on RPMsg message reception).

{{Info| This driverdrivers is provided as example. It, and implements only the transfer from Cortex-M to cortex-A}}

=== Configuration ===
==== Kernel configuration ====
No kernel configuration is needed. The rpmsg_sdb Linux driver is proposed as module and can be installed using thanks to the associated [https://github.com/STMicroelectronics/meta-st-stm32mpu-app-logicanalyser/tree/thud/recipes-kernel/rpsmg-sdb-mod  Yocto recipe].

==== Device tree ====
No device tree device tree declaration is needed. The rpmsg_sdb driver is registered as ana RPMsg driver. it is probed when the remote processor creates the "rpmsg-sdb-channel" service.

==== Source code ====
The source code is available in the [https://github.com/STMicroelectronics/meta-st-stm32mpu-app-logicanalyser/tree/thud/recipes-kernel/rpsmg-sdb-mod  rpsmg-sdb-mod Yocto recipe].

=== How to use ===
==== User space interface ====
The rpmsg_sdb driver exposes a '''"/dev/rpmsg_sdb"''' sysfs that offers an interface to allocate and manage the shared buffers. 

* open/close: get/release file descriptor.<syntaxhighlight lang="c">

  int fd;
  fd= open('/dev/rpmsg_sdb');
  close(fd);</syntaxhighlight>


* mmap: allocate and map memories<syntaxhighlight lang="c">

  void *buff0_id, *buff1_id;

  buff0_id = mmap(NULL, size,  PROT_READ | PROT_WRITE, 	MAP_PRIVATE, fd, 0);
  buff1_id = mmap(NULL, size,  PROT_READ | PROT_WRITE, 	MAP_PRIVATE, fd, 0);</syntaxhighlight>


* RPMSG_SDB_IOCTL_SET_EFD ioctl: register event for a buffer<syntaxhighlight lang="c">

  typedef struct
  {
  	int bufferId, eventfd;
  } rpmsg_sdb_ioctl_set_efd;

  int efd[NB_BUF];
  rpmsg_sdb_ioctl_set_efd q_set_efd;

  for (i=0;i<NB_BUF;i++){
	/* Create the evenfd, and sent it to kernel driver, for notification of buffer full */
	efd[i] = eventfd(0, 0);
  }
  q_set_efd.bufferId = i;  /* i is the index of the buffer */
  q_set_efd.eventfd = efd[i];

  ioctl(fd, RPMSG_SDB_IOCTL_SET_EFD, buff0_id, &q_set_efd);</syntaxhighlight>

*RPMSG_SDB_IOCTL_GET_DATA_SIZE ioctl : get the size of a buffer<syntaxhighlight lang="c">

  typedef struct
  {
  	int bufferId;
  	uint32_t size;
  } rpmsg_sdb_ioctl_get_data_size;

  rpmsg_sdb_ioctl_get_data_size q_get_data_size;

  ioctl(fd, RPMSG_SDB_IOCTL_GET_DATA_SIZE, buff0_id, eventfd);</syntaxhighlight>

p*manage event<syntaxhighlight lang="c">

  while (1) {
	ret = poll(fds, NB_BUF, TIMEOUT * 1000);
	if (ret < 0) {
		perror("poll()");
		break;
	} else if (ret) {
		printf("Data is available now.\n");
	} else if (ret == 0) {
		printf("No data within five seconds.\n");
		break;
	}
	for (j=0;j<NB_BUF;j++){
		if (fds[j].revents & POLLIN) {
			/* Event received for the buffer j: New data is available for buffer j */
		}
	}
}</syntaxhighlight>

==== RPMsg messaging ====
The RPMsg protocol is used for the communication with the Cortex-M:
* Information about the on buffer allocated and mmaped is sent to the Cortex-M.
:The message is structured in a string with following format: '''"BxAyyyyyyyyLzzzzzzzz"'''
:*'''x''': buffer index (32 bits, decimal format, no leading zero),

:*'''yyyyyyyy''': physical address of the buffer in DDR ( 32 bits, 8-digit  digits hexadecimal format, leading zero),

:*'''zzzzzzzz''': length of the buffer (32 bits, 8-digit  digits hexadecimal format, leading zero).

* Buffer filled event received from the Cortex-M:
:When the Cortex-M4 has filled a buffer it can inform the Linux applicationApplication by sending ana RPMsg with following string formatFormat : '''"BxLzzzzzzzz"''''.
:*'''x''': buffer index (32 bits, decimal format, no leading zero),

:*'''zzzzzzzz''': length of the buffer (32 bits, 8-digit  digits hexadecimal format, leading zero).

:On reception of this message reception the rpmsg_sdb driver sends an event to the applicationapplication .
<noinclude>

{{PublicationRequestId | 14367| AnneJ| 2019-12-10}}</noinclude>
Line 1: Line 1:
 
== Introduction ==
 
== Introduction ==
As explained in "[[Exchanging_buffers_with_the_coprocessor]]", the RPMsg  protocol may be not efficient enough to directly exchange large buffers between the Cortexes. In this case it is recommended to implement the indirect buffer exchange mode:
+
As explained in "[[Exchanging_buffers_with_the_coprocessor]]", the RPMsg  protocol may be not efficient enough to directly exchange large buffers between the Cortexes. In this case implementing the indirect buffer exchange mode is recommended:
* allocate contiguous buffers to store the data to exchange,
+
* allocate contiguous buffers to store the data to exchange
* use RPMsg to exchange reference to these buffers with the remote processor.
+
* use RPMsg to exchange references to these buffers with the remote processor.
This article gives an example of a mechanism that can be put in place to exchange indirect buffers between a main processor and a coprocessor.
+
This article gives an example mechanism that can be implemented to exchange indirect buffers between a main processor and a coprocessor.
   
 
== Architecture overview ==
 
== Architecture overview ==
Line 10: Line 10:
 
[[File:copro-sw-ipc-big-data.png | |link=]]
 
[[File:copro-sw-ipc-big-data.png | |link=]]
 
* <u>On Cortex-A</u>:  
 
* <u>On Cortex-A</u>:  
:* The rpmsg_sdb linux driver implements the service to allocate and share buffers with the Cortex-M
+
:* The rpmsg_sdb Linux driver implements the service to allocate and share buffers with the Cortex-M.
:* The Linux Application requests and memory-maps (mmap) the buffers to be able to access to the associated memory.
+
:* The Linux application requests and memory-maps (mmap) the buffers needed to access the associated memory.
 
* <u>On Cortex-M</u>:  
 
* <u>On Cortex-M</u>:  
:*Application has to implement the "rpmsg-sdb-channel"  RPMsg service to manage the buffer information.  
+
:*The application has to implement the "rpmsg-sdb-channel"  RPMsg service to manage the buffer information.  
 
:*A DMA can be used to transfer data to/from DDR.
 
:*A DMA can be used to transfer data to/from DDR.
For an example, refer to [[How_to_exchange_large_data_buffers_with_the_coprocessor_-_example| How to exchange large data buffers with the coprocessor - example]].
+
Refer to [[How_to_exchange_large_data_buffers_with_the_coprocessor_-_example| How to exchange large data buffers with the coprocessor - example]] for an example.
   
 
== rpmsg_sdb driver ==
 
== rpmsg_sdb driver ==
 
The RPMsg shared data buffer driver example is in charge of:
 
The RPMsg shared data buffer driver example is in charge of:
* allocating large buffers in contiguous memory (DDR) and mmap them for an application usage.
+
* Allocating large buffers in contiguous memory (DDR) and memory mapping them (mmap) for use by an application.
 
* implementing the RPMsg service to share buffer information (address, size)  with the coprocessor.
 
* implementing the RPMsg service to share buffer information (address, size)  with the coprocessor.
* sending events to Linux Application (relying on [http://man7.org/linux/man-pages/man2/eventfd.2.html eventfd] interface) when buffers are available (on RPMsg message reception).
+
* Sending events to a Linux application (relying on the [http://man7.org/linux/man-pages/man2/eventfd.2.html eventfd] interface) when buffers are available (on RPMsg message reception).
   
{{Info| This drivers is provided as example, and implements only the transfer from Cortex-M to cortex-A}}
+
{{Info| This driver is provided as example. It implements only the transfer from Cortex-M to cortex-A}}
   
 
=== Configuration ===
 
=== Configuration ===
 
==== Kernel configuration ====
 
==== Kernel configuration ====
No kernel configuration is needed. The rpmsg_sdb Linux driver is proposed as module and can be installed thanks to the associated [https://github.com/STMicroelectronics/meta-st-stm32mpu-app-logicanalyser/tree/thud/recipes-kernel/rpsmg-sdb-mod  Yocto recipe].
+
No kernel configuration is needed. The rpmsg_sdb Linux driver is proposed as module and can be installed using the associated [https://github.com/STMicroelectronics/meta-st-stm32mpu-app-logicanalyser/tree/thud/recipes-kernel/rpsmg-sdb-mod  Yocto recipe].
   
 
==== Device tree ====
 
==== Device tree ====
No device tree device tree declaration is needed. The rpmsg_sdb driver is registered as a RPMsg driver. it is probed when the remote processor creates the "rpmsg-sdb-channel" service
+
No device tree declaration is needed. The rpmsg_sdb driver is registered as an RPMsg driver. it is probed when the remote processor creates the "rpmsg-sdb-channel" service.
 
==== Source code ====
 
==== Source code ====
 
The source code is available in the [https://github.com/STMicroelectronics/meta-st-stm32mpu-app-logicanalyser/tree/thud/recipes-kernel/rpsmg-sdb-mod  rpsmg-sdb-mod Yocto recipe].
 
The source code is available in the [https://github.com/STMicroelectronics/meta-st-stm32mpu-app-logicanalyser/tree/thud/recipes-kernel/rpsmg-sdb-mod  rpsmg-sdb-mod Yocto recipe].
Line 106: Line 106:
 
</syntaxhighlight>
 
</syntaxhighlight>
 
==== RPMsg messaging ====
 
==== RPMsg messaging ====
The RPMsg protocol is used for the communication with the Cortex-M:
+
The RPMsg protocol is used for communication with the Cortex-M:
* Information on buffer allocated and mmaped is sent to the Cortex-M.
+
* Information about the buffer allocated and mmaped is sent to the Cortex-M.
 
:The message is structured in a string with following format: '''"BxAyyyyyyyyLzzzzzzzz"'''
 
:The message is structured in a string with following format: '''"BxAyyyyyyyyLzzzzzzzz"'''
:*'''x''': buffer index (32 bits, decimal format, no leading zero),
+
:*'''x''': buffer index (32 bits, decimal format, no leading zero)
:*'''yyyyyyyy''': physical address of the buffer in DDR ( 32 bits, 8 digits hexadecimal format, leading zero),
+
:*'''yyyyyyyy''': physical address of the buffer in DDR (32 bits, 8-digit hexadecimal format, leading zero)
:*'''zzzzzzzz''': length of the buffer (32 bits, 8 digits hexadecimal format, leading zero)
+
:*'''zzzzzzzz''': length of the buffer (32 bits, 8-digit hexadecimal format, leading zero).
 
* Buffer filled event received from the Cortex-M:
 
* Buffer filled event received from the Cortex-M:
:When the Cortex-M4 has filled a buffer it can inform the Linux Application by sending a RPMsg with following string Format : '''"BxLzzzzzzzz"''''.
+
:When the Cortex-M4 has filled a buffer it can inform the Linux application by sending an RPMsg with following string format : '''"BxLzzzzzzzz"''''.
:*'''x''': buffer index (32 bits, decimal format, no leading zero),
+
:*'''x''': buffer index (32 bits, decimal format, no leading zero)
:*'''zzzzzzzz''': length of the buffer (32 bits, 8 digits hexadecimal format, leading zero)
+
:*'''zzzzzzzz''': length of the buffer (32 bits, 8-digit hexadecimal format, leading zero).
:On this message reception the rpmsg_sdb driver sends an event to application .
+
:On reception of this message the rpmsg_sdb driver sends an event to the application.
   
   

Attachments

Discussions