This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

AM625: RPMsg过程中,出现邮箱队列已满的问题

Part Number: AM625

目前属于预研阶段,在A53和M4F间进行通信时,需要测试各种情况,于是在测试Vring空间时,关掉A53的接收函数,A53应用程序仍在尝试通过 rpmsg 向 M4发送消息。 最终所有邮箱都被填满、A53应用程序无法再向M4发送 rpmsg 消息.

终端控制台中看到错误消息:"Failed to send mailbox message....尝试增加 MBOX_TX_QUEGE_LEN"

该错误消息来自内核,当我在不接收来自M4的ACK回复时,连续发送18条消息以上就会出现这个错误,但是我在内核的相关代码中发现,MBOX_TX_QUEGE_LEN的值被定义为20,这与我发送18条信息就导致该错误明显不对。

https://e2e.ti.com/support/processors-group/processors/f/processors-forum/1179393/am6442-problem-detecting-rpmsg-mailbox-full-when-communicating-to-r5-core

我从上面链接得到一些解答,但是Vring空间缓冲区设置为256是不是就没有意义了?因为MBOX_TXQUEGE_LEN限制了消息的数量,VRING_BUFFER的数量根本不可能达到上限。

同时我发现一个奇妙的方式,在我的rpmsg_char_simple.c代码中,关于159行的打印信息,当我注释掉159的printf()函数时,会出现"Failed to send mailbox message....尝试增加 MBOX_TX_QUEGE_LEN"

错误信息,但是保留该打印信息,就能够正常输出,这是为什么呢?我怀疑是printf()函数的延迟导致的,但是我尝试将printf()函数换成usleep()在此处添加延迟,依然报错!只有在该while循环中保留该打印信息,才能够成功运行,而不会出现邮箱队列满的问题,希望能够告诉我原因!感谢

/*
 * rpmsg_char_simple.c
 *
 * Simple Example application using rpmsg-char library
 *
 * Copyright (c) 2020 Texas Instruments Incorporated - https://www.ti.com
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * *  Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * *  Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * *  Neither the name of Texas Instruments Incorporated nor the names of
 *    its contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

#include <sys/select.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <stdint.h>
#include <stddef.h>
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <time.h>
#include <stdbool.h>
#include <semaphore.h>

#include <linux/rpmsg.h>
#include <ti_rpmsg_char.h>

#define NUM_ITERATIONS  100
#define REMOTE_ENDPT    14

int send_msg(int fd, char *msg, int len)
{
//      clock_t start, end;
//      double t;
//      start = clock();
        int ret = 0;

        ret = write(fd, msg, len);
        if (ret < 0) {
                perror("Can't write to rpmsg endpt device\n");
                return -1;
        }
//      end = clock();
//      t = ((double)(end - start) / CLOCKS_PER_SEC);
//      printf("T = %f\n",t);
        return ret;
}

int recv_msg(int fd, int len, char *reply_msg, int *reply_len)
{
        int ret = 0;
//      clock_t start, end;
//      double t;
//      start = clock();

        /* Note: len should be max length of response expected */
        ret = read(fd, reply_msg, len);
        if (ret < 0) {
                perror("Can't read from rpmsg endpt device\n");
                return -1;
        } else {
                *reply_len = ret;
        }
//      end = clock();
//      t = ((double)(end - start) / CLOCKS_PER_SEC);
//      printf("T = %f\n",t);

        return 0;
}

