高通gpio調試


Gpio調試方法
1:高通文檔說明
通過直接讀取gpio相應配置寄存器的值來分析對應gpio的配置情況;
 
寄存器地址:




上面說明的是寄存器每位代表的含義,是以msm8940為例的,對於我們的msm8940可以參考msm8940的芯片手冊《80-p4978-2x_a_msm8940_hardware_register_description.pdf》
第15 TLMM control and status registers這章節的說明
 
2讀寫方法:
Android 里有一個工具/system/bin/r  ,這個工具只有在userdebug版本中會被編譯出來,源碼放在android/system/core/toolbox/r.c  里面。(有興趣的同學可以看下它的源碼)
 
這個工具會依賴於/dev/mem這個節點,可以先看一下/dev/mem這個節點是否已經存在,如果不存在需要打開kernel里的配置宏:CONFIG_DEVMEM=y,如果存在的話就不用管了。
如果上面條件都具備了,就可以用/system/bin/r 這個工具來讀寫GPIO寄存器,來控制GPIO 了。下面說一下這個工具的具體用法。
 
以GPIO 64為例,通過上面的高通文檔里可以看到寄存器配置:
Register – TLMM_GPIO_CFGn, n=[0..133]: 0x01000000 + 0x1000* (n)
GPIO64 ,TLMM_GPIO_CFG64: 0x01000000 +0x1000*0x40 = 0x01040000
(64換成16進制為0x40)
讀寄存器:
adb root
adb shell
#X596:/ # system/bin/r  0x1040000
01040000: 000002c3
 
bit[1:0] is 3, that means PULL_UP
bit[5:2] is 0, that means FUNC_0 (normal GPIO)
(FUNC_SEL在80-p4978-1b_a_msm8940_gpio_configuration_spreadsheet.xlsm可以查到):
bit[8:6] is 3, that means DRV_8_MA( 8mA drive strength)
bit[9] is 1, that means output enabled(GPIO behaves as output).
 
Register – TLMM_GPIO_IN_OUTn, n=[0..133]: 0x01000004 + 0x00001000* (n)
GPIO64, TLMM_GPIO_CFG64: 0x01000004+0x1000*0x40 = 0x01040004
讀寄存器:
X596:/ # system/bin/r  0x1040004
01040004: 00000003
 
寫寄存器:
X596:/ # system/bin/r  0x1040004 2
01040004: 00000002
 
Bit [1] 為 0, 表示GPIO64 輸出低,Bit [1] 為 1, 表示GPIO64 輸出高。
 
注意:如果要設置modem中用到的GPIO, 需要把modem中的配置去掉,用/system/bin/r命令才可以配置成功,這里有個patch, 是用GPIO108 為例的:
 
到此為止就是/system/bin/r 的使用方法。
 
 
下面說一下/system/bin/r 這個工具(有興趣的可以看一下,沒興趣的下面的就不用看了),源碼在android/system/core/toolbox/r.c 里面用到節點/dev/mem。這個節點應該是在android/kernel/msm-3.18/drivers/char/mem.c 里創建的,需要打開宏 CONFIG_DEVMEM。這個文件里不只創建一個節點,還有一個/dem/kmem節點。
/dev/mem: 物理內存的全鏡像。可以用來訪問物理內存。
用來訪問物理IO設備,比如X用來訪問顯卡的物理內存,或嵌入式中訪問GPIO。用法一般就是open,然后mmap,接着可以使用map之后的地址來訪問物理內存。這其實就是實現用戶空間驅動的一種方法。
Mmap的使用方法:https://baike.baidu.com/item/mmap/1322217?fr=aladdin
/dev/kmem: kernel看到的虛擬內存的全鏡像。可以用來訪問kernel的內容。
一般可以用來查看kernel的變量,或者用作rootkit之類的。
/dev/mem節點的使用方法可以查看r.c 代碼。
下面是一段/dev/kmem使用的一段代碼:
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
 
#define DEVKMEM         "/dev/kmem"
 
#define PAGE_SIZE       0x1000
#define PAGE_MASK       (~(PAGE_SIZE-1))
 
 
int main(int argc, char* argv[])
{
    int fd;
    char *mbase;
    char read_buf[10];
    unsigned int regAddr;
    unsigned int varAddr;
 
    varAddr = strtoul(argv[1], 0, 16);
 
    unsigned int ptr = varAddr & ~(PAGE_MASK);
 
    fd = open(DEVKMEM, O_RDONLY);
    if (fd == -1) {
        perror("open");
        exit(-1);
    }
 
    mbase = mmap(0,PAGE_SIZE,PROT_READ,MAP_SHARED,fd, (varAddr & PAGE_MASK));
    if (mbase == MAP_FAILED) {
        printf("map failed %s\n",strerror(errno));
    }
 
    printf("varAddr = 0x%X \n", varAddr);
    printf("mapbase = 0x%X \n", (unsigned int)mbase);
    printf("value   = 0x%X \n",*(unsigned int*)(mbase+ptr));
    printf("char    = %c%c%c%c \n",
                    *(char *)(mbase+ptr), *(char *)(mbase+ptr+1),
                    *(char *)(mbase+ptr+2), *(char *)(mbase+ptr+3));
 
    close(fd);
    munmap(mbase,PAGE_SIZE);
 
    return 0;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM