Vybrid MCC User Guide For MCC Version 1.0
Table of Contents
- Table of contents
- Vybrid MCC 1.0 User Guide
- Introduction
- Design Overview
- API Example
- API Reference
- int mcc_initialize(MCC_NODE node)
- int mcc_destroy(MCC_NODE node)
- int mcc_create_endpoint(MCC_ENDPOINT *endpoint, MCC_PORT port)
- int mcc_destroy_endpoint(MCC_ENDPOINT *endpoint)
- int mcc_send(MCC_ENDPOINT *endpoint, void *msg, MCC_MEM_SIZE msg_size, unsigned int timeout_us)
- int mcc_recv_copy(MCC_ENDPOINT *endpoint, void *buffer, MCC_MEM_SIZE buffer_size, MCC_MEM_SIZE *recv_size, unsigned int timeout_us)
- int mcc_recv_nocopy(MCC_ENDPOINT *endpoint, void **buffer_p, MCC_MEM_SIZE *recv_size, unsigned int timeout_us)
- int mcc_msgs_available(MCC_ENDPOINT *endpoint, unsigned int *num_msgs)
- int mcc_free_buffer(void *buffer)
- int mcc_get_info(MCC_NODE node, MCC_INFO_STRUCT info_data)*
- Building
- Ping-Pong Demo
- Out of Box Demo
- Vybrid Tower Revision F and Earlier notes
- DS-5 Build issues
- References
Introduction
The MCC (Multi-Core Communication) is the subsystem that enables MQX applications running on the M4 core to communicate with Linux applications on the A5 core.
Features
- Lightweight, fast
- API calls are simple send / receive between endpoints
- Uses shared SRAM and interrupts
- Received data can be passed by pointer or copied
- Variable timeouts
- Configurable (at build time): Buffer sizes, # of buffers, Max # of endpoints
Design Overview
Endpoints
The user applications communicate by sending data to each other’s endpoints.
Endpoints are receive buffer queues, implemented in shared SRAM, and are addressed by a triplet containing core, node, and port:
- Core – Identifies the core within the processor. In the current Vybrid processor, the A5 is core 0, and the M4 is core 1.
- Node – In Linux any user process participating in MCC is a unique node. Node numbering is arbitrary. MQX has only one node and can also be an arbitrary number.
- Port – Both Linux and MQX can have an arbitrary number of ports per node (up to a configurable maximum), arbitrarily numbered with the exception of port 0 being reserved.
The [core, node, port] triplets are part of the user’s system design and implementation. There is no discovery protocol.
Buffer Management
Data is transferred between cores in fixed size buffers, allocated in shared SRAM.
All buffers are allocated at initialization time in the free buffer pool. There is only one free buffer pool that is shared by all cores for data transfers in both directions.
When sending, data is always copied from the user application into the buffer. If no buffer is available at the time of the send call, the user application can wait for a specified amount of time, wait “forever”, or have an error condition returned.
When receiving, the API supports receiving with copying to a user supplied buffer, or the application can request a pointer to the buffer thus eliminating the copy. In the case of the latter, the user application is responsible for freeing the buffer via the appropriate API call. Similar to send, the user application can choose to wait or not for a received message.
Shared SRAM
Currently 64 KB of shared SRAM is used by MCC. This is used for “bookkeeping data” (e.g., endpoint and signal queue head and tail pointers) and fixed size data buffers.
Each of the following can be configured at build time. The numbers in parenthesis are default values:
- Maximum number of endpoints (10)
- Number of data buffers (10)
- Size of each data buffer (1KB)
All accesses to shared SRAM are protected by hardware semaphores.
Signaling
The Vybrid processor allows each core to create a hardware interrupt to the other core. The MCC running on one core interrupts the other core when:
- A buffer has been queued to an endpoint on the interrupted core.
- A buffer has been freed by the interrupting core.
A signal queue (one per core) indicates the type of interrupt (queue or free) and, in the case of queued, which endpoint.
Version Control
The mcc_get_info() API call returns a version string in the form of mmm.nnn where mmm is the major number of the version and nnn is the minor number.
The major number of MQX and Linux must match to ensure compatibility. The minor numbers may be different.
API Example
As part of the system design, the designers agreed that MQX would be node 0 and the application would be receiving on port 2. Therefore, Linux will send to [1,0,2]. Similarly, Linux will receive on [0,0,1].
Linux pseudo code:
mcc_initialize(0) mcc_create_endpoint([0,0,1], 1) mcc_send([1,0,2], “hello”, 5, 5000) // no more than 5 secs for buffer mcc_recv_copy([0,0,1], &buf, sizeof(buf), length, 0xffffffff) //forever
MQX pseudo code:
mcc_initialize(0) mcc_create_endpoint([1,0,2], 2) mcc_recv_nocopy([1,0,2], &buf_p, length, 0xffffffff) //forever mcc_send([0,0,1], “hello”, 5, 5000) // no more than 5 secs for buffer
API Reference
#include "libmcc.h"
int mcc_initialize(MCC_NODE node)
Description: Initialize the MCC subsystem for a given node. This should only be called once in MQX and once per process in Linux.
Parameters:
node the node number that will be used in endpoints created by this process.
Return Values:
MCC_ERR_DEV an error in the subsystem – the kernel driver may not be loaded. Check for /dev/mcc.
MCC_SUCCESS
int mcc_destroy(MCC_NODE node)
Description: Frees all resources of the node. Deletes all endpoints and frees any buffers that may have been queued there.
Parameters:
node the node number that will be used in endpoints created by this process.
Return Values:
MCC_SUCCESS
int mcc_create_endpoint(MCC_ENDPOINT *endpoint, MCC_PORT port)
Description: Creates a receive endpoint for the calling process. The core and node provided in endpoint must match the caller’s core and node and the port argument must match the endpoint port.
Parameters:
endpoint the endpoint triplet to be created.
Return Values:
MCC_ERR_NOMEM – maximum number of endpoints exceeded
MCC_ERR_ENDPOINT – invalid value for core, node, or port
MCC_SUCCESS
int mcc_destroy_endpoint(MCC_ENDPOINT *endpoint)
Description: Frees any buffers that may be queued and deletes the endpoint.
Parameters:
endpoint the endpoint triplet to be deleted.
Return Values:
MCC_ERR_ENDPOINT – the endpoint doesn’t exist
MCC_SUCCESS
int mcc_send(MCC_ENDPOINT *endpoint, void *msg, MCC_MEM_SIZE msg_size, unsigned int timeout_us)
Description: Send a message to an endpoint.
Parameters:
endpoint the receiving endpoint to send to
msg a pointer to a buffer containing the data
msg_size the number of bytes to send
timeout_us the length in time, in microseconds, to wait for a free buffer. A value of 0 means don’t wait, 0xffffffff means wait forever.
Return Values:
MCC_ERR_ENDPOINT the endpoint does not exist
MCC_ERR_INVAL an invalid address has been supplied for msg or the msg_size exceeds the size of a data buffer.
MCC_ERR_TIMEOUT timeout exceeded before a buffer became available
MCC_SUCCESS
int mcc_recv_copy(MCC_ENDPOINT *endpoint, void *buffer, MCC_MEM_SIZE buffer_size, MCC_MEM_SIZE *recv_size, unsigned int timeout_us)
Description: Receive a message from the specified endpoint if one is available. The data will be copied from the receive buffer into the user supplied buffer.
Parameters:
endpoint the receiving endpoint to receive from
buffer a pointer to a buffer that the data will be copied to
buffer_size the maximum number of bytes to copy
recv_size a pointer to an int that will contain the number of bytes actually copied into the buffer.
timeout_us the length in time, in microseconds, to wait for a free buffer. A value of 0 means don’t wait, 0xffffffff means wait forever.
Return Values:
MCC_ERR_ENDPOINT the endpoint does not exist
MCC_ERR_INVAL an invalid address has been supplied for msg
MCC_ERR_TIMEOUT timeout exceeded before a buffer became available
MCC_SUCCESS
int mcc_recv_nocopy(MCC_ENDPOINT *endpoint, void **buffer_p, MCC_MEM_SIZE *recv_size, unsigned int timeout_us)
Description: Receive a message from the specified endpoint if one is available. The data is not copied. Instead a pointer to the data is returned.
Parameters:
endpoint the receiving endpoint to receive from
buffer_p a pointer to a buffer pointer that where the data is.
recv_size a pointer to an int that will contain the number of valid bytes in the buffer.
timeout_us the length in time, in microseconds, to wait for a free buffer. A value of 0 means don’t wait, 0xffffffff means wait forever.
Return Values:
MCC_ERR_ENDPOINT the endpoint does not exist
MCC_ERR_INVAL an invalid address has been supplied for msg
MCC_ERR_TIMEOUT timeout exceeded before a buffer became available
MCC_SUCCESS
int mcc_msgs_available(MCC_ENDPOINT *endpoint, unsigned int *num_msgs)
Description: Gets the number of buffers currently queued at the endpoint.
Parameters:
endpoint the receiving endpoint to receive from
num_msgs a pointer to an int that will contain the number of buffers queued.
Return Values:
MCC_ERR_ENDPOINT the endpoint does not exist
MCC_SUCCESS
int mcc_free_buffer(void *buffer)
Description: Free a buffer previously retuned by mcc_recv_nocopy()
Parameters:
buffer_p the buffer pointer.
Return Values:
MCC_ERR_ENDPOINT the endpoint does not exist
MCC_ERR_INVAL an invalid address has been supplied for buffer
MCC_SUCCESS
int mcc_get_info(MCC_NODE node, MCC_INFO_STRUCT info_data)*
Description: Returns information about the sub system. At this time the only information returned is the version number. Please see the “Version Control” section in the “Design Overview” of this document.
Parameters:
node the node of the calling process
info_data a pointer to the MCC_INFO_STRUCT structure to hold returned data.
Return Values:
MCC_ERR_ENDPOINT the endpoint does not exist
MCC_SUCCESS
Building
In order to use MCC and run the mcc-pingpong demo application, you need to build the required components for both MQX and Linux:
Building MQX
I. Install MQX
Download the MQX installer for Linux from your LinuxLink dashboard. Then:
IMPORTANT Do not install MQX at the same location as the LinuxLink SDK**
chmod +x FreescaleMQXRTOS<version>.sh
./FreescaleMQXRTOS<version>.sh
II. Install DS-5
Your Vybrid kit contains a link to download DS-5 with a 1-year license. Please follow this link, which will have instructions to download and install DS-5.
III. Import and build the following MQX projects (the order is important!) with DS-5:
Import as "Existing Projects into Workspace", and MAKE SURE "Copy into workspace” is NOT checked
<mqx_install_location>/mqx/build/ds5/bsp_twrvf65gs10_m4 - this is the standard Vybrid M4 MQX BSP
<mqx_install_location>/mqx/build/ds5/psp_twrvf65gs10_m4 - this is the standard Vybrid M4 MQX PSP
<mqx_install_location>/mcc/build/ds5/mcc_twrvf65gs10_m4 - this is the MCC sub-system
At this point you can write and link your MQX application using the MCC API. For an example, see the Ping-Pong Demo section below.
Building Linux
Important Note for building for Phytec phyCORE Vybrid (pcm052) with Linux 3.13
Linux 3.13 for the Phytec phyCORE Vybrid enables UART2 by default. This will conflict with MQX, as it also uses UART2 for its default serial debug console.
It is necessary to either disable UART2 in MQX, or in Linux. For Linux, remove the "vf610-uart2;" line in the source tree at arch/arm/boot/dts/vf610-pcm-952.dtsi:
&clks { /* UART2 clock is not enabled unless below property is present */ vf610-uart2; };
Then, rebuild your device tree blob. To do this with Desktop Factory, run the following command:
$ make kernel-restage kernel
I. Using either the Web Factory or the Desktop Factory, build a Vybrid BSP and include the following packages:
mcc-kmod - this is the kernel driver module libmcc - this is the API user-space library mqxboot - this is the utility to load and boot an MQX image
In addition, you will want to include at least one of the following packages:
mcc-pingpong - if you want to run the mcc-pingpong-demo - this is the portion of the mcc-pingpong demo that runs on Linux. vybrid-out-of-box-demo - if you want to run the OOBE demo - this is the Qt portion of the vybrid-out-of-box-demo that runs on Linux.
When the build is complete the toolchain (located in the Factory build tree as well as in the SDK installer) contains the necessary library to write and build an MCC application with DS-5 and TimeStorm plugins. There may be a pre-built BSP available on your LinuxLink dashboard as well.
II. To use DS-5 with the TimeStorm plugins:
Download the installer tsplugins.sh from your LinuxLink dashboard. Then:
chmod +x tsplugins.sh ./tsplugins.sh
NOTE: If you installed DS-5 with sudo, you will need to run the tsplugins.sh installer with sudo as well:
sudo ./tsplugins.sh
Ping-Pong Demo
This assumes you have already followed the Vybrid Getting Started guide to install and boot the Vybrid BSP built with the MCC components, and have followed the "Building MQX" guide directly above.
To build the MQX image of the Ping-Pong demo application in DS-5, import and build
<mqx_install_location>/mcc/examples/pingpong/ds5/pingpong_example_twrvf65gs10_m4
The "Int Ram Debug" directory of the project will contain pingpong_example_twrvf65gs10_m4.bin.
Copy that file to the root directory of your target RFS. You can use scp if you are booting from a micro-SD card or copy directly to the NFS exported RFS.
From Linux on the Vybrid Tower, issue these commands:
modprobe mcc mqxboot pingpong_example_twrvf65gs10_m4.bin 0x3f000000 0x3f000485 mcc-pingpong
You should see MQX output on the serial console and Linux output on its serial console over USB.
Out of Box Demo
This assumes you have already followed the Vybrid Getting Started guide to install and boot the Vybrid BSP built with the MCC components, and have followed the "Building MQX" guide directly above.
To build the MQX image of the Out of Box Experience demo (OOBE demo), import and build
<mqx_install_location>/mcc/examples/oobe/ds5/oobe_twrvf65gs10_m4
The "Int Ram Debug" directory of the project will contain the file oobe_twrvf65gs10_m4.bin.
Copy oobe_twrvf65gs10_m4.bin to the same directory as your kernel image. In u-boot, load oobe_twrvf65gs10_m4.bin file via the following commands (in this example, an SD card is used):
fatload mmc 0:1 0x3f000000 oobe_twrvf65gs10_m4.bin mw.l 0x4006e028 0x3f000485 mw.l 0x4006b08c 0x00015a5a
You can continue to boot on as normal by loading and booting the kernel image.
Vybrid Tower Revision F and Earlier notes
If you have a Rev F or earlier Vybrid Tower, please see the following link for notes on console conflict and sharing between MQX and Linux:
https://linuxlink.timesys.com/docs/projects/mcc/wiki/Revision_F_notes
DS-5 Build issues
If you experience the following build issue, please downgrade your DS-5 installation to version 5.16:
"../../../../source/psp/cortex_m/core/M4/support.S", line 29: Error: #5: cannot open source input file "asm_mac.h": File name too long
#include <asm_mac.h>
../../../../source/psp/cortex_m/core/M4/support.S: 0 warnings, 1 error
Fatal error: A1905U: Pre-processor step failed for '../../../../source/psp/cortex_m/core/M4/support.S'
References
“Faraday IPC Architecture Specification” (doc_ipc_ipc_impresario.pdf)
Justin Lydick / Freescale
Updated as of 11/14/2011
“Vybrid MCC Design” (Vybrid_mcc_design_2012_11_26.pdf)
Ed Nash / Timesys, Michal Princ / Freescale, Roshni Shah / Timesys,
Updated as of 11/26/2012