全志R128 SDK HAL 模块开发指南之 MSGBOX

2024-05-15 11:04

本文主要是介绍全志R128 SDK HAL 模块开发指南之 MSGBOX,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

MSGBOX

msgbox 用来实现多 CPU 之间通讯,在一些 IC 内部可能同时存在多种核心用来实现多种不同功能,这些不同核心运行不同架构、不同系统,需要通过 MSGBOX 用来实现这些不同系统间通讯。

模块介绍

  • msgbox 为一个双端 fifo 结构,cpu0 从一端写,cpu1 从一端读。
  • rpmsg 为 linux 用来实现通讯的一种框架
  • msgbox 为片上处理器之间提供了中断通讯机制

对于 R128 平台,CPU Remote ID如下

CPURemote ID
ARM M33 Star0
RISC-V C9061
HIFI5 DSP2

模块配置

配置路径如下:

Kernel Setup --->Drivers Setup --->SoC HAL Drivers --->msgbox devices --->[*] enable msgbox driver

源码结构

msgbox/├── msgbox_amp            // msgbox AMP 实现│   ├── Makefile│   └── msgbox_amp.c        ├── platform              // 平台寄存器定义│   ├── msgbox-sun20iw2.h└── platform-msgbox.h     // 公共头文件

模块接口说明

头文件

#include <hal_msgbox.h>

初始化接口

函数原型:

int32_t hal_msgbox_init(void);

参数:

返回值:

  • 0:成功
  • 负数:失败

通道申请接口

函数原型:

uint32_t hal_msgbox_alloc_channel(struct msg_endpoint *edp, int32_t remote, int32_t read, int32_t write);

参数:

  • edp:msgbox的端点
  • remote:远端核心id
  • read:读通道
  • write:写通道

返回值:

  • 0:成功
  • 负数:失败

数据发送接口

函数原型:

uint32_t hal_msgbox_channel_send(struct msg_endpoint *edp, uint8_t *bf, uint32_t len);

参数:

  • edp:msgbox的端点
  • bf:数据buffer
  • len:buffer长度

返回值:

  • 0:成功
  • 负数:失败

通道释放接口

函数原型:

void hal_msgbox_free_channel(struct msg_endpoint *edp);

参数:

  • edp:msgbox的端点

返回值:

  • 0:成功
  • 负数:失败

MSGBOX 申请流程

  1. 使用hal_msgbox_alloc_channel接口申请 msgbox 通道
  2. 填充msg_endpoint接收回调,这个会在 msgbox 的中断函数里调用
  3. 通过hal_msgbox_channel_send进行数据发送
  4. 接收通过中断的方式进行接收,会调用msg_endpoint的回调,无需主动调用

MSGBOX 接收流程

  1. 在接收函数里会首先遍历所有的msg_endpoint,判断当前终端是否有中断发送
  2. irq_msgbox_channel_handler里会读取当前msg_endpoint的寄存器,来判断是否有中断,如果有,则读取数据
  3. 退出中断

MSGBOX 发送流程

  1. 调用hal_msgbox_channel_send接口进行数据发送
  2. msgbox_channel_send_data会判断是远端处理器是哪个,并且计算 local->remote 的系数 N 是多少,这个系数回存放在 to_coef_n 的表格里
  3. 计算完成后往远端的 msgbox 的 fifo 中写数据
  4. 发送完成

模块使用范例

