寄存器操作
位操作
清零
//假设为第三位
int val &= ~(1<<3);
//假设为第三、四位
int val &= ~(3<<3);
置一
int val |=(1<<3);
切换
int val ^= (1<<3);// 异或操作:0变1,1变0
获取值
int val = readl(GPIO1_DR);
val = (val>>3)&0x01;
对寄存器读写数据
在修改寄存器数据时,如果是对位进行操作(其他位用于其他功能),则必须要进行先读后修改
否则会影响其他位
#include <linux/io.h>
void writel(unsigned char data , unsigned int addr)
unsigned char readl(unsigned int addr)
//e.g.
int val = readl(GPIO1_DR);
val |= (1<<3);
writel(val,GPIO1_DR);
内存映射
从芯片手册得到的是物理地址,需要内存映射为虚拟地址后才能使用
/* --------------------------------- CCM寄存器 --------------------------------- */
#define CCM_CCGR1_BASE 0x20C406C
/* ------------------------------- IO复用控制寄存器 ----------------------------- */
#define IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03_BASE 0x20E0068
#define IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03_BASE 0x20E02F4
/* --------------------------------- GPIO寄存器 -------------------------------- */
#define GPIO1_DR_BASE 0x209C000 // 写
#define GPIO1_GDIR_BASE 0x209C004
#define GPIO1_PSR_BASE 0x209C008 // 读
/* ------------------ 内存映射后的虚拟地址指针(入口函数中进行内存映射) --------------- */
static void __iomem *CCM_CCGR1;
static void __iomem *MUX_CTL_PAD_GPIO1_IO03;
static void __iomem *PAD_CTL_PAD_GPIO1_IO03;
static void __iomem *GPIO1_DR;
static void __iomem *GPIO1_GDIR;
static void __iomem *GPIO1_PSR;
chr_dev_init(void)
{
//...
/* ---------------------------------- 内存映射 --------------------------------- */
CCM_CCGR1 = ioremap(CCM_CCGR1_BASE, 4);
MUX_CTL_PAD_GPIO1_IO03 = ioremap(IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03_BASE, 4);
PAD_CTL_PAD_GPIO1_IO03 = ioremap(IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03_BASE, 4);
GPIO1_DR = ioremap(GPIO1_DR_BASE, 4);
GPIO1_GDIR = ioremap(GPIO1_GDIR_BASE, 4);
GPIO1_PSR = ioremap(GPIO1_PSR_BASE, 4);
//...
}
chr_dev_exit(void)
{
//...
/* --------------------------------- 取消内存映射 -------------------------------- */
iounmap(CCM_CCGR1);
iounmap(MUX_CTL_PAD_GPIO1_IO03);
iounmap(PAD_CTL_PAD_GPIO1_IO03);
iounmap(GPIO1_DR);
iounmap(GPIO1_GDIR);
iounmap(GPIO1_PSR);
//...
}
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 宋振威的博客!
评论
