单片机
返回首页

Linux下s3c6410的GPIO操作(6)

2022-06-09 来源:eefocus

1、在  Linux下s3c6410的GPIO操作(3) 这篇博客中少分析了一个函数,当时列出了源码,但没分析,现在补上。


什么函数呢?如下所示:


#ifdef CONFIG_S3C_GPIO_CFG_S3C64XX


/**

 * s3c_gpio_setcfg_s3c64xx_4bit - S3C64XX 4bit single register GPIO config.

 * @chip: The gpio chip that is being configured.

 * @off: The offset for the GPIO being configured.

 * @cfg: The configuration value to set.

 *

 * This helper deal with the GPIO cases where the control register has 4 bits

 * of control per GPIO, generally in the form of:

 * 0000 = Input

 * 0001 = Output

 * others = Special functions (dependant on bank)

int s3c_gpio_setcfg_s3c64xx_4bit(struct s3c_gpio_chip *chip,

unsigned int off, unsigned int cfg)

{

void __iomem *reg = chip->base;


得到GPIO端口控制寄存器的基地址,不同的端口可能不同哦!如下所示:


(第一种)、


static struct s3c_gpio_chip gpio_4bit[] = {

{

.base =S3C64XX_GPA_BASE,

.config  = &gpio_4bit_cfg_eint0111,

.chip = {

.base = S3C64XX_GPA(0),

.ngpio  = S3C64XX_GPIO_A_NR,

.label  = 'GPA',

}


(第二种)


static struct s3c_gpio_chip gpio_4bit2[] = {

{

.base =S3C64XX_GPH_BASE + 0x4,

.config  = &gpio_4bit_cfg_eint0111,

.chip = {

.base = S3C64XX_GPH(0),

.ngpio  = S3C64XX_GPIO_H_NR,

.label  = 'GPH',

}


(第三种)、


static struct s3c_gpio_chip gpio_2bit[] = {

{

.base = S3C64XX_GPF_BASE,

.config  = &gpio_2bit_cfg_eint11,

.chip = {

.base = S3C64XX_GPF(0),

.ngpio  = S3C64XX_GPIO_F_NR,

.label  = 'GPF',

}


既然端口分三种,那么对应的操作函数也应该分为三种,但实际上分成了两种,按控制寄存器的控制位数分为4和2.


这两种操作函数分别是s3c_gpio_setcfg_s3c64xx_4bit函数和s3c_gpio_setcfg_s3c24xx函数。



unsigned int shift = (off & 7) * 4;

u32 con;



if (off < 8 && chip->chip.ngpio > 8)

reg -= 4;


这个判断是为4-2这种情况准备的,因为上面的基地址是第二个控制寄存器的基地址,所以要减去4得到第一个控制寄存器的基地址。可以这样进行判断,一个很重要的原因就是下面这个表,观察一下,是否发现4Bit类型的都没有超过8个。所以我才说这个是针对4-2这种情况的。


/* GPIO bank summary:

 *

 * Bank GPIOs  Style SlpCon  ExtInt Group

 * A 8  4Bit Yes  1

 * B 7  4Bit Yes  1

 * C 8  4Bit Yes  2

 * D 5  4Bit Yes  3

 * E 5  4Bit Yes  None

 * F 16  2Bit Yes  4 [1]

 * G 7  4Bit Yes  5

 * H 10  4Bit[2] Yes  6

 * I 16  2Bit Yes  None

 * J 12  2Bit Yes  None

 * K 16  4Bit[2] No  None

 * L 15  4Bit[2] No None

 * M 6  4Bit No  IRQ_EINT

 * N 16  2Bit No  IRQ_EINT

 * O 16  2Bit Yes  7

 * P 15  2Bit Yes  8

 * Q 9  2Bit Yes  9

 *

 * [1] BANKF pins 14,15 do not form part of the external interrupt sources

 * [2] BANK has two control registers, GPxCON0 and GPxCON1

 */



if (s3c_gpio_is_cfg_special(cfg)) {

cfg &= 0xf;

cfg <<= shift;

}


#define s3c_gpio_is_cfg_special(_cfg)

(((_cfg) & S3C_GPIO_SPECIAL_MARK) == S3C_GPIO_SPECIAL_MARK)


#define S3C_GPIO_SPECIAL_MARK(0xfffffff0)


主要目的是为了判断传入的 unsigned int cfg这个参数,这个参数的之可以为0xfffffffx,其中x有下表所示:

当然,也可以传入的参数直接为上表中的数值,看开头的注释,就可以明白了。


con = __raw_readl(reg);

con &= ~(0xf << shift);

con |= cfg;

__raw_writel(con, reg);

这一部分很简单,无非就是读后,再写。


return 0;

}


注:如果大家对上面的shift的处理不是很明白,可以举个实际例子。如9的时候,unsigned int shift = (off & 7) * 4;的shift为1,别忘了现在是对第二个控制寄存器操作,0-7是第一个寄存器,8以后是第二个寄存器,那9就是第二个控制寄存器的第二个控制段,也就是第二个4位,这么说应该明白了吧。

#endif /* CONFIG_S3C_GPIO_CFG_S3C64XX */


2、


上面说的是两个函数中的其中一个,现在来说第二个,s3c_gpio_setcfg_s3c24xx,源码如下:


/**

 * s3c_gpio_setcfg_s3c24xx - S3C24XX style GPIO configuration.

 * @chip: The gpio chip that is being configured.

 * @off: The offset for the GPIO being configured.

 * @cfg: The configuration value to set.

 *

 * This helper deal with the GPIO cases where the control register

 * has two bits of configuration per gpio, which have the following

 * functions:

 * 00 = input

 * 01 = output

 * 1x = special function

*/




int s3c_gpio_setcfg_s3c24xx(struct s3c_gpio_chip *chip,

   unsigned int off, unsigned int cfg)

{

void __iomem *reg = chip->base;

unsigned int shift = off * 2;

u32 con;



if (s3c_gpio_is_cfg_special(cfg)) {

cfg &= 0xf;

if (cfg > 3)

return -EINVAL;



cfg <<= shift;

}



con = __raw_readl(reg);

con &= ~(0x3 << shift);

con |= cfg;

__raw_writel(con, reg);



return 0;

}


和上面那个函数一样,而且还相对简单,就不分析了。

进入单片机查看更多内容>>
相关视频
  • RISC-V嵌入式系统开发

  • SOC系统级芯片设计实验

  • 云龙51单片机实训视频教程(王云,字幕版)

  • 2022 Digi-Key KOL 系列: 你见过1GHz主频的单片机吗?Teensy 4.1开发板介绍

  • TI 新一代 C2000™ 微控制器:全方位助力伺服及马达驱动应用

  • MSP430电容触摸技术 - 防水Demo演示

精选电路图
  • PIC单片机控制的遥控防盗报警器电路

  • 使用ESP8266从NTP服务器获取时间并在OLED显示器上显示

  • 用NE555制作定时器

  • 如何构建一个触摸传感器电路

  • 基于ICL296的大电流开关稳压器电源电路

  • 基于TDA2003的简单低功耗汽车立体声放大器电路

    相关电子头条文章