硬件

SPI0,CE0

SPI Master Driver

设备树

arch\arm\boot\dts\bcm2710-rpi-3-b.dts

&gpio {
spi0_pins: spi0_pins {
brcm,pins = <9 10 11>;
brcm,function = <4>; /* alt0 */
}; spi0_cs_pins: spi0_cs_pins {
brcm,pins = <8 7>;
brcm,function = <1>; /* output */
};
}
&spi0 {
pinctrl-names = "default";
pinctrl-0 = <&spi0_pins &spi0_cs_pins>;
cs-gpios = <&gpio 8 1>, <&gpio 7 1>; spidev0: spidev@0{
compatible = "spidev";
reg = <0>; /* CE0 */
#address-cells = <1>;
#size-cells = <0>;
spi-max-frequency = <125000000>;
}; spidev1: spidev@1{
compatible = "spidev";
reg = <1>; /* CE1 */
#address-cells = <1>;
#size-cells = <0>;
spi-max-frequency = <125000000>;
};
};

spi0

arch\arm\boot\dts\bcm283x.dtsi

    soc {
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <1>; spi: spi@7e204000 {
compatible = "brcm,bcm2835-spi";
reg = <0x7e204000 0x1000>;
interrupts = <2 22>;
clocks = <&clocks BCM2835_CLOCK_VPU>;
#address-cells = <1>;
#size-cells = <0>;
status = "disabled";
}; }

arch\arm\boot\dts\bcm270x.dtsi

    soc: soc {
spi0: spi@7e204000 {
/* Add alias */
dmas = <&dma 6>, <&dma 7>;
dma-names = "tx", "rx";
};
}

bcm2835-spi

drivers\spi\spi-bcm2835.c

static struct platform_driver bcm2835_spi_driver = {
.driver = {
.name = DRV_NAME,
.of_match_table = bcm2835_spi_match,
},
.probe = bcm2835_spi_probe,
.remove = bcm2835_spi_remove,
};

compatible

static const struct of_device_id bcm2835_spi_match[] = {
{ .compatible = "brcm,bcm2835-spi", },
{}
};

probe函数

static int bcm2835_spi_probe(struct platform_device *pdev)
{
struct spi_master *master;
struct bcm2835_spi *bs;
struct resource *res;
int err; master = spi_alloc_master(&pdev->dev, sizeof(*bs));
if (!master) {
dev_err(&pdev->dev, "spi_alloc_master() failed\n");
return -ENOMEM;
} platform_set_drvdata(pdev, master); master->mode_bits = BCM2835_SPI_MODE_BITS;
master->bits_per_word_mask = SPI_BPW_MASK(8);
master->num_chipselect = 3;
master->setup = bcm2835_spi_setup;
master->set_cs = bcm2835_spi_set_cs;
master->transfer_one = bcm2835_spi_transfer_one;
master->handle_err = bcm2835_spi_handle_err;
master->prepare_message = bcm2835_spi_prepare_message;
master->dev.of_node = pdev->dev.of_node; bs = spi_master_get_devdata(master); res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
bs->regs = devm_ioremap_resource(&pdev->dev, res);
if (IS_ERR(bs->regs)) {
err = PTR_ERR(bs->regs);
goto out_master_put;
} bs->clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(bs->clk)) {
err = PTR_ERR(bs->clk);
dev_err(&pdev->dev, "could not get clk: %d\n", err);
goto out_master_put;
} bs->irq = platform_get_irq(pdev, 0);
if (bs->irq <= 0) {
dev_err(&pdev->dev, "could not get IRQ: %d\n", bs->irq);
err = bs->irq ? bs->irq : -ENODEV;
goto out_master_put;
} clk_prepare_enable(bs->clk); bcm2835_dma_init(master, &pdev->dev); /* initialise the hardware with the default polarities */
bcm2835_wr(bs, BCM2835_SPI_CS,
BCM2835_SPI_CS_CLEAR_RX | BCM2835_SPI_CS_CLEAR_TX); err = devm_request_irq(&pdev->dev, bs->irq, bcm2835_spi_interrupt, 0,
dev_name(&pdev->dev), master);
if (err) {
dev_err(&pdev->dev, "could not request IRQ: %d\n", err);
goto out_clk_disable;
} err = devm_spi_register_master(&pdev->dev, master);
if (err) {
dev_err(&pdev->dev, "could not register SPI master: %d\n", err);
goto out_clk_disable;
} return 0; out_clk_disable:
clk_disable_unprepare(bs->clk);
out_master_put:
spi_master_put(master);
return err;
}

在probe函数中调用了devm_spi_register_master

spi device

