当前位置: 首页 > wzjs >正文

夏津网站开发青岛推广优化

夏津网站开发,青岛推广优化,做任务赚钱的app秒提现,做本地门户网站文章目录 1、前言2、SPI总线注册3、SPI设备注册4、SPI驱动注册5、SPI BSP驱动 1、前言 学习参考书籍以及本文涉及的示例程序:李山文的《Linux驱动开发进阶》本文属于个人学习后的总结,不太具备教学功能。 2、SPI总线注册 驱动源码文件:dri…

文章目录

  • 1、前言
  • 2、SPI总线注册
  • 3、SPI设备注册
  • 4、SPI驱动注册
  • 5、SPI BSP驱动

1、前言

  1. 学习参考书籍以及本文涉及的示例程序:李山文的《Linux驱动开发进阶》
  2. 本文属于个人学习后的总结,不太具备教学功能。

2、SPI总线注册

驱动源码文件:drivers/spi/spi.c,负责注册spi总线和spi设备以及spi控制器设备:

上面的spi_init是整个总线注册的入口,但是没有spi_exit出口函数。这一点很多驱动的总线也是这样,只有注册,没有注销,这是因为总线会一直存在,只有当系统关闭时,总线才不需要了。相关的spi总线结构体如下:

除了注册bus,还注册了class:

相关class结构体为:

注册类后,会在/sys/class目录下生成spi_master文件夹,而dev_groups会在/sys/class/spi_master目录下生成相关的属性文件分组目录。

3、SPI设备注册

在注册SPI控制器驱动时,此时会扫描设备树中的spi控制器节点,找到匹配的,则会注册成设备,并且会将控制器设备树节点下的子节点全部注册为spi设备。如下代码所示,spi注册控制器时,在最后会调用of_register_spi_devices函数来解析设备树,然后将其注册为spi设备。

int spi_register_controller(struct spi_controller *ctlr)
{.../* Register devices from the device tree and ACPI */of_register_spi_devices(ctlr);	// 将spi子设备注册进spi总线acpi_register_spi_devices(ctlr);return status;...
}

4、SPI驱动注册

SPI驱动分为控制器驱动和设备驱动,其中控制器驱动又称为BSP驱动程序,该驱动程序一般由芯片原厂的驱动工程师来编写,而设备驱动程序指对芯片的外部设备来编写驱动。

先看SPI控制器驱动的注册,该驱动注册由platform总线注册,这是因为在SPI控制器驱动注册前,SPI的设备驱动无法注册,原因就是SPI子设备驱动的注册依赖于SPI控制器驱动,只有当SPI控制器驱动注册完毕后,module_spi_driver宏才能使用(实际上是spi_register_driver和spi_unregister_driver函数)。所以SPI控制器驱动注册只能依靠platform平台总线注册,因为platform平台总线驱动编译到内核中的,一定会注册, 即module_platform_driver宏一定是可以使用的。

5、SPI BSP驱动

spi bsp驱动其实就是编写spi的控制器驱动。linux中spi控制器被抽象为spi_master或者spi_controller,在bsp中,我们常用spi_master,结构体如下:

