新闻  |   论坛  |   博客  |   在线研讨会
zynq7020开发记录(持续更新)--SPI编译、配置和使用
电子禅石 | 2024-02-03 19:43:54    阅读:90781   发布文章

1706960214369416.png

set_property PACKAGE_PIN G14   [get_ports SPI0_MISO]
set_property IOSTANDARD LVCMOS33 [get_ports SPI0_MISO]

set_property PACKAGE_PIN J15  [get_ports SPI0_MOSI]
set_property IOSTANDARD LVCMOS33 [get_ports SPI0_MOSI]

set_property PACKAGE_PIN J18   [get_ports SPI0_SCLK]
set_property IOSTANDARD LVCMOS33 [get_ports SPI0_SCLK]

set_property PACKAGE_PIN L19   [get_ports SPI_CS_tri_o[0]]
set_property PACKAGE_PIN M17   [get_ports SPI_CS_tri_o[1]]
set_property PACKAGE_PIN G19   [get_ports SPI_CS_tri_o[2]]
# set_property PACKAGE_PIN J20   [get_ports SPI_CS_tri_o[3]]
# set_property PACKAGE_PIN J19   [get_ports SPI_CS_tri_o[4]]  
# set_property PACKAGE_PIN F16   [get_ports SPI_CS_tri_o[5]]
# set_property PACKAGE_PIN F17   [get_ports SPI_CS_tri_o[6]]
set_property IOSTANDARD LVCMOS33 [get_ports SPI_CS_tri_o[*]]


image.png

// 对于 system-top.dts,添加 对spi1节点的引用声明
aliases {
		ethernet0 = &gem0;
		serial0 = &uart1;
		serial1 = &uart0;
		spi0 = &qspi;
		spi1 = &spi0;
	};

// 对于 pcw.dtsi,添加对于 spi1 设备的描述
&spi0 {
	is-decoded-cs = <0>;
	num-cs = <3>;
	status = "okay";
};
// 上面pcw.dtsi添加并修改成
&spi0 {
	// 下面这三行不变
	is-decoded-cs = <0>;
	num-cs = <3>;
	status = "okay";

	device@0 {
		compatible = "spidev";
		reg = <0>;
		spi-max-frequency = <5000000>;
		#address-cells = <1>;
		#size-cells = <1>;
    };
};

  2.修改内核配置

make ARCH=arm CROSS_COMPILE=/usr/local/gcc-linaro-7.5.0-2019.12-x86_64_
arm-linux-gnueabihf/bin/arm-linux-gnueabihf- menuconfig
#### 执行修改操作
make ARCH=arm CROSS_COMPILE=/usr/local/gcc-linaro-7.5.0-2019.12-x86_64
_arm-linux-gnueabihf/bin/arm-linux-gnueabihf- all

## 配置下面两个宏使之生效
CONFIG_SPI_CADENCE = y
CONFIG_SPI_SPIDEV = y
# 并打开以下宏
Device Drivers  --->
	[*] SPI support  --->
        <*>   Cadence SPI controller
        <*>   Xilinx SPI controllor common module
		<*>   User mode SPI device driver support

  

image.png             

4.测试

spi_mio.h 

#ifndef _SPI_MIO_H_
#define _SPI_MIO_H_

#include <stdint.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/types.h>
#include <linux/spi/spidev.h>
#include <iostream>
#include <string>
#include <cstring>
#include <fstream>
#include <sstream>
#include <queue>
#include <chrono>
#include <vector>
#include <list>
#include <map>
#include <numeric> 
#include <stdexcept>
#include <utility>
#include <functional>
#include <atomic>
#include <mutex>
#include <thread> 
#include <sys/stat.h>           
#include <sys/types.h>  
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/time.h>  
#include <sys/times.h>        
#include <unistd.h>                  
#include <getopt.h>             
#include <errno.h>  
#include <sys/mman.h>
#include <math.h>
#include <time.h>
#include <signal.h>
#include <unistd.h>
#include <getopt.h>
#include <sys/ioctl.h>
#include <linux/types.h>
#include <linux/fb.h>
#include <linux/spi/spidev.h>
#include <termios.h>
#include <sys/vfs.h>
#include <mntent.h>
#include <sys/epoll.h>
#include <poll.h>
#include <dirent.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/shm.h>

