亚洲av成人无遮挡网站在线观看,少妇性bbb搡bbb爽爽爽,亚洲av日韩精品久久久久久,兔费看少妇性l交大片免费,无码少妇一区二区三区

  免費(fèi)注冊(cè) 查看新帖 |

Chinaunix

  平臺(tái) 論壇 博客 文庫(kù)
最近訪問(wèn)板塊 發(fā)新帖
查看: 959 | 回復(fù): 0
打印 上一主題 下一主題

linux設(shè)備驅(qū)動(dòng)歸納總結(jié)(十三):1.觸摸屏與ADC時(shí)鐘 [復(fù)制鏈接]

論壇徽章:
0
跳轉(zhuǎn)到指定樓層
1 [收藏(0)] [報(bào)告]
發(fā)表于 2011-02-14 19:58 |只看該作者 |倒序?yàn)g覽
linux設(shè)備驅(qū)動(dòng)歸納總結(jié)(十三):1.觸摸屏與ADC時(shí)鐘


xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

這節(jié)的內(nèi)容說(shuō)不上是驅(qū)動(dòng),只是寫個(gè)代碼讓觸摸屏能夠工作,隨便介紹一下時(shí)鐘子系統(tǒng)(我不知道這樣叫合不合適),僅次而已。

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx


一、程序不能工作


程序的源代碼在13th_ts_input/13th_ts_input/1st。大致的操作就是配置寄存器,設(shè)置觸摸屏為自動(dòng)坐標(biāo)轉(zhuǎn)換模式,具體請(qǐng)根據(jù)程序?qū)φ?/font>S3C2440文檔。

但是寫完的程序不能工作,檢查原因。

1、中斷注冊(cè)失。

cat /prov/interrupt 就知道,系統(tǒng)已經(jīng)注冊(cè)了adctc中斷,為了能讓我的模塊加載成功,內(nèi)核編譯時(shí)不能加入adc和觸摸屏驅(qū)動(dòng)。

make menuconfig

1、Device Drivers ---> Input device support --->[ ] Touchscreens

2、Device Drivers ---> Character devices --->[ ] ADC driver for FriendlyARM Mini2440/QQ2440 development boards


重新編譯后啟動(dòng),模塊加載成功,但觸摸屏還是不能工作。


2、使能adc時(shí)鐘


如果有編寫過(guò)裸機(jī)程序的應(yīng)該知道,ad轉(zhuǎn)換和觸摸屏的正常工作還依賴于時(shí)鐘控制寄存器的配置,必須使能adc時(shí)鐘(CLKCON[15])。

但在linux下,有一套專門的規(guī)矩來(lái)使能時(shí)鐘,接下來(lái)先從內(nèi)核啟動(dòng)時(shí)的代碼開(kāi)始介紹:

該網(wǎng)友的博客上有更詳細(xì)的介紹,可以看看,雖然是2410的。

2410下clock源碼分析

1、arch/arm/mach-s3c2440/mach-mini2440.c

265 static void __init mini2440_map_io(void)

266 {

267         s3c24xx_init_io(mini2440_iodesc, ARRAY_SIZE(mini2440_iodesc));

268         s3c24xx_init_clocks(12000000); //初始化系統(tǒng)時(shí)鐘

269         s3c24xx_init_uarts(mini2440_uartcfgs, ARRAY_SIZE(mini2440_uartcfgs));

270 }

內(nèi)核啟動(dòng)時(shí)會(huì)通過(guò)mini2440_map_io函數(shù)調(diào)用s3c24xx_init_clocks來(lái)初始化系統(tǒng)時(shí)鐘,接下來(lái)看一下函數(shù)原型。

2arch/arm/plat-s3c/init.c

75 void __init s3c24xx_init_clocks(int xtal)

76 {

77         if (xtal == 0)

78                 xtal = 12*1000*1000;

79

80         if (cpu == NULL)

81                 panic("s3c24xx_init_clocks: no cpu setup?\n");

82

83        if (cpu->init_clocks == NULL)

84                 panic("s3c24xx_init_clocks: cpu has no clock init\n");

85         else

86                 (cpu->init_clocks)(xtal); //查找struct cpu_table

87 }

函數(shù)的原型很簡(jiǎn)單,就是調(diào)用了cpu結(jié)構(gòu)里面的成員init_clocks。接下來(lái)看一下2440cpu結(jié)構(gòu)體在里面的成員。

3、arch/arm/plat-s3c24xx/cpu.c

