I need to transfer some MB of data from the M4 to the Linux OS. Therefore i took the RPMSG “string echo” example and adopted that code for my program. Now i noticed a strange buffer allocation behavior and wrote a little program to clarify my issue. According to the documentation there are 256 buffers á 512 bytes with a payload length of 496. The documentation says that “rpmsg_rtos_send” will block if no free buffer is available. So when you take a look at my example program you will see that within the endless loop the same data is sent. This loop never produces an error… The RPMSG message is written to somewhere, maybe the module “imx_rpmsg_tty” takes the data and stores it? However after some time the error “imx_rpmsg_tty virtio0.rpmsg-openamp-demo-channel.-1.0: RX copy to tty layer failed” shows up on my console. And in fact data is missing. Is this behavior to be expected? I would expect the transmit to be stalled until i read out some data within Linux but i never saw this behaviour. Please note that “rpmsg_rtos_send_nocopy” behaves identically. Thanks in advance!
#include "rpmsg/rpmsg_rtos.h"
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
#include "string.h"
#include "board.h"
#include "mu_imx.h"
#include "debug_console_imx.h"
////////////////////////////////////////////////////////////////////////////////
// Definitions
////////////////////////////////////////////////////////////////////////////////
#define APP_TASK_STACK_SIZE 256
/*
* APP decided interrupt priority
*/
#define APP_MU_IRQ_PRIORITY 3
char dummy_data[512];
/*!
* @brief A basic RPMSG task
*/
static void StrEchoTask(void *pvParameters)
{
int result;
struct remote_device *rdev = NULL;
struct rpmsg_channel *app_chnl = NULL;
void *rx_buf;
int len;
unsigned long src;
void *tx_buf;
unsigned long size;
// Print the initial banner
PRINTF("\r\nRPMSG String Echo FreeRTOS RTOS API Demo...\r\n");
// RPMSG Init as REMOTE
PRINTF("RPMSG Init as Remote\r\n");
result = rpmsg_rtos_init(0 /*REMOTE_CPU_ID*/, &rdev, RPMSG_MASTER, &app_chnl);
assert(result == 0);
PRINTF("Name service handshake is done, M4 has setup a rpmsg channel [%d ---> %d]\r\n", app_chnl->src, app_chnl->dst);
PRINTF("Please enter something to start...\r\n");
result = rpmsg_rtos_recv_nocopy(app_chnl->rp_ept, &rx_buf, &len, &src, 0xFFFFFFFF);
assert(result == 0);
result = rpmsg_rtos_recv_nocopy_free(app_chnl->rp_ept, rx_buf);
assert(result == 0);
PRINTF("Starting.\r\n");
for (;;)
{
size = 460;
memset(dummy_data, 0, 512);
memset(dummy_data, 'a', size);
dummy_data[size-2] = '\r';
dummy_data[size-1] = '\n';
result = rpmsg_rtos_send(app_chnl->rp_ept, dummy_data, size, src);
if (result != 0)
{
PRINTF("Got error code:. %d.\r\n", result);
continue;
}
/*
// There should exist 256 buffers with 512 bytes.
// 16 bytes are header and 496 bytes can be used for data.
// Get tx buffer from RPMsg.
tx_buf = rpmsg_rtos_alloc_tx_buffer(app_chnl->rp_ept, &size);
assert(tx_buf);
assert(size > 0);
// Fill the buffer with junk data.
memset(tx_buf, 0xFF, size);
// Echo back received message with nocopy send.
result = rpmsg_rtos_send_nocopy(app_chnl->rp_ept, tx_buf, size, src);
assert(result == 0);*/
PRINTF("Sent %d data bytes\r\n", size);
}
}
/*
* MU Interrrupt ISR
*/
void BOARD_MU_HANDLER(void)
{
/*
* calls into rpmsg_handler provided by middleware
*/
rpmsg_handler();
}
int main(void)
{
hardware_init();
/*
* Prepare for the MU Interrupt
* MU must be initialized before rpmsg init is called
*/
MU_Init(BOARD_MU_BASE_ADDR);
NVIC_SetPriority(BOARD_MU_IRQ_NUM, APP_MU_IRQ_PRIORITY);
NVIC_EnableIRQ(BOARD_MU_IRQ_NUM);
/* Create a demo task. */
xTaskCreate(StrEchoTask, "String Echo Task", APP_TASK_STACK_SIZE,
NULL, tskIDLE_PRIORITY+1, NULL);
/* Start FreeRTOS scheduler. */
vTaskStartScheduler();
/* Should never reach this point. */
while (true);
}