struct spi_controller {struct device	dev;struct list_head list;s16			bus_num;u16			num_chipselect;u16			dma_alignment;u32			mode_bits;u32			buswidth_override_bits;u32			bits_per_word_mask;
#define SPI_BPW_MASK(bits) BIT((bits) - 1)
#define SPI_BPW_RANGE_MASK(min, max) GENMASK((max) - 1, (min) - 1)u32			min_speed_hz;u32			max_speed_hz;u16			flags;
#define SPI_CONTROLLER_HALF_DUPLEX	BIT(0)	/* can't do full duplex */
#define SPI_CONTROLLER_NO_RX		BIT(1)	/* can't do buffer read */
#define SPI_CONTROLLER_NO_TX		BIT(2)	/* can't do buffer write */
#define SPI_CONTROLLER_MUST_RX		BIT(3)	/* requires rx */
#define SPI_CONTROLLER_MUST_TX		BIT(4)	/* requires tx */
#define SPI_MASTER_GPIO_SS		BIT(5)	/* GPIO CS must select slave */bool			slave;size_t (*max_transfer_size)(struct spi_device *spi);size_t (*max_message_size)(struct spi_device *spi);struct mutex		io_mutex;spinlock_t		bus_lock_spinlock;struct mutex		bus_lock_mutex;bool			bus_lock_flag;int			(*setup)(struct spi_device *spi);int (*set_cs_timing)(struct spi_device *spi, struct spi_delay *setup,struct spi_delay *hold, struct spi_delay *inactive);int			(*transfer)(struct spi_device *spi,struct spi_message *mesg);void			(*cleanup)(struct spi_device *spi);bool			(*can_dma)(struct spi_controller *ctlr,struct spi_device *spi,struct spi_transfer *xfer);bool				queued;struct kthread_worker		*kworker;struct kthread_work		pump_messages;spinlock_t			queue_lock;struct list_head		queue;struct spi_message		*cur_msg;bool				idling;bool				busy;bool				running;bool				rt;bool				auto_runtime_pm;bool                            cur_msg_prepared;bool				cur_msg_mapped;bool				last_cs_enable;bool				last_cs_mode_high;bool                            fallback;struct completion               xfer_completion;size_t				max_dma_len;int (*prepare_transfer_hardware)(struct spi_controller *ctlr);int (*transfer_one_message)(struct spi_controller *ctlr,struct spi_message *mesg);int (*unprepare_transfer_hardware)(struct spi_controller *ctlr);int (*prepare_message)(struct spi_controller *ctlr,struct spi_message *message);int (*unprepare_message)(struct spi_controller *ctlr,struct spi_message *message);int (*slave_abort)(struct spi_controller *ctlr);void (*set_cs)(struct spi_device *spi, bool enable);int (*transfer_one)(struct spi_controller *ctlr, struct spi_device *spi,struct spi_transfer *transfer);void (*handle_err)(struct spi_controller *ctlr,struct spi_message *message);const struct spi_controller_mem_ops *mem_ops;struct spi_delay	cs_setup;struct spi_delay	cs_hold;struct spi_delay	cs_inactive;int			*cs_gpios;struct gpio_desc	**cs_gpiods;bool			use_gpio_descriptors;
#ifdef __GENKSYMS__u8			unused_native_cs;u8			max_native_cs;
#elses8			unused_native_cs;s8			max_native_cs;
#endifstruct spi_statistics	statistics;struct dma_chan		*dma_tx;struct dma_chan		*dma_rx;void			*dummy_rx;void			*dummy_tx;int (*fw_translate_cs)(struct spi_controller *ctlr, unsigned cs);bool			ptp_sts_supported;unsigned long		irq_flags;ANDROID_KABI_RESERVE(1);ANDROID_KABI_RESERVE(2);
};

以下列出几个比较重要字段的解释,后面会重点看看transfer_one_message字段,该字段实现真实数据的传输:

linux提供了一个函数来分配一个spi控制器:

static inline struct spi_controller *spi_alloc_master(struct device *host,unsigned int size)
{return __spi_alloc_controller(host, size, false);
}

然后使用如下函数注册:

int devm_spi_register_controller(struct device *dev,struct spi_controller *ctlr)

对于bsp而言,在使用前必须开启spi时钟。如下所示,设备树中spi时钟属性,用来指定时钟源:

spi bsp示例程序可以参考:李山文的《Linux驱动开发进阶》spi子系统示例程序。

