【转】 使用Beaglebone Black的PRU(三)——实现高达100MHz的GPIO输出
友情提示:请先按照本系列(一)(二)的说明安装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文件如下:
- /dts-v1/;
- /plugin/;
- / {
- compatible = "ti,beaglebone", "ti,beaglebone-black";
- /* identification */
- part-number = "BB-BONE-PRU";
- version = "00A0";
- exclusive-use =
- "P8.12";
- fragment@0 {
- target = <&am33xx_pinmux>;
- __overlay__ {
- mygpio: pinmux_mygpio{
- pinctrl-single,pins = <
- 0x30 0x06
- >;
- };
- };
- };
- fragment@1 {
- target = <&ocp>;
- __overlay__ {
- test_helper: helper {
- compatible = "bone-pinmux-helper";
- pinctrl-names = "default";
- pinctrl-0 = <&mygpio>;
- status = "okay";
- };
- };
- };
- fragment@2{
- target = <&pruss>;
- __overlay__ {
- status = "okay";
- };
- };
- };
写完以后用命令
- dtc -@ -O dtb -o BB-BONE-PRU-00A0.dtbo BB-BONE-PRU-00A0.dts
生成dtbo文件,然后拷贝到 /lib/firmare目录中。
第二步:编写linux中运行的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\n");
- 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 (PRU_EVTOUT_0, PRU0_ARM_INTERRUPT);
- prussdrv_pru_disable (PRU_NUM);//Disable PRU and close memory mapping
- prussdrv_exit ();
- return(0);
- }
- gcc mytest.c -lpthread -lprussdrv -o mytest
第三步:编写在PRU中运行的汇编程序
- .origin 0
- .entrypoint START
- //Refer to this mapping in the file - \prussdrv\include\pruss_intc_mapping.h
- #define PRU0_ARM_INTERRUPT 19
- #define CONST_PRUCFG C4
- 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, 10000000
- LOOP1:
- SET r30.t14 //set P8.12
- MOV r0, 250
- DELAY1:
- SUB r0, r0, 1
- QBNE DELAY1, r0, 0
- CLR r30.t14 //clear P8.12
- MOV r0, 250
- DELAY2:
- SUB r0, r0, 1
- QBNE DELAY2, r0, 0
- SUB r1, r1, 1
- QBNE LOOP1, r1, 0
- // Send notification to Host for program completion
- MOV r31.b0, PRU0_ARM_INTERRUPT+16
- // Halt the processor
- HALT
- pasm -b prucode.p
代码中 SET r30.t14 和 CLR r30.t14 这两句分别将P8.12管脚置成高电平和低电平。在它们后面各放了一段循环延时的程序。因为PRU的主频是200MHz,每条指令执行时间是固定的1/200000000秒。因此通过恰当地设置延时循环的次数,可以精确控制高低电平的时间。比如在本代码中高低电平各自持续了250*2/200M秒(乘2是因为每次循环都有“减一”和“判断结束”两个指令),即产生了周期为200KHz的方波。经过示波器验证十分精确……
第四步:执行程序
- echo BB-BONE-PRU > $SLOTS
然后就可以运行程序了:
- ./mytest
【转】 使用Beaglebone Black的PRU(三)——实现高达100MHz的GPIO输出的更多相关文章
- 输入三个数a,b,n,输出a和b不大于n的公倍数的个数
题:输入三个数a,b,n,输出a和b不大于n的公倍数的所有个数. 这题的思想是先求得a和b的最大公约数,然后用a和b的积除以最大公约数,得到最小公倍数,再持续加上最小公倍数,直到超过n,记下n的个数. ...
- 合宙AIR105(三): 定时器, 定时器中断和PWM输出
目录 合宙AIR105(一): Keil MDK开发环境, DAP-Link 烧录和调试 合宙AIR105(二): 时钟设置和延迟函数 合宙AIR105(三): 定时器, 定时器中断和PWM输出 Ai ...
- BeagleBone Black 板第三课:Debian7.5系统安装和远程控制BBB板
BBB板第三课:Debian7.5系统安装和远程控制BBB板 由于BBB板系统是Debian 7.4.据说使用Debian系统能够实现非常多BBB板的无缝连接.能够更好的学习和控制BBB板,所以就决定 ...
- Python基础(三)—— print()格式化输出变量
先举一个简单的例子说明: name = 'Jack' answer = input('你好,%s '%(name) + '你认识 Sean 不, 输入 yes or no\n') print('Sea ...
- Python三种注释及分行换行输出
1.单行注释 以#开头,#右边的所有东西都被当成文字说明,而不是真正要执行的程序,只是起到辅助说明作用(#后需要先添加一个空格). 单行注释写到行内代码后边,或者单独一行均可. # 我是单行注释,#号 ...
- 【iCore3 双核心板】例程三十六:DAC实验——输出直流电压
实验指导书及代码包下载: http://pan.baidu.com/s/1bRVnzS iCore3 购买链接: https://item.taobao.com/item.htm?id=5242294 ...
- Appium学习实践(三)测试用例脚本以及测试报告输出
之前Appium学习实践(二)Python简单脚本以及元素的属性设置中的脚本,会有一个问题,就是在每个测试用例完成之后都会执行tearDown,然后重新setUp,这样导致脚本的执行效率偏低,而且会有 ...
- 【iCore3 双核心板_FPGA】例程二:GPIO输出实验——点亮三色LED
实验指导书及代码包下载: http://pan.baidu.com/s/1boiOJBT iCore3 购买链接: https://item.taobao.com/item.htm?id=524229 ...
- ADO.NET 快速入门(三):从存储过程获取输出参数
一些存储过程通过参数返回值.当参数在SQL表达式或者存储过程中被定义为“输出”,参数值会返回给调用者.返回值存储在 OleDbCommand 或者 SqlCommand 对象的参数集合的参数里. ...
随机推荐
- NET下RabbitMQ实践[示例篇]
在上一篇文章中,介绍了在window环境下安装erlang,rabbitmq-server,以免配置用户,权限,虚拟机等内容. 今天将会介绍如果使用rabbitmq进行简单的消息入队, ...
- UVA 11928 The Busy Dog
题意:一只狗被拴在杆子上,从起点开始按直线依次跑到给出的点最后回到起点问绕杆子几圈,逆时针为正,顺时针为负,撞到杆子输出Ouch!. 解法:用叉积判断方向,用余弦定理求出以杆子为顶点的角,加和除以2π ...
- [selenium webdriver Java]常用api
1. 获取元素文本 WebElement类的getText()方法返回元素的innerText属性.所以元素里如果有子节点一样也会被返回出来.如下所示 public class GetText { @ ...
- bzoj 3122 [Sdoi2013]随机数生成器(逆元,BSGS)
Description Input 输入含有多组数据,第一行一个正整数T,表示这个测试点内的数据组数. 接下来T行,每行有五个整数p,a,b,X1,t,表示一组数据.保证X1和t都是合法的页码. ...
- Yum本地源配置
1.mount -t auto /dev/cdrom /mnt 使用光驱 mount -t iso9660 -o loop /home/software/rhel-server-6.4-x8 ...
- 【noip2007】树网的核
题解: 首先我们要知道一个性质:如果有多条直径 这个核不论在哪条直径上 答案都是一样的 这样我们就可以随便找一条直径 在这条直径上枚举核的位置 并且dfs预处理maxlon[i] (i在直径上) 表示 ...
- [Objective-c 基础 - 2.1] 封装
A.封装内部细节,根据需求暴露方法 #import <Foundation/Foundation.h> @interface Student : NSObject { int age; } ...
- 转载ASP.net 中 OutputCache 指令各个参数的作用
使用@ OutputCache指令 使用@ OutputCache指令,能够实现对页面输出缓存的一般性需要.@ OutputCache指令在ASP.NET页或者页中包含的用户控件的头部声明.这种方式非 ...
- 三、servlet如何配置
生命周期 可以第一次请求时就实例化,也可以web容器启动时就实例化 WebServlet(loadOnStartUp=1) <loadOnStartUp.../> 直接收整型值,越小优先级 ...
- Judge
1. 循环list中的所有元素然后删除重复 public static List removeDuplicate(List list) { for ( int i = 0 ; i ...