#include <FreeRTOS.h>
#include <queue.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <string.h>
#include <awlog.h>
#include <hal_msgbox.h>#include <console.h>#define RECEIVE_QUEUE_LENGTH 16
#define RECEIVE_QUEUE_WAIT_MS 100struct msgbox_demo {int remote_id;int read_ch;int write_ch;QueueHandle_t recv_queue;
};static void print_help_msg(void)
{printf("\n");printf("USAGE:\n");printf("  hal_msgbox <REQUIRED_ARGUMENTS> [OPTIONS]\n");printf("\n");printf("REQUIRED_ARGUMENTS:\n");printf("  -E REMOTE_ID: specify remote id\n");printf("  -R READ_CH  : specify read channel\n");printf("  -W WRITE_CH : specify write channel\n");printf("OPTIONS:\n");printf("  -s MESSAGE  : send MESSAGE\n");printf("  -r          : receive messages\n");printf("  -t TIMEOUT  : exit in TIMEOUT seconds when receive\n");printf("e.g. (communicate with remote 0, use read channel 3 and write channel 3):\n");printf("  hal_msgbox -E 0 -R 3 -W 3 -s \"hello\" : send string \"hello\"\n");printf("  hal_msgbox -E 0 -R 3 -W 3 -r           : receive messages (default in 10 seconds)\n");printf("  hal_msgbox -E 0 -R 3 -W 3 -r -t 20     : receive messages in 20 seconds\n");printf("\n");
}static int recv_callback(unsigned long data, void *private_data)
{BaseType_t taskwoken = pdFALSE;printf("Receive callback (data: 0x%lx)\n", data);struct msgbox_demo *demo = private_data;BaseType_t ret = xQueueSendFromISR(demo->recv_queue, &data, &taskwoken);if (ret == errQUEUE_FULL) {printf("recv_queue is full\n");return -1;}if (ret == pdPASS) {portYIELD_FROM_ISR(taskwoken);}return 0;
}static int cmd_hal_msgbox(int argc, char *argv[])
{int ret = 0;int c;struct msgbox_demo demo= {.remote_id = -1,.read_ch = -1,.write_ch = -1,.recv_queue = NULL,};struct msg_endpoint ept;TickType_t start_ticks, current_ticks;int do_send = 0;const char *data_send= NULL;int do_recv = 0;int timeout_sec = 10;uint32_t data_recv;if (argc <= 1) {print_help_msg();ret = -1;goto out;}while ((c = getopt(argc, argv, "hs:rt:E:W:R:")) != -1) {switch (c) {case 'h' :print_help_msg();ret = 0;goto out;case 'E':demo.remote_id = atoi(optarg);break;case 'R':demo.read_ch = atoi(optarg);break;case 'W':demo.write_ch = atoi(optarg);break;case 's':do_send = 1;data_send = optarg;break;case 'r':do_recv = 1;break;case 't':timeout_sec = atoi(optarg);break;default:print_help_msg();ret = -1;goto out;}}if (demo.remote_id < 0 || demo.read_ch < 0 || demo.write_ch < 0) {printf("Error. Please specify remote id, read channel and write channel\n");print_help_msg();ret = -1;goto out;}printf("remote id: %d, write channel: %d, read channel: %d\n",demo.remote_id, demo.write_ch, demo.read_ch);if (do_recv) {demo.recv_queue = xQueueCreate(RECEIVE_QUEUE_LENGTH, sizeof(uint32_t));if (!demo.recv_queue) {printf("Failed to create receive queue\n");ret = -1;goto out;}ept.rec = (void *)recv_callback;ept.private = &demo;}ret = hal_msgbox_alloc_channel(&ept, demo.remote_id, demo.read_ch, demo.write_ch);if (ret != 0) {printf("Failed to allocate msgbox channel\n");goto delete_recv_queue;}if (do_send) {ret = hal_msgbox_channel_send(&ept, (unsigned char *)data_send, strlen(data_send));if (ret != 0) {printf("Failed to send message\n");goto free_channel;}}if (do_recv) {printf("hal_msgbox will exit in %d seconds\n", timeout_sec);start_ticks = xTaskGetTickCount();printf("start_ticks: %u\n", start_ticks);while (1) {if (pdTRUE == xQueueReceive(demo.recv_queue, &data_recv,RECEIVE_QUEUE_WAIT_MS / portTICK_PERIOD_MS)) {printf("Received from queue: 0x%x\n", data_recv);}current_ticks = xTaskGetTickCount();if ((current_ticks - start_ticks) * portTICK_PERIOD_MS>= timeout_sec * 1000) {printf("current_ticks: %u\n", current_ticks);break;}}}printf("hal_msgbox exited\n");ret = 0;free_channel:hal_msgbox_free_channel(&ept);
delete_recv_queue:if (do_recv) {vQueueDelete(demo.recv_queue);}
out:return ret;
}FINSH_FUNCTION_EXPORT_CMD(cmd_hal_msgbox, hal_msgbox, hal msgbox);

