zoukankan      html  css  js  c++  java
  • 树莓派 -- oled


    硬件

    SPI0,CE0
    这里写图片描述

    SPI Master Driver

    设备树

    archarmootdtscm2710-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

    archarmootdtscm283x.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";
            };
    
        }

    archarmootdtscm270x.dtsi

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

    bcm2835-spi

    driversspispi-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
    ");
            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
    ", 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
    ", 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
    ", 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
    ", 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
    ", 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
    ", strerror (errno)) ;
    
      if (ioctl (fd, SPI_IOC_WR_BITS_PER_WORD, &spiBPW) < 0)
        return wiringPiFailure (WPI_ALMOST, "SPI BPW Change failure: %s
    ", strerror (errno)) ;
    
      if (ioctl (fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed)   < 0)
        return wiringPiFailure (WPI_ALMOST, "SPI Speed Change failure: %s
    ", 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
  • 相关阅读:
    WCF 第四章 绑定 在多个绑定上暴露一个服务契约
    WCF 第五章 行为 事务跨操作事务流
    WCF 第五章 导出并发布元数据(服务行为)
    WCF 第五章 行为 通过配置文件暴露一个服务行为
    WCF 第五章 不支持会话的绑定的默认并发和实例
    WCF 第五章 并发和实例(服务行为)
    WCF 第五章 行为 总结
    WCF 第四章 绑定 绑定元素
    WCF 第五章 行为 事务之选择一个事务协议OleTx 或者WSAT
    WCF 第四章 绑定 比较各种绑定的性能和可扩展性
  • 原文地址:https://www.cnblogs.com/feiwatson/p/9478204.html
Copyright © 2011-2022 走看看