using namespace std;
class spi
{
private:
    std::string device;

    uint32_t mode;
    uint8_t  bits;
    uint32_t speed;

public:
    int fd_spi;
    using ptr = std::shared_ptr<spi>;

public:
    // 默认为/dev下的设备节点,可根据实际变化,模式0,一次传输8bits, 速率1e6
    spi(std::string device = "/dev/spidev1.0", uint32_t mode = 0, uint8_t  bits = 8, uint32_t speed = 1e6);
    ~spi();

    int init();
    int transfer(int fd, uint8_t *tx, uint8_t *rx, uint32_t len);
    void delay(uint32_t count);   
 
};

class my_dev : public spi
{
private:
    uint8_t my_dev_register_config[3] = {0x01, 0x00, 0x34};
public:
    using spi::spi;
    my_dev() {}
    ~my_dev() {}

    void my_dev_init();
};

#endif

spi_mio.cpp

#include "spi_mio.h"

using namespace std;


spi::spi(std::string device_, uint32_t mode_, uint8_t  bits_, uint32_t speed_)
{
    device = device_;

    mode = mode_;
    bits = bits_;
    speed = speed_;

	fd_spi = open(device_.c_str(), O_RDWR);
	if (fd_spi < 0) {
        std::cout << "can't open spi device" << std::endl;
    }

    init();

}

spi::~spi()
{
    if (fd_spi > 0) {
        close(fd_spi);
    }
}

int spi::init()
{
    int ret = 0;
    if (fd_spi > 0)
    {
        if (ioctl(fd_spi, SPI_IOC_WR_MODE32, &mode) == -1 ||
            ioctl(fd_spi, SPI_IOC_RD_MODE32, &mode) == -1 ||
            ioctl(fd_spi, SPI_IOC_WR_BITS_PER_WORD, &bits) == -1 ||
            ioctl(fd_spi, SPI_IOC_RD_BITS_PER_WORD, &bits) == -1 ||
            ioctl(fd_spi, SPI_IOC_WR_MAX_SPEED_HZ, &speed) == -1 ||
            ioctl(fd_spi, SPI_IOC_RD_MAX_SPEED_HZ, &speed) == -1)
        {
            std::cout << "spi device init failed" << std::endl;
            return -1;
        }
    }
    return ret;
}

int spi::transfer(int fd, uint8_t *tx, uint8_t *rx, uint32_t len)
{
	int ret = 0;

	struct spi_ioc_transfer tr = {
                                .tx_buf = (unsigned long)tx,
                                .rx_buf = (unsigned long)rx,
                                .len = len, 
                                // .speed_hz = speed,  
                                // .bits_per_word = bits,  
                                 };

	ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
	if (ret < 1){
        std::cout << "can't send spi message" << std::endl;
        return -1;
    }
	return ret;	
}

void spi::delay(uint32_t count)
{
    uint32_t fool = 0;
    while (count--){
       fool++; 
    }
}

void my_dev::my_dev_init()
{
    uint8_t recv[8];
	write(fd_spi, my_dev_register_config, 3);
    // transfer(fd_spi, my_dev_register_config, recv, 3);	// 用于双向传输
}
main.cpp

#include "spi_mio.h"

int main()
{
    my_dev dev1;
    dev1.my_dev_init();
	return 0;
}


原文链接:https://blog.csdn.net/Vanau/article/details/122460021


*博客内容为网友个人发布,仅代表博主个人观点,如有侵权请联系工作人员删除。

参与讨论
登录后参与讨论
lantu  2024-02-21 15:06:41 

期待更新

属于自己的技术积累分享,成为嵌入式系统研发高手。
推荐文章
最近访客