如何解决用于与 Beaglebone Black 上的 GPIO 模块接口的 Linux 内核模块
我在 Beaglebone Black 上编写了一个 Linux 内核模块,以使用其寄存器与 GPIO 模块接口。一个按钮与GPIO20相连,一个LED通过一个200欧姆的晶体管与GPIO30相连。我希望当 insmod
内核模块按下按钮,LED 亮起,然后再次按下 LED 熄灭,依此类推。以下是我的内核模块代码。我的问题是按下按钮时,LED 不切换状态。
#include <linux/module.h> /* Needed by all modules */
#include <linux/kernel.h> /* Needed for KERN_INFO */
#include <linux/io.h>
#include <linux/delay.h>
#define GPIO_ADDR_BASE 0X44E07000
#define ADDR_SIZE 0X1000
#define GPIO_SETDATAOUT_OFFSET 0X194
#define GPIO_CLEARDATAOUT_OFFSET 0X190
#define GPIO_OE_OFFSET 0X134
#define GPIO_DATAIN_OFFSET 0X138
// enable IRQ
#define GPIO_IRQSTATUS_RAW_0_OFFSET 0X24
// enable interrupt
#define GPIO_IRQSTATUS_SET_0_OFFSET 0X34
// define intterupt type
#define GPIO_RISINGDETECT_OFFSET 0X148
// enable debounce feature
#define GPIO_DEBOUNCENABLE_OFFSET 0X150
// set debounce time
#define GPIO_DEBOUNCINGTIME_OFFSET 0X154
#define LED_VALUE_0 ~(1 << 30)
#define LED_VALUE_1 (1 << 30)
#define BUTTON_VALUE_0 ~(1 << 20)
#define BUTTON_VALUE_1 (1 << 20)
void __iomem *base_addr;
int init_module(void)
{
uint32_t reg_data = 0;
printk(KERN_EMERG "Hello");
base_addr = ioremap(GPIO_ADDR_BASE,ADDR_SIZE);
// CONfig for LED
/* write 0 to GPIO Pin 30 mean config this pin is output */
writel_relaxed(LED_VALUE_0,base_addr + GPIO_OE_OFFSET);
// at insert module time,led off
writel_relaxed(LED_VALUE_1,base_addr + GPIO_CLEARDATAOUT_OFFSET);
// CONfig for BUTTON
// config button pin is GPIO input
writel_relaxed(BUTTON_VALUE_1,base_addr + GPIO_OE_OFFSET);
// active IRQ
writel_relaxed(0x1,base_addr + GPIO_IRQSTATUS_RAW_0_OFFSET);
// enable interrupt
writel_relaxed(0x1,base_addr + GPIO_IRQSTATUS_SET_0_OFFSET);
// enable rising interrupt
writel_relaxed(0x1,base_addr + GPIO_RISINGDETECT_OFFSET);
// enable debounce feature
writel_relaxed(1 << 20,base_addr + GPIO_DEBOUNCENABLE_OFFSET);
// set debounce time
writel_relaxed(0xFF,base_addr + GPIO_DEBOUNCINGTIME_OFFSET);
while (1) {
reg_data = readl_relaxed(base_addr + GPIO_DATAIN_OFFSET);
if (reg_data == 1)
{
writel_relaxed(LED_VALUE_1,base_addr + GPIO_SETDATAOUT_OFFSET);
mdelay(1000);
}
}
return 0;
}
void cleanup_module(void)
{
printk(KERN_EMERG "Goodbye");
/* off led */
writel_relaxed(LED_VALUE_1,base_addr + GPIO_CLEARDATAOUT_OFFSET);
/* config default GPIO Pin is input
* set Pin 30 to default
*/
writel_relaxed(LED_VALUE_1,base_addr + GPIO_CLEARDATAOUT_OFFSET);
}
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Phu Luu An");
MODULE_DESCRIPTION("Hello world kernel module");
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。