往寄存器的相应位写值的函数

来源:互联网 发布:淘宝网购毛线钩针 编辑:程序博客网 时间:2024/06/06 17:53

/*s3c2410_gpio_cfgpin()函数*/
/*在寄存器的相应位添加功能值的函数*/
/*这个函数非常重要*/
/*比如,在寄存器GPH的[13:12]位添加10,就要用到此函数*/

/*[13:12]两位共有4种状态,10是S3C2410_GPH6_TXD2,00是S3C2410_GPH6_INP,
01是S3C2410_GPH6_OUTP,11是S3C2410_GPH6_nRTS1*/

/*
#define S3C2410_GPIO_BASE(pin)   ((((pin) & ~31) >> 1) + S3C24XX_VA_GPIO)

#define S3C24XX_VA_GPIO    S3C2410_ADDR(0x00E00000) /*00E0 0000 + F000 0000= F0E0 0000*/

#define S3C2410_ADDR(x)   (0xF0000000 + (x))
#define S3C2410_GPIO_BANKB   (32*1)

#define S3C2410_GPIO_OFFSET(pin) ((pin) & 31)

#define local_irq_save(flags) do { (flags) = swpipl(IPL_MAX); barrier(); } while(0)
#define local_irq_restore(flags) do { barrier(); setipl(flags); barrier(); } while(0)
*/


void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int function)
{
/*基地址的获取*/
/*11111   ~11111=1110 0000 (pin) & ~31 即是屏蔽掉末5位,保留其余位*/
/*然后右移1位*/
/*为什么要右移一位呢?*/
/*因为偏移值只需要占用4位就可以了,能表示16以内的就行,可以一次改变2位寄存器的值*/

/*最终就是找到寄存器的基地址*/

void __iomem *base = S3C2410_GPIO_BASE(pin);

/*S3C2410_GPH6 = 32*7+6 = 230 = 1110 0110*/
/*S3C2410_GPH6 & ~31 = 1110 0000 = 224 = 32*7 */
/*(S3C2410_GPH6 & ~31) >> 1 = 0111 0000 = 112 = 16*7 = 0x70*/

/*((S3C2410_GPH6 & ~31) >> 1) + S3C2410_VA_GPIO = 0xF0E0 0000 + 0x70 = 0xF0E0 0070 */

/*也就是寄存器GPH的地址为0xF0E0 0070*/
/*而其偏移值6,表示要对[13:12]两位赋值*/

/*掩码*/

unsigned long mask;

/*控制字*/

unsigned long con;

/*标志*/

unsigned long flags;

/*掩码的设置*/
/*bankA是一位一位的改变寄存器的值*/
/*而之后的bank则是两位两位地改变寄存器的值*/
/*这些都是通过设置掩码来实现的*/
/*如bankA的掩码设置可以在[31:0]的任一位设置为1*/
/*而其余bank则只能在偶数位开始的两位设置为1*/


if (pin < S3C2410_GPIO_BANKB) /*如果pin < 32,即为bankA*/
{
   mask = 1 << S3C2410_GPIO_OFFSET(pin); /*则只保留末5位*/
   /*32,很值得推敲的数字,即为寄存器的32位,而S3C2410_GPIO_OFFSET(pin)表示寄存器的哪一位*/
   /*如果是0 0110,就表示是[6]位*/
}
else /*pin >= 32,bankH=32*7=224 */
{
   mask = 3 << S3C2410_GPIO_OFFSET(pin)*2; /*掩码,一次处理两位*/

   /*S3C2410_GPIO_OFFSET(230) = 6 */
   /* 6*2 = 12 */
   /* 3 << 12 即 [13:12] = 11 */
   /*就是处理两位*/
}

/*中断保留*/

local_irq_save(flags);

/*读取寄存器的值*/
/*如读取寄存器GPH的值*/

con = __raw_readl(base + 0x00);

/*掩码处理*/

con &= ~mask; /*把[13:12]位置0,其余位保留*/
    /*就是空出[13:12]位,好用来添加功能值*/

/*添加功能*/

con |= function; /*把[13:12]位添加为10*/
    /*可见,bankB以后的寄存器,都是一次处理两位*/
/*写入寄存器*/

__raw_writel(con, base + 0x00); /*往bankH寄存器里写值*/

/*中断恢复*/

local_irq_restore(flags);
}