spi驅動流程學習
</pre><pre code_snippet_id="1593617" snippet_file_name="blog_20160301_2_3014540" name="code" class="cpp">
diff --git a/1980c/base/kernel/linux-3.10/arch/arm/configs/M88_phone_v1_0_defconfig b/1980c/base/kernel/linux-3.10/arch/arm/configs/M88_phone_v1_0_defconfig index a4e81bb..b15afeb 100755 --- a/1980c/base/kernel/linux-3.10/arch/arm/configs/M88_phone_v1_0_defconfig +++ b/1980c/base/kernel/linux-3.10/arch/arm/configs/M88_phone_v1_0_defconfig @@ -380,7 +380,7 @@ CONFIG_MMC_COMIP_IOPOWER=y CONFIG_ON2_COMIP=y CONFIG_PWM_COMIP=y CONFIG_RESET_COMIP=y -# CONFIG_SPI_COMIP is not set +CONFIG_SPI_COMIP=y # CONFIG_TPZ_COMIP is not set # CONFIG_TPZ2_COMIP is not set @@ -1833,6 +1833,7 @@ CONFIG_DEVMEM=y # CONFIG_SERIAL_MAX310X is not set CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y +CONFIG_SERIAL_SC16IS7X2=y # CONFIG_SERIAL_SCCNXP is not set # CONFIG_SERIAL_TIMBERDALE is not set # CONFIG_SERIAL_ALTERA_JTAGUART is not set @@ -1905,7 +1906,7 @@ CONFIG_SPI_MASTER=y # # SPI Protocol Masters # -# CONFIG_SPI_SPIDEV is not set +CONFIG_SPI_SPIDEV=y # CONFIG_SPI_TLE62X0 is not set # diff --git a/1980c/base/kernel/linux-3.10/arch/arm/mach-lc186x/board/board-M88.c b/1980c/base/kernel/linux-3.10/arch/arm/mach-lc186x/board/board-M88.c index 9fc4a01..65e4bdb 100755 --- a/1980c/base/kernel/linux-3.10/arch/arm/mach-lc186x/board/board-M88.c +++ b/1980c/base/kernel/linux-3.10/arch/arm/mach-lc186x/board/board-M88.c @@ -28,6 +28,11 @@ #include <plat/comip-backlight.h> #include <plat/comip-thermal.h> #include <plat/comip-battery.h> +#if defined(CONFIG_SPI_COMIP) || defined(CONFIG_SPI_COMIP_MODULE) +#include <linux/spi/spi.h> +#include <plat/spi.h> +#include <mach/devices.h> +#endif #if defined(CONFIG_COMIP_LC1160) #include <plat/lc1160.h> #include <plat/lc1160-pmic.h> @@ -61,6 +66,166 @@ #include <linux/mpu.h> #endif +#if defined(CONFIG_SPI_COMIP) || defined(CONFIG_SPI_COMIP_MODULE) +#include <linux/serial_sc16is7x2.h> + +static struct sc16is7x2_platform_data sc16is7x2_pdata = { + .uartclk = 115200, + .uart_base = 0, + .gpio_base = 0, + .label = NULL, + .names = NULL, + .gpio_for_irq =12345, + .gpio_for_reset =12345, +}; + +//掛在spi0上的從裝置陣列 +static struct spi_board_info comip_spi_board_info[] = { + {//掛在spi0上的第一個從裝置 + .modalias = "sc16is7x2",//從裝置的別名,用來和從裝置的驅動進行關聯 + .platform_data = &sc16is7x2_pdata,//如果從裝置有需要傳入驅動的私有資料,則通過該屬性傳入 + .controller_data = NULL, + .irq = 0,//此處忽略,在從裝置probe中會重新賦值 + .max_speed_hz = 100000, + .bus_num = 0,//用來標識該從裝置掛載在哪個spi控制器上 + .chip_select = 0,//使用第幾個片選訊號,一個spi控制器能支援片選總個數由master->num_chipselect 確定。所以此處的值應介於0 ~ master->num_chipselect之間。 + .mode = SPI_MODE_0, + }, + +//測試spidev.c新增==============================start + {//掛在spi0上的第二個從裝置,生成的裝置節點為/dev/spidev0.1 (第一個數字表示匯流排號,第二個數字表示片選號) + .modalias = "spidev", + .max_speed_hz = 200000, + .bus_num = 0, //spi0 + .chip_select = 1,//這是掛在spi0上的第二個外設,該片選的值必須為1(另外一個外設的片選為0,此處的值必須和另外一個的不同),否則probe不到該外設 + .platform_data = NULL, + }, + + {//掛在spi1上的第一個從裝置,生成的裝置節點為/dev/spidev1.0 (第一個數字表示匯流排號,第二個數字表示片選號) + .modalias = "spidev", + .max_speed_hz = 200000, + .bus_num = 1, //spi0 + .chip_select = 0, + .platform_data = NULL, + }, + + {//掛在spi2上的第一個從裝置,生成的裝置節點為/dev/spidev2.0 (第一個數字表示匯流排號,第二個數字表示片選號) + .modalias = "spidev", + .max_speed_hz = 200000, + .bus_num = 2, //spi0 + .chip_select = 0, + .platform_data = NULL, + }, +//測試spidev.c新增==============================end + +/* + {//掛在spi0上的第二個從裝置 + .modalias = "foo1", + .max_speed_hz = 200000, + .bus_num = 0, //spi0 + .chip_select = 0, + .platform_data = NULL, + }, + {//掛在spi1上的第一個從裝置 + .modalias = "foo2", + .max_speed_hz = 150000, + .bus_num = 1,//spi1 + .chip_select = 0, + .platform_data = NULL, + }, + {//掛在spi2上的第一個從裝置 + .modalias = "foo3", + .max_speed_hz = 150000, + .bus_num = 2,//spi2 + .chip_select = 0, + .platform_data = NULL, + }, +*/ +}; + +//新增片選訊號的回撥函式,這個回撥函式因board而異,因此放在board中實現 +//參考最終呼叫位置ssi->pdata->cs_state(ssi->chip_select, level);實現 +static int spi0_cs_state(int chipselect, int level) +{ + /*TODO: + 每次資料傳輸都會呼叫這個函式(如果有的話) + 實際呼叫時,引數chipselect來自spi_board_info中的chip_select。但是chip_select的含義 + 是由使用者決定的,假設由從裝置傳來的chip_select為0,表示使用GPIO_118作為 + 片選,為1表示用GPIO_119作為片選,傳入2表示使用spi控制器自身支援的 + 一個片選訊號,那麼此處的實現可能是如下這樣的: + if(0 == chipselect) { + ret = gpio_request(GPIO_118, "gpio_name") + //do error check of ret + gpio_direction_output(GPIO_118, level); + gpio_free(GPIO_118); + return 1; + } + if(1 == chipselect) { + ret = gpio_request(GPIO_119, "gpio_name") + //do error check of ret + gpio_direction_output(GPIO_119, level); + gpio_free(GPIO_119); + return 1; + } + if(2 == chipselect) { + TODO: 需要用某種方式配置控制器的暫存器...... + 一種可能的方法是在這裡返回一個flag,然後驅動 + 基於該返回值去配置好對應暫存器 + return 1; + } + */ + return 1; +} + +static struct comip_spi_platform_data comip_spi0_info = { + .num_chipselect = 2,//該spi控制器(spi0)所能支援的片選總數,有幾個外設就填幾,如果填小了,則多餘的外設不會probe + .cs_state = spi0_cs_state, +}; + +static struct comip_spi_platform_data comip_spi1_info = {//foo + .num_chipselect = 1, + .cs_state = NULL, +}; + +static struct comip_spi_platform_data comip_spi2_info = {//foo + .num_chipselect = 1, + .cs_state = NULL, +}; +static void __init comip_init_spi(void) +{ + comip_set_spi0_info(&comip_spi0_info);//註冊spi0裝置(控制器),並傳入該裝置的私有資料comip_spi0_info + comip_set_spi1_info(&comip_spi1_info);//foo + comip_set_spi2_info(&comip_spi2_info);//foo + +/*註冊掛在spi0上的所有從裝置。 +這個函式會先將每個從裝置的節點資訊逐個掛在全域性連結串列board_list中,每掛載一個的 +同時會遍歷一遍spi_master_list,針對每個master節點,通過呼叫spi_match_master_to_boardinfo,來比對 +master節點的bus_num和當前從裝置的bus_num,如果發現二者一致則會註冊該從裝置的device +在從裝置的設備註冊過程中會將該從裝置和其對應的master繫結,該繫結在spi_new_device中 +的spi_alloc_device呼叫中實現,實現的方法就是讓從裝置的master域指向該master。從設備註冊 +過程會去match對應的從裝置驅動,當然還是通過name去找了。找到了我們就看到對應的 +從裝置的probe會被執行。 +如果無法匹配到對應的master,則從裝置不會被註冊,驅動的probe當然不會被呼叫。 +*/ + spi_register_board_info(comip_spi_board_info, ARRAY_SIZE(comip_spi_board_info)); + +/* +在spi.c中維護了兩個全域性連結串列,如下: +static LIST_HEAD(board_list); +static LIST_HEAD(spi_master_list); +board_list 中會存放所有的spi從裝置節點,節點的新增動作發生在spi_register_board_info中。 +spi_master_list中會存放所有的spi控制器節點,即master的節點。這在spi控制器驅動註冊過程中,通過 +呼叫spi_register_master來進行節點的新增。 +以上可以看出必須先註冊控制器的device,而後註冊控制器的驅動以新增控制器對應的 +master節點到連結串列中。 + +從以上分析也可以看到,針對spi_board_info例項化的按照不同的spi控制器的分組其實是沒有 +必要的,因為不管是掛在哪個控制器上的從裝置的info都會被新增到同一個連結串列中(全域性的board_list), +然後再去和邋spi_master_list中的每個maser去匹配。 +*/ +} +#endif + #ifdef CONFIG_USB_HSIC_USB3503 #include <linux/platform_data/usb3503.h> #endif @@ -627,6 +792,13 @@ static struct mfp_pin_cfg comip_mfp_cfg[] = { {CODEC_PA_PIN, MFP_PIN_MODE_GPIO}, #endif +#if defined(CONFIG_SPI_COMIP) || defined(CONFIG_SPI_COMIP_MODULE) + {MFP_PIN_GPIO(157), MFP_PIN_MODE_0}, + {MFP_PIN_GPIO(158), MFP_PIN_MODE_0}, + {MFP_PIN_GPIO(159), MFP_PIN_MODE_0}, + {MFP_PIN_GPIO(160), MFP_PIN_MODE_0}, +#endif + #if defined (CONFIG_USB_HSIC_USB3503) {HSIC_RESET_N_PIN, MFP_PIN_MODE_GPIO}, {HSIC_INT_N_PIN, MFP_PIN_MODE_GPIO}, @@ -811,6 +983,12 @@ static struct mfp_pull_cfg comip_mfp_pull_cfg[] = { {MFP_PIN_GPIO(148), MFP_PULL_UP}, #endif +#if defined(CONFIG_SPI_COMIP) || defined(CONFIG_SPI_COMIP_MODULE) + {MFP_PIN_GPIO(157), MFP_PULL_UP}, + {MFP_PIN_GPIO(158), MFP_PULL_UP}, + {MFP_PIN_GPIO(159), MFP_PULL_UP}, + {MFP_PIN_GPIO(160), MFP_PULL_UP}, +#endif }; #ifdef CONFIG_BAT_ID_BQ2022A @@ -2195,6 +2373,9 @@ static void __init comip_init_board_early(void) comip_init_mfp(); comip_init_gpio_lp(); comip_init_i2c(); +#if defined(CONFIG_SPI_COMIP) || defined(CONFIG_SPI_COMIP_MODULE) + comip_init_spi(); +#endif comip_init_lcd(); comip_init_codec(); } diff --git a/1980c/base/kernel/linux-3.10/arch/arm/mach-lc186x/devices.c b/1980c/base/kernel/linux-3.10/arch/arm/mach-lc186x/devices.c old mode 100644 new mode 100755 index 1304805..2aed2c6 --- a/1980c/base/kernel/linux-3.10/arch/arm/mach-lc186x/devices.c +++ b/1980c/base/kernel/linux-3.10/arch/arm/mach-lc186x/devices.c @@ -22,9 +22,9 @@ void __init comip_register_device(struct platform_device *dev, void *data) { int ret; - dev->dev.platform_data = data; + dev->dev.platform_data = data;//傳入裝置的私有資料以供其驅動提取 - ret = platform_device_register(dev); + ret = platform_device_register(dev);//平臺設備註冊的最後一步 if (ret) dev_err(&dev->dev, "unable to register device: %d\n", ret); } @@ -314,6 +314,7 @@ void __init comip_set_i2c4_info(struct comip_i2c_platform_data *info) comip_register_device(&comip_device_i2c4, info); } +#if defined(CONFIG_SPI_COMIP) || defined(CONFIG_SPI_COMIP_MODULE) static struct resource comip_resource_spi0[] = { [0] = { .start = SSI0_BASE, @@ -337,15 +338,15 @@ static struct resource comip_resource_spi0[] = { }, }; -struct platform_device comip_device_spi0 = { - .name = "comip-spi", - .id = 0, - .resource = comip_resource_spi0, - .num_resources = ARRAY_SIZE(comip_resource_spi0), +struct platform_device comip_device_spi0 = {//spi控制器的device資訊(這是一個平臺裝置) + .name = "comip-spi",//裝置名稱,用來匹配驅動 + .id = 0,//裝置id,對應於驅動中的master->bus_num, 用來區別同一個驅動下的不同裝置。因為一個驅動可以對應多個裝置。對本例而言,我們只有一個spi驅動,但是卻有三個spi控制器在用它 + .resource = comip_resource_spi0,//裝置資源陣列,暫存器對映或中斷號或dma號等等 + .num_resources = ARRAY_SIZE(comip_resource_spi0),//上述資源的數量(即上述陣列寬度) }; void __init comip_set_spi0_info(struct comip_spi_platform_data *info) -{ +{//註冊spi控制器為platform device,info將作為該裝置的私有資料傳入,以供驅動提取 comip_register_device(&comip_device_spi0, info); } @@ -418,6 +419,7 @@ void __init comip_set_spi2_info(struct comip_spi_platform_data *info) { comip_register_device(&comip_device_spi2, info); } +#endif static u64 comip_mmc_dma_mask = COMIP_DMA_BIT_MASK; static struct resource comip_resource_mmc0[] = { diff --git a/1980c/base/kernel/linux-3.10/arch/arm/plat-lc/drivers/base/spi/comip-spi.c b/1980c/base/kernel/linux-3.10/arch/arm/plat-lc/drivers/base/spi/comip-spi.c old mode 100644 new mode 100755 index 68debfb..8f4a2fc --- a/1980c/base/kernel/linux-3.10/arch/arm/plat-lc/drivers/base/spi/comip-spi.c +++ b/1980c/base/kernel/linux-3.10/arch/arm/plat-lc/drivers/base/spi/comip-spi.c @@ -763,9 +763,9 @@ static void comip_spi_cleanup(struct spi_device *spi) static int __init comip_spi_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct comip_spi_platform_data *pdata = dev->platform_data; - struct spi_master *master; - struct comip_ssi *ssi; + struct comip_spi_platform_data *pdata = dev->platform_data;//由該裝置傳入的針對該spi控制器的私有資料,每個控制器都可以通過自己的裝置屬性集傳入與眾不同的私有資料資訊 + struct spi_master *master;//針對spi框架層的master屬性集 + struct comip_ssi *ssi;//該具體的spi控制器的屬性集 struct resource *r; int dma_tx_channel; int dma_rx_channel; @@ -798,21 +798,22 @@ static int __init comip_spi_probe(struct platform_device *pdev) /* Allocate master with space for drv_data and null dma buffer. */ master = spi_alloc_master(dev, sizeof(struct comip_ssi)); + //注意這個實現在給master分配的空間中會追加上該具體的spi控制器的屬性集資訊(即追加了sizeof(*ssi)) if (!master) { dev_err(&pdev->dev, "cannot alloc spi_master\n"); ret = -ENOMEM; goto out; } - master->bus_num = pdev->id; - master->num_chipselect = pdata->num_chipselect; + master->bus_num = pdev->id;//bus_num就是裝置的id + master->num_chipselect = pdata->num_chipselect;//片選總數 master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LOOP; master->cleanup = comip_spi_cleanup; master->setup = comip_spi_setup; master->transfer = comip_spi_transfer; - ssi = spi_master_get_devdata(master); - ssi->master = master; + ssi = spi_master_get_devdata(master);//因為上面給master分配的空間是追加了ssi的空間的,所以這裡可以通過master得到ssi + ssi->master = master;//以下開始設定ssi的屬性集引數 ssi->pdata = pdata; ssi->pdev = pdev; ssi->res = r; @@ -830,7 +831,7 @@ static int __init comip_spi_probe(struct platform_device *pdev) ssi->base = ioremap(r->start, r->end - r->start + 1); if (!ssi->base) { ret = -ENOMEM; - dev_err(&pdev->dev, "cannot remap io 0x%08x\n", r->start); + dev_err(&pdev->dev, "cannot remap io 0x%08x\n", (unsigned int)r->start); goto out_ioremap; } diff --git a/1980c/base/kernel/linux-3.10/drivers/spi/spidev.c b/1980c/base/kernel/linux-3.10/drivers/spi/spidev.c old mode 100644 new mode 100755 index 911e9e0..0459719 --- a/1980c/base/kernel/linux-3.10/drivers/spi/spidev.c +++ b/1980c/base/kernel/linux-3.10/drivers/spi/spidev.c @@ -39,6 +39,22 @@ #include <asm/uaccess.h> +/**********************************/ +#define ENTER \ +do{ printk(KERN_INFO "[SPIDEV_DBG][%04d][%s]\n", __LINE__, __func__); }while(0) + +#define PRINT_DBG(format,x...) \ +do{ printk(KERN_INFO "[SPIDEV_DBG][%04d] " format, __LINE__, ## x); }while(0) + +#define PRINT_INFO(format,x...) \ +do{ printk(KERN_INFO "[SPIDEV_INFO][%04d] " format, __LINE__, ## x); }while(0) + +#define PRINT_WARN(format,x...) \ +do{ printk(KERN_INFO "[SPIDEV_WARN][%04d] " format, __LINE__, ## x); }while(0) + +#define PRINT_ERR(format,x...) \ +do{ printk(KERN_ERR "[SPIDEV_ERR][%04d][%s] " format, __LINE__, __func__, ## x); }while(0) +/**********************************/ /* * This supports access to SPI devices using normal userspace I/O calls. @@ -579,6 +595,7 @@ static int spidev_probe(struct spi_device *spi) int status; unsigned long minor; + ENTER; /* Allocate driver data */ spidev = kzalloc(sizeof(*spidev), GFP_KERNEL); if (!spidev) @@ -677,6 +694,8 @@ static int __init spidev_init(void) * that will key udev/mdev to add/remove /dev nodes. Last, register * the driver which manages those device numbers. */ + + ENTER; BUILD_BUG_ON(N_SPI_MINORS > 256); status = register_chrdev(SPIDEV_MAJOR, "spi", &spidev_fops); if (status < 0)
我的參考程式碼百度網盤路徑:work\DTT\spi-work-flow.rar
相關推薦
spi驅動流程學習
</pre><pre code_snippet_id="1593617" snippet_file_name="blog_20160301_2_3014540" name="code" class="cpp">diff --git a/1980c/b
linux spi驅動開發學習(四)-----spi驅動程式完整流程分析
所有的應用程式使用dev/目錄下建立的裝置,這些字元裝置的操作函式集在檔案spidev.c中實現。 點選(此處)摺疊或開啟 static const struct file_operations spidev_fops = { .owner = THIS
linux spi驅動開發學習(三)-----spi_bitbang.c詳解
SPI介面在模式0下輸出第一位資料的時刻 SPI介面有四種不同的資料傳輸時序,取決於CPOL和CPHL這兩位的組合。圖1中表現了這四種時序, 時序與CPOL、CPHL的關係也可以從圖中看出。 圖1 CPOL是用來決定SCK時鐘訊號空閒時的電平,CPOL=0,空閒電平為低
SPI驅動流程(S3C2440)
2.6.18核心下已經添加了完整的spi子系統了,參考mtd的分析,將從下到上層,再從上到下層的對其進行分析。以下先從下到上的進行分析: driver/spi下有兩個底層相關的spi驅動程式:spi_s3c24xx.c和spi_s3c24xx_gpio.c其中spi_s3c24xx.c是基於s3c24xx
Linux系統SPI驅動學習筆記(一)
SPI是"Serial Peripheral Interface" 的縮寫,是一種四線制的同步序列通訊介面,用來連線微控制器、感測器、儲存裝置,SPI裝置分為主裝置和從裝置兩種,用於通訊和控制的四根線分別是: CS 片選訊號SCK 時鐘訊號MISO 主裝置的
Hasen的linux設備驅動開發學習之旅--時鐘
interval 好的 mask 再次 ask 中斷處理程序 eas 中斷 基礎 /** * Author:hasen * 參考 :《linux設備驅動開發具體解釋》 * 簡單介紹:android小菜鳥的linux * 設備驅動開發學習之
SPI驅動框架-1(DM8127 Linux2.6.37為例)
orm span remove mac 設備 single 隊列 drive for 一、驅動程序結構 1、platform_device 文件:/arch/arm/mach-omap2/device.c static struct omap2_mcspi_platfor
Linux 啟動流程學習
基礎知識Linux 啟動流程學習 開機自檢(加載BIOS) 無論什麽機器,在開機後都要進行通電自檢(硬件),如果硬件有問題,則無法繼續下去。 (例如當內存條松動時或者損壞,就會發出嘀嘀嘀警報聲)。接著開始加載BIOS(Basic Input Output System BIOS是一個寫入到主板上的一個軟件程序
Am335x SPI 驅動測試
添加 版本 drivers 是否 support class device fig 驅動 內核版本:3.14.65 CPU:Am335x 1、編譯內核: make menuconfig Device Drivers -> <*&g
linux裝置驅動開發學習--記憶體和IO訪問
一 I/O 埠 1. 讀寫位元組埠(8 位寬) unsigned inb(unsigned port); void outb(unsigned char byte, unsigned port); 2. 讀寫字埠(16 位寬) unsigned inw(unsigne
linux驅動開發學習--對中斷和核心定時器的學習筆記
一 中斷理解 &nb
MTK SPI驅動開發
MTK SPI驅動開發 1.由於SPI驅動 MTK封裝的比較好,所以比較好處理。 唯一需要注意的是spi使用的全域性Buffer必須要放在記憶體地址為“NONCACHEDZI”的區域 直接上程式碼管腳配置此處不再贅述 /****************************
SPI驅動檔案解析
三:SPI裝置驅動程式 在板檔案中新增SPI裝置 <span style="color:#444444"><strong>static </strong> <strong>struct</strong> spi_b
java丨事件驅動程式設計學習筆記(二)
一、匿名監聽器 監聽器類是特意為建立一個GUI元件(例如,一個按鈕)而設計的監聽物件。監聽器類不被其他應用程式所共享,因此,正確的做法是將它作為一個內部類定義在框架中。 可以使用匿名內部類簡化內部類監聽器。匿名內部類時沒有名字的內部類。它進一步完成定義內部類和建立一個該類的例項。 內部類Enlarg
mini2440 SPI驅動移植(轉)
按照下面帖子的方法,本人試驗成功,只需按照下面步驟進行就行了。 原帖地址: http://blog.csdn.net/lxmky/article/details/6858322 注:原文最後短接的MISO和MOSI指的是SPI1的,區別於SPI0 min
STM32之SPI與QSPI學習筆記
QSPI介面簡介 QSPI是Queued SPI的簡寫,是Motorola公司推出的SPI介面的擴充套件,比SPI應用更加廣泛。 在SPI協議的基礎上,Motorola公司對其功能進行了增強,增加了佇列傳輸機制,推出了佇列序列外圍介面協議(即QSPI協議)。 QSPI是一種專用的通訊
rk3399下spi驅動
SPI 使用 Note:本文從firefly wiki擷取 SPI是一種高速的,全雙工,同步序列通訊介面,用於連線微控制器、感測器、儲存裝置等。 Firefly-RK3399 開發板提供了 SPI1 (單片選)介面,具體位置如下圖: SPI工作方式 SPI以主從方式工
【驅動】第2課、輸入子系統驅動之學習筆記
一、筆記1、問題:原本的字元驅動框架被拆分為兩部分,在本例的 buttons.c 驅動中,沒有用 open, read, write 等操作,只是在按鍵中斷及其觸發的系統定時器中斷中得到按鍵值並上報, 問題:原本一套驅動程式呼叫的步驟被拆分為幾部分了?都在哪裡?如今一套按鍵 操作的驅動呼叫流程是怎樣的?答:
Linux裝置驅動開發學習筆記
2016.6.25 這部門主要是之前學習linux裝置驅動開發時候的一些筆記,主要學習的參考書是《Linux裝置驅動開發詳解第2版》 書連結:http://note.youdao.com/noteshare?id=bbf134da309035b2093c5abcd5c7c8ac&
jsp流程學習1
1.第一次訪問某個網站時,伺服器現將jsp翻譯成java,再將java翻譯成class檔案。 2.第二次訪問直接訪問class檔案,如果服務端程式碼修改了,將會在再次訪問時重新翻譯、編譯。 3.jsp和servlet可以相互轉換 4.因為第一次請求服務端會有翻譯或編譯的過程,因此比較慢;後續