gpio.c : 提供了GPIO初始化、输出、输入操作函数: (参考了勤为本的gpioc封装gpio接口和使用示例,不过我做了非常多的修改和浓缩,原本200多行弄成了50多行)
#include "gpio.h"
#define GPIO_GET_PORT(gpio) ((gpio) / 32)
#define GPIO_GET_PIN(gpio) ((gpio) % 32)
// gpio的工作模式--输入、输出
typedef enum
{
gpio_mode_output = 0, // 输出
gpio_mode_input = 1 // 输入
} gpio_mode_t;
// gpio高低电平值
typedef enum
{
gpio_level_low = 0, // 低电平
gpio_level_high = 1 // 高电平
} gpio_level_t;
void gpio_init(unsigned int gpio, gpio_mode_t mode)
{
volatile unsigned int *gpio_cfgx = (volatile unsigned int *)(LS1C_GPIO_CFG0 + (0x00000004) * GPIO_GET_PORT(gpio));
volatile unsigned int *gpio_enx = (volatile unsigned int *)(LS1C_GPIO_EN0 + (0x00000004) * GPIO_GET_PORT(gpio));
*gpio_cfgx |= (1 << GPIO_GET_PIN(gpio));
if (mode == gpio_mode_output)
*gpio_enx &= ~(1 << GPIO_GET_PIN(gpio));
else if (mode == gpio_mode_input)
*gpio_enx |= (1 << GPIO_GET_PIN(gpio));
}
void gpio_set(unsigned int gpio, gpio_level_t level)
{
volatile unsigned int *gpio_outx = (volatile unsigned int *)(LS1C_GPIO_OUT0 + (0x00000004) * GPIO_GET_PORT(gpio));
if (level == gpio_level_high)
*gpio_outx &= ~(1 << GPIO_GET_PIN(gpio));
else if (level == gpio_level_low)
*gpio_outx |= (1 << GPIO_GET_PIN(gpio));
}
gpio_level_t gpio_get(unsigned int gpio)
{
volatile unsigned int *gpio_inx = (volatile unsigned int *)(LS1C_GPIO_IN0 + (0x00000004) * GPIO_GET_PORT(gpio));
if ((*gpio_inx >> (GPIO_GET_PIN(gpio)) & 1) == 1)
return gpio_level_high;
else if ((*gpio_inx >> (GPIO_GET_PIN(gpio)) & 1) == 1)
return gpio_level_low;
}
gpio.h : gpio.c头文件
#ifndef __GPIO_H__
#define __GPIO_H__
#define LS1C_GPIO_CFG0 (0xbfd010c0)
#define LS1C_GPIO_EN0 (0xbfd010d0)
#define LS1C_GPIO_IN0 (0xbfd010e0)
#define LS1C_GPIO_OUT0 (0xbfd010f0)
#define LS1C_GPIO_CFG1 (0xbfd010c4)
#define LS1C_GPIO_EN1 (0xbfd010d4)
#define LS1C_GPIO_IN1 (0xbfd010e4)
#define LS1C_GPIO_OUT1 (0xbfd010f4)
#define LS1C_GPIO_CFG2 (0xbfd010c8)
#define LS1C_GPIO_EN2 (0xbfd010d8)
#define LS1C_GPIO_IN2 (0xbfd010e8)
#define LS1C_GPIO_OUT2 (0xbfd010f8)
#define LS1C_GPIO_CFG3 (0xbfd010cc)
#define LS1C_GPIO_EN3 (0xbfd010dc)
#define LS1C_GPIO_IN3 (0xbfd010ec)
#define LS1C_GPIO_OUT3 (0xbfd010fc)
#endif
驱动函数 :点灯 P51 GPIO 每隔300ms 点亮熄灭 ( 驱动随便写的,只是方便自己测试用的 )
#include "driver.h"
#define DRIVER_MAJOR 233 /* 主设备号 */
#define DRIVER_NAME "chrdevbase" /* 设备名 */
static int driver_open(struct inode *inode, struct file *filp)
{
return 0;
}
static ssize_t driver_read(struct file *filp, char __user *buf, size_t cnt, loff_t *offt)
{
return 0;
}
static ssize_t driver_write(struct file *filp, const char __user *buf, size_t cnt, loff_t *offt)
{
return 0;
}
static int driver_release(struct inode *inode, struct file *filp)
{
return 0;
}
static struct file_operations test_fops = {
.owner = THIS_MODULE,
.open = driver_open,
.read = driver_read,
.write = driver_write,
.release = driver_release,
};
static int __init driver_module_init(void)
{
int ret = 0;
printk("<1> driver_module_init\n");
gpio_init(51, gpio_mode_output);
if (DRIVER_MAJOR > 0)
{
/* 静态注册字符设备驱动 */
ret = register_chrdev(DRIVER_MAJOR, DRIVER_NAME, &test_fops);
if (ret < 0)
{
return 0;
}
}
else
{
}
while (1)
{
gpio_set(51, 1);
msleep(300);
gpio_set(51, 0);
msleep(300);
}
return 0;
}
static void __exit driver_module_exit(void)
{
printk("<1> driver_module_exit\n");
/* 注销字符设备驱动 */
unregister_chrdev(DRIVER_MAJOR, DRIVER_NAME);
}
module_init(driver_module_init);
module_exit(driver_module_exit);
MODULE_AUTHOR("ZTD"); // 描述模块的作者
MODULE_LICENSE("GPL"); // 描述模块的许可证
MODULE_DESCRIPTION("driver module test"); // 描述模块的介绍信息
MODULE_ALIAS("alias xxx"); // 描述模块的别名信息
注意点:
( 1 )龙芯GPIO操作不需要配置PAD[127:0]复用配置寄存器和时钟频率配置寄存器,只需要上图中的四个GPIO寄存器