68 static struct cpu_table cpu_ids[] __initdata = {

69 {

70         .idcode = 0x32410000,

71         .idmask = 0xffffffff,

72         .map_io = s3c2410_map_io,

73         .init_clocks = s3c2410_init_clocks,

74         .init_uarts = s3c2410_init_uarts,

75         .init = s3c2410_init,

76         .name = name_s3c2410

77 },

。。。。。

87 {

88         .idcode = 0x32440000,

89         .idmask = 0xffffffff,

90         .map_io = s3c244x_map_io,

91         .init_clocks = s3c244x_init_clocks, //2440init_clocks函數(shù)原型在這里

92         .init_uarts = s3c244x_init_uarts,

93         .init = s3c2440_init,

94         .name = name_s3c2440

95 },

可以看,cpu->init_clocks的原型就是s4c244x_init_clocks,繼續(xù)看該函數(shù)里面做了什么操作

4/arch/arm/plat-s3c24xx/s3c244x.c

125 void __init s3c244x_init_clocks(int xtal)

126 {

127 /* initialise the clocks here, to allow other things like the

128 * console to use them, and to add new ones after the initialisation

129 */

130

131         s3c24xx_register_baseclocks(xtal); //三個(gè)步驟,接下來(lái)看一下

132         s3c244x_setup_clocks();

133         s3c2410_baseclk_add();

134 }

函數(shù)里面有三個(gè)操作,接下來(lái)逐個(gè)逐個(gè)看。

5、arch/arm/plat-s3c/clock.c

340 int __init s3c24xx_register_baseclocks(unsigned long xtal)

341 {

342         printk(KERN_INFO "S3C24XX Clocks, (c) 2004 Simtec Electronics\n");

343

344         clk_xtal.rate = xtal;

345

346 /* register our clocks */

347

348         if (s3c24xx_register_clock(&clk_xtal) < 0) //注冊(cè)時(shí)鐘

349                printk(KERN_ERR "failed to register master xtal\n");

350

351         if (s3c24xx_register_clock(&clk_mpll) < 0)

352                 printk(KERN_ERR "failed to register mpll clock\n");

353

354         if (s3c24xx_register_clock(&clk_upll) < 0)

355                 printk(KERN_ERR "failed to register upll clock\n");

356

357         if (s3c24xx_register_clock(&clk_f) < 0)

358                 printk(KERN_ERR "failed to register cpu fclk\n");

359

360         if (s3c24xx_register_clock(&clk_h) < 0)

361                 printk(KERN_ERR "failed to register cpu hclk\n");

362

363         if (s3c24xx_register_clock(&clk_p) < 0)

364                 printk(KERN_ERR "failed to register cpu pclk\n");

365

366         return 0;

367 }

跟名字一樣, s3c24xx_register_baseclocks注冊(cè)了系統(tǒng)中基本所需的時(shí)鐘,如pclk

6、arch/arm/plat-s3c24xx/s3c244x.c

76 void __init_or_cpufreq s3c244x_setup_clocks(void)

77 {

78         struct clk *xtal_clk;

79         unsigned long clkdiv;

80         unsigned long camdiv;

81         unsigned long xtal;

82         unsigned long hclk, fclk, pclk;

83         int hdiv = 1;

84

85         xtal_clk = clk_get(NULL, "xtal");

86         xtal = clk_get_rate(xtal_clk);

87         clk_put(xtal_clk);

88

89         fclk = s3c24xx_get_pll(__raw_readl(S3C2410_MPLLCON), xtal) * 2;

90

91         clkdiv = __raw_readl(S3C2410_CLKDIVN);

92         camdiv = __raw_readl(S3C2440_CAMDIVN);

93

94 /* work out clock scalings */

95

96         switch (clkdiv & S3C2440_CLKDIVN_HDIVN_MASK) {

97         case S3C2440_CLKDIVN_HDIVN_1:

98                 hdiv = 1;

99                 break;

100

101         case S3C2440_CLKDIVN_HDIVN_2:

102                 hdiv = 2;

103                 break;

104

105         case S3C2440_CLKDIVN_HDIVN_4_8:

106                 hdiv = (camdiv & S3C2440_CAMDIVN_HCLK4_HALF) ? 8 : 4;

107                 break;

108

109         case S3C2440_CLKDIVN_HDIVN_3_6:

110                 hdiv = (camdiv & S3C2440_CAMDIVN_HCLK3_HALF) ? 6 : 3;

111                 break;

112         }

113

114         hclk = fclk / hdiv;

115         pclk = hclk / ((clkdiv & S3C2440_CLKDIVN_PDIVN) ? 2 : 1);

116

117 /* print brief summary of clocks, etc */

118

119         printk("S3C244X: core %ld.%03ld MHz, memory %ld.%03ld MHz, peripheral %ld.%03ld MH z\n",

120         print_mhz(fclk), print_mhz(hclk), print_mhz(pclk));

121

122         s3c24xx_setup_clocks(fclk, hclk, pclk);

123 }

上面的函數(shù)通過(guò)從寄存器讀取信息并給fclkhclkpclk值,然后通過(guò) s3c24xx_setup_clocks函數(shù)添加到指定結(jié)構(gòu)體。


7、arch/arm/plat-s3c24xx/s3c2410-clock.c

211 int __init s3c2410_baseclk_add(void)

212 {

213         unsigned long clkslow = __raw_readl(S3C2410_CLKSLOW);

214         unsigned long clkcon = __raw_readl(S3C2410_CLKCON);

215         struct clk *clkp;

216         struct clk *xtal;

217         int ret;

218         int ptr;

219

220         clk_upll.enable = s3c2410_upll_enable;

221

222         if (s3c24xx_register_clock(&clk_usb_bus) < 0)

223                 printk(KERN_ERR "failed to register usb bus clock\n");

224

225 /* register clocks from clock array */

226

227         clkp = init_clocks; //該結(jié)構(gòu)體中存放著需要enable的時(shí)鐘成員,對(duì)應(yīng)寄存器CLKCON

228         for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++, clkp++) {

229 /* ensure that we note the clock state */

230

231                 clkp->usage = clkcon & clkp->ctrlbit ? 1 : 0;

232

233                 ret = s3c24xx_register_clock(clkp); //注冊(cè)并使能

234                 if (ret < 0) {

235                         printk(KERN_ERR "Failed to register clock %s (%d)\n",

236                         clkp->name, ret);

237                 }

238         }

239

240 /* We must be careful disabling the clocks we are not intending to

241 * be using at boot time, as subsystems such as the LCD which do

242 * their own DMA requests to the bus can cause the system to lockup

243 * if they where in the middle of requesting bus access.

244 *

245 * Disabling the LCD clock if the LCD is active is very dangerous,

246 * and therefore the bootloader should be careful to not enable

247 * the LCD clock if it is not needed.

248 */

249

250 /* install (and disable) the clocks we do not need immediately */

251

252         clkp = init_clocks_disable; //該結(jié)構(gòu)體中存放著需要disable的時(shí)鐘成員,對(duì)應(yīng)寄存器CLKCON

253         for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) {

254

255         ret = s3c24xx_register_clock(clkp); //注冊(cè),默認(rèn)使能

256         if (ret < 0) {

257                 printk(KERN_ERR "Failed to register clock %s (%d)\n",

258                 clkp->name, ret);

259         }

260

261         s3c2410_clkcon_enable(clkp, 0); //使能后又將成員disable

262         }

