配置学习总结高通平台GPIO

前言:
近期在BSP的工作学习中,Group Leader 给安排了一项任务,就是分别在Android项目代码里面的SBL1,LK,以及各自负责的驱动模块代码(我是Audio驱动)中间配置GPIO ,使用循环语句,控制GPIO的输出电压,从而通过示波器得到相应的电压变化方波。因为之前对这方面没有接触过,所以在一边查询资料,一边在前辈的指导下尝试,完成了任务的一大半,下面将是我这一周对于在高通平台下面的android系统源码中间的GPIO相关的总结。

一,GPIO的概念与功能
General Purpose Input and Output   通用可编程输入输出接口
GPIO相当于芯片与外设之间的接口。他在Android 手机中间主要用于以下几个功能:

    1. 芯片通过GPIO向外输出一个高/低电平,从而控制外部器件某件事的发生。
    2. 芯片通过GPIO 读入一个外界的高/低电平,从而检车外部设备的的当前状态。(我们的任务大多数是利用GPIO的这个功能,控制手机背光或者闪光灯)。
    3. 将GPIO口作为外部中断信号的一个输入口,实时监测外部事件的发生。、
    4. 将GPIO用作其他特定用途,例如用作I2C通信,数据线,地址线。

二,GPIO的配置

1,在通常情况下,第一步:通过gpio_tlmm_config 函数来配置这个GPIO的各种设置
参数含义分别是设置GPIO编号,用途功能(一般是0),输入输出方向,是否拉高拉低,电流强度,以及是否使能。

第二步,是设置GPIO 输入输出高电/低电平通常情况下面,在内核中,有如下两个函数(或者类似函数)
  gpio_get_value,针对输入,读取值
  gpio_set_value针对输出,写出值

 2,在源码中间,比较规范的做法是有 如下几个步骤函数(默认功能位普通的输入输出功能,值时0)
  gpio_is_validate()    //判断这个GPIO号码是或否有效
 gpio_request()   //申请占用这个GPIO
 gpio_direction_input()/gpio_driection_output()    //方向和输出的值
 gpio_free()      //释放这个GPIO的占用


三,从任务的角度分析(追溯预案吗,底层代码)。
总结从SBL1阶段的GPIO配置为总结主要背景。
第一步:定位GPIO控制代码的增加位置。
   在SBL1阶段,代码主要在项目文件目录 MSM8909.LA1.2_Driveronly/nonhlos/boot_images/core/boot/secboot3/hw/msm8909/sbl1下面的代码,主要是该目录下面几个C文件和头文件。例如在sbl1_hw.c文件,为了确认代码添加的函数,通过添加串口LOG确认这个C文件中间几个函数的执行顺序。最后确认在sbl1_hw_init_secondary函数中间添加代码。

第二步:封装需要添加的代码成为一个函数
1,需要增加的预定义函数以及文件
//add by buqing.wang  start
#define GPIO_FLASH_NOW_ID 31    //flash gpio id
#define GPIO_FLASH_COUNT 10    //  10 cycle
#define HWREG_OUT(address, value)      (*((volatile uint32_t*)(address)) = (value) )// Write to hardware register      
#define HWREG_IN(address)                (*((volatile uint32_t*)(address))) // Read from hardware register    
//add by buwing.wang end

2增加函数的代码
// buqing.wang 2015-8-21 added to control the flash GPIO-31  start

/*===========================================================================

**  Function :  add to write gpio data

** ==========================================================================
*/
   void tct_set_gpio_bits(unsigned n, uint32_t reg)
    {
     HWREG_OUT(reg,HWREG_IN(reg) | n );
    }

  //写值
     void tct_sbl1_gpio_write_new(uint32_t gpio_num,uint32_t value)    
     {    
          HWREG_OUT(GPIO_IN_OUT_ADDR(gpio_num),value);
          tct_set_gpio_bits(0x200,(TLMM_BASE_ADDR + (gpio_num)*0x1000));
          printlog("-----------------from joymine  for write -----   %d",gpio_status(GPIO_FLASH_NOW_ID));
     }  

//配置以及循环写值从而得到灯光闪烁   
void flash_gpio_config()
{
   int i = 0;
//配置GPIO的各种状态
   gpio_tlmm_config( GPIO_FLASH_NOW_ID, 0, GPIO_OUTPUT, GPIO_PULL_UP, GPIO_6MA, GPIO_ENABLE);
   for(i=0 ; i < GPIO_FLASH_COUNT ; i ++ )
     {
          mdelay(1000);//延迟,从而使灯光闪烁更加的易于观察,否则时间太短,现象不明显。
          tct_sbl1_gpio_write_new(GPIO_FLASH_NOW_ID,2);//输出高电平
          mdelay(1000);
         tct_sbl1_gpio_write_new(GPIO_FLASH_NOW_ID,0);   //输出低电平  
    }
}
// buqing.wang 2015-8-21 added to control the flash GPIO-31  end

3  从源码学习GPIO写值原理

#define HWREG_OUT(address, value)      (*((volatile uint32_t*)(address)) = (value) )// Write to hardware register      
#define HWREG_IN(address)                (*((volatile uint32_t*)(address))) // Read from hardware register
#define  TLMM_BASE_ADDR   0x00800000
#define GPIO_IN_OUT_ADDR(x)    (TLMM_BASE_ADDR + 0x1004 + (x)*0x10)
#define GPIO_CONFIG_ADDR(x)    (TLMM_BASE_ADDR+ (x)*0x10)

由上面的代码可知,
写值得具体过程是:

 HWREG_OUT(GPIO_IN_OUT_ADDR(gpio_num),value);
 HWREG_OUT(reg,HWREG_IN(reg) | n );

首先根据GPIO编号,这个GPIO运行阶段加载的基地址(此处是sbl1阶段,基地址是TLMM_BASE_ADDR ),计算出一个该GPIO读写值运算的存储器地址,HWREG_OUT在该地址上面写入在该地址写入电平的值。





你可能感兴趣的:(Linux,驱动)