当前位置: 编程技术>移动开发
本页文章导读:
▪i.mx536(cotex-a8核)的SPI驱动懂得一(probe) i.mx536(cotex-a8核)的SPI驱动理解一(probe)
//整个probe主要包含以下几步,与其它的ARM芯片很相似
//(1)填充三个结构体struct mxc_spi_master,struct spi_master,struct mxc_spi
//(2)申请IO资源,中断
//(3)SPI寄存器.........
▪ 一个不错的可以自定义卡通片的tableview类 一个不错的可以自定义动画的tableview类https://github.com/applidium/ADLivelyTableView ......
▪ Chrome 手机浏览器的过程生命周期,国内的浏览器能做到这个地步就可以了 Chrome 手机浏览器的进程生命周期,国内的浏览器能做到这个地步就可以了移动应用的生命周期,我觉得 chrome 的表现非常好,这里大概展示一下:
com.android.chrome 基本进程,还没有研究它.........
[1]i.mx536(cotex-a8核)的SPI驱动懂得一(probe)
来源: 互联网 发布时间: 2014-02-18
i.mx536(cotex-a8核)的SPI驱动理解一(probe)
//整个probe主要包含以下几步,与其它的ARM芯片很相似 //(1)填充三个结构体struct mxc_spi_master,struct spi_master,struct mxc_spi //(2)申请IO资源,中断 //(3)SPI寄存器配置 //(4)spi_bitbang_start(即调用spi_register_master) //(5)spi_new_device static int mxc_spi_probe(struct platform_device *pdev) { //spi私有数据结构体,imx芯片独有,主要存储板级配置文件中设置的一些参数 //个人觉得这个结构体有点多余,还没弄清楚原因? struct mxc_spi_master *mxc_platform_info; //描述spi控制器结构体,spi驱动通用 struct spi_master *master; struct mxc_spi *master_drv_data = NULL; //一般的ARM控制器的SPI驱动都会包含以上三个结构体(具体名称不用) struct resource *res; unsigned int spi_ver, wml; int ret = -ENODEV; /* Get the platform specific data for this master device */ //为什么这里可以强制转换struct platform_data为struct mxc_spi_master? //因为platform_data是一个void类型的指针 mxc_platform_info = (struct mxc_spi_master *)pdev->dev.platform_data; if (!mxc_platform_info) { dev_err(&pdev->dev, "can't get the platform data for CSPI\n"); return -EINVAL; } /* Allocate SPI master controller */ master = spi_alloc_master(&pdev->dev, sizeof(struct mxc_spi)); if (!master) { dev_err(&pdev->dev, "can't alloc for spi_master\n"); return -ENOMEM; } /* Set this device's driver data to master */ //保存master到pdev platform_set_drvdata(pdev, master); /* Set this master's data from platform_info */ //主机控制器编号,如果板子上有多个spi总线,靠这个域区分 master->bus_num = pdev->id + 1; //支持spi设备个数 master->num_chipselect = mxc_platform_info->maxchipselect; //模式标志位 master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; #ifdef CONFIG_SPI_MXC_TEST_LOOPBACK master->num_chipselect += 1; #endif /* Set the master controller driver data for this master */ //spi_master_get_devdata调用dev_set_drvdata获取设备私有数据 //读取保存在master->dev中的私有数据 //这个私有数据是在上面的spi_alloc_master中配置的。 master_drv_data = spi_master_get_devdata(master); //mxc_bitbang是一个spi_bitbang结构体,struct spi_bitbang 是具体的负责数据传输的结构体 master_drv_data->mxc_bitbang.master = spi_master_get(master); //把存储在mxc_platform_info中的一些参数(板级配置文件中设置)存储到master_drv_data if (mxc_platform_info->chipselect_active) master_drv_data->chipselect_active = mxc_platform_info->chipselect_active; if (mxc_platform_info->chipselect_inactive) master_drv_data->chipselect_inactive = mxc_platform_info->chipselect_inactive; /* Identify SPI version */ //根据扳级配置文件中设置的版本 spi_ver = mxc_platform_info->spi_version; if (spi_ver == 7) { master_drv_data->spi_ver_def = &spi_ver_0_7; } else if (spi_ver == 5) { master_drv_data->spi_ver_def = &spi_ver_0_5; } else if (spi_ver == 4) { master_drv_data->spi_ver_def = &spi_ver_0_4; } else if (spi_ver == 0) { master_drv_data->spi_ver_def = &spi_ver_0_0; } else if (spi_ver == 23) { master_drv_data->spi_ver_def = &spi_ver_2_3; } dev_dbg(&pdev->dev, "SPI_REV 0.%d\n", spi_ver); /* Set the master bitbang data */ //SPI传输的各个函数 master_drv_data->mxc_bitbang.chipselect = mxc_spi_chipselect; master_drv_data->mxc_bitbang.txrx_bufs = mxc_spi_transfer; //该函数做一些初始化的工作 master_drv_data->mxc_bitbang.master->setup = mxc_spi_setup; master_drv_data->mxc_bitbang.master->cleanup = mxc_spi_cleanup; master_drv_data->mxc_bitbang.setup_transfer = mxc_spi_setup_transfer; /* Initialize the completion object */ //completion是内核中一个轻量级机制,允许一个线程告诉另一个线程工作已完成 init_completion(&master_drv_data->xfer_done); /* Set the master controller register addresses and irqs */ //获取板级配置文件中设置的资源 master_drv_data->res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!master_drv_data->res) { dev_err(&pdev->dev, "can't get platform resource for CSPI%d\n", master->bus_num); ret = -ENOMEM; goto err; } //检测申请的资源是否可用,并把资源标志为已用 if (!request_mem_region(master_drv_data->res->start, master_drv_data->res->end - master_drv_data->res->start + 1, pdev->name)) { dev_err(&pdev->dev, "request_mem_region failed for CSPI%d\n", master->bus_num); ret = -ENOMEM; goto err; } //映射虚拟内存 master_drv_data->base = ioremap(master_drv_data->res->start, master_drv_data->res->end - master_drv_data->res->start + 1); if (!master_drv_data->base) { dev_err(&pdev->dev, "invalid base address for CSPI%d\n", master->bus_num); ret = -EINVAL; goto err1; } //获取板级配置文件中设置的中断号 master_drv_data->irq = platform_get_irq(pdev, 0); if (master_drv_data->irq < 0) { dev_err(&pdev->dev, "can't get IRQ for CSPI%d\n", master->bus_num); ret = -EINVAL; goto err1; } /* Register for SPI Interrupt */ //注册中断函数mxc_spi_isr ret = request_irq(master_drv_data->irq, mxc_spi_isr, 0, "CSPI_IRQ", master_drv_data); if (ret != 0) { dev_err(&pdev->dev, "request_irq failed for CSPI%d\n", master->bus_num); goto err1; } master_drv_data->dev = &pdev->dev; /* Setup the DMA */ //如果设置了dma,(这个在我的板级配置文件中未配置) master_drv_data->usedma = 0; res = platform_get_resource(pdev, IORESOURCE_DMA, 0); if (res) { master_drv_data->dma_tx_id = res->start; master_drv_data->dma_tx_id = res->start; if (pdev->dev.dma_mask == NULL) dev_warn(&pdev->dev, "no dma mask\n"); else master_drv_data->usedma = 1; } if (master_drv_data->usedma) { master_drv_data->dma_tx_ch = mxc_dma_request(master_drv_data->dma_tx_id, "mxc_spi"); if (master_drv_data->dma_tx_ch < 0) { dev_info(&pdev->dev, "Can't allocate RX DMA ch\n"); master_drv_data->usedma = 0; ret = -ENXIO; goto err_no_txdma; } mxc_dma_callback_set(master_drv_data->dma_tx_ch, mxc_spi_dma_tx_callback, (void *)master_drv_data); /* Allocate tmp_buf for tx_buf */ master_drv_data->tmp_buf = kzalloc(SPI_BUFSIZ, GFP_KERNEL); if (master_drv_data->tmp_buf == NULL) { ret = -ENOMEM; goto err_tmp_buf_alloc; } } /* Setup any GPIO active */ //配置SPI口IO,一般高级ARM芯片有多个SPI口,配置哪个由bus_num决定,bus_num是板级配置文件中设置 gpio_spi_active(master->bus_num - 1); /* Enable the CSPI Clock, CSPI Module, set as a master */ //i.mx536的SPI控制器的寄存器配置 master_drv_data->ctrl_addr = master_drv_data->base + master_drv_data->spi_ver_def->ctrl_reg_addr; master_drv_data->dma_addr = master_drv_data->base + master_drv_data->spi_ver_def->dma_reg_addr; master_drv_data->stat_addr = master_drv_data->base + master_drv_data->spi_ver_def->stat_reg_addr; master_drv_data->period_addr = master_drv_data->base + master_drv_data->spi_ver_def->period_reg_addr; master_drv_data->test_addr = master_drv_data->base + master_drv_data->spi_ver_def->test_reg_addr; master_drv_data->reset_addr = master_drv_data->base + master_drv_data->spi_ver_def->reset_reg_addr; //开启SPI时钟 master_drv_data->clk = clk_get(&pdev->dev, "cspi_clk"); clk_enable(master_drv_data->clk); //获取时钟频率 master_drv_data->spi_ipg_clk = clk_get_rate(master_drv_data->clk); __raw_writel(master_drv_data->spi_ver_def->reset_start, master_drv_data->reset_addr); udelay(1); __raw_writel((master_drv_data->spi_ver_def->spi_enable + master_drv_data->spi_ver_def->master_enable), master_drv_data->base + MXC_CSPICTRL); __raw_writel(MXC_CSPIPERIOD_32KHZ, master_drv_data->period_addr); __raw_writel(0, MXC_CSPIINT + master_drv_data->ctrl_addr); if (master_drv_data->usedma) { /* Set water mark level to be the half of fifo_size in DMA */ wml = master_drv_data->spi_ver_def->fifo_size / 2; wml = wml << master_drv_data->spi_ver_def->tx_wml_shift; __raw_writel((__raw_readl(master_drv_data->dma_addr) & ~master_drv_data->spi_ver_def->tx_wml_mask) | wml, master_drv_data->dma_addr); } /* Start the SPI Master Controller driver */ //启动SPI控制器 //最终调用spi_register_master来注册spi控制器 ret = spi_bitbang_start(&master_drv_data->mxc_bitbang); if (ret != 0) goto err2; printk(KERN_INFO "CSPI: %s-%d probed\n", pdev->name, pdev->id); #ifdef CONFIG_SPI_MXC_TEST_LOOPBACK { int i; struct spi_board_info *bi = &loopback_info[0]; for (i = 0; i < ARRAY_SIZE(loopback_info); i++, bi++) { if (bi->bus_num != master->bus_num) continue; dev_info(&pdev->dev, "registering loopback device '%s'\n", bi->modalias); spi_new_device(master, bi); } } #endif clk_disable(master_drv_data->clk); return ret; err2: gpio_spi_inactive(master->bus_num - 1); clk_disable(master_drv_data->clk); clk_put(master_drv_data->clk); if (master_drv_data->usedma) kfree(master_drv_data->tmp_buf); err_tmp_buf_alloc: if (master_drv_data->usedma) mxc_dma_free(master_drv_data->dma_tx_ch); err_no_txdma: free_irq(master_drv_data->irq, master_drv_data); err1: //最终调用free函数,释放内存 iounmap(master_drv_data->base); release_mem_region(pdev->resource[0].start, pdev->resource[0].end - pdev->resource[0].start + 1); err: spi_master_put(master); kfree(master); platform_set_drvdata(pdev, NULL); return ret; }
[2] 一个不错的可以自定义卡通片的tableview类
来源: 互联网 发布时间: 2014-02-18
一个不错的可以自定义动画的tableview类
https://github.com/applidium/ADLivelyTableView
https://github.com/applidium/ADLivelyTableView
[3] Chrome 手机浏览器的过程生命周期,国内的浏览器能做到这个地步就可以了
来源: 互联网 发布时间: 2014-02-18
Chrome 手机浏览器的进程生命周期,国内的浏览器能做到这个地步就可以了
2. 如果把创建的tab 关闭,则仅剩下一个进程:
3. 输入网址 m.baidu.com,发现启动了 sandboxed_process0 关闭了,启动一个 sandboxed_process1进程:
再输入一个网址:
再打开一个 tab :
移动应用的生命周期,我觉得 chrome 的表现非常好,这里大概展示一下:
com.android.chrome 基本进程,还没有研究它是做什么的
com.android.chrome:sandboxed_process0 空白tab对应的进程
com.android.chrome:sandboxed_process[1~n] 正常页面对应的进程名称。 但是并不像 PC 浏览器一样是每个 TAB 一个进程那样,具体规则后续再做分析。
简单的分析方法:
adb 链接手机之后, adb shell top | grep chrome 来查看 chrome 的生命周期
1. 打开 Chrome,会开启一个空tab, 此时会创建两个进程,两次刷新的结果如下:14038 0 0% S 13 682096K 28364K fg u0_a8 com.android.chrome 14038 3 6% S 31 723816K 59464K fg u0_a8 com.android.chrome 14055 0 0% S 14 721328K 51724K fg u0_i41 com.android.chrome:sandboxed_process0 14038 2 22% S 31 723816K 63708K fg u0_a8 com.android.chrome 14055 0 0% S 14 721328K 51724K fg u0_i41 com.android.chrome:sandboxed_process0 14038 2 0% S 31 723816K 63520K fg u0_a8 com.android.chrome 14055 0 0% S 14 721328K 51724K fg u0_i41 com.android.chrome:sandboxed_process0 14038 0 1% S 31 723816K 63520K fg u0_a8 com.android.chrome
14038 0 0% S 31 716252K 59408K fg u0_a8 com.android.chrome
3. 输入网址 m.baidu.com,发现启动了 sandboxed_process0 关闭了,启动一个 sandboxed_process1进程:
14038 0 2% S 44 736976K 65128K fg u0_a8 com.android.chrome 14388 1 1% S 14 714468K 45816K fg u0_i43 com.android.chrome:sandboxed_process1 14038 1 3% S 44 736976K 65160K fg u0_a8 com.android.chrome 14388 1 2% S 14 714468K 46020K fg u0_i43 com.android.chrome:sandboxed_process1 14038 0 5% S 44 736976K 65196K fg u0_a8 com.android.chrome 14388 1 2% S 14 714468K 46020K fg u0_i43 com.android.chrome:sandboxed_process1 14038 0 8% S 44 736976K 65232K fg u0_a8 com.android.chrome 14388 1 5% S 14 714468K 46020K fg u0_i43 com.android.chrome:sandboxed_process1
再次打开一个新的 tab, 发现有启动了一个 sandboxed_process0
14038 1 4% S 45 738184K 69832K fg u0_a8 com.android.chrome 14805 1 1% S 14 719604K 49680K fg u0_i44 com.android.chrome:sandboxed_process0 14388 1 0% S 14 707288K 39920K fg u0_i43 com.android.chrome:sandboxed_process1 14038 0 16% S 45 738184K 69836K fg u0_a8 com.android.chrome 14388 1 0% S 14 707288K 40184K fg u0_i43 com.android.chrome:sandboxed_process1 14805 1 0% S 14 719604K 49680K fg u0_i44 com.android.chrome:sandboxed_process0 14388 1 0% S 14 707288K 40184K fg u0_i43 com.android.chrome:sandboxed_process1
14038 0 0% S 45 738880K 70432K fg u0_a8 com.android.chrome 14388 1 0% S 14 707288K 40180K fg u0_i43 com.android.chrome:sandboxed_process1 14841 0 1% S 14 726272K 58548K fg u0_i45 com.android.chrome:sandboxed_process2
再打开一个 tab :
14038 2 26% S 45 739200K 71408K fg u0_a8 com.android.chrome 14841 0 0% S 14 716800K 50188K fg u0_i45 com.android.chrome:sandboxed_process2 14388 1 0% S 14 707288K 40184K fg u0_i43 com.android.chrome:sandboxed_process1 15029 0 0% S 14 719680K 49864K fg u0_i46 com.android.chrome:sandboxed_process0
将Chrome 切换到后台,发现只剩下一个进程,并且占用内存也不算太大。
14038 1 0% S 44 730760K 64444K bg u0_a8 com.android.chrome 14038 1 0% S 44 730760K 64444K bg u0_a8 com.android.chrome 14038 1 0% S 44 730760K 64444K bg u0_a8 com.android.chrome 14038 1 0% S 44 730760K 64556K bg u0_a8 com.android.chrome 14038 1 0% S 44 730760K 64556K bg u0_a8 com.android.chrome
最新技术文章: