1.对绝对地址赋值操作
对绝对地址0x100000赋值操作
*(unsigned int *)0x100000=1234;
让程序跳转到绝对地址是0x100000去执行
*((void (*) () )0x100000) ();
首先要将0x100000强制转换维函数指针,即:
(void (*) () )0x100000
然后再调用它
*((void (*) () )0x100000) ();
使用typedef可以更直观
typedef void(*) () voidFuncPtr; *((voidFuncPtr)0x100000) ();
2. ioremap
2.1 void __iomem *地址
/* 寄存器物理地址 */ #define CCM_CCGR1_BASE (0X020C406C) #define SW_MUX_GPIO1_IO03_BASE (0X020E0068) #define SW_PAD_GPIO1_IO03_BASE (0X020E02F4) #define GPIO1_DR_BASE (0X0209C000) #define GPIO1_GDIR_BASE (0X0209C004) /* 映射后的寄存器虚拟地址指针 */ static void __iomem *IMX6U_CCM_CCGR1; static void __iomem *SW_MUX_GPIO1_IO03; static void __iomem *SW_PAD_GPIO1_IO03; static void __iomem *GPIO1_DR; static void __iomem *GPIO1_GDIR;
/* 寄存器地址映射 */ IMX6U_CCM_CCGR1 = ioremap(CCM_CCGR1_BASE, 4); SW_MUX_GPIO1_IO03 = ioremap(SW_MUX_GPIO1_IO03_BASE, 4); SW_PAD_GPIO1_IO03 = ioremap(SW_PAD_GPIO1_IO03_BASE, 4); GPIO1_DR = ioremap(GPIO1_DR_BASE, 4); GPIO1_GDIR = ioremap(GPIO1_GDIR_BASE, 4);
int retvalue = 0; u32 val = 0; /*、使能GPIO1时钟 */ val = readl(IMX6U_CCM_CCGR1); val &= ~(3 << 26); /* 清楚以前的设置 */ val |= (3 << 26); /* 设置新值 */ writel(val, IMX6U_CCM_CCGR1); /*设置GPIO1_IO03的复用功能,将其复用为 * GPIO1_IO03,最后设置IO属性。 */ writel(5, SW_MUX_GPIO1_IO03); /*寄存器SW_PAD_GPIO1_IO03设置IO属性 *bit 16:0 HYS关闭 *bit [15:14]: 00 默认下拉 *bit [13]: 0 kepper功能 *bit [12]: 1 pull/keeper使能 *bit [11]: 0 关闭开路输出 *bit [7:6]: 10 速度100Mhz *bit [5:3]: 110 R0/6驱动能力 *bit [0]: 0 低转换率 */ writel(0x10B0, SW_PAD_GPIO1_IO03); /* 设置GPIO1_IO03为输出功能 */ val = readl(GPIO1_GDIR); val &= ~(1 << 3); /* 清除以前的设置 */ val |= (1 << 3); /* 设置为输出 */ writel(val, GPIO1_GDIR); /* 默认关闭LED */ val = readl(GPIO1_DR); val |= (1 << 3); writel(val, GPIO1_DR);
2.2 volatile unsigned int *地址
static volatile unsigned int *CCM_CCGR1 ; static volatile unsigned int *IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03; static volatile unsigned int *GPIO1_GDIR ; static volatile unsigned int *GPIO1_DR ;
CCM_CCGR1 = ioremap(0x20C406C, 4); IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03 = ioremap(0x20E0068, 4); GPIO1_GDIR = ioremap(0x0209C000 + 0x4, 4); GPIO1_DR = ioremap(0x0209C000 + 0, 4);
/* GPIO1_IO03 */ /* a. 使能GPIO1 * set CCM to enable GPIO1 * CCM_CCGR1[CG13] 0x20C406C * bit[27:26] = 0b11 */ *CCM_CCGR1 |= (3<<26); /* b. 设置GPIO1_IO03用于GPIO * set IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03 * to configure GPIO1_IO03 as GPIO * IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03 0x20E0068 * bit[3:0] = 0b0101 alt5 */ val = *IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03; val &= ~(0xf); val |= (5); *IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03 = val; /* c. 设置GPIO1_IO03作为output引脚 * set GPIO1_GDIR to configure GPIO1_IO03 as output * GPIO1_GDIR 0x0209C000 + 0x4 * bit[3] = 0b1 */ *GPIO1_GDIR |= (1<<3);
2.3 struct+ioremap
struct iomux { volatile unsigned int unnames[23]; volatile unsigned int IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO00; /* offset 0x5c */ volatile unsigned int IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO01; volatile unsigned int IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO02; volatile unsigned int IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03; volatile unsigned int IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO04; volatile unsigned int IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO05; volatile unsigned int IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO06; volatile unsigned int IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO07; volatile unsigned int IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO08; volatile unsigned int IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO09; volatile unsigned int IOMUXC_SW_MUX_CTL_PAD_UART1_TX_DATA; volatile unsigned int IOMUXC_SW_MUX_CTL_PAD_UART1_RX_DATA; volatile unsigned int IOMUXC_SW_MUX_CTL_PAD_UART1_CTS_B; }; struct imx6ull_gpio { volatile unsigned int dr; volatile unsigned int gdir; volatile unsigned int psr; volatile unsigned int icr1; volatile unsigned int icr2; volatile unsigned int imr; volatile unsigned int isr; volatile unsigned int edge_sel; }; /* enable GPIO4 */ static volatile unsigned int *CCM_CCGR3; /* enable GPIO5 */ static volatile unsigned int *CCM_CCGR1; /* set GPIO5_IO03 as GPIO */ static volatile unsigned int *IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER1; /* set GPIO4_IO14 as GPIO */ static volatile unsigned int *IOMUXC_SW_MUX_CTL_PAD_NAND_CE1_B; static struct iomux *iomux; static struct imx6ull_gpio *gpio4; static struct imx6ull_gpio *gpio5;
CCM_CCGR1 = ioremap(0x20C406C, 4); CCM_CCGR3 = ioremap(0x20C4074, 4); IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER1 = ioremap(0x229000C, 4); IOMUXC_SW_MUX_CTL_PAD_NAND_CE1_B = ioremap(0x20E01B0, 4); iomux = ioremap(0x20e0000, sizeof(struct iomux)); gpio4 = ioremap(0x020A8000, sizeof(struct imx6ull_gpio)); gpio5 = ioremap(0x20AC000, sizeof(struct imx6ull_gpio));
if (which == 0) { /* 1. enable GPIO5 * CG15, b[31:30] = 0b11 */ *CCM_CCGR1 |= (3<<30); /* 2. set GPIO5_IO03 as GPIO * MUX_MODE, b[3:0] = 0b101 */ *IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER3 = 5; /* 3. set GPIO5_IO03 as output * GPIO5 GDIR, b[3] = 0b1 */ gpio5->gdir |= (1<<3); } else if(which == 1) { /* 1. enable GPIO1 * CG13, b[27:26] = 0b11 */ *CCM_CCGR1 |= (3<<26); /* 2. set GPIO1_IO03 as GPIO * MUX_MODE, b[3:0] = 0b101 */ iomux->IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03 = 5; /* 3. set GPIO1_IO03 as output * GPIO1 GDIR, b[3] = 0b1 */ gpio1->gdir |= (1<<3); } else if(which == 2) { /* 1. enable GPIO1 * CG13, b[27:26] = 0b11 */ *CCM_CCGR1 |= (3<<26); /* 2. set GPIO1_IO05 as GPIO * MUX_MODE, b[3:0] = 0b101 */ iomux->IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO05 = 5; /* 3. set GPIO1_IO05 as output * GPIO1 GDIR, b[5] = 0b1 */ gpio1->gdir |= (1<<5); } else if(which == 3) { /* 1. enable GPIO1 * CG13, b[27:26] = 0b11 */ *CCM_CCGR1 |= (3<<26); /* 2. set GPIO1_IO06 as GPIO * MUX_MODE, b[3:0] = 0b101 */ iomux->IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO06 = 5; /* 3. set GPIO1_IO06 as output * GPIO1 GDIR, b[6] = 0b1 */ gpio1->gdir |= (1<<6); } if (which == 0) { /* 1. enable GPIO5 * CG15, b[31:30] = 0b11 */ *CCM_CCGR1 |= (3<<30); /* 2. set GPIO5_IO01 as GPIO * MUX_MODE, b[3:0] = 0b101 */ *IOMUXC_SNVS_SW_MUX_CTL_PAD_SNVS_TAMPER1 = 5; /* 3. set GPIO5_IO01 as input * GPIO5 GDIR, b[1] = 0b0 */ gpio5->gdir &= ~(1<<1); } else if(which == 1) { /* 1. enable GPIO4 * CG6, b[13:12] = 0b11 */ *CCM_CCGR3 |= (3<<12); /* 2. set GPIO4_IO14 as GPIO * MUX_MODE, b[3:0] = 0b101 */ IOMUXC_SW_MUX_CTL_PAD_NAND_CE1_B = 5; /* 3. set GPIO4_IO14 as input * GPIO4 GDIR, b[14] = 0b0 */ gpio4->gdir &= ~(1<<14); }