Linux GPIO模拟SPI接口介绍

一. 前言

        上次通过GPIO模拟IIC的驱动一块0.98英寸的OLED后,想着下次用下GPIO模拟SPI接口试下。本文会介绍怎么用GPIO模拟SPI接口的方式为设备添加一块spi nor flash,flash模块如下图所示:

        上图是一个spi nor模块,上面焊接了W25Q32FV(一块4M的spi nor flash),模块引出了flash的引脚,板子的GPIO接引脚来驱动flash。

        板子采用的是一块MT7620A的开发板,内核的版本是Linux 3.18.45。

二. 步骤

1. CPU与模块的连线
模块            MT7620A板子
VCC               3.3V
GND               GND
CS                MDIO(GPIO#22)
DO                SCL(GPIO#2)
CLK               SDA(GPIO#1)
DI                MDC(GPIO#23)
2. 内核修改
Device Drivers  --->
    [*] SPI support  --->
        <*>   GPIO-based bitbanging SPI Master

        内核SPI驱动选上"GPIO-based bitbanging SPI Master",表示内核支持GPIO模拟SPI接口。

3. 设备树修改

        由于SPI用到了MDIO和I2C接口的GPIO,所以需要在pinctrl中将他们复用为普通GPIO模式,如下所示:

pinctrl {
		state_default: pinctrl0 {
			default {
				ralink,group = "pa", "spi refclk", "wdt", "uartf", "nd_sd", "mdio", "i2c";
				ralink,function = "gpio";
			};
		};
	};

        接下来添加spi模块相关的设备树,如下所示:

palmbus@10000000 {
		gpio0: gpio@600 {
			status = "okay";
		};
	
		gpio2: gpio@660 {
			status = "okay";
		};

		gpio3: gpio@688 {
			status = "okay";
		};

		spi@b00 {
			status = "okay";

			m25p80@0 {
				#address-cells = <1>;
				#size-cells = <1>;
				compatible = "mx25l12805d";
				reg = <0 0>;
				linux,modalias = "m25p80", "w25q128";
				spi-max-frequency = <10000000>;

                partition@0 {
					label = "u-boot";
					reg = <0x0 0x30000>;
					read-only;
				};

				partition@30000 {
					label = "u-boot-env";
					reg = <0x30000 0x10000>;
					read-only;
				};

				factory: partition@40000 {
					label = "factory";
					reg = <0x40000 0x10000>;
					read-only;
				};

				partition@50000 {
					label = "firmware";
					reg = <0x50000 0xdb0000>;
				};
				
				partition@ff0000 {
					label = "config";
					reg = <0xe00000 0x100000>;
				};
		};
        spi {
            compatible = "spi-gpio";
            #address-cells = <0x1>;
            ranges;

            gpio-sck = <&gpio0 1 0>;
            gpio-miso = <&gpio0 2 0>;
            gpio-mosi = <&gpio0 23 0>;
            cs-gpios = <&gpio0 22 0>;
            num-chipselects = <1>;

            /* clients */
            w25q32@1 {
                #address-cells = <1>;
                #size-cells = <1>;
                compatible = "w25q32";
                reg = <0 0>;
                spi-max-frequency = <10000000>;
                
                partition@0 {
                    label = "other_flash";
                    reg = <0x0 0x0400000>;
                };
            };
        };
	};

        从以上设备树可以看出,我们的设备原来也是使用了一块flash来存放uboot和内核等其他内容的。      

        compatible = "spi-gpio"会与spi-gpio驱动match,导致spi-gpio驱动probe函数运行,gpio-sck,gpio-miso,gpio-mosi和cs-gpios表示分别用什么GPIO模块spi对应的信号线,num-chipselects=<1>表示片选的个数为1。

        w25q32@1表示spi的从设备了,这里就是我们的spi nor flash模块。"w25q32"表示我们使用的flash型号,这里指定的型号不对也没关系,内核会读flash的ID号,自动识别出flash的型号。

        以上就是全部的修改了。

三. 效果

1. 修改之前的内核打印
[    1.280000] m25p80 spi32766.0: found w25q256, expected mx25l12805d
[    1.290000] m25p80 spi32766.0: w25q256 (32768 Kbytes)
[    1.300000] 5 ofpart partitions found on MTD device spi32766.0
[    1.320000] Creating 5 MTD partitions on "spi32766.0":
[    1.330000] 0x000000000000-0x000000030000 : "u-boot"
[    1.340000] 0x000000030000-0x000000040000 : "u-boot-env"
[    1.350000] 0x000000040000-0x000000050000 : "factory"
[    1.360000] 0x000000050000-0x000000e00000 : "firmware"
[    1.370000] 0x000000e00000-0x000000f00000 : "config"
2. 修改之后的内核打印
[    1.290000] m25p80 spi32766.0: w25q32 (4096 Kbytes)
[    1.300000] 1 ofpart partitions found on MTD device spi32766.0
[    1.310000] Creating 1 MTD partitions on "spi32766.0":
[    1.320000] 0x000000000000-0x000000400000 : "other_flash"
[    1.350000] m25p80 spi32765.0: found w25q256, expected mx25l12805d
[    1.360000] m25p80 spi32765.0: w25q256 (32768 Kbytes)
[    1.370000] 5 ofpart partitions found on MTD device spi32765.0
[    1.380000] Creating 5 MTD partitions on "spi32765.0":
[    1.390000] 0x000000000000-0x000000030000 : "u-boot"
[    1.400000] 0x000000030000-0x000000040000 : "u-boot-env"
[    1.410000] 0x000000040000-0x000000050000 : "factory"
[    1.420000] 0x000000050000-0x000000e00000 : "firmware"
[    1.430000] 0x000000e00000-0x000000f00000 : "config"

        从以上的内核打印可以看出,内核识别到了一块w25q32 (4096 Kbytes)的flash,并且还创建了一块分区"other_flash",分区的大小是4M,这是我在设备上定义的。

3. 修改前的分区表
/ # cat /proc/mtd 
dev:    size   erasesize  name
mtd0: 00030000 00010000 "u-boot"
mtd1: 00010000 00010000 "u-boot-env"
mtd2: 00010000 00010000 "factory"
mtd3: 00db0000 00010000 "firmware"
mtd4: 00100000 00010000 "config"
4. 修改后的分区表
/ # cat /proc/mtd 
dev:    size   erasesize  name
mtd0: 00400000 00010000 "other_flash"
mtd1: 00030000 00010000 "u-boot"
mtd2: 00010000 00010000 "u-boot-env"
mtd3: 00010000 00010000 "factory"
mtd4: 00db0000 00010000 "firmware"
mtd5: 00100000 00010000 "config"
5. mount "other_flash"分区
/ # mount -t jffs2 /dev/mtdblock0 /media
[  560.280000] jffs2: notice: (2013) jffs2_build_xattr_subsystem: complete building xattr subsystem, 0 of xdatum (0 unchecked, 0 orphan) and 0 of xref (0 dead, 0 orphan) found.
/ # 
/ # df -h
Filesystem                Size      Used Available Use% Mounted on
tmpfs                    61.2M         0     61.2M   0% /tmp
/dev/mtdblock0            4.0M    260.0K      3.7M   6% /media

        从以上打印可以看出,新的4M的spi nor flash就成功mount到了/media目录。

四. 总结

        本文介绍了Linux通过GPIO模块SPI接口的方式,并且通过实例介绍了怎么驱动一块spi nor flash。这里有一处缺点:就是"other_flash"分区总是mtd0,这样会导致分区号整体向后偏移1,导致原来的代码需要修改这里还没有找到有效的办法解决。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/353858.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

acwing周赛140 b题

思路&#xff1a;我们按照从小到大的顺序将数组逆转好&#xff0c;然后枚举数组首项&#xff0c;分别让其1&#xff0c;-1&#xff0c;0&#xff0c;然后求出公差&#xff0c;从前往后遍历即可。 代码&#xff1a; int ans1(){//不动int cha (a[n] - a[1] 1) / (n - 1);int…

原创改进 | 融合蝠鲼觅食与联想学习的量子多目标灰狼优化算法(Matlab)

​前面的文章里作者介绍了多目标灰狼优化算法(Multi-Objective Grey Wolf Optimizer&#xff0c;MOGWO)&#xff0c;该算法是由Mirjalili等(灰狼算法的提出者)于2016年提出[1]&#xff0c;发表在中科院一区期刊《expert systems with applications》。 MOGWO保留了灰狼算法的种…

无际线复选框

效果演示 实现了一个网格布局&#xff0c;其中每个网格是一个复选框&#xff0c;可以选择是否显示。每个复选框都有一个漂浮的天花板&#xff0c;表示它是一个房间的天花板。每个房间的天花板都有一个不同的形状和颜色&#xff0c;分别对应不同的房间。整个页面的背景是一个由两…

小米13utltra激活冰箱

安装adb驱动https://www.jianshu.com/p/6c41d34d9202 直接下载使用 连接上小米手机,退出账号,关闭锁屏密码,打开usb调试,usb调试(安全设置) adb shell dpm set-device-owner com.catchingnow.icebox/.receiver.DPMReceiver如果显示Success&#xff0c;则您已成功激活冰箱。 …

【DeepLearning-8】MobileViT模块配置

完整代码&#xff1a; import torch import torch.nn as nn from einops import rearrange def conv_1x1_bn(inp, oup):return nn.Sequential(nn.Conv2d(inp, oup, 1, 1, 0, biasFalse),nn.BatchNorm2d(oup),nn.SiLU()) def conv_nxn_bn(inp, oup, kernal_size3, stride1):re…

PostgreSQL技术大讲堂 - 第43讲:流复制原理

PostgreSQL从小白到专家&#xff0c;是从入门逐渐能力提升的一个系列教程&#xff0c;内容包括对PG基础的认知、包括安装使用、包括角色权限、包括维护管理、、等内容&#xff0c;希望对热爱PG、学习PG的同学们有帮助&#xff0c;欢迎持续关注CUUG PG技术大讲堂。 第43讲&#…

每日OJ题_算法_二分查找⑦_力扣153. 寻找旋转排序数组中的最小值

目录 力扣153. 寻找旋转排序数组中的最小值 解析代码 力扣153. 寻找旋转排序数组中的最小值 153. 寻找旋转排序数组中的最小值 - 力扣&#xff08;LeetCode&#xff09; 难度 中等 已知一个长度为 n 的数组&#xff0c;预先按照升序排列&#xff0c;经由 1 到 n 次 旋转 后…

Java NIO初体验

概述 由于BIO&#xff08;同步阻塞IO&#xff09;对系统资源的浪费较大。Java1.4中引⼊了NIO框架&#xff0c;在java.nio包中提供了Channel、Selector、Buffer等抽象类&#xff0c;可以快速构建多路复⽤的IO程序&#xff0c;⽤于提供更接近操作系统底层的⾼性能数据操作⽅式。…

11. 双目视觉之立体视觉基础

目录 1. 深度恢复1.1 单目相机缺少深度信息1.2 如何恢复场景深度&#xff1f;1.3 深度恢复的思路 2. 对极几何约束2.1 直观感受2.2 数学上的描述 1. 深度恢复 1.1 单目相机缺少深度信息 之前学习过相机模型&#xff0c;最经典的就是小孔成像模型。我们知道相机通过小孔成像模…

零基础轻松学编程,中文编程开发工具下载及构件教程

零基础轻松学编程&#xff0c;中文编程开发工具下载及构件教程 一、前言 零基础学编程&#xff0c;中文编程工具下载&#xff0c;中文编程开发工具构件之选择件列表框构件教程&#xff0c; 想学编程可 编程交流.群.一起交流学习&#xff08;关注收藏或点击最下方官网卡片进入…

【c语言】详解操作符(上)

1. 操作符的分类 2. 原码、反码、补码 整数的2进制表示方法有三种&#xff0c;即原码、反码、补码 有符号整数的三种表示方法均有符号位和数值位两部分&#xff0c;2进制序列中&#xff0c;最高位的1位是被当做符号位其余都是数值位。 符号位都是用0表示“正”&#xff0c;用…

设计模式:简介及基本原则

简介 设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了重用代码、让代码更容易被他人理解、保证代码可靠性。 毫无疑问&#xff0c;设计模式于己于他人于系统都是多赢的&#xff0c;设计模式使代码编制真正工程化&#xff…

Kotlin快速入门5

Kotlin的继承与重写 kotlin的继承 Kotlin中所有类都继承自Any类&#xff0c;Any类是所有类的超类&#xff0c;对于没有超类型声明的类是默认超类&#xff08;Any 不是 java.lang.Object&#xff09;&#xff1a; class LearnKotlin // 默认继承自Any Any类默认提供三个函数…

Scikit-learn (sklearn)速通 -【莫凡Python学习笔记】

视频教程链接&#xff1a;【莫烦Python】Scikit-learn (sklearn) 优雅地学会机器学习 视频教程代码 scikit-learn官网 莫烦官网学习链接 本人matplotlib、numpy、pandas笔记 1 为什么学习 Scikit learn 也简称 sklearn, 是机器学习领域当中最知名的 python 模块之一. Sk…

IDEA搭建JDK源码学习环境(可添加注释、修改、debug)

工程详见&#xff1a;https://github.com/wenpanwenpan/study-source-jdk1.8.0_281 1、找到src.zip和javafx-src.zip 找到你想要调试的JDK&#xff0c;笔者本地电脑上装了两个版本的JDK&#xff0c;这里以jdk1.8.0_281为例将JDK目录下的javafx-src.zip和src.zip两个压缩包进行…

【GitHub项目推荐--不错的 TypeScript 学习项目】【转载】

在线白板工具 Excalidraw 标星 33k&#xff0c;是一款非常轻量的在线白板工具&#xff0c;可以直接在浏览器打开&#xff0c;轻松绘制具有手绘风格的图形。 如下图所示&#xff0c;Excalidraw 支持最常用的图形元素&#xff1a;方框、圆、菱形、线&#xff0c;可以方便的使用…

【Web】小白也能做的RWCTF体验赛baby题部分wp

遇到不会的题&#xff0c;怎么办&#xff01;有的师傅告诉你完了&#xff0c;废了&#xff0c;寄了&#xff01;只有Z3告诉你&#xff0c;稳辣&#xff01;稳辣&#xff01;都稳辣&#xff01; 这种CVE复现的题型&#xff0c;不可能要求选手从0到1进行0day挖掘&#xff0c;其实…

12.15字符编码(血干JAVA系列)

字符编码 12.15.1 Java常见编码简介12.15.2得到本机的编码显示【例12.68】使用上述方法得到JVM的默认编码 12.15.3乱码产生【例12.69】使用1SO8859-1编码 12.15.1 Java常见编码简介 12.15.2得到本机的编码显示 在 前 面 讲 解 常 用 类 库 的 时 候 曾 经 介 绍 过 &#xff0…

HarmonyOS 沉浸式状态栏实现

比如说 我们代码是这样的 Entry Component struct Index {build() {Column() {Column() {Column() {Text(定标标题).fontSize(20).fontColor(Color.White)}.height(50).justifyContent(FlexAlign.Center)}.width(100%).backgroundColor(#FF0000)}.height(100%)} }你预览器上看…

k8s 版本发布与回滚

一、实验环境准备&#xff1a; kubectl get pods -o wide kubectl get nodes -o wide kubectl get svc 准备两个nginx镜像&#xff0c;版本号一个是V3&#xff0c;一个是V4 二、准备一个nginx.yaml文件 apiVersion: apps/v1 kind: Deployment metadata:name: nginx-deploylab…