这篇关于全志R128 SDK HAL 模块开发指南之 MSGBOX的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/991657

相关文章

Python正则表达式匹配和替换的操作指南

《Python正则表达式匹配和替换的操作指南》正则表达式是处理文本的强大工具,Python通过re模块提供了完整的正则表达式功能,本文将通过代码示例详细介绍Python中的正则匹配和替换操作,需要的朋... 目录基础语法导入re模块基本元字符常用匹配方法1. re.match() - 从字符串开头匹配2.

基于 Cursor 开发 Spring Boot 项目详细攻略

《基于Cursor开发SpringBoot项目详细攻略》Cursor是集成GPT4、Claude3.5等LLM的VSCode类AI编程工具,支持SpringBoot项目开发全流程,涵盖环境配... 目录cursor是什么?基于 Cursor 开发 Spring Boot 项目完整指南1. 环境准备2. 创建

JavaScript中的高级调试方法全攻略指南

《JavaScript中的高级调试方法全攻略指南》什么是高级JavaScript调试技巧,它比console.log有何优势,如何使用断点调试定位问题,通过本文,我们将深入解答这些问题,带您从理论到实... 目录观点与案例结合观点1观点2观点3观点4观点5高级调试技巧详解实战案例断点调试:定位变量错误性能分

Java使用jar命令配置服务器端口的完整指南

《Java使用jar命令配置服务器端口的完整指南》本文将详细介绍如何使用java-jar命令启动应用,并重点讲解如何配置服务器端口,同时提供一个实用的Web工具来简化这一过程,希望对大家有所帮助... 目录1. Java Jar文件简介1.1 什么是Jar文件1.2 创建可执行Jar文件2. 使用java

Python中logging模块用法示例总结

《Python中logging模块用法示例总结》在Python中logging模块是一个强大的日志记录工具,它允许用户将程序运行期间产生的日志信息输出到控制台或者写入到文件中,:本文主要介绍Pyt... 目录前言一. 基本使用1. 五种日志等级2.  设置报告等级3. 自定义格式4. C语言风格的格式化方法

Python实现精确小数计算的完全指南

《Python实现精确小数计算的完全指南》在金融计算、科学实验和工程领域,浮点数精度问题一直是开发者面临的重大挑战,本文将深入解析Python精确小数计算技术体系,感兴趣的小伙伴可以了解一下... 目录引言:小数精度问题的核心挑战一、浮点数精度问题分析1.1 浮点数精度陷阱1.2 浮点数误差来源二、基础解决

Java实现在Word文档中添加文本水印和图片水印的操作指南

《Java实现在Word文档中添加文本水印和图片水印的操作指南》在当今数字时代,文档的自动化处理与安全防护变得尤为重要,无论是为了保护版权、推广品牌,还是为了在文档中加入特定的标识,为Word文档添加... 目录引言Spire.Doc for Java:高效Word文档处理的利器代码实战:使用Java为Wo

SpringBoot 多环境开发实战(从配置、管理与控制)

《SpringBoot多环境开发实战(从配置、管理与控制)》本文详解SpringBoot多环境配置,涵盖单文件YAML、多文件模式、MavenProfile分组及激活策略,通过优先级控制灵活切换环境... 目录一、多环境开发基础(单文件 YAML 版)(一)配置原理与优势(二)实操示例二、多环境开发多文件版

使用docker搭建嵌入式Linux开发环境

《使用docker搭建嵌入式Linux开发环境》本文主要介绍了使用docker搭建嵌入式Linux开发环境,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面... 目录1、前言2、安装docker3、编写容器管理脚本4、创建容器1、前言在日常开发全志、rk等不同

从入门到精通详解Python虚拟环境完全指南

《从入门到精通详解Python虚拟环境完全指南》Python虚拟环境是一个独立的Python运行环境,它允许你为不同的项目创建隔离的Python环境,下面小编就来和大家详细介绍一下吧... 目录什么是python虚拟环境一、使用venv创建和管理虚拟环境1.1 创建虚拟环境1.2 激活虚拟环境1.3 验证虚