将SPI驱动程序移植到Uboot中
记录一下在uboot内移植spi驱动的过程
芯片:freescale Mpc8308
uboot版本:u-boot-2009.11-rc1.2
需求:我们需要在uboot下通过spi配置一个时钟芯片(dpll)用来给fpga提供时钟
要移植spi驱动,前提是要通过手册了解该cpu的spi的结构和寄存器描述,一般作为cpu的外围设备,spi是有一个spi控制器的
简单看一下8308的spi模块结构
spi的四根线,MOSI,MISO,CS,CLK
CS以外的几根线是从Master上引出来的
而CS是由cpu的gpio来扮演的
驱动方面
uboot中产品的配置文件我的在include/configs/MPC8308EDD.h
这个是修改过的,
在u-boot-2009.11-rc1.2/driver/spi中找到mpc8xxx_spi.c文件,我们姑且认为这个就是最相近的驱动了(根据芯片名称与文件名称)
相关Makefile
COBJS-$(CONFIG_MPC8XXX_SPI) += mpc8xxx_spi.o
在lib_ppc/board.c(不通uboot,目录不同)中有spi_init()的初始化调用,如下
#if defined(CONFIG_HARD_SPI) static int init_func_spi (void) { puts ("SPI: "); spi_init (); puts ("ready\n"); return (0); } #endif
将需要的宏添加到MPC8308EDD.h中
/* * eSPI - Enhanced SPI */ #define CONFIG_HARD_SPI #define CONFIG_FSL_ESPI
现在spi模块驱动有了,初始化有了,但是我们还需要一个spi的对象,struct spi_slave
struct spi_slave *spi_slave_init(void) { struct spi_slave *slave; unsigned int bus = 0; unsigned int cs = 3; unsigned int mode = SPI_MODE_0; slave = spi_setup_slave(bus, cs, 1000000, mode); if (!slave) { printf("Invalid device %d:%d\n", bus, cs); return NULL; } spi_claim_bus(slave); return slave; } static int spi_read_write(struct spi_slave *spi, const u8 *cmd, size_t cmd_len, const u8 *data_out, u8 *data_in, size_t data_len) { unsigned long flags = SPI_XFER_BEGIN; int ret; if (data_len == 0) flags |= SPI_XFER_END; ret = spi_xfer(spi, cmd_len * 8, cmd, NULL, flags); if (ret) { debug("SF: Failed to send command (%zu bytes): %d\n", cmd_len, ret); } else if (data_len != 0) { ret = spi_xfer(spi, data_len * 8, data_out, data_in, SPI_XFER_END); if (ret) debug("SF: Failed to transfer %zu bytes of data: %d\n", data_len, ret); } return ret; }
这个spi_read_write是根据我的读写需求后补的
在lib_ppc/board.c函数board_init_r最后添加spi的slave初始化
struct spi_slave *slave;
slave = spi_slave_init();
目前为止,spi驱动理论上移植完了,一次ok的可能性太小了^_^,后面讲问题
1.一切配置正常但从设备并没有工作
初始化正常,从设备也配置了,而且spi的各引脚信号都能测到,从设备是一个时钟芯片,并没有时钟输出
信号能测到那么检查信号的正确性了,按照时钟芯片的要求,将spi的初始化模式修改
- spi->mode = SPI_MODE_REV | SPI_MODE_MS | SPI_MODE_EN;
- spi->mode = (spi->mode & 0xfff0ffff) | (1 << 16); /* Use SYSCLK / 8
- (16.67MHz typ.) */
+ spi->mode = 0;
+ spi->mode = SPMODE_INIT_VAL | SPMODE_ENABLE;
+// spi->mode = (spi->mode & 0xfff0ffff) | (1 << 16); /* Use SYSCLK / 8 (16.67MHz typ.) */
spi->event = 0xffffffff; /* Clear all SPI events */
spi->mask = 0x00000000; /* Mask all SPI interrupts */
spi->com = 0; /* LST bit doesn't do anything, so disregard */
+ printf("mode = 0x%x\n",spi->mode);
spi->com = 0; /* LST bit doesn't do anything, so disregard */
+ printf("mode = 0x%x\n",spi->mode);
原文链接:https://blog.****.net/davion_zhang/article/details/50883806
原文地址:https://www.cnblogs.com/Ph-one/p/11539827.html
推荐阅读
-
将SPI驱动程序移植到Uboot中
-
go语言Socket编程-Socket编程 什么是Socket Socket,英文含义是插座、插孔,一般称之为套接字,用于描述IP地址和端口。可以实现不同程序间的数据通信。 Socket起源于Unix,而Unix基本哲学之一就是“一切皆文件”,都可以用“打开open –> 读写write/read –> 关闭close”模式来操作。Socket就是该模式的一个实现,网络的Socket数据传输是一种特殊的I/O,Socket也是一种文件描述符。Socket也具有一个类似于打开文件的函数调用:Socket,该函数返回一个整型的Socket描述符,随后的连接建立、数据传输等操作都是通过该Socket实现的。 套接字的内核实现较为复杂,不宜在学习初期深入学习,了解到如下结构足矣。 套接字通讯原理示意 在TCP/IP协议中,“IP地址+TCP或UDP端口号”唯一标识网络通讯中的一个进程。“IP地址+端口号”就对应一个socket。欲建立连接的两个进程各自有一个socket来标识,那么这两个socket组成的socket pair就唯一标识一个连接。因此可以用Socket来描述网络连接的一对一关系。 常用的Socket类型有两种:流式Socket(SOCK_STREAM)和数据报式Socket(SOCK_DGRAM)。流式是一种面向连接的Socket,针对于面向连接的TCP服务应用;数据报式Socket是一种无连接的Socket,对应于无连接的UDP服务应用。 网络应用程序设计模式 C/S模式 传统的网络应用设计模式,客户机(client)/服务器(server)模式。需要在通讯两端各自部署客户机和服务器来完成数据通信。 B/S模式 浏览器(Browser)/服务器(Server)模式。只需在一端部署服务器,而另外一端使用每台PC都默认配置的浏览器即可完成数据的传输。 优缺点 对于C/S模式来说,其优点明显。客户端位于目标主机上可以保证性能,将数据缓存至客户端本地,从而提高数据传输效率。且,一般来说客户端和服务器程序由一个开发团队创作,所以他们之间所采用的协议相对灵活。可以在标准协议的基础上根据需求裁剪及定制。例如,腾讯所采用的通信协议,即为ftp协议的修改剪裁版。 因此,传统的网络应用程序及较大型的网络应用程序都首选C/S模式进行开发。如,知名的网络游戏魔兽世界。3D画面,数据量庞大,使用C/S模式可以提前在本地进行大量数据的缓存处理,从而提高观感。 C/S模式的缺点也较突出。由于客户端和服务器都需要有一个开发团队来完成开发。工作量将成倍提升,开发周期较长。另外,从用户角度出发,需要将客户端安插至用户主机上,对用户主机的安全性构成威胁。这也是很多用户不愿使用C/S模式应用程序的重要原因。 B/S模式相比C/S模式而言,由于它没有独立的客户端,使用标准浏览器作为客户端,其工作开发量较小。只需开发服务器端即可。另外由于其采用浏览器显示数据,因此移植性非常好,不受平台限制。如早期的偷菜游戏,在各个平台上都可以完美运行。 B/S模式的缺点也较明显。由于使用第三方浏览器,因此网络应用支持受限。另外,没有客户端放到对方主机上,缓存数据不尽如人意,从而传输数据量受到限制。应用的观感大打折扣。第三,必须与浏览器一样,采用标准http协议进行通信,协议选择不灵活。 因此在开发过程中,模式的选择由上述各自的特点决定。根据实际需求选择应用程序设计模式。 简单的C/S模型通信 Server端:Listen函数 func Listen(network, address string) (Listener, error) network:选用的协议:TCP、UDP, 如:“tcp”或 “udp” address:IP地址+端口号, 如:“127.0.0.1:8000”或 “:8000” Listener 接口: type Listener interface { Accept (Conn, error) Close error Addr Addr } Conn 接口: type Conn interface { Read(b byte) (n int, err error) Write(b byte) (n int, err error) Close error LocalAddr Addr RemoteAddr Addr SetDeadline(t time.Time) error SetReadDeadline(t time.Time) error SetWriteDeadline(t time.Time) error } 参看 [<u>https://studygolang.com/pkgdoc</u>](https://studygolang.com/pkgdoc) 中文帮助文档中的demo: 示例代码:TCP服务器.go package main import ( "net" "fmt" ) func main { // 创建监听 listener, err:= net.Listen("tcp", ":8000") if err != nil { fmt.Println("listen err:", err) return } defer listener.Close // 主协程结束时,关闭listener fmt.Println("服务器等待客户端建立连接...") // 等待客户端连接请求 conn, err := listener.Accept if err != nil { fmt.Println("accept err:", err) return } defer conn.Close // 使用结束,断开与客户端链接 fmt.Println("客户端与服务器连接建立成功...") // 接收客户端数据 buf := make(byte, 1024) // 创建1024大小的缓冲区,用于read n, err := conn.Read(buf) if err != nil { fmt.Println("read err:", err) return } fmt.Println("服务器读到:", string(buf[:n])) // 读多少,打印多少。 }
-
在 Centos7 环境中构建 SVN 服务器,将 svn 移植到其他服务器
-
从单张图片中提取 "会说话的头像 "动漫将人脸表情符号移植到动漫表情符号中
-
我的闪亮新体验:将flash.nvim成功移植到VscodeVim中!
-
如何将sys设备信息移植到UBI文件系统中?【转帖】