什么时spi的bitbang

http://blog.sina.com.cn/s/blog_6524fd1f01010wsv.html

SPI只有主模式和从模式之分,没有读和写的说法,外设的写操作和读操作是同步完成的。如果只进行写操作,主机只需忽略接收到的字节;反之,若主机要读取从机的一个字节,就必须发送一个空字节来引发从机的传输。也就是说,你发一个数据必然会收到一个数据;你要收一个数据必须也要先发一个数据

SPI原理超详细讲解---值得一看_Z小旋-CSDN博客_spi通信的详细讲解

测试程序:

Linux下SPI驱动的移植和应用程序的测试_ccccccsdn的博客-CSDN博客_spi测试

spi设备端驱动:

spidev_open函数:

static int spidev_open(struct inode *inode, struct file *filp)
{struct spidev_data *spidev;int         status = -ENXIO;mutex_lock(&device_list_lock);//通过设备号找出对应的spidev设备list_for_each_entry(spidev, &device_list, device_entry) {if (spidev->devt == inode->i_rdev) {status = 0;break;}}//给tx_buffer和rx_buffer分配内存空间if (!spidev->tx_buffer) {spidev->tx_buffer = kmalloc(bufsiz, GFP_KERNEL);}if (!spidev->rx_buffer) {spidev->rx_buffer = kmalloc(bufsiz, GFP_KERNEL);}mutex_unlock(&device_list_lock);return 0;}

open函数中涉及的spidev_data数据 结构:

struct spidev_data {dev_t            devt;struct spi_device  *spi;struct list_head   device_entry;......u8           *tx_buffer;u8           *rx_buffer;u32          speed_hz;
};

数据传输从spidev_ioctl函数开始,直接看default:

static long spidev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{struct spidev_data *spidev;struct spi_device   *spi;unsigned       n_ioc;struct spi_ioc_transfer   *ioc;spi = spi_dev_get(spidev->spi);default:ioc = spidev_get_ioc_message(cmd, (struct spi_ioc_transfer __user *)arg, &n_ioc);if (!ioc)break;   /* n_ioc is also 0 *//* translate to spi_message, execute */retval = spidev_message(spidev, ioc, n_ioc);kfree(ioc);break;}

spidev_message函数:

static int spidev_message(struct spidev_data *spidev,struct spi_ioc_transfer *u_xfers, unsigned n_xfers)
{struct spi_message msg;struct spi_transfer *k_xfers;struct spi_transfer    *k_tmp;struct spi_ioc_transfer *u_tmp;unsigned      n, total, tx_total, rx_total;u8         *tx_buf, *rx_buf;int            status = -EFAULT;spi_message_init(&msg);k_xfers = kcalloc(n_xfers, sizeof(*k_tmp), GFP_KERNEL);tx_buf = spidev->tx_buffer;rx_buf = spidev->rx_buffer;total = 0;tx_total = 0;rx_total = 0;for (n = n_xfers, k_tmp = k_xfers, u_tmp = u_xfers; n ;n--, k_tmp++, u_tmp++) {k_tmp->len = u_tmp->len;total += k_tmp->len;if (u_tmp->tx_buf) {tx_total += k_tmp->len;k_tmp->tx_buf = tx_buf;//将每个spi_ioc_transfer里的tx_buf的内容复制到spidev->tx_buffer里,同时对应的                //spi_transfer的tx_buf也得到复制。if (copy_from_user(tx_buf, (const u8 __user *)(uintptr_t) u_tmp->tx_buf,u_tmp->len)){}tx_buf += k_tmp->len;}//将spi_ioc_transfer里的各成员值赋值到对应的spi_transfer中k_tmp->cs_change = !!u_tmp->cs_change;k_tmp->tx_nbits = u_tmp->tx_nbits;k_tmp->rx_nbits = u_tmp->rx_nbits;k_tmp->bits_per_word = u_tmp->bits_per_word;k_tmp->delay_usecs = u_tmp->delay_usecs;k_tmp->speed_hz = u_tmp->speed_hz;if (!k_tmp->speed_hz)k_tmp->speed_hz = spidev->speed_hz;//spi_transfer插入到spi_message的队列中spi_message_add_tail(k_tmp, &msg);}status = spidev_sync(spidev, &msg);rx_buf = spidev->rx_buffer;//将spidev中的rx_buffer中的内容复制到各个spi_ioc_transfer的rx_buf中去for (n = n_xfers, u_tmp = u_xfers; n; n--, u_tmp++) {if (u_tmp->rx_buf) {if (copy_to_user((u8 __user *)(uintptr_t) u_tmp->rx_buf, rx_buf,u_tmp->len)) {}rx_buf += u_tmp->len;}}}

spi_message_add_tail函数:

static inline void
spi_message_add_tail(struct spi_transfer *t, struct spi_message *m)
{list_add_tail(&t->transfer_list, &m->transfers);
}

spidev_sync函数分析:

static ssize_t
spidev_sync(struct spidev_data *spidev, struct spi_message *message)
{int status;struct spi_device *spi;spi = spidev->spi;status = spi_sync(spi, message);return status;
}
spi_sync__spi_sync

__spi_sync函数:

static int __spi_sync(struct spi_device *spi, struct spi_message *message)
{int status;struct spi_controller *ctlr = spi->controller;unsigned long flags;if (ctlr->transfer == spi_queued_transfer) {status = __spi_queued_transfer(spi, message, false);} if (status == 0) {if (ctlr->transfer == spi_queued_transfer) {//走路线1__spi_pump_messages(ctlr, false);}status = message->status;}return status;
}

__spi_queued_transfer函数:

static int __spi_queued_transfer(struct spi_device *spi,struct spi_message *msg,bool need_pump)
{struct spi_controller *ctlr = spi->controller;unsigned long flags;msg->actual_length = 0;msg->status = -EINPROGRESS;list_add_tail(&msg->queue, &ctlr->queue);return 0;
}

__spi_pump_messages函数:

static void __spi_pump_messages(struct spi_controller *ctlr, bool in_kthread)
{unsigned long flags;bool was_busy = false;if (list_empty(&ctlr->queue) || !ctlr->running) {if (!ctlr->busy) {        //----------路线3return;}ctlr->busy = false;        //----------路线2ctlr->idling = true;kfree(ctlr->dummy_rx);ctlr->dummy_rx = NULL;kfree(ctlr->dummy_tx);ctlr->dummy_tx = NULL;ctlr->idling = false;return;}//----------路线1ctlr->cur_msg =list_first_entry(&ctlr->queue, struct spi_message, queue);list_del_init(&ctlr->cur_msg->queue);if (ctlr->busy)was_busy = true;elsectlr->busy = true;ctlr->transfer_one_message(ctlr, ctlr->cur_msg);}

transfer_one_message函数指针指向spi_transfer_one_message函数:

static int spi_transfer_one_message(struct spi_controller *ctlr,struct spi_message *msg)
{struct spi_transfer *xfer;bool keep_cs = false;int ret = 0;unsigned long long ms = 1;spi_set_cs(msg->spi, true);list_for_each_entry(xfer, &msg->transfers, transfer_list) {if (xfer->tx_buf || xfer->rx_buf) {ret = ctlr->transfer_one(ctlr, msg->spi, xfer);} if (msg->status != -EINPROGRESS){}msg->actual_length += xfer->len;}out:if (ret != 0 || !keep_cs){spi_set_cs(msg->spi, false);}if (msg->status == -EINPROGRESS){msg->status = ret;    //msg->status=0}spi_res_release(ctlr, msg);spi_finalize_current_message(ctlr);return ret;
}

spi_finalize_current_message函数:

void spi_finalize_current_message(struct spi_controller *ctlr)
{struct spi_message *mesg;unsigned long flags;int ret;mesg = ctlr->cur_msg;ctlr->cur_msg = NULL;ctlr->cur_msg_prepared = false;// 走路线2kthread_queue_work(&ctlr->kworker, &ctlr->pump_messages);}
kthread_init_work(&ctlr->pump_messages, spi_pump_messages);
static void spi_pump_messages(struct kthread_work *work)
{struct spi_controller *ctlr =container_of(work, struct spi_controller, pump_messages);__spi_pump_messages(ctlr, true);
}

spi总线驱动:

static int tcc_spi_probe(struct platform_device *pdev)
{struct spi_master *master;struct device    *dev = &pdev->dev;master = spi_alloc_master(dev, sizeof(struct tcc_spi));master->transfer_one = tcc_spi_transfer_one;devm_spi_register_master(dev, master);}
#define devm_spi_register_master(_dev, _ctlr) \devm_spi_register_controller(_dev, _ctlr)
devm_spi_register_controllerspi_register_controller
int spi_register_controller(struct spi_controller *ctlr)
{struct device      *dev = ctlr->dev.parent;of_spi_register_master(ctlr);INIT_LIST_HEAD(&ctlr->queue);device_add(&ctlr->dev);if (ctlr->transfer){}else {status = spi_controller_initialize_queue(ctlr);}of_register_spi_devices(ctlr);
}
static int of_spi_register_master(struct spi_controller *ctlr)
{int nb, i, *cs;struct device_node *np = ctlr->dev.of_node;if (!np)return 0;nb = of_gpio_named_count(np, "cs-gpios");ctlr->num_chipselect = max_t(int, nb, ctlr->num_chipselect);cs = devm_kzalloc(&ctlr->dev, sizeof(int) * ctlr->num_chipselect,GFP_KERNEL);ctlr->cs_gpios = cs;if (!ctlr->cs_gpios)return -ENOMEM;for (i = 0; i < ctlr->num_chipselect; i++)cs[i] = -ENOENT;for (i = 0; i < nb; i++)cs[i] = of_get_named_gpio(np, "cs-gpios", i);return 0;
}
static int spi_controller_initialize_queue(struct spi_controller *ctlr)
{int ret;ctlr->transfer = spi_queued_transfer;if (!ctlr->transfer_one_message)ctlr->transfer_one_message = spi_transfer_one_message;/* Initialize and start queue */ret = spi_init_queue(ctlr);ctlr->queued = true;ret = spi_start_queue(ctlr);return 0;}
static int spi_init_queue(struct spi_controller *ctlr)
{struct sched_param param = { .sched_priority = MAX_RT_PRIO - 1 };ctlr->running = false;ctlr->busy = false;kthread_init_worker(&ctlr->kworker);ctlr->kworker_task = kthread_run(kthread_worker_fn, &ctlr->kworker,"%s", dev_name(&ctlr->dev));kthread_init_work(&ctlr->pump_messages, spi_pump_messages);return 0;
}
static int spi_start_queue(struct spi_controller *ctlr)
{unsigned long flags;ctlr->running = true;ctlr->cur_msg = NULL;//走路线3kthread_queue_work(&ctlr->kworker, &ctlr->pump_messages);return 0;
}

of_register_spi_devices函数:

static void of_register_spi_devices(struct spi_controller *ctlr)
{struct spi_device *spi;struct device_node *nc;for_each_available_child_of_node(ctlr->dev.of_node, nc) {if (of_node_test_and_set_flag(nc, OF_POPULATED))continue;spi = of_register_spi_device(ctlr, nc);}

of_register_spi_device函数:

of_register_spi_devicerc = spi_add_device(spi);spi_setup(spi);

tcc803x spi驱动解析相关推荐

  1. 【嵌入式Linux学习七步曲之第五篇 Linux内核及驱动编程】PowerPC + Linux2.6.25平台下的SPI驱动架构分析

    PowerPC + Linux2.6.25平台下的SPI驱动架构分析 Sailor_forever  sailing_9806#163.com (本原创文章发表于Sailor_forever 的个人b ...

  2. PX4原生固件SPI驱动动编写与IMU传感器替换

    适用于PX4原生固件 核心目标:完成XSENS的MTI3,IMU替换.MTI3是一款航姿参考系统,可以独立的输出四元数,加速度,磁力计等,角速度等航姿信息.里面有完整的卡尔曼滤波,可以替换飞控本身里面 ...

  3. 第三章 PX4-Pixhawk-SPI底层驱动解析

    第三章 PX4-SPI底层驱动解析 这一章节我们会对PX4的底层驱动进行解析,我们这里主要解析的是SPI协议,因为这个协议是所有传感器的一个协议,至于IIC和串口就可以类似的读写一下,大家看完这个解析 ...

  4. 第三章 PX4-SPI底层驱动解析

    版权声明:本文为博主原创文章,未经博主允许不得转载. 第三章 PX4-SPI底层驱动解析 这一章节我们会对PX4的底层驱动进行解析,我们这里主要解析的是SPI协议,因为这个协议是所有传感器的一个协议, ...

  5. STM32F103系列_OLED屏幕(SSD1306、SSD1315驱动)SPI驱动【DMA】(高刷)

    STM32F103系列_OLED屏幕(SSD1306.SSD1315驱动)SPI驱动[DMA](高刷) 一.SSD1306和SSD1315 二.电路原理图(SPI接法) 三.STM32_SPI 四.S ...

  6. 乐鑫esp8266学习rtos3.0笔记第7篇:我又来了,基于rtos3.0版本 SDK编程 SPI 驱动 ws2812b 七彩灯,代码全部开源奉献给你们!

    本系列博客学习由非官方人员 半颗心脏 潜心所力所写,不做开发板.仅仅做个人技术交流分享,不做任何商业用途.如有不对之处,请留言,本人及时更改. 序号 SDK版本 内容 链接 1 nonos2.0 搭建 ...

  7. 串口转SPI驱动协议的制定

    串口转SPI驱动协议的制定 最近在做到一个项目,需要使用SPI去驱动外设,但是我们不是直接使用主控去编写外设的SPI驱动.所以就会有一个串口转SPI的需求,即使用UART发送数据转为SPI驱动.做了简 ...

  8. 【先楫HPM6750系列】RT-Thread SPI驱动和WiFi联网

    本文将会介绍--如何使用RT-Thread Studio创建基于HPM6750EVKMINI开发板的RT-Thread项目,并逐步添加WiFi联网能力.iperf网络带宽测试命令.以及简单的基于soc ...

  9. Linux下SPI驱动详解

    更多嵌入式原创文章,请关注公众号:一口Linux 1. SPI总线 1.1. SPI总线概述 SPI,是英语Serial Peripheral interface的缩写,顾名思义就是串行外围设备接口. ...

最新文章

  1. Python 简介day01
  2. 笔记本电脑u盘装linux系统,用U盘给Linux笔记本电脑重装Win7/XP系统的图文教程
  3. 截取列表前面100行_python列表
  4. 工作心得之-------关于“表现”
  5. 为什么会有那么多的人选择Java?学Java到底好不好?
  6. Python判断变量的数据类型的两种方法
  7. 网钛CMS PHP版蓝色响应式UI美化模板
  8. WebSVN(2.3.1版本)中文注释以及中文路径乱码的解决方法【未完待续】
  9. java第三方包学习之jsoup
  10. 基于python实现的电影推荐系统
  11. java数字金额大写金额_Java将数字金额转为大写中文金额
  12. 西北农林科技大学CSDN高校俱乐部运营策划书
  13. gcc -O0 -O1 -O2 -O3 -Os 编译优化等级
  14. 运行jar包时报错:[mybatis-config.xml] cannot be opened because it does not exist
  15. 计算机网络基础心得体会结尾,学习《计算机网络基础知识》心得体会
  16. 为什么很多企业要自研CRM系统,而不够买SAAS云服务提供的CRM系统或SCRM系统?...
  17. Java自然周的获取
  18. 科技公司的域名大战!
  19. css文字中间省略号使用js实现
  20. leetcode#561 Array Partition I

热门文章

  1. 计算机高职400到430大学,高职考会计专业各高校的录取分数是多少?
  2. 【3D商城】切换产品与场景效果
  3. 提高数据科学效率的 8 个Python神库
  4. 一路学习做站SEO 站长生涯也就此开始
  5. 网络安全等级保护标准
  6. 哈希匹配算法在单片机上的应用
  7. 小米路由器3G建站折腾笔记5 - 安装phpMyAdmin、Typecho、WordPress
  8. 中国消防车市场趋势报告、技术动态创新及市场预测
  9. 虚拟机VMware15安装
  10. 学校的花花草草都印在我的脑海里