全志 Tina Linux RISC-V E907核心开发指南支持百问网V85x系列开发板100ask-v853-pro v851s等 admin 2023-05-24 10:45:01 篇首语:本文由小编为大家整理,主要介绍了全志 Tina Linux RISC-V E907核心开发指南支持百问网V85x系列开发板100ask-v853-pro v851s等相关的知识,希望对你有一定的参考价值。 编写目的:介绍v85X 上E907 的启动环境和AMP 的环境搭建。 使用范围:全志V85X 系列芯片 环境 A7 SDK:Tina E907 SDK:melis 4 SDK 快捷命令说明 这里主要介绍几个下文会用到的命令,并不会介绍全部命令,如果想了解全部命令,可以在lunch 方案后使用hmm打印出所有tina提供的快捷命令。 ckernel, m kernel_menuconfig, mkernel:分别对应进入到内核目录,配置内核,单独编译内核cboot0, mboot0:进入boot0 目录,单独编译boot0cmelis, mmelis, mmelis menuconfig:分别对应进入melis 根目录,编译melis,配置melismake:编译整个tina 除了melis 外的所有东西,如boot0,uboot,内核,跟文件系统等cconfigs:进入板级配置目录,这里主要存放板级的设备树,分区等配置文件p:打包命令,将编译后的东西打包成固件 5 E907 启动环境 5.1 预先工作 选择方案 cd tinasource build/envsetup.shlunch选择对应的V85x方案 5.2 配置boot0 启动e907 e907 在boot0 阶段启动,需要对boot0 进行一些配置 cboot0vim board/sun8iw21p1/common.mk# 如下图取消注释保存退出mboot0 #编译 图5-1: 配置1 5.2.1 关闭RISCV 的IOMMU 本步骤只有需要在boot0 阶段启动E907 的需要配置。打开设备树,注释掉下面2 条属性,因为 e907 在boot0 阶段就启动了,不能打开其IOMMU。 cconfigsvim ../board.dts 图5-2: 关闭IOMMU 5.3 配置打包e907 固件 cconfigscd ../../default/vim boot_package_nor.cfg # 取消melis-elf选项的注释,如下图vim boot_package.cfg # 取消melis-elf选项的注释,如下图保存退出 图5-3: 打包配置 5.4 Linux 配置 ckernelm kernel_menuconfig# 如下图选中2个驱动mkernel -j 图5-4: 补丁下载 mmelis menuconfig # 如下图选中standby支持 图5-5: e907-standby 配置 5.5 编译打包 至此关于E907 启动的配置完成,进行编译烧录即可 make -j16 # 编译tinammelis # 编译melisp烧录 6 AMP 环境搭建 AMP 环境用于Linux 和E907 间通信,Linux 依赖于2 个驱动,melis 依赖于openamp 驱 动。 remoteproc 驱动:主要用来管理E907 固件的加载器的rpmsg:在virtio 框架上实现的消息传送框架 6.1 Linux 配置 注意:需要前面的启动环境配置好后,再执行以下操作。 需要打开的配置有: remoteproc 驱动rpmsg 驱动 6.1.1 remoteproc 驱动 ckernelm kernel_menuconfig 选中 图6-1: rproc config 6.1.2 rpmsg 驱动 ckernelm kernel_menuconfig# 红框必选,蓝色框为sdk提供的rpmsg demo,视情况而选择# 建议选上sunxi rpmsg ctrl driver 方便后面测试rpmsg通信功能 选中 图6-2: rpmsg config 6.2 melis 配置 主要进行2 个配置: msgbox 配置openamp 配置 6.2.1 msgbox 配置 mmelis menuconfig #选择下面2项 选中 图6-3: msgbox-melis config 6.2.2 openamp 配置 mmelis menuconfig# 红框是必选,蓝框是可选的rpmsg demo 刚刚Linux 端选择了rpmsg hearbeat demo 和ctrl driver,我们这里也选上对应的驱动hearbeatdriver 和client driver。 选中 图6-4: openamp config 为了方便在控制台测试rpmsg 通信,rpmsg client driver 还需开启下面2 个选项 图6-5: rpmsg client config 6.3 打包 make -j16 # 编译tinammelis # 编译melisp烧录 6.4 测试 本章节介绍一些AMP 提供的控制台命令,用于测试AMP 环境 6.4.1 E907 控制 1.在linux 控制台执行:echo stop > /sys/kernel/debug/remoteproc/remoteproc0/state (停止e907) 2.在linux 控制台执行:echo start > /sys/kernel/debug/remoteproc/remoteproc0/state (启动e907) 若控制台出现remoteproc0: remote processor e907_rproc is now up,表明启动e907 成功。 如果使能了rpmsg_heartbeat 和rpmsg_ctrl 驱动,可以在Linux 控制台start 之后会看到如下输出: 图6-6: rproc test 红框里面表示有2 个设备成功创建,代表rpmsg 正常。 6.4.2 rpmsg 通信测试 借助rpmsg_ctrl 驱动帮助我们进行测试 6.4.2.1 名字监听. 平台:melis 控制台 输入如下图命令: eptdev_bind 命令:监听name=test 的链接,最大连接数5 个 图6-7: rproc test 6.4.2.2 节点创建 平台:Linux 控制台 输入如下图的命令,进行节点创建 图6-8: rpmsg test 图6-9: rpmsg test 根据log 可以看出,创建了一个rpmsg0-4 5 个设备,因为melis 只监听的5 个,故最多只能创建5 个。 6.4.2.3 节点通信 rpmsg 节点支持标准的文件操作,直接读写即可。 Linux 向e907 发数据: 图6-10: rpmsg test 图6-11: rpmsg test e907 向Linux 发数据: 图6-12: rpmsg test 图6-13: test 6.4.2.4 节点关闭 Linux 主动释放: 图6-14: rpmsg test 图6-15: rpmsg test e907 主动释放: 图6-16: rpmsg test 图6-17: rpmsg test e907 端接触监听,会释放所有的链接: 图6-18: rpmsg test 图6-19: rpmsg test 7 开发使用 7.1 rpmsg 内核开发 linux 端请参考driver/rpmsg/rpmsg_client_e907.c 。 melis 端请参考ekernel/subsys/thirdparty/openamp/rpmsg_demo/ 目录下的文件。 7.2 rpmsg 用户层接口 控制台调试命令参考测试章节,这里列举代码使用示例。 Linux 端: #include # 创建端点int fd;struct rpmsg_ept_info info;char ept_dev_name[32];strcpy(info.name, "test");info.id = 0xfffff; # id由itctl进行更新fd = open(ctrl_dev, O_RDWR);ret = ioctl(fd, RPMSG_CREATE_EPT_IOCTL, &info);# 当ioctl返回值==0时,端点已经创建成功,设备节点会出现在/dev/rpmsg%d(=info.id)下close(fd);#读写设备节点snprintf(ept_dev_name, 32, "/dev/rpmsg%d", info.id);fd = open(ept_dev_name, O_RDWR);write,read,poll...close(fd);# 关闭节点fd = open(ctrl_dev, O_RDWR);ret = ioctl(fd, RPMSG_DESTROY_EPT_IOCTL, &info);close(fd); melis 端: 方法1:基于rpmsg_ctrl 驱动,等待主机建立连接 // 头文件#include static int ept_cb(struct rpmsg_endpoint *ept, void *data,size_t len, uint32_t src, void *priv)// 收到数据int bind_cb(struct rpmsg_ept_client *client)// client绑定,每个client代表一个连接// client->priv和client->ept->priv 可供用户使用int unbind_cb(struct rpmsg_ept_client *client)// 连接关闭int main()// cnt: 监听的数量,即最多对test创建cnt个连接// 最后一个参数priv,其实里面设置的是client->privrpmsg_client_bind("test", ept_cb, bind_cb, unbind_cb,cnt, NULL);// do some things// 取消绑定会unbind所有与其相关的clientrpmsg_client_unbind("test"); 具体代码参考ekernel/subsys/thirdparty/openamp/rpmsg_demo/rpmsg_ctrl/test.c; 方法2:基于rpmsg 原生框架,melis 端主动创建连接,触发主机端的rpmsg driver 的probe。 melis 端代码参考: 1.ekernel/subsys/thirdparty/openamp/rpmsg_demo/demo.c 2.ekernel/subsys/thirdparty/openamp/rpmsg_demo/hearbeat.c Linux 端参考代码: 1.drivers/rpmsg/rpmsg_client_e907.c 2.drivers/rpmsg/rpmsg_client_heart.c 7.3 amp 控制台 SDK 在Linux 端提供了进入E907 控制台的功能,配置步骤如下: 内核配置 ckernelm kernel_menuconfig # 选择下图配置 图7-1: rpmsg config Tina 配置 crootm menuconfig # 选择下图配置 图7-2: amp_shell config melis 配置 图7-3: amp_shell config 编译& 打包& 下载 mmelis -j32make -j32p 使用 在echo start > /sys/kernel/debug/remoteproc/remoteproc0/state 后检查有无rpmsg_ctrl 成功创建的log 或者是否存在/dev/rpmsg_ctrl0 节点。如果正常,直 接在Linux 控制台啊输入amp_shell 即可进入e907 控制台,amp_exit退出控制台。支持执行多次amp_shell,开启多个控制台。 图7-4: amp_shell test 图7-5: amp_shell test 7.4 大数据传输 由于rpmsg 特性,不适合传输大数据量;如需使用大数据传输,请参考本章节。 7.4.1 配置 内核打开rpbuf 驱动: m kernel_menuconfigDevice Drivers --->RPBuf drivers --->-*- RPBuf device interface<*> RPMsg-based RPBuf service driver<*> Allwinner RPBuf controller driver<*> Allwinner RPBuf sample driver Note:Allwinner RPBuf sample driver 是一个简单的rpbuf 内核层使用demo,可以不使能。 e907 配置: Kernel SetupSubsystem supportAllwinner Components SupportRPBuf framework [*] RPMsg-based RPBuf service component [*] RPBuf controller component [*] RPMsg-based RPBuf service component demo OpenAMP Support [*] RPBuf demo Tina 打开rpbuf_demo 软件包: m menuconfigAllwinner ---> RPBuf ---> <*> rpbuf_demo <*> rpbuf_test 7.4.2 测试 rpmsg_test:会自动生成随机数据并附带MD5 校验值,另一端收到会重新计算MD5 并与收到的进行对比。 (e907) rpbuf_test -c -N "rpbuf_demo" -L 0x100000 # 创建size=0x100000的buffer(Linux) rpbuf_test -d 1000 -s -L 0x100000 -N "rpbuf_demo" # 发送测试数据(Linux) rpbuf_test -r -t 1000 -L 0x100000 -N "rpbuf_demo" # 接收数据(e907) rpbuf_test -s -L 0x100000 -N "rpbuf_demo" #发送测试数据(e907) rpbuf_test -N "rpbuf_demo" -d # 删除buffer 出现success 表明校验成功。 过程log 如下: 图7-6: Linux 端log 图7-7: e907 端log rpbuf_demo:用于在控制台简单传输数据 (e907) rpbuf_demo -c -N "rpbuf_demo" -L 0x1000 # 创建size=4k的buffer(Linux) rpbuf_demo -d 1000 -L 0x1000 -N "rpbuf_demo" -s "hello" # 发送数据,并在1000ms后释放buffer(Linux) rpbuf_demo -r -t 1000 -L 0x1000 -N "rpbuf_demo" # 接收数据(e907) rpbuf_demo -s "hello" -N "rpbuf_demo" # 发送数据(e907) rpbuf_demo -N "rpbuf_demo" -d # 删除buffer 图7-8: Linux 端log 图7-9: e907 端log 7.4.3 使用 内核层接口,参考drivers/rpbuf/rpbuf_sample_sunxi.c: Linux 端使用流程: 在需要用到rpbuf 接口的驱动的设备树节点种添加一条属性:rpbuf = <&rpbuf_controller0>;, 可以创建多个controller,当面默认只有一个rpbuf_controller0; 获取controller:调用controller = rpbuf_get_controller_by_of_node(np, 0); 创建buffer:调用rpbuf_alloc_buffer(controller, name, len, ops, cbs, priv); 接收数据:收到数据时候会调用cbd->rx_cb 回调 判断状态:创建出的buffer 不一样马上可用,需要用判断状态,调用rpbuf_buffer_is_available(buffer) 发送数据: buf_va = rpbuf_buffer_va(buffer); buf_len = rpbuf_buffer_len(buffer); 直接对buf_va 地址进行写入即可 rpbuf_transmit_buffer(buffer, offset, data_len); 释放buffer:rpbuf_free_buffer(buffer); 应用层端口,具体细节可以参考package/allwinner/rpbuf/ 创建bufferfd = open(0, O_RDWR);ioctl(fd, RPBUF_CTRL_DEV_IOCTL_CREATE_BUF, &buffer->info);buf_fd = open(buf_dev_path, O_RDWR);addr = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED, buf_fd, 0);接收数据:rpbuf_receive_buffer_block(buffer, &offset, &data_len) 阻塞接收rpbuf_receive_buffer_nonblock(buffer, &offset, &data_len) 非阻塞接收发送数据:buf_va = rpbuf_buffer_va(buffer);直接对buf_va 地址进行写入即可rpbuf_transmit_buffer(buffer, offset, data_len);释放buffer:close(buf_fd);ioctl(fd, RPBUF_CTRL_DEV_IOCTL_DESTROY_BUF, &buffer->info);close(fd); e907 端接口,可以参考ekernel/subsys/aw/rpbuf/rpbuf_demo/rpbuf_demo.c e907 端使用流程: 获取controller:调用controller = rpbuf_get_controller_by_id(0); 代码默认提供一个controller, 这里直接使用创建buffer:调用rpbuf_alloc_buffer(controller, name, len, ops, cbs, priv);接收数据:收到数据时候会调用cbd->rx_cb 回调判断状态:创建出的buffer 不一样马上可用,需要用判断状态,调用rpbuf_buffer_is_available (buffer)发送数据:buf_va = rpbuf_buffer_va(buffer);buf_len = rpbuf_buffer_len(buffer);直接对buf_va 地址进行写入即可rpbuf_transmit_buffer(buffer, offset, data_len);释放buffer:rpbuf_free_buffer(buffer); 7.4.4 Note 关于controller:代码默认已经提供了一个基于rpmsg 实现的controller0 了,正常情况下 直接使用改controller 即可关于rpbuf_alloc_buffer 的ops 参数:controller0 已经基于ion 实现了内存分配函数。如 无必要,使用controller 的内存分配函数即可,即创建buffer 时,ops 参数置NULL。关于互斥:由于通信双方都能拿到的buffer 的地址,难以在驱动实现互斥,所以需要在具体 应用上自行保证互斥。 8 其他 8.1 rpmsg 需知 端点是rpmsg 通信的基础;每个端点都有自己的src 和dst 地址,范围(1 - 1023,除了0x35) rpmsg 每次发送数据最大为512 -16 字节;(数据块大小为512,头部占用16 字节) rpmsg 使用name server 机制,当E907 创建的端点名,和linux 注册的rpmsg 驱动名一样的时候,rpmsg bus 总线会调用其probe 接口。所以如果需要 Linux 端主动发起创建端点并通知e907,则需要借助上面提到的rpmsg_ctrl 驱动。 rpmsg 是串行调用回调的,故建议rpmsg_driver 的回调中不要调用耗时长的函数,避免影响其他rpmsg 驱动的运行 8.2 rpbuf 简介 rpbuf 全志基于rpmsg 开发的一套通信机制,它主要解决rpmsg 不适合传输大数据量的问题。 其实现原理是使用rpmsg 传输数据的地址,而不是数据的本身,避免了数据的多次拷贝以及每次 传输不能大于496 字节的限制。 rpbuf 中使用名字和长度来唯一标识一个buffer,故不能创建相同名字的buffer。 rpbuf 中的buffer 有3 个状态: remote_dummy_buffers:该buffer 远端已创建,本地未创建local_dummy_buffers:该buffer 本地已创建,远端未创建buffers:远端、本地已创建,此时buffer 才可用 8.3 修改e907 地址 目前在perf1 板子上,给e907 预留的内存为:0x48000000 开始的4M 空间 如果需要修改E907 固件的运行地址和大小,可按如下步骤进行修改: 8.3.1 修改设备树(Linux) cconfigsvim ../board.dts# 找到e907_dram项,修改成想要的地址,例如这里向修改成0x49000000e907_dram: riscv_memserve reg = <0x0 0x49000000 0x0 0x00400000>;no-map;;# 重新编译内核mkernel 8.3.2 修改配置项(melis) mmelis menuconfig# 如下图进行修改;e907没有mmu,故第一项和第二项相等# 将第一项和第二项改成0x49000000# 第三项为大小,可按需修改 图8-1: e907 dram config 8.3.3 修改链接脚本(melis) cmelisvim source/projects/v853-e907-ver1-board/kernel.lds# 如下图所示,按照所需修改DRAM_SEG_KRN 项目mmelis -j16 图8-2: e907 lds config 8.4 添加新板级注意事项 当用户需要添加新的板子时,需要注意修改build/expand_melis.sh 来支持mmelis, cmelis命令。例如,用户在添加了新的板级v853_user,在melis 添加了新的板 级e907_user,则需要对build/expand_melis.sh文件进行如下修改: 图8-3: 新板级配置 8.5 melis 系统 8.5.1 常用命令 help:列出当前系统支持的所有命令p addr [len]:打印内存数据m addr value:修改内存数据top:显示当前系统各个线程CPU 占用率ps:显示当前系统各个线程状态free:查看当前系统内存信息 8.5.2 自定义命令 当用户想要在e907 控制台上执行自定义的命令时候,可以用FINSH_FUNCTION_EXPORT_ALIAS导出自定义的函数。例如: 图8-4: 添加自定义命令 图8-5: 执行自定义命令以上是关于全志 Tina Linux RISC-V E907核心开发指南支持百问网V85x系列开发板100ask-v853-pro v851s等的主要内容,如果未能解决你的问题,请参考以下文章 python如何计算程序(代码块)的运行时间? Oracle变量的定义赋值及使用 您可能还会对下面的文章感兴趣: 相关文章 浏览器打不开网址提示“ERR_CONNECTION_TIMED_OUT”错误代码的解决方法 如何安装ocx控件 VMware的虚拟机为啥ip地址老是自动变化 vbyone和EDP区别 linux/debian到底怎么重启和关机 苹果平板键盘被弄到上方去了,如何调回正常? 机器学习常用距离度量 如何查看kindle型号