龙芯技术社区
直播中

马博

13年用户 64经验值
擅长:操作系统/软件 EDA/IC/PCB设计 微处理器/微控制 数字及可编程逻辑 模拟与电源 基础元器件 操作系统/软件 EDA/IC/PCB设计 微处理器/微控制 数字及可编程逻辑 模拟与电源 基础元器件 操作系统/软件 EDA/IC/PCB设计 微处理器/微控制 数字及可编程逻辑 模拟与电源 基础元器件 操作系统/软件 EDA/IC/PCB设计 微处理器/微控制 数字及可编程逻辑 模拟与电源 基础元器件 操作系统/软件 EDA/IC/PCB设计 微处理器/微控制 数字及可编程逻辑 模拟与电源 基础元器件 操作系统/软件 EDA/IC/PCB设计 微处理器/微控制 数字及可编程逻辑 模拟与电源 基础元器件 操作系统/软件 EDA/IC/PCB设计 微处理器/微控制 数字及可编程逻辑 模拟与电源 基础元器件 操作系统/软件 EDA/IC/PCB设计 微处理器/微控制 数字及可编程逻辑 模拟与电源 基础元器件 操作系统/软件 EDA/IC/PCB设计 微处理器/微控制 数字及可编程逻辑 模拟与电源 基础元器件 操作系统/软件 EDA/IC/PCB设计 微处理器/微控制 数字及可编程逻辑 模拟
私信 关注
[2K系列]

【龙芯2K0300蜂鸟板试用】第四篇 龙芯2K0300蜂鸟板--继续点灯

今天继续点灯,当然与前两次方法(python和内核模块)不一样,今天采用类似裸机编程的方式。

一.GPIO子系统

第三种方式其实就是通过访问Linux操作系统提供的GPIO子系统驱动框架来实现的。该驱动框架把CPU的GPIO引脚导出到用户空间,然后用户通过访问/sys文件系统进行该引脚的控制访问。

GPIO子系统支持基本的输入输出功能(其实就是GPIO的定义),包括支持中断输入的检测功能。这样通过GPIO子系统便可以控制类似LED、BEEP、KEY、红外发射对管等这类硬件模块。

通常在各个linux开发板装载的默认镜像中,LED灯会使用LED子系统驱动控制(同理,KEY使用了INPUT输入子系统驱动控制),此时所分配的引脚便与某个驱动模块绑定了,该引脚功能在用户空间是无法再被修改的。即,该引脚是无法在用户空间中使用GPIO子系统进行相关操作的。当然,我们可以提前修改内核的设备树(注释掉关于LED部分代码,可以参考我之前的第一个帖子),然后编译重新下载即可,这样该引脚与特定的驱动模块解绑了,我们便可以在用户空间下使用GPIO子系统灵活配置引脚功能(比如输入、输出或中断输入检测)。

二. GPIO子系统的命令行方式点灯

根据原理图的定义,LED连接的是GPIO 85引脚。此时,可以通过将GPIO子系统导出到用户空间下进行点灯操作,操作命令如下图1所示。
1.png
2.png

图1 GPIO子系统的命令行方式点灯

  1. export文件:内核申请将该编号的GPIO导出到用户空间,如果内核没有把该GPIO用于其它功能,那么在/sys/class/gpio目录下会新增一个对应编号的gpioX目录,如上图1导出了gpio85和gpio10。
  2. unexport文件:export的相反操作,取消导出的gpio。
  3. direction文件:表示GPIO引脚的方向,in(输入)/out(输出)。
  4. value文件:表示GPIO的电平,1(高电平)/0(低电平)。

三. 继续点灯

有了上面的介绍,我们便可以在用户空间下,以文件的方式进行点灯了(区别与python和内核模块方式)。

1.工程目录如下图2所示。
5.png

图2 工程组织目录

2.头文件led.h

#ifndef _LED_H_
#define _LED_H_

#define LED_GPIO_INDEX 	"85"

extern int led_init(void);
extern int led_deinit(void);
extern int led_on(void);
extern int led_off(void);

#endif

3.源文件led.c

#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include "includes/led.h"

