友情提示:请先按照本系列(一)(二)的说明安装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. jquery放大镜

    效果体验:http://runjs.cn/detail/dvygyp5t demo下载 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Tra ...

  2. CF GYM 100703I Endeavor for perfection

    题意:有n个学习领域,每个领域有m个课程,学习第i个领域的第j个课程可以获得sij个技能点,在每个领域中选择一个课程,要求获得的n个技能点的最大值减最小值最小,输出符合要求的策略. 解法:尺取法.将课 ...

  3. HTML DOM 教程Part1

    2015-05-08 摘自W3C School HTML DOM HTML DOM 定义了访问和操作HTML文档的标准方法.HTML DOM 把 HTML 文档呈现为带有元素.属性和文本的树结构(节点 ...

  4. [Bhatia.Matrix Analysis.Solutions to Exercises and Problems]ExI.5.3

    Let $\scrM$ be a $p$-dimensional subspace of $\scrH$ and $\scrN$ its orthogonal complement. Choosing ...

  5. MSP430F5438点亮led

    今天只是想点亮一个led灯,因为没有视频,搞得很多的东西都是自己摸,下午本来讲和咨询店家,TMD说好给一点技术支持,结果一点也不给,我真想草泥马了,其实代码早就写出来了,只是哥哥不知道这款开发板还有接 ...

  6. C#操作Json(转)

    原文:http://wenku.baidu.com/link?url=3dlqKdF26ZdQIAcX9jvP2ZYEtl3J0sKOV8XuHQI0Rz4SjB9S46nqmGiMXUVQa_1Pm ...

  7. HTTP协议 概述

    本文主要说明一些 Http 相关的基本概念和基本知识,主要针对像我一样的初学者,知识主要来自于<Http 权威指南> 除了分享这些基本知识之外,笔者也是为将来找工作复习之用.(协议就是协议 ...

  8. C++ 虚函数表与内存模型

    1.虚函数 虚函数是c++实现多态的有力武器,声明虚函数只需在函数前加上virtual关键字,虚函数的定义不用加virtual关键字. 2.虚函数要点 (1) 静态成员函数不能声明为虚函数 可以这么理 ...

  9. android NDK 实用学习(四)-类缓存

    1,为什么需要类缓存: 答:由于频繁的查找类及类成员变量需要很大的时间与空间开销,可参考如下文章: http://www.ibm.com/developerworks/cn/java/j-jni/ h ...

  10. HDFS体系结构:(Distributed File System)

    分布式系统的大概图 服务器越来越多,客户端对服务器的管理就会越来越复杂,客户端如果是我们用户,就要去记住大量的ip. 对用户而言访问透明的就是分布式文件系统. 分布式文件系统最大的特点:数据存储在多台 ...