/* single thread communicating with a single endpoint */
int rpmsg_char_ping(int rproc_id, char *dev_name, int local_endpt, int remote_endpt,
                    int num_msgs)
{
        int ret = 0;
        int i = 0;
        int packet_len;
        char eptdev_name[32] = { 0 };
        char packet_buf[512] = { 0 };
        char *str = "hello worldaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa1234567a";
        char str1[1024] = {0};
        int data_len = strlen(str);
        rpmsg_char_dev_t *rcdev;
        int flags = 0;
        clock_t start, end;
        double t,num = 0;

        /*
         * Open the remote rpmsg device identified by dev_name and bind the
         * device to a local end-point used for receiving messages from
         * remote processor
         */
        sprintf(eptdev_name, "rpmsg-char-%d-%d", rproc_id, getpid());
        rcdev = rpmsg_char_open(rproc_id, dev_name, local_endpt, remote_endpt,
                                eptdev_name, flags);
        if (!rcdev) {
                perror("Can't create an endpoint device");
                return -EPERM;
        }
        printf("Created endpt device %s, fd = %d port = %d\n", eptdev_name,
                        rcdev->fd, rcdev->endpt);

        printf("Exchanging %d messages with rpmsg device ti.ipc4.ping-pong on rproc id %d ...\n\n",
                        num_msgs, rproc_id);

//      start = clock();
        for (i = 0; i < num_msgs; i++) {
        /*      memset(packet_buf, 0, sizeof(packet_buf));
                sprintf(packet_buf, "hello there %d!", i);
                packet_len = strlen(packet_buf);
                printf("Sending message #%d: %s\n", i, packet_buf);
                ret = send_msg(rcdev->fd, (char *)packet_buf, packet_len); */
                sprintf(str1, "hello there %d,%s", i,str);
                data_len = strlen(str1);
                printf("sending messages #%d\n,",i);
                char *block_ptr = str1;
                int block_len = strlen(block_ptr);
                do{
                        if(data_len < 496){
                                block_len = data_len;
                        }
                        memset(packet_buf, 0, sizeof(packet_buf));
                        memcpy(packet_buf,block_ptr,496);
                        packet_len = strlen(packet_buf);
                        start = clock();
                        ret = send_msg(rcdev->fd, (char *)packet_buf, packet_len);
                        end = clock();
                        t = ((double)(end - start)) / CLOCKS_PER_SEC * 1000000;
                        num += t;
                        printf("%s, len = %d\n", packet_buf,packet_len);
                        block_len = strlen(block_ptr);
                        if(block_len > 496)
                                block_ptr += 496;
                        if (ret < 0) {
                                printf("send_msg failed for iteration %d, ret = %d\n",i, ret);
                                goto out;
                        }
                        if (ret != packet_len) {
                                printf("bytes written does not match send request, ret = %d, packet_len = %d\n",
                                                i, ret);
                                goto out;
                        }
                }while(block_len > 496);
                /*      printf("Receiving message #%d: ", i);
                do{
                        memset(packet_buf, 0, sizeof(packet_buf));
                        ret = recv_msg(rcdev->fd, 512, (char *)packet_buf, &packet_len);
                        if (ret < 0) {
                                printf("recv_msg failed for iteration %d, ret = %d\n", i, ret);
                                goto out;
                        }
                        printf("%s, len = %d\n", packet_buf,packet_len);
                }while(packet_len == 496);*/
        }
//      end = clock();
//      t = ((double)(end - start) / CLOCKS_PER_SEC) * 1000000;
        printf("T1 = %f us\n",num);
        num = 0;
        for (i = 0; i < num_msgs; i++) {
                //printf("Receiving message #%d: ", i);
                do{
                        memset(packet_buf, 0, sizeof(packet_buf));
                        start = clock();
                        ret = recv_msg(rcdev->fd, 512, (char *)packet_buf, &packet_len);
                        end = clock();
                        t = ((double)(end - start)) / CLOCKS_PER_SEC * 1000000;
                        num += t;
                        if (ret < 0) {
                                printf("recv_msg failed for iteration %d, ret = %d\n", i, ret);
                                goto out;
                        }
                        //printf("%s, len = %d\n", packet_buf,packet_len);
                }while(packet_len == 496);
        }
//      end = clock();
//      t = ((double)(end - start) / CLOCKS_PER_SEC) * 1000000;
        printf("T2 = %f us\n",num);

        printf("\nCommunicated %d messages successfully on %s\n\n",
                num_msgs, eptdev_name);

out:
        ret = rpmsg_char_close(rcdev);
        if (ret < 0)
                perror("Can't delete the endpoint device\n");

        return ret;
}

void usage()
{
        printf("Usage: rpmsg_char_simple [-r <rproc_id>] [-n <num_msgs>] [-d \
               <rpmsg_dev_name] [-p <remote_endpt] [-l <local_endpt] \n");
        printf("\t\tDefaults: rproc_id: 0 num_msgs: %d rpmsg_dev_name: NULL remote_endpt: %d\n",
                NUM_ITERATIONS, REMOTE_ENDPT);
}

int main(int argc, char *argv[])
{
        int ret, status, c;
        int rproc_id = 0;
        int num_msgs = NUM_ITERATIONS;
        int remote_endpt = REMOTE_ENDPT;
        int local_endpt = RPMSG_ADDR_ANY;
        char *dev_name = NULL;

        while (1) {
                c = getopt(argc, argv, "r:n:p:d:l:");
                if (c == -1)
                        break;

                switch (c) {
                case 'r':
                        rproc_id = atoi(optarg);
                        break;
                case 'n':
                        num_msgs = atoi(optarg);
                        break;
                case 'p':
                        remote_endpt = atoi(optarg);
                        break;
                case 'd':
                        dev_name = optarg;
                        break;
                case 'l':
                        local_endpt = atoi(optarg);
                        break;
                default:
                        usage();
                        exit(0);
                }
        }

        if (rproc_id < 0 || rproc_id >= RPROC_ID_MAX) {
                printf("Invalid rproc id %d, should be less than %d\n",
                        rproc_id, RPROC_ID_MAX);
                usage();
                return 1;
        }

        /* Use auto-detection for SoC */
        ret = rpmsg_char_init(NULL);
        if (ret) {
                printf("rpmsg_char_init failed, ret = %d\n", ret);
                return ret;
        }

        status = rpmsg_char_ping(rproc_id, dev_name, local_endpt, remote_endpt, num_msgs);

        rpmsg_char_exit();

        if (status < 0) {
                printf("TEST STATUS: FAILED\n");
        } else {
                printf("TEST STATUS: PASSED\n");
        }

        return 0;
}

此致!

FengLang

  •  1. 增加邮箱队列容量:如果邮箱队列容量不足导致了队列已满的问题,可以尝试增加邮箱队列的容量来解决问题。

    2. 优化消息发送速度:如果消息发送速度过快导致了队列已满的问题,可以尝试优化消息发送的速度,例如增加消息发送的间隔时间或者采用更高效的消息发送方式。

    3. 实现消息重发机制:在消息发送过程中,可以实现消息重发机制,当队列已满时,可以将消息放入重发队列,并定时重发消息,直到消息成功发送为止。

    4. 使用更高效的消息队列实现:如果当前使用的消息队列实现性能不足,可以考虑使用更高效的消息队列实现来解决问题。 

  • 您好

    能够告诉我关于只有保留printf()函数,才不会报错的原因吗?

  • 您好,个人理解可能是因为printf()函数是该语言中的标准输出函数,可以在不需要其他代码的情况下独立运行。