AM335x的PRUSSv2简介与使用

2019-07-15 15:38发布

AM335x的PRUSSv2简介与使用

PRUSSv2= Programmable Real-time Unit Sub-System = PRU-ICSS = PRU Industrial Communication Sub-System = 上一代PRUSSv2进化版
这是一个AM335x等芯片上自带的,独立于ARM CPU运行的子系统。其时钟频率为200MHz,可以直接控制特定的IO口,可以达到非常高的实时性要求。一般两种情况需要用到它:一是linux系统的实时性不满足要求的时候;二是芯片的功能模块不够用的时候(比如你想要10UART,但芯片上只有6个,那你可以用它再创造4个)。
几个可能的应用场合:高速ADC摄像机接口显示屏接口音频处理电机反馈控制
从某种意义上说,有了它,我们就有了一个片上CPLDFPGA,只不过PRU编程不是用VDHL语言,而是用专门的汇编语言。它的汇编语句都是在一个时钟周期内执行完的,没有流水线之类可能扰乱程序时序的因素,这使得程序的可预测性大大提高。
AM335x芯片上带有两个PRU
配置BBB,安装PRU assembler和示例程序
[plain]root@beaglebone:~/tmp# git clone git://github.com/beagleboard/am335x_pru_package.gitCloning into 'am335x_pru_package'......root@beaglebone:~/tmp# cd am335x_pru_package/pru_sw/app_loader/interfaceroot@beaglebone:~/tmp/am335x_pru_package/pru_sw/app_loader/interface# make CROSS_COMPILE="" #无需交叉编译root@beaglebone:~/tmp/am335x_pru_package/pru_sw/app_loader/interface# cd ../../utils/pasm_sourceroot@beaglebone:~/tmp/am335x_pru_package/pru_sw/utils/pasm_source# ./linuxbuildroot@beaglebone:~/tmp/am335x_pru_package/pru_sw/utils/pasm_source# cd ../../example_appsroot@beaglebone:~/tmp# git clone git://github.com/beagleboard/am335x_pru_package.gitCloning into 'am335x_pru_package'......root@beaglebone:~/tmp# cd am335x_pru_package/pru_sw/app_loader/interfaceroot@beaglebone:~/tmp/am335x_pru_package/pru_sw/app_loader/interface# make CROSS_COMPILE="" #无需交叉编译root@beaglebone:~/tmp/am335x_pru_package/pru_sw/app_loader/interface# cd ../../utils/pasm_sourceroot@beaglebone:~/tmp/am335x_pru_package/pru_sw/utils/pasm_source# ./linuxbuildroot@beaglebone:~/tmp/am335x_pru_package/pru_sw/utils/pasm_source# cd ../../example_apps编辑一下example_apps目录中的Makefile,把 PASM?=../utils/pasm_2 改成 PASM?=../utils/pasm_2.arm
然后重启。至此,BBB也已经配置好了。重启后我们用自带的example_apps测试一下[plain]root@beaglebone:~#cd tmp/am335x_pru_package/pru_sw/example_apps/binroot@beaglebone:~/tmp/am335x_pru_package/pru_sw/example_apps/bin# modprobe uio_pruss #每次重启都要运行这句话root@beaglebone:~/tmp/am335x_pru_package/pru_sw/example_apps/bin# ./PRU_memAccessPRUDataRamINFO: Starting PRU_memAccessPRUDataRam example.AM33XXINFO: Initializing example.INFO: Executing example.File ./PRU_memAccessPRUDataRam.bin open passedINFO: Waiting for HALT command.INFO: PRU completed transfer.INFO: Example executed succesfully.
测试成功。本文最开始的git文件建议在电脑上也clone一份,里面有几个关于PRUpdf文档可能需要经常查看。
现在,已经安装好了am335x_pru_package,本文将用它来编写、编译一个最简单的PRU程序——闪烁BBB上的led灯。
大体来说每个PRU程序都包括两部分:ARM核的Linux系统中运行的C语言程序PRU中运行的汇编程序(编译成.bin文件)其中c语言程序有两个作用:将汇编程序传到PRU中;与PRU程序互相传递数据和互动。汇编程序源文件包括.p.hp两种后缀的文件,最后编译成.bin文件被传到PRU执行。.hp文件类似于c语言的.h头文件,可以在.p文件中被include,它不是必须的,本例为了简单起见也不用.hp文件。OK,我们开始做吧!
Step by step步骤
首先新建两个文件,内容分别如下:[cpp]//mytest.c  #include <stdio.h>  #include <prussdrv.h>  #include <pruss_intc_mapping.h>  
#define PRU_NUM 0  
int main (void){unsigned int ret;tpruss_intc_initdata pruss_intc_initdata = PRUSS_INTC_INITDATA;
prussdrv_init ();//Initialize the PRU  if (prussdrv_open(PRU_EVTOUT_0))//Open PRU Interrupt  {printf("prussdrv_open open failed ");return (-1);}prussdrv_pruintc_init(&pruss_intc_initdata);prussdrv_exec_program (PRU_NUM, "./prucode.bin");//Execute example on PRU  prussdrv_pru_wait_event (PRU_EVTOUT_0);//Waiting for this instruction: MOV r31.b0, PRU0_ARM_INTERRUPT+16  prussdrv_pru_clear_event (PRU0_ARM_INTERRUPT);prussdrv_pru_disable (PRU_NUM);//Disable PRU and close memory mapping  prussdrv_exit ();
return(0);}//mytest.c#include <stdio.h>#include <prussdrv.h>#include <pruss_intc_mapping.h>
#define PRU_NUM 0
int main (void){    unsigned int ret;    tpruss_intc_initdata pruss_intc_initdata = PRUSS_INTC_INITDATA;       prussdrv_init ();//Initialize the PRU    if (prussdrv_open(PRU_EVTOUT_0))//Open PRU Interrupt    {        printf("prussdrv_open open failed ");        return (-1);    }    prussdrv_pruintc_init(&pruss_intc_initdata);    prussdrv_exec_program (PRU_NUM, "./prucode.bin");//Execute example on PRU    prussdrv_pru_wait_event (PRU_EVTOUT_0);//Waiting for this instruction: MOV r31.b0, PRU0_ARM_INTERRUPT+16    prussdrv_pru_clear_event (PRU0_ARM_INTERRUPT);    prussdrv_pru_disable (PRU_NUM);//Disable PRU and close memory mapping    prussdrv_exit ();
    return(0);}