#define devm_spi_register_master(_dev, _ctlr) \
devm_spi_register_controller(_dev, _ctlr)

在drivers/spi/spi.c中,定义了devm_spi_register_controller

/**
* devm_spi_register_controller - register managed SPI master or slave
* controller
* @dev: device managing SPI controller
* @ctlr: initialized controller, originally from spi_alloc_master() or
* spi_alloc_slave()
* Context: can sleep
*
* Register a SPI device as with spi_register_controller() which will
* automatically be unregistered and freed.
*
* Return: zero on success, else a negative error code.
*/
int devm_spi_register_controller(struct device *dev,
struct spi_controller *ctlr)
{
struct spi_controller **ptr;
int ret;
ptr = devres_alloc(devm_spi_unregister, sizeof(*ptr), GFP_KERNEL);
if (!ptr)
return -ENOMEM;
ret = spi_register_controller(ctlr);
if (!ret) {
*ptr = ctlr;
devres_add(dev, ptr);
} else {
devres_free(ptr);
}
return ret;
}

在spi_register_controller中调用

    status = device_add(&ctlr->dev);

spi device的file operations在drivers/spi/spidev.c中定义

static const struct file_operations spidev_fops = {
.owner = THIS_MODULE,
/* REVISIT switch to aio primitives, so that userspace
* gets more complete API coverage. It'll simplify things
* too, except for the locking.
*/
.write = spidev_write,
.read = spidev_read,
.unlocked_ioctl = spidev_ioctl,
.compat_ioctl = spidev_compat_ioctl,
.open = spidev_open,
.release = spidev_release,
.llseek = no_llseek,
};

wiringPi oled例程

wiringPi在用户空间通过SPI master device的API, open, release, ioctl, read, write来驱动oled.

static const char       *spiDev0  = "/dev/spidev0.0" ;
static const char *spiDev1 = "/dev/spidev0.1" ;
/*
* wiringPiSPISetupMode:
* Open the SPI device, and set it up, with the mode, etc.
*********************************************************************************
*/ int wiringPiSPISetupMode (int channel, int speed, int mode)
{
int fd ; mode &= 3 ; // Mode is 0, 1, 2 or 3
channel &= 1 ; // Channel is 0 or 1 if ((fd = open (channel == 0 ? spiDev0 : spiDev1, O_RDWR)) < 0)
return wiringPiFailure (WPI_ALMOST, "Unable to open SPI device: %s\n", strerror (errno)) ; spiSpeeds [channel] = speed ;
spiFds [channel] = fd ; // Set SPI parameters. if (ioctl (fd, SPI_IOC_WR_MODE, &mode) < 0)
return wiringPiFailure (WPI_ALMOST, "SPI Mode Change failure: %s\n", strerror (errno)) ; if (ioctl (fd, SPI_IOC_WR_BITS_PER_WORD, &spiBPW) < 0)
return wiringPiFailure (WPI_ALMOST, "SPI BPW Change failure: %s\n", strerror (errno)) ; if (ioctl (fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed) < 0)
return wiringPiFailure (WPI_ALMOST, "SPI Speed Change failure: %s\n", strerror (errno)) ; return fd ;
}

树莓派 devfs sysfs中SPI设备

查看/dev

pi@raspberrypi:~ $ ls /dev | grep spi
spidev0.0
spidev0.1

查看/sys/class

pi@raspberrypi:/sys/class/spi_master $ ls
spi0
pi@raspberrypi:/sys/class/spi_master $ cd spi0
pi@raspberrypi:/sys/class/spi_master/spi0 $ ls
device of_node power spi0.0 spi0.1 statistics subsystem uevent
pi@raspberrypi:/sys/class/spi_master/spi0 $ cd of_node
pi@raspberrypi:/sys/class/spi_master/spi0/of_node $ ls
#address-cells cs-gpios interrupts pinctrl-0 #size-cells status
clocks dma-names name pinctrl-names spidev@0
compatible dmas phandle reg spidev@1
pi@raspberrypi:/sys/class/spi_master/spi0/of_node $ cat compatible
brcm,bcm2835-spi
pi@raspberrypi:/sys/class/spi_master/spi0/of_node $ cd spidev@0
pi@raspberrypi:/sys/class/spi_master/spi0/of_node/spidev@0 $ ls
#address-cells compatible name phandle reg #size-cells spi-max-frequency
pi@raspberrypi:/sys/class/spi_master/spi0/of_node/spidev@0 $ cat compatible
spidev

