最近在97X上要做高频的数据采集,用的是qt,由于刚开始太清楚linux内核的任务调度机制,
也是本着偷懒的原则就在qt程序里直接用system执行shell命令,
结果用示波器测试发现,单单是gpio的一次拉高置低的时间就耗去了10ms,
龟龟,对于后面用到的ad那结果可想,这个懒还是偷不得的啊。
于是就用了mmap和fwrite测了一下,mmap操作一个io拉高拉低,是200纳秒,fwrite是400纳秒,
测试代码如下,虽然网上很多例子,但还是贴出来,以方便自己以后查阅,同时也是想linux小白进军的一步
mapp_gpio.c:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#define GPIO_BASE (0xB8003000)
#define MAP_SIZE 0x32
static int dev_fd;
int main(void){
char dev_name[] = "/dev/mem";
dev_fd = open(dev_name,O_RDWR);
if(dev_fd < 0){
printf("open %s is error\n",dev_name);
return -1;
}
printf("1\n");
unsigned char *gpio_map_base = (unsigned char *)mmap(NULL,MAP_SIZE,PROT_READ|PROT_WRITE,MAP_SHARED,dev_fd,GPIO_BASE);
printf("2\n");
*(volatile unsigned int *)(gpio_map_base + 0x0100) |= (0x00000008);
while(1){
*(volatile unsigned int *)(gpio_map_base + 0x0104) |= (0x00000008);
*(volatile unsigned int *)(gpio_map_base + 0x0104) &= (~0x00000008);
}
printf("3\n");
if (dev_fd)
close(dev_fd);
munmap(gpio_map_base,MAP_SIZE);
return 0;
}
对于实时进程,Linux采用了两种调度策略,即FIFO(先来先服务调度)和RR(时间片轮转调度)。
因为实时进程具有一定程度的紧迫性,所以衡量一个 实时进程是否应该运行,Linux采用了一个比较固定的标准。
实时进程的counter只是用来表示该进程的剩余时间片,并不作为衡量它是否值得运行的标 准。
实时进程的counter只是用来表示该进程的剩余时间片,并不作为衡量它是否值得运行的标准,
这和普通进程是有区别的。上面已经看到,每个进程有两 个优先级(动态优先级和实时优先级),
实时优先级就是用来衡量实时进程是否值得运行的。(本段摘抄与百度)
fopen_gpio.c
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>FILE *fp;
char str[256];
int set_io_hight(void){
char buffer[10];
sprintf(str,"/sys/class/gpio/gpio%d/value",131);
strcpy(buffer,"1");
if ((fp = fopen(str, "rb+")) == NULL) {
printf("Cannot open value file.\n");
}
fwrite(buffer,sizeof(char),sizeof(buffer)-1,fp);
fclose(fp);
return 1;
}
int set_io_low(void){
char buffer[10];
sprintf(str,"/sys/class/gpio/gpio%d/value",131);
if ((fp = fopen(str, "rb+")) == NULL) {
printf("Cannot open value file.\n");
}
strcpy(buffer,"0");
fwrite(buffer,sizeof(char),sizeof(buffer)-1,fp);
fclose(fp);
return 1;
}int main(void)
{
int num=0x47;
if ((fp = fopen("/sys/class/gpio/export", "w")) == NULL) {
printf("Cannot open export file.\n");
exit(1);
}
num = 131;
fprintf(fp, "%d", num);
printf("num = %d\n",num);
fclose(fp);
// linux equivalent code "echo out > direction" to set the port as an input
sprintf(str,"/sys/class/gpio/gpio%d/direction",num);
if ((fp = fopen(str, "rb+")) == NULL) {
printf("Cannot open direction file.\n");
exit(1);
}
fprintf(fp, "out");
fclose(fp);
while(1){
set_io_hight();
set_io_low();
}
return 0;
}
以上程序是本菜鸟参照网上例程,以及新塘的数据手册编码而来
离线
Linux不是实时系统,那拉高拉低之间不会被别的进程打断吗?
离线
Linux不是实时系统,那拉高拉低之间不会被别的进程打断吗?
linux操作系统的是多任务操作系统,通过任务的调度可以实现并发执行,不知道你这个打断是内部打断还是什么的?
离线
那楼主最后NUC972 ADC采集用什么方式了?
mmap ? fwrite?
具体如何实现的?
离线
目前正在挖坑,挖完再上贴
离线
shell的确是非常耗时
离线
牛!谢谢分享!
离线
文件读写不是应该很慢吗,怎么会跟mmap就差一倍
离线