下面贴出dummy-spimaster.c

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/spi/spi.h>
#include <linux/sysfs.h>
#include <linux/slab.h>static int dummy_spimaster_setup(struct spi_device *spi)
{int ret = 0;if(spi->chip_select >= spi->master->num_chipselect){printk(KERN_INFO " invalid chip_select\n");return -1;}return ret;
}static void dummy_spimaster_set_cs(struct spi_device *spi, bool enable)
{if (enable) {//set IO(spi->chip_select) high levelprintk(KERN_INFO "spi cs[%d]: high\n", spi->chip_select);}else {//set IO(spi->chip_select) low levelprintk(KERN_INFO "spi cs[%d]: low\n", spi->chip_select);}
}static int dummy_spimaster_transfer_one(struct spi_master *master, struct spi_device *spi, struct spi_transfer *tfr)
{int bytes;unsigned char *rx_buff = tfr->rx_buf;const unsigned char *tx_buff = tfr->tx_buf;bytes = tfr->len;while(bytes) {if(tx_buff) {printk(KERN_INFO "TX: %c \n", *tx_buff);tx_buff ++ ;}if(rx_buff) {*rx_buff = 'a';//读取时每次获取'a'rx_buff ++ ;}bytes -- ;}return 0;
}static int dummy_spimaster_probe(struct platform_device *pdev)
{int ret;struct spi_master *master;master = spi_alloc_master(&pdev->dev, 0);if (!master) {printk(KERN_ERR "unable to alloc SPI master\n");return -EINVAL;}master->dev.of_node = pdev->dev.of_node;master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST;master->bus_num = -1;master->auto_runtime_pm = false;//不支持PM,如果需要支持,则需要实现platform_driver中.driver.pmmaster->num_chipselect = 4;master->transfer_one = dummy_spimaster_transfer_one;master->setup = dummy_spimaster_setup;master->max_speed_hz = 100 * 1000 * 1000; //100MHzmaster->min_speed_hz = 3 * 1000;    //3kHzmaster->set_cs = dummy_spimaster_set_cs;ret = devm_spi_register_master(&pdev->dev, master);if (ret) {dev_err(&pdev->dev, "spi register master failed!\n");spi_master_put(master);return ret;}platform_set_drvdata(pdev, master);return 0;
} static int dummy_spimaster_remove(struct platform_device *pdev)
{struct spi_master	*master = platform_get_drvdata(pdev);spi_unregister_master(master);printk("%s:%d\n", __FUNCTION__, __LINE__);return 0;
}static const struct of_device_id dummy_spimaster_match[] = {{ .compatible = "dummy-spi-master", },{}
};
MODULE_DEVICE_TABLE(of, dummy_spimaster_match);static struct platform_driver dummy_spimaster_driver = {.driver = {.name = "dummy_spimaster_driver",.owner = THIS_MODULE,.of_match_table = dummy_spimaster_match,},.probe = dummy_spimaster_probe,.remove = dummy_spimaster_remove,//.driver.pm = 
};module_platform_driver(dummy_spimaster_driver);MODULE_LICENSE("GPL");
MODULE_AUTHOR("1477153217@qq.com");
MODULE_VERSION("0.1");
MODULE_DESCRIPTION("dummy spi controller driver test");

static int dummy_spimaster_transfer_one(struct spi_master *master, struct spi_device *spi, struct spi_transfer *tfr)
{int bytes;unsigned char *rx_buff = tfr->rx_buf;const unsigned char *tx_buff = tfr->tx_buf;bytes = tfr->len;while(bytes) {if(tx_buff) {printk(KERN_INFO "TX: %c \n", *tx_buff);tx_buff ++ ;}if(rx_buff) {*rx_buff = 'a';//读取时每次获取'a'rx_buff ++ ;}bytes -- ;}return 0;
}

接下来再看spi设备驱动程序:

http://www.dtcms.com/wzjs/276312.html

相关文章:

  • wordpress主页导航谷歌seo网站运营
  • 手机模板网站模板下载工具浙江网站建设营销
  • 网站建设公司合同模板石家庄网站建设方案
  • 电子商务seo名词解释夫唯seo教程
  • 个旧网站建设网络营销相关的岗位有哪些
  • 平面设计教程网站有哪些网络营销策划书怎么写
  • 中联建设集团网站成都短视频代运营
  • 网站报价单模板搜索排行
  • gogogo高清在线观看视频百度seo优化分析
  • 铁威马 Nas 做网站电脑培训学校能学什么
  • 笔记本可以做网站吗网络营销案例分析题及答案
  • 代理商加盟网站网站测试
  • 网站导航栏注明做百度搜索关键词
  • 五金日杂店做网站百度医生
  • 快速建设网站视频教程长沙seo优化排名
  • 南昌汉邦网站建设怎么优化网络
  • 诚信网站认证怎么做网片
  • 渗透网站后台数据截图每日精选12条新闻
  • 怎样用模块做网站谷歌 google
  • wordpress it模板下载地址佛山做网络优化的公司
  • 望城门户网站seo关键词排名
  • 做网站图片什么软件浏览器正能量网站免费
  • 网站建设的通知网站维护分工兰州seo
  • 传统网站模版网络推广的几种方式
  • 那个网站教人做冰点免费的网页模板网站
  • 如何做自己网站云播东莞快速优化排名
  • 做网站优化的话术百度视频免费下载
  • 收费网站建设百度网盘搜索入口
  • 网站建设的同义词西安危机公关公司
  • 加盟招商网站建设如何去做网络推广