您好!
我在 AM3358上、特别是在 BeagleBone Black 上运行 PRU 时遇到一些问题。 我从 https://github.com/beagleboard/am335x_pru_package 运行了"PRU_memAccess_DDR_PRUsharedRAM"示例 、没有问题。 然后、在开发在 PRU 上运行的我自己的代码的过程中、PRU 在尝试写入 DDR 存储器时开始挂起。 请注意、OCP 主端口已启用。
然后、我发现有时、重启后、PRU 在运行其他已知不挂起的代码时仍会挂起!
附件是我的代码。 我已经注释了一些应该写入 DDR 存储器进行测试的器件。 请告诉我如何读写 PRU 中的 DDR 存储器、而不会使其挂起!
谢谢、
William Kalfus
ddrmemtest.c:
#include
#include "prussdrv.h"
#include
#include
#include
#include
#define PRU_CODE_FILE "additiontest.bin"
int main() {
int mem_fd = open ("/dev/mem、 O_RDWR);
if (mem_fd < 0) {
printf (" 打开 /dev/mem 失败");
返回 -1;
}
void* DDR_mem = mmap (0、0xFFFFFFF、PROT_WRITE|PROT_READ、MAP_SHARED、mem_FD、 0x8000000);
if (DDR_mem = NULL) {
printf (" 映射 设备失败");
Close (mem_fd);
返回 -1;
}
void* DDR = DDR_mem;
// 获取 要存储的值
printf ("输入 要存储的值: ");
scanf("%d", (unsigned int*)DDR);
// 初始化 PRU
printf ("正在初始 化 PRU...\n");
prussdrv_init();
int ret = prussdrv_open (PRU_EVTOUT_0);
if (ret) {
printf ("打开 PRU 失败\n");
回程;
}
// 配置 PRU 中断
tpruss_intc_initdata pruss_intc_initdata = PRUSS_INTC_INITDATA;
prussdrv_pruintc_init (&pruss_intc_initdata);
// 将 addend1 和 addend2的地址写入 PRU 数据 存储器
printf ("将 数据加载 到 PRU 存储器...\n");
void* pru0_datamem;
prussdrv_map_prumem (PRUSS0_PRU0_DataRAM、 &pru0_datamem);
unsigned int* pru0_datamem_int = (unsigned int*) pru0_datamem;
printf ("地址 %d\n"、 (unsigned int) DDR);
pru0_datamem_int[0] = (unsigned int) DDR;
// 现在 加载 并 运行 PRU 代码
printf ("加载 PRU 代码 并 执行...\n");
prussdrv_exec_program (0 /* PRU0 */、 PRU_code_file);
// 等待 PRU 完成 代码执行
printf ("正在等待 PRU 停止...\n");
prussdrv_PRU_WAIT_EVENT (PRU_EVTOUT_0);
printf ("PRU 暂停。\n");
prussdrv_PRU_CLEAR_EVENT (PRU_EVTOUT_0、 PRU0_ARM_INTERRUPT);
void* sharedMem;
prussdrv_map_prumem (PRUSS0_SHARGE_DataRAM、 &sharedMem);
unsigned int* sharedMem_int = (unsigned int*) sharedMem;
// PRU 将将值存储在0x0001_2000处,即0x2000字节
// 存储到 共享 存储器中、 因此 它的索引 为0x2000/4 = 0x800
unsigned int res = sharedMem_int[0x800];
// 读取 结果
printf ("结果: %d\n"、 res);
// 关闭 PRU
prussdrv_PRU_disable (0);
prussdrv_exit();
munmap (DDR_mem、 0x0FFFFFFF);
Close (mem_fd);
返回 0;
}
ddrmemtest.p:
// PRU 加法 测试
// addend 1的地址存储在数据 RAM 地址0中,addend 2存储在1中,
// 结果 为 3
.origin 0
.entrypoint 加法
#define CONST_PRUCFG C4
#define CTPPR_0 0x22028
#define CTPPR_1 0x2202C
添加:
// 启用 OCP 主 端口
LBCO R0、 CONST_PRUCFG、 4、 4
CLR R0、 R0、 4
SBCO R0、 CONST_PRUCFG、 4、 4
// 将 C28设置 为0x0001_2000
MOV R0 、0x00000120
MOV R1、 CTPPR_0
SBBO R0、 R1、 0、 4
MOV R0 、0x00100000
MOV R1、 CTPPR_1
SBBO R0、 R1、 0、 4
LDI R0 、0x7
//SBCO R0、 C31、0、 4
// 将 值 地址读 入 R0
//LBCO R0、 C24、 0、 4
// 现在 将 值 本身加载 到 R1中
//LBBO R1、 R0、 0、 4
// 将结果存储 在 共享 存储器中
SBCO R1、 C28、 0、 4
// 完成, 通知 主机 并 停止
// 记住: R31 是特殊 的- 写入 它 会生成 中断
// 要解码 写入的值:
// 主机 正在等待 PRU_EVTOUT0
//在 pruss_intc_mapping.h (第101行)中,PRU_EVTOUT0被映射到 CHANNEL2
//在同一文件(第100行)中,CHANNEL2被映射到 PRU0_ARM_INTERRUPT
//在同一个文件(第52行) 中,我们可以看到这是数字19
//查看 PRU 参考指南(第7节),我们可以看到 int 19
// 对应 于 pr1_PRU_mst_intr[3]_intr_req
//根据 TRM 的第4.4.1.2.2节,触发中断位
// R31的5必须为1,位3:0必须为值3 (因为
// 中断方括号中的值)
// 因此、 我们 写入 R31 (1 << 5) + 3 = 35
MOV R31.b0、 35
停止