树莓派 -- oled的更多相关文章

  1. 树莓派OLED模块的使用教程大量例程详解

    简介 Python有两个可以用的OLED库 [Adafruit_Python_SSD1306库]->只支持SSD1306 [Luma.oled库]->支持SSD1306 / SSD1309 ...

  2. 树莓派 -- oled 续(2) python

    上文中的代码通过wiringPi的API调用devfs API来显示图片. 这里分析的Python代码也通过类似的方法来显示图片. 主要用到了两个Library. import spidev impo ...

  3. 树莓派 -- oled 续(1) wiringPi

    在上文中,分析了wiringPi 的oled demo是使用devfs来控制spi master和spi slave通讯. https://blog.csdn.net/feiwatson/articl ...

  4. 基础篇:一文讲懂树莓派命令行文本编辑工具Vim的使用

    简介 众所周知,在Linux系统下的命令行调试界面,经常会遇到需要文本编辑的情况,而树莓派官方系统默认自带了Nano编辑器,Nano的操作门槛更低,但却不如Vim编辑器方便.Vim编辑器是由早期在Li ...

  5. 树莓派使用 OLED 屏显示图片及文字

    树莓派默认是不带显示屏的,如果想要查看系统的一些信息,需要使用电脑登录到树莓派,或者通过 HDMI 连接外接显示器查看.这样做总是有点麻烦,我们可以通过外接一个 OLED 屏来显示一些关键参数或者图片 ...

  6. 31 树莓派外接Oled屏幕

    http://shumeipai.nxez.com/2017/09/13/solve-the-raspberry-pi-drive-oled-problem.html

  7. 树莓派之OLED12864视频播放—BadApple

    代码地址如下:http://www.demodashi.com/demo/13218.html 概述 本篇教程讲述了使用树莓派驱动OLED12864液晶屏,并在液晶屏上播放动画和视频. 硬件平台 树莓 ...

  8. Raspberry Pi3驱动Oled ssh1106屏

    Raspberry Pi3可以直接使用GPIO接口驱动OLED屏 一.接线 根据网上随便找的图可以看到树莓派3的GPIO接口引脚顺序 PS:26pin的GPIO为前26针 根据OLED屏的引脚说明,如 ...

  9. 树莓派 PICO基础教程(基于MicroPython)

    目录 1 树莓派 PICO 简介 1.1 简介 1.2 配置 [^2] 1.3 引脚图 1.4 尺寸 2 安装 2.1 烧录固件 2.2 安装IDE(Thonny IDE) 2.3 离线运行程序 3 ...

随机推荐

  1. 洛谷 P3952 时间复杂度【模拟】

    把No写成NO,WA了一发-- 现在看这题也不难-- 用一个栈,记一下前面F的字母,是否合法,合法的有多长,每次入栈弹栈即可 #include<iostream> #include< ...

  2. Luogu P1122最大子树和 【水树形Dp】By cellur925

    题目描述 小明对数学饱有兴趣,并且是个勤奋好学的学生,总是在课后留在教室向老师请教一些问题.一天他早晨骑车去上课,路上见到一个老伯正在修剪花花草草,顿时想到了一个有关修剪花卉的问题.于是当日课后,小明 ...

  3. Linux 虚拟机配置网络

  4. flask框架模板系统

    flask模板引擎 flask默认使用了Jinja2模板引擎,我们在使用模板的时候,需要在同级目录文件夹下 创建一个templates的文件夹,然后这个文件夹内放置我们想要的模板实例即可: 在正常普通 ...

  5. NOIP-2018

    时隔一年,再度踏入NOIp的考场,内心感慨万分 Day0 在中巴上昏睡了3h++,终于到了长沙理工大学,国际学术交流中心......不太对,好像是国际交流中心与综合实验楼连线--理工大学的另一个大门外 ...

  6. 洛谷 P2062 分队问题

    这题太毒了....一开始就是死活想不到,结果看了很多遍题解,重新做的时候还是做不出来.. 好像有一点被错误的题解误导了? #include<cstdio> #include<algo ...

  7. 牛客网暑期ACM多校训练营(第五场)

    J-plan(贪心) 题目描述 There are n students going to travel. And hotel has two types room:double room and t ...

  8. Oracle代码 规则 创建表 表空间 用户等

    -----创建表空间----------create tablespace bdccslogging datafile 'D:\oracle\product\10.2.0\oradata\bdccs\ ...

  9. thinkphp3.2 + soap

    服务器配置 扩展libxml2下载地址:http://xmlsoft.org/downloads.html 在windows下的php.ini文件里 找到这一行代码(如没有则自行添加) extensi ...

  10. Oracle 表-初步涉水不深(第一天)

    oracle 关系型数据库 注释:面对大型数据处理,市场占有率40%多(但是目前正往分布式转换) 故事:本来一台大型计算机才能处理的数据,美国科学家用100台家用电脑连接,成功处理了数据.. tabl ...