每个PRU都连接着一个OCP主口,它允许访问linux主机设备对应的内存地址。此功能允许PRU控制通用GPIO的输入和输出状态。PRU可访问Linux主机内存,但是访问速度要慢上好几倍,因为内存访问需要路由到外部的PRU-ICSS,在通过PRU-ICSS接口从/OCP从口接收返回结果。
首先测试用 PRU 通过/OCP主口访问 通用 GPIO 口。
设备树覆盖层如下,用示波器连接beaglebone的GND和P9_11,板子开机发现示波器一直显示的是高电平,如下操作将环境变量写入文件,这样就不用每次开机手动加载环境变量了。
对于通用GPIO口,模式和地址如下查询手册即可。对于增强型GPIO口,0x05表示输出模式,0x26表示输入模式。
__overlay__ {
gpio_pins: pinmux_gpio_pins { // The GPIO pins
pinctrl-single,pins = <
0x070 0x07 // P9_11 MODE7 | OUTPUT | GPIO pull-down
0x074 0x27 // P9_13 MODE7 | INPUT | GPIO pull-down
>;
};
pru_pru_pins: pinmux_pru_pru_pins { // The PRU pin modes
pinctrl-single,pins = <
0x1a4 0x05 // P9_27 pr1_pru0_pru_r30_5, MODE5 | OUTPUT | PRU
0x19c 0x26 // P9_28 pr1_pru0_pru_r31_3, MODE6 | INPUT | PRU
>;
};
};
$ vim ./bashrc
export SLOTS=/sys/devices/bone_capemgr.9/slots
export PINS=/sys/kernel/debug/pinctrl/44e10800.pinmux/pins
$ sudo sh -c "echo EBB-PRU-Example > $SLOTS"
加载好设备树之后,发现示波器上的高电平变成了低电平,说明设备树加载成功。
使用如下主程序测试motor_direction.cpp:
#include <stdio.h>
#include <sys/time.h>
#include <sys/poll.h>
#include <sys/epoll.h>
#include <iostream>
#include "prussdrv.h"
#include <pruss_intc_mapping.h>
#define DELAY_US 4000 // Max. value = 21474836 us
#define TICKS ((DELAY_US / 5) * 1000)
#define PRU_NUM 0
using namespace std;
int main(void)
{
if(getuid()!=0){
printf("必须使用root权限,否则会提示段错误\n");
}
tpruss_intc_initdata pruss_intc_initdata = PRUSS_INTC_INITDATA;
prussdrv_init();
prussdrv_open(PRU_EVTOUT_0);
prussdrv_pruintc_init( &pruss_intc_initdata);
// PRU开始时间
struct timeval start;
gettimeofday(&start,NULL);
prussdrv_exec_program (PRU_NUM, "./motor_direction.bin");
prussdrv_pru_wait_event (PRU_EVTOUT_0);
// pru结束时间
struct timeval end;
gettimeofday(&end,NULL);
double diff;
diff = end.tv_sec -start.tv_sec + (end.tv_usec - start.tv_usec)*0.000001;
cout<< "EBB PRU程序已完成,历时约 "<< diff << "秒!" << endl;
// prussdrv_pru_clear_event (PRU_EVTOUT_0, PRU0_ARM_INTERRUPT);
prussdrv_pru_disable(PRU_NUM);
prussdrv_exit ();
return 0;
}
PRU程序如下motor_direction.p:
// 选择gpio0_30和gpio0_31 对应 p9_11(OUT)和p9_13(IN)
.origin 0
.entrypoint ENABLEOCP
#define DELAY_US 4000 // Max. value = 21474836 us
#define TICKS ((DELAY_US / 5) * 1000)
#define PRU0_R31_VEC_VALID 32
#define PRU_EVTOUT_0 3
#define GPIO0 0x44e07000 // GPIO 0 See the AM335x TRM,Table 2.2 Peripheral Map
#define GPIO1 0x4804c000 // GPIO 1
#define GPIO2 0x481ac000 // GPIO 2
#define GPIO3 0x481ae000 // GPIO 3
#define GPIO_CLEARDATA 0x190 // for clearing the GPIO registers, See the TRM section 25.4.1
#define GPIO_DATAOUT 0x194 // for setting the GPIO registers
#define GPIO_DATAIN 0x1