263

264 /* show the clock-slow value */

265

266         xtal = clk_get(NULL, "xtal");

267

268         printk("CLOCK: Slow mode (%ld.%ld MHz), %s, MPLL %s, UPLL %s\n",

269         print_mhz(clk_get_rate(xtal) /

270         ( 2 * S3C2410_CLKSLOW_GET_SLOWVAL(clkslow))),

271         (clkslow & S3C2410_CLKSLOW_SLOW) ? "slow" : "fast",

272         (clkslow & S3C2410_CLKSLOW_MPLL_OFF) ? "off" : "on",

273         (clkslow & S3C2410_CLKSLOW_UCLK_OFF) ? "off" : "on");

274

275         s3c_pwmclk_init();

276         return 0;

277 }


48 int s3c2410_clkcon_enable(struct clk *clk, int enable)

49 {

50         unsigned int clocks = clk->ctrlbit;

51         unsigned long clkcon;

52

53         clkcon = __raw_readl(S3C2410_CLKCON);

54

55         if (enable)

56                 clkcon |= clocks;

57         else

58                 clkcon &= ~clocks; //傳入?yún)?shù)為0,所以是disable

59

60 /* ensure none of the special function bits set */

61         clkcon &= ~(S3C2410_CLKCON_IDLE|S3C2410_CLKCON_POWER);

62

63         __raw_writel(clkcon, S3C2410_CLKCON);

64

65         return 0;

66 }

可以看到,s3c2410_baseclk_add分了兩部分的操作。

第一部分:獲取init_clock的數(shù)據(jù)結(jié)構(gòu),并且調(diào)用s3c24xx_register_clock 來(lái)配置寄存器CLKCON默認(rèn)使能init_clock結(jié)構(gòu)里面指定時(shí)鐘。

第二部分:獲取init_clock_disable數(shù)據(jù)結(jié)構(gòu),除了調(diào)用s3c24xx_register_clock注冊(cè)后,還調(diào)用3c2410_clkcon_enable來(lái)配置寄存器CLKCON來(lái)disableinit_clock_disable結(jié)構(gòu)體里面的時(shí)鐘。


init_clockinit_clock_disable里面的成員與寄存器CLKCON的成員對(duì)應(yīng).

接下來(lái)看看clkp的數(shù)據(jù)結(jié)構(gòu)init_clock在哪里定義:

/arch/arm/plat-s3c24xx/s3c2410-clock.c