[cpp]//prucode.p  .origin 0.entrypoint START
//Refer to this mapping in the file - prussdrvincludepruss_intc_mapping.h  #define PRU0_ARM_INTERRUPT 19  #define CONST_PRUCFG C4  
//Refer to AM335X Technical Reference Manual & BBB SRM  #define GPIO1 0x4804c000  #define GPIO_CLEARDATAOUT 0x190  #define GPIO_SETDATAOUT 0x194  
START:// Enable OCP master port  LBCO r0, CONST_PRUCFG, 4, 4CLR r0, r0, 4 // Clear SYSCFG[STANDBY_INIT] to enable OCP master port  SBCO r0, CONST_PRUCFG, 4, 4
MOV r1, 3 // loop 3 times  LOOP0:MOV r2, 1<<22MOV r3, GPIO1 | GPIO_SETDATAOUTSBBO r2, r3, 0, 4
MOV r0, 100000000DEL1:SUB r0, r0, 1QBNE DEL1, r0, 0
MOV r2, 1<<22MOV r3, GPIO1 | GPIO_CLEARDATAOUTSBBO r2, r3, 0, 4
MOV r0, 100000000DEL2:SUB r0, r0, 1QBNE DEL2, r0, 0
SUB r1, r1, 1QBNE LOOP0, r1, 0
// Send notification to Host for program completion  MOV r31.b0, PRU0_ARM_INTERRUPT+16
// Halt the processor  HALT//prucode.p.origin 0.entrypoint START
//Refer to this mapping in the file - prussdrvincludepruss_intc_mapping.h#define PRU0_ARM_INTERRUPT      19#define CONST_PRUCFG            C4
//Refer to AM335X Technical Reference Manual & BBB SRM#define GPIO1 0x4804c000#define GPIO_CLEARDATAOUT 0x190#define GPIO_SETDATAOUT 0x194
START:    // Enable OCP master port    LBCO      r0, CONST_PRUCFG, 4, 4    CLR       r0, r0, 4         // Clear SYSCFG[STANDBY_INIT] to enable OCP master port    SBCO      r0, CONST_PRUCFG, 4, 4
    MOV r1, 3 // loop 3 timesLOOP0:    MOV r2, 1<<22    MOV r3, GPIO1 | GPIO_SETDATAOUT    SBBO r2, r3, 0, 4
    MOV r0, 100000000DEL1:    SUB r0, r0, 1    QBNE DEL1, r0, 0
    MOV r2, 1<<22    MOV r3, GPIO1 | GPIO_CLEARDATAOUT    SBBO r2, r3, 0, 4
    MOV r0, 100000000DEL2:    SUB r0, r0, 1    QBNE DEL2, r0, 0
    SUB r1, r1, 1    QBNE LOOP0, r1, 0
    // Send notification to Host for program completion    MOV       r31.b0, PRU0_ARM_INTERRUPT+16
    // Halt the processor    HALT


0条回答

一周热门 更多>