int led_init(void)
{
	int fd;
	fd = open("/sys/class/gpio/export", O_WRONLY);
	if(fd < 0)
		return 1 ;

	write(fd, LED_GPIO_INDEX, strlen(LED_GPIO_INDEX));
	close(fd);

	fd = open("/sys/class/gpio/gpio" LED_GPIO_INDEX "/direction", O_WRONLY);
	if(fd < 0)
		return 2;

	write(fd, "out", strlen("out"));
	close(fd);	
	
	return 0;
}

int led_deinit(void)
{
	int fd;
	fd = open("/sys/class/gpio/unexport", O_WRONLY);
	if(fd < 0)
		return 1;

	write(fd, LED_GPIO_INDEX, strlen(LED_GPIO_INDEX));
	close(fd);
	
	return 0;
}

int led_on(void)
{
	int fd;

	fd = open("/sys/class/gpio/gpio" LED_GPIO_INDEX "/value", O_WRONLY);
	if(fd < 0)
		return 1;

	write(fd, "1", 1);
	close(fd);

	return 0;
}

int led_off(void)
{
	int fd;

	fd = open("/sys/class/gpio/gpio" LED_GPIO_INDEX "/value", O_WRONLY);
	if(fd < 0)
		return 1;

	write(fd, "0", 1);
	close(fd);

	return 0;
}
  1. main.c
#include "includes/led.h"

int main(int argc, char *argv[])
{
	char buf[10];
	int res;
	printf("This is third led demo\\n");
	
	res = led_init();

	if(res){
		printf("led init error,code = %d",res);
		return 0;
	}

	while(1){
		printf("Please input the value : 0--off 1--on 2--blink q--exit\\n");
		scanf("%10s", buf);

		switch (buf[0]){
			case '0':
				led_off();
				break;

			case '1':
				led_on();
				break;
			case '2':
				for(res = 0; res < 5; res++)
				{
					led_on();
					usleep(500000);
					led_off();
					usleep(500000);
				}
				break;

			case 'q':
				led_deinit();
				printf("Exit\\n");
				return 0;

			default:
				break;
		}
	}
}
  1. makefile文件
Target = led_demo
ARCH = loongarch
CC = loongarch64-linux-gnu-gcc

build_dir = build_$(ARCH)
src_dir =  sources
inc_dir = includes .

sources = $(foreach dir,$(src_dir),$(wildcard $(dir)/*.c))
objects = $(patsubst %.c,$(build_dir)/%.o,$(notdir $(sources)))
includes = $(foreach dir,$(inc_dir),$(wildcard $(dir)/*.h))
CFLAGS = $(patsubst %, -I%, $(inc_dir))
$(build_dir)/$(Target) : $(objects)  | create_build
	$(CC) $^ -o $@ 
$(build_dir)/%.o : $(src_dir)/%.c $(includes) | create_build
	$(CC) -c $(CFLAGS) $< -o $@ 
.PHONY:clean cleanall check create_build
clean:
	rm -rf $(build_dir)
cleanall:
	rm -rf build_x86 build_arm
check:
	[url=home.php?mod=space&uid=70594]@echo[/url] $(CFLAGS)
	@echo $(CURDIR)
	@echo $(src_dir)
	@echo $(sources)
	@echo $(objects)
create_build:
	[url=home.php?mod=space&uid=2293869]@MKDIR[/url] -p $(build_dir)

四.小结

通过程序方式点灯总共有三种方式(我个人理解的命令行方式,因为没有组织成语句框架结构且不能随意操作,所以不算在内)。

  1. python方式,最简单且易操作,可以说所有的实体东西都是透明的,极大的迎合了不懂计算机的人士需求(虽然说得不好听,但是python的初衷就是让不懂计算机体系知识的人士也能玩转计算机系统,和ardunio设计的初衷类似。)。
  2. 内核模块方式:具有挑战性,难度高,但是对于理解计算机体系知识有帮助,是玩转嵌入式linux系统应用设计的必备技能。
  3. GPIO子系统方式:相对内核模块方式要简单些,因为是在用户空间内编程,所以可以像裸机编程方式一样进行操作,其他子系统也可以像上述过程一样操作。

第三种点灯

更多回帖

发帖
×
20
完善资料,
赚取积分