130 static struct clk init_clocks[] = {

131 {

132         .name = "lcd",

133         .id = -1,

134         .parent = &clk_h,

135         .enable = s3c2410_clkcon_enable,

136         .ctrlbit = S3C2410_CLKCON_LCDC,

137 }, {

138         .name = "gpio",

139         .id = -1,

140         .parent = &clk_p,

141         .enable = s3c2410_clkcon_enable,

142         .ctrlbit = S3C2410_CLKCON_GPIO,

143 }, {

144         .name = "usb-host",

145         .id = -1,

146         .parent = &clk_h,

。。。。。。

可以看到,lcd、gpio等這類的時(shí)鐘是系統(tǒng)啟動(dòng)時(shí)就已經(jīng)使能了,所以之前我的lcd驅(qū)動(dòng)才能正常工作。

90 static struct clk init_clocks_disable[] = {

91 {

92         .name = "nand",

93         .id = -1,

94         .parent = &clk_h,

95         .enable = s3c2410_clkcon_enable,

96         .ctrlbit = S3C2410_CLKCON_NAND,

97 }, {

98         .name = "sdi",

99         .id = -1,

100         .parent = &clk_p,

101         .enable = s3c2410_clkcon_enable,

102         .ctrlbit = S3C2410_CLKCON_SDI,

103 }, {

104         .name = "adc", //觸摸屏的時(shí)鐘放在 init_clocks_disable中,所以觸摸屏不能工作!

105         .id = -1,

106         .parent = &clk_p,

107         .enable = s3c2410_clkcon_enable,

108         .ctrlbit = S3C2410_CLKCON_ADC,

109 }, {

。。。。。

現(xiàn)在就可以知道,為什么觸摸屏不能工作了,因?yàn)樵谙到y(tǒng)啟動(dòng)時(shí)被禁止了。所以需要在函數(shù)中啟動(dòng)它。


既然知道了原因,解決方法就好辦了——adc成員從init)clocks_disable中刪除并添加到init_clocks中。


同時(shí)還有一個(gè)不用修改內(nèi)核代碼的方法。


xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx


二、clk_enable


第二個(gè)方法很簡(jiǎn)單,從獲取內(nèi)核中的adc時(shí)鐘,然后將它使能。

先看獲取函數(shù):

struct clk *clk_get(struct device *dev, const char *con_id)

第一個(gè)參數(shù)中,因?yàn)?font face="DejaVu Serif, serif">clk->id一般為-1,所以直接傳入NULL就可以了。如果clk->id不為-1,函數(shù)會(huì)通過(guò)第一個(gè)參數(shù)傳入的dev獲取dev->bus_id。

第二個(gè)參數(shù)是一個(gè)字符串,用來(lái)指定你要獲取的時(shí)鐘的名字。

參數(shù)傳入后,內(nèi)核查找到一個(gè)dev->id(或者-1)是否與clk->id一致,并且con_idclk->name一致的時(shí)鐘,如果不一致就會(huì)獲取失敗。

所以,我這里的函數(shù)應(yīng)該是:clk_get(NULL, “adc”)。


使能時(shí)鐘使用函數(shù):

int clk_enable(struct clk *clk)

禁止時(shí)鐘使用函數(shù):

void clk_disable(struct clk *clk)


在原來(lái)的函數(shù)中使用這三條代碼后(13th_ts_input/13th_ts_input/2nd),觸摸屏就能工作了?纯葱Ч

[root: 2nd]# insmod ts_driver.ko

hello ts

[root: 2nd]# tc down //當(dāng)接觸觸摸屏是打印

x:0, y:947

tc up

tc down

x:382, y:608

tc up

tc down


xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx


三、防抖(13th_ts_input/13th_ts_input/3rd


同樣的,最后在代碼中添加個(gè)定時(shí)器,實(shí)現(xiàn)防抖功能。


xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

源代碼: 13th_ts_input.rar  

您需要登錄后才可以回帖 登錄 | 注冊(cè)

本版積分規(guī)則 發(fā)表回復(fù)

  

北京盛拓優(yōu)訊信息技術(shù)有限公司. 版權(quán)所有 京ICP備16024965號(hào)-6 北京市公安局海淀分局網(wǎng)監(jiān)中心備案編號(hào):11010802020122 niuxiaotong@pcpop.com 17352615567
未成年舉報(bào)專區(qū)
中國(guó)互聯(lián)網(wǎng)協(xié)會(huì)會(huì)員  聯(lián)系我們:huangweiwei@itpub.net
感謝所有關(guān)心和支持過(guò)ChinaUnix的朋友們 轉(zhuǎn)載本站內(nèi)容請(qǐng)注明原作者名及出處

清除 Cookies - ChinaUnix - Archiver - WAP - TOP