友情提示:请先按照本系列(一)(二)的说明安装PRU工具并跑通hello world再继续按本文操作。

PRU操作GPIO有很多种方式,本系列之(二)中的是一种,但最快速的方式是通过直接“写”r30和“读”r31这两个寄存器的相应位来操作对应的IO口:比如将r30的第14位置1就会把P8.12这个引脚置成高电平,很简单吧?要注意PRU中的r30寄存器对应的管脚只能输出,r31寄存器对应的管脚只能输入。

第一步:写dts文件配置引脚功能

我们知道BBB每个引脚都有很多个功能(PINMUX)。要想用上述方式操作某个引脚,必须首先配置该引脚为相应的功能。引脚的功能需要查阅自带手册的“Expansion Header P8/9 Pinout”这两个图表。配置引脚功能目前没有别的办法,只能通过编写device tree文件来实现。

还以P8.12这个引脚为例,查表得它的偏移地址是0x30。它的第6个功能pr1_pru0_pru_r30_14是我们想要的,所以我们就需要把引脚功能配置成0x06。另外BBB默认是禁用PRU的,所以还需要在dts中开启PRU。

对应的dts文件如下:

  1. /dts-v1/;
  2. /plugin/;
  3. / {
  4. compatible = "ti,beaglebone", "ti,beaglebone-black";
  5. /* identification */
  6. part-number = "BB-BONE-PRU";
  7. version = "00A0";
  8. exclusive-use =
  9. "P8.12";
  10. fragment@0 {
  11. target = <&am33xx_pinmux>;
  12. __overlay__ {
  13. mygpio: pinmux_mygpio{
  14. pinctrl-single,pins = <
  15. 0x30 0x06
  16. >;
  17. };
  18. };
  19. };
  20. fragment@1 {
  21. target = <&ocp>;
  22. __overlay__ {
  23. test_helper: helper {
  24. compatible = "bone-pinmux-helper";
  25. pinctrl-names = "default";
  26. pinctrl-0 = <&mygpio>;
  27. status = "okay";
  28. };
  29. };
  30. };
  31. fragment@2{
  32. target = <&pruss>;
  33. __overlay__ {
  34. status = "okay";
  35. };
  36. };
  37. };

写完以后用命令

  1. dtc -@ -O dtb -o BB-BONE-PRU-00A0.dtbo BB-BONE-PRU-00A0.dts

生成dtbo文件,然后拷贝到 /lib/firmare目录中。

第二步:编写linux中运行的C程序

 
跟本系列之(二)一样,就不赘述了。代码如下:
  1. #include <stdio.h>
  2. #include <prussdrv.h>
  3. #include <pruss_intc_mapping.h>
  4. #define PRU_NUM 0
  5. int main (void)
  6. {
  7. unsigned int ret;
  8. tpruss_intc_initdata pruss_intc_initdata = PRUSS_INTC_INITDATA;
  9. prussdrv_init ();//Initialize the PRU
  10. if (prussdrv_open(PRU_EVTOUT_0))//Open PRU Interrupt
  11. {
  12. printf("prussdrv_open open failed\n");
  13. return (-1);
  14. }
  15. prussdrv_pruintc_init(&pruss_intc_initdata);
  16. prussdrv_exec_program (PRU_NUM, "./prucode.bin");//Execute example on PRU
  17. prussdrv_pru_wait_event (PRU_EVTOUT_0);//Waiting for this instruction: MOV r31.b0, PRU0_ARM_INTERRUPT+16
  18. prussdrv_pru_clear_event (PRU_EVTOUT_0, PRU0_ARM_INTERRUPT);
  19. prussdrv_pru_disable (PRU_NUM);//Disable PRU and close memory mapping
  20. prussdrv_exit ();
  21. return(0);
  22. }
写完之后编译一下,按照本系列前文的方法:
  1. gcc mytest.c -lpthread -lprussdrv -o mytest

第三步:编写在PRU中运行的汇编程序

 
这个例子实际上比点亮BBB上的led还好理解:
  1. .origin 0
  2. .entrypoint START
  3. //Refer to this mapping in the file - \prussdrv\include\pruss_intc_mapping.h
  4. #define PRU0_ARM_INTERRUPT      19
  5. #define CONST_PRUCFG            C4
  6. START:
  7. // Enable OCP master port
  8. LBCO      r0, CONST_PRUCFG, 4, 4
  9. CLR       r0, r0, 4         // Clear SYSCFG[STANDBY_INIT] to enable OCP master port
  10. SBCO      r0, CONST_PRUCFG, 4, 4
  11. MOV r1, 10000000
  12. LOOP1:
  13. SET r30.t14 //set P8.12
  14. MOV r0, 250
  15. DELAY1:
  16. SUB r0, r0, 1
  17. QBNE DELAY1, r0, 0
  18. CLR r30.t14 //clear P8.12
  19. MOV r0, 250
  20. DELAY2:
  21. SUB r0, r0, 1
  22. QBNE DELAY2, r0, 0
  23. SUB r1, r1, 1
  24. QBNE LOOP1, r1, 0
  25. // Send notification to Host for program completion
  26. MOV       r31.b0, PRU0_ARM_INTERRUPT+16
  27. // Halt the processor
  28. HALT
写好后编译一下:
  1. pasm -b prucode.p
 

代码中 SET r30.t14 和 CLR r30.t14 这两句分别将P8.12管脚置成高电平和低电平。在它们后面各放了一段循环延时的程序。因为PRU的主频是200MHz,每条指令执行时间是固定的1/200000000秒。因此通过恰当地设置延时循环的次数,可以精确控制高低电平的时间。比如在本代码中高低电平各自持续了250*2/200M秒(乘2是因为每次循环都有“减一”和“判断结束”两个指令),即产生了周期为200KHz的方波。经过示波器验证十分精确……

 
 

第四步:执行程序

 
首先记得加载dtbo文件,配置引脚功能:
  1. echo BB-BONE-PRU > $SLOTS

然后就可以运行程序了:

  1. ./mytest
 
……好吧,其实这个例子显然并不会刚好输出200KHz的方波。是因为 SET r30.t14 和 CLR r30.t14 这两句以及大循环的减一和判断结束指令也占用了时间。

【转】 使用Beaglebone Black的PRU(三)——实现高达100MHz的GPIO输出的更多相关文章

  1. 输入三个数a,b,n,输出a和b不大于n的公倍数的个数

    题:输入三个数a,b,n,输出a和b不大于n的公倍数的所有个数. 这题的思想是先求得a和b的最大公约数,然后用a和b的积除以最大公约数,得到最小公倍数,再持续加上最小公倍数,直到超过n,记下n的个数. ...

  2. 合宙AIR105(三): 定时器, 定时器中断和PWM输出

    目录 合宙AIR105(一): Keil MDK开发环境, DAP-Link 烧录和调试 合宙AIR105(二): 时钟设置和延迟函数 合宙AIR105(三): 定时器, 定时器中断和PWM输出 Ai ...

  3. BeagleBone Black 板第三课:Debian7.5系统安装和远程控制BBB板

    BBB板第三课:Debian7.5系统安装和远程控制BBB板 由于BBB板系统是Debian 7.4.据说使用Debian系统能够实现非常多BBB板的无缝连接.能够更好的学习和控制BBB板,所以就决定 ...

  4. Python基础(三)—— print()格式化输出变量

    先举一个简单的例子说明: name = 'Jack' answer = input('你好,%s '%(name) + '你认识 Sean 不, 输入 yes or no\n') print('Sea ...

  5. Python三种注释及分行换行输出

    1.单行注释 以#开头,#右边的所有东西都被当成文字说明,而不是真正要执行的程序,只是起到辅助说明作用(#后需要先添加一个空格). 单行注释写到行内代码后边,或者单独一行均可. # 我是单行注释,#号 ...

  6. 【iCore3 双核心板】例程三十六:DAC实验——输出直流电压

    实验指导书及代码包下载: http://pan.baidu.com/s/1bRVnzS iCore3 购买链接: https://item.taobao.com/item.htm?id=5242294 ...

  7. Appium学习实践(三)测试用例脚本以及测试报告输出

    之前Appium学习实践(二)Python简单脚本以及元素的属性设置中的脚本,会有一个问题,就是在每个测试用例完成之后都会执行tearDown,然后重新setUp,这样导致脚本的执行效率偏低,而且会有 ...

  8. 【iCore3 双核心板_FPGA】例程二:GPIO输出实验——点亮三色LED

    实验指导书及代码包下载: http://pan.baidu.com/s/1boiOJBT iCore3 购买链接: https://item.taobao.com/item.htm?id=524229 ...

  9. ADO.NET 快速入门(三):从存储过程获取输出参数

    一些存储过程通过参数返回值.当参数在SQL表达式或者存储过程中被定义为“输出”,参数值会返回给调用者.返回值存储在 OleDbCommand 或者 SqlCommand 对象的参数集合的参数里.   ...

随机推荐

  1. Application Pool Identities

    Whether you are running your site on your own server or in the cloud, security must be at the top of ...

  2. 【JMeter】ant+jmeter生成html报告

    源博文来自于  http://my.oschina.net/hellotest/blog/517518 主要应用于接口的回归或者性能的简单查看功能.操作为先在jmeter中写好测试计划,保存为jmx文 ...

  3. 转载-KMP算法前缀数组优雅实现

    转自:http://www.cnblogs.com/10jschen/archive/2012/08/21/2648451.html 我们在一个母字符串中查找一个子字符串有很多方法.KMP是一种最常见 ...

  4. Python 连接mysql

    下面我们使用MySQLdb 实现连接mysql 数据库并进行操作. #!/usr/bin/env python # -*-coding:UTF-8-*- import MySQLdb def conn ...

  5. C#编写 "Hello,Word!" 您的第一个程序。

    教程 下面的示例展示编写C#“Hello World”程序的几种不同的方法. 示例 1 //Hello1.cs public class Hello1 { public static void Mai ...

  6. uvalive 4119 Always an Interger

    差分数列+字符串处理 题意:是让你判断一个整系数多项式的值是否一直都能被一个所给的正整数所整除. 通过对差分数列的不断求导,我们可以发现,对于任意多项式P,我们只需要判断n从1到k+1是否满足就行了, ...

  7. javascript设计模式5

    子类引用父类 function extend(subClass,superClass){ var F=function(){}; F.prototype=superClass.prototype; s ...

  8. STL——sort函数简介

    参考:http://blog.csdn.net/s030501408/article/details/5329477 0)与C标准库qsort的比较:http://bbs.csdn.net/topic ...

  9. 2.2CUDA-Memory(存储)和bank-conflict

    在CUDA基本概念介绍有简单介绍CUDA memory.这里详细介绍: 每一个线程拥有自己的私有存储器,每一个线程块拥有一块共享存储器(Shared memory):最后,grid中所有的线程都可以访 ...

  10. 洛谷 P1169 [ZJOI2007]棋盘制作

    2016-05-31 14:56:17 题目链接: 洛谷 P1169 [ZJOI2007]棋盘制作 题目大意: 给定一块矩形,求出满足棋盘式黑白间隔的最大矩形大小和最大正方形大小 解法: 神犇王知昆的 ...