当前位置:  编程技术>移动开发
本页文章导读:
    ▪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

    
[3] Chrome 手机浏览器的过程生命周期,国内的浏览器能做到这个地步就可以了
    来源: 互联网  发布时间: 2014-02-18
Chrome 手机浏览器的进程生命周期,国内的浏览器能做到这个地步就可以了

移动应用的生命周期,我觉得 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
2. 如果把创建的tab 关闭,则仅剩下一个进程:
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



    
最新技术文章:
▪Android开发之登录验证实例教程
▪Android开发之注册登录方法示例
▪Android获取手机SIM卡运营商信息的方法
▪Android实现将已发送的短信写入短信数据库的...
▪Android发送短信功能代码
▪Android根据电话号码获得联系人头像实例代码
▪Android中GPS定位的用法实例
▪Android实现退出时关闭所有Activity的方法
▪Android实现文件的分割和组装
▪Android录音应用实例教程
▪Android双击返回键退出程序的实现方法
▪Android实现侦听电池状态显示、电量及充电动...
▪Android获取当前已连接的wifi信号强度的方法
▪Android实现动态显示或隐藏密码输入框的内容
▪根据USER-AGENT判断手机类型并跳转到相应的app...
▪Android Touch事件分发过程详解
▪Android中实现为TextView添加多个可点击的文本
▪Android程序设计之AIDL实例详解
▪Android显式启动与隐式启动Activity的区别介绍
▪Android按钮单击事件的四种常用写法总结
▪Android消息处理机制Looper和Handler详解
▪Android实现Back功能代码片段总结
▪Android实用的代码片段 常用代码总结
▪Android实现弹出键盘的方法
▪Android中通过view方式获取当前Activity的屏幕截...
▪Android提高之自定义Menu(TabMenu)实现方法
▪Android提高之多方向抽屉实现方法
▪Android提高之MediaPlayer播放网络音频的实现方法...
▪Android提高之MediaPlayer播放网络视频的实现方法...
▪Android提高之手游转电视游戏的模拟操控
 


站内导航:


特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

©2012-2021,,E-mail:www_#163.com(请将#改为@)

浙ICP备11055608号-3