当前位置: 首页 > news >正文

【正点原子FPGA连载】第十三章QSPI Flash读写测试实验 摘自【正点原子】DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南

1)实验平台:正点原子MPSoC开发板
2)平台购买地址:https://detail.tmall.com/item.htm?id=692450874670
3)全套实验源码+手册+视频下载地址: http://www.openedv.com/thread-340252-1-1.html

第十三章QSPI Flash读写测试实验

PS的输入/输出外设(IOP)有两个具有不同功能特性和IO接口性能的QSPI控制器。它们共享相同的APB从接口和MIO引脚。一次只能使用控制器中的一个。QSPI控制器可以访问多比特位宽的Flash设备,以实现较少的引脚数达到高吞吐量的应用。
本章我们将通过QSPI Flash控制器,来完成对QSPI Flash的读写操作。本章包括以下几个部分:
1313.1简介
13.2实验任务
13.3硬件设计
13.4软件设计
13.5下载验证

13.1简介

MPSOC中的QSPI Flash控制器分为传统QSPI控制器(LQSPI)和通用QSPI控制器(GQSPI)两个。传统QSPI控制器通过AXI从接口提供了线性可寻址的内存空间。支持引导配置(BOOT)和应用软件配置的就地执行(execute-in-place)。通用QSPI控制器提供I/O,DMA和SPI三种接口模式,不支持引导(BOOT)和就地执行(execute-in-place)。I/O接口配置如下图所示:
在这里插入图片描述

图13.1.1 QSPI I/O接口配置
传统QSPI控制器(LQSPI)只在线性寻址模式下工作。在这种模式下,可以连接一个或两个Flash器件,为了最小化引脚数量,两块Flash可以通过8bit并行模式或者4bit堆叠排列模式连接到传统QSPI控制器。线性地址模式下,控制器通过使用部分器件操作来消除读Flash时的软件开销。QSPI控制器给Flash发送命令,控制Flash总线到AXI接口的数据流。控制器响应AXI接口上的Flash存储器请求,把Flash存储器当作ROM存储器。
通用QSPI控制器(GQSPI)满足软件对通用低级访问的要求。由于QSPI控制器的通用性,软件可以在任何模式下生成任何命令序列。同时,QSPI控制器支持SPI、Dual SPI和Quad SPI模式下的功能。QSPI控制器运行在I/O、DMA和SPI三种模式下。通用QSPI控制器也支持连接一块或两块Flash设备,为了最小化引脚数量,两块Flash可以通过8bit并行模式或者4bit堆叠排列模式连接到通用QSPI控制器。
在通用I/O模式下,软件和存储设备密切交互。软件将Flash命令写到通用FIFO中,并将数据写到TXFIFO。软件读取RXD寄存器,获取从Flash设备接收到的数据。在I/O模式下,通用QSPI控制器消除了写TXFIFO时产生的软件开销。
在通用DMA模式下,内部DMA模块将Flash设备中的数据传输到系统内存中。这种模式避免了用处理器从Flash中读数据,并且消除了TXFIFO中写满来自Flash数据时产生的软件开销。
在SPI模式下,通用QSPI控制器可以作为标准SPI控制器使用。
双QSPI结构框图如下图所示,控制器由一个传统线性QSPI控制器和一个通用QSPI控制器组成。当控制寄存器设置为1时,选择通用QSPI控制器。传统QSPI控制器和通用QSPI控制器共享带延迟线的接收捕获逻辑。
在这里插入图片描述

图13.1.2 双QSPI控制器

13.2实验任务

本章的实验任务是使用QSPI Flash控制器,先后对开发板上的QSPI Flash进行写、读操作。通过对比读出的数据是否等于写入的数据,从而验证读写操作是否正确。
13.3硬件设计
根据实验任务我们可以画出本次实验的系统框图,如下图所示:
在这里插入图片描述

图 13.3.1 系统框图
从图 13.3.1中可以看出,本次实验是在“Hello Wold”实验的基础上增加了一个QSPI Flash控制器。我们将通过该控制器对QSPI Flash进行读写操作,并通过串口打印读写数据对比之后的结果。
首先创建Vivado工程,工程名为“qspi_flash_test”,然后创建Block Design设计(system.bd)并添加Zynq Ultrascale+ MPSOC模块。接下来按照《“Hello World”实验》中的步骤对Zynq Ultrascale+ MPSOC模块进行配置,配置完成后我们要添加本次实验所使用的QSPI Flash控制器模块。如下图所示:
在这里插入图片描述

图 13.3.2 QSPI配置界面
如图 13.3.2所示,在左侧导航栏中选择“I/O Configuraton”,然后在右侧勾选“QSPI”,并选择“Single”模式,QSPI Data Mode选择“x4”,QSPI使用默认的“MIO0…5”。“Single”指的是单个Flash器件。看以看出,该模式下控制器使用了MIO0至MIO5共6个引脚。
最后点击右下角的“OK”,本次实验Zynq Ultrascale+ MPSOC处理系统就配置完成了。配置完成后的模块如下图所示:
在这里插入图片描述

图 13.3.3 Zynq Ultrascale+ MPSOC模块
到这里我们的Block Design就设计完成了,在Diagram窗口空白处右击,然后选择“Validate Design”验证设计。验证完成后弹出对话框提示“Validation Successful”表明设计无误,点击“OK”确认。最后按快捷键“Ctrl + S”保存设计。
接下来在Source窗口中右键点击Block Design设计文件“system.bd”,然后依次执行“Generate Output Products”和“Create HDL Wrapper”。
然后在菜单栏中选择 File > Export > Export hardware,将硬件文件导出到新建的vitis文件夹下,最后在菜单栏选择Tools > Launch Vitis,将路径设置到本工程的vitis文件夹下,启动Vitis软件。

13.4软件设计

在Vitis软件中新建名为“qspi_flash_test”的应用工程。然后为应用工程新建一个源文件“main.c”,我们在新建的main.c文件中输入本次实验的代码。代码的主体部分如下所示:

1    #include "xparameters.h"   /* Vitis generated parameters */
2    #include "xqspipsu.h"      /* QSPIPSU device driver */
3    #include "xil_printf.h"
4    #include "xil_cache.h"
5    
6    //定义flash读写命令
7    #define WRITE_STATUS_CMD   0x01
8    #define WRITE_CMD          0x02
9    #define READ_CMD           0x03
10   #define WRITE_DISABLE_CMD  0x04
11   #define READ_STATUS_CMD        0x05
12   #define WRITE_ENABLE_CMD   0x06
13   #define VOLATILE_WRITE_ENABLE_CMD  0x50
14   #define QUAD_MODE_ENABLE_BIT       0x06
15   #define FAST_READ_CMD      0x0B
16   #define DUAL_READ_CMD      0x3B
17   #define QUAD_READ_CMD      0x6B
18   #define BULK_ERASE_CMD     0xC7
19   #define    SEC_ERASE_CMD       0xD8
20   #define READ_ID                0x9F
21   #define READ_CONFIG_CMD        0x35
22   #define WRITE_CONFIG_CMD   0x01
23   
24   #define READ_CMD_4B            0x13
25   #define FAST_READ_CMD_4B   0x0C
26   #define DUAL_READ_CMD_4B   0x3C
27   #define QUAD_READ_CMD_4B   0x6C
28   
29   #define READ_FLAG_STATUS_CMD   0x70
30   
31   #define COMMAND_OFFSET     0  //Flash instruction
32   #define ADDRESS_1_OFFSET   1  //数据偏移地址的最高位
33   #define ADDRESS_2_OFFSET   2  //数据偏移地址的中间位
34   #define ADDRESS_3_OFFSET   3  //数据偏移地址的最低位
35   #define ADDRESS_4_OFFSET   4  //数据偏移地址为四字节时 最低位
36   
37   #define DATA_OFFSET     5  //Start of Data for Read/Write
38   #define DUMMY_OFFSET    4  //Dummy byte offset for fast, dual and quad reads
39   
40   #define DUMMY_SIZE      1  //Number of dummy bytes for fast, dual and quad reads
41   
42   #define DUMMY_CLOCKS    8  //Number of dummy bytes for fast, dual and quad reads
43   
44   #define RD_ID_SIZE      4  //Read ID command + 3 bytes ID response 
45   #define BULK_ERASE_SIZE 1  //Bulk Erase command size
46   #define SEC_ERASE_SIZE  4  //Sector Erase command + Sector address 
47   #define BANK_SEL_SIZE   2  //BRWR or EARWR command + 1 byte bank value
48   
49   #define RD_CFG_SIZE     2  //1 byte Configuration register + RD CFG command
50   
51   #define WR_CFG_SIZE     3  //WRR command + 1 byte each Status and Config Reg
52   
53   #define DIE_ERASE_SIZE  4  //Die Erase command + Die address
54   
55   #define OVERHEAD_SIZE   4
56   
57   //flash基地址
58   #define FLASH1BASE 0x0000000
59   
60   //16MB
61   #define SIXTEENMB 0x1000000
62   
63   //quad enable mask bit
64   #define FLASH_QUAD_EN_MASK 0x02
65   
66   #define FLASH_SRWD_MASK 0x80
67   
68   // Bank mask
69   #define BANKMASK 0xF000000
70   
71   
72   // Identification of Flash
73   // Micron:
74   // Byte 0 is Manufacturer ID;
75   // Byte 1 is first byte of Device ID - 0xBB or 0xBA
76   // Byte 2 is second byte of Device ID describes flash size:
77   // 128Mbit : 0x18; 256Mbit : 0x19; 512Mbit : 0x20
78   #define MICRON_ID_BYTE0        0x20
79   #define MICRON_ID_BYTE2_128    0x18
80   #define MICRON_ID_BYTE2_256    0x19
81   #define MICRON_ID_BYTE2_512    0x20
82   #define MICRON_ID_BYTE2_1G 0x21
83   #define MICRON_ID_BYTE2_2G 0x22
84   
85   // Spansion:
86   // Byte 0 is Manufacturer ID;
87   // Byte 1 is Device ID - Memory Interface type - 0x20 or 0x02
88   // Byte 2 is second byte of Device ID describes flash size:
89   // 128Mbit : 0x18; 256Mbit : 0x19; 512Mbit : 0x20
90   #define SPANSION_ID_BYTE0  0x01
91   #define SPANSION_ID_BYTE2_64   0x17
92   #define SPANSION_ID_BYTE2_128  0x18
93   #define SPANSION_ID_BYTE2_256  0x19
94   #define SPANSION_ID_BYTE2_512  0x20
95   
96   #define WINBOND_ID_BYTE0   0xEF
97   #define WINBOND_ID_BYTE2_128   0x18
98   
99   #define ISSI_ID_BYTE0      0x9D
100  #define ISSI_ID_BYTE2_08   0x14
101  #define ISSI_ID_BYTE2_16   0x15
102  #define ISSI_ID_BYTE2_32   0x16
103  #define ISSI_ID_BYTE2_64   0x17
104  #define ISSI_ID_BYTE2_128  0x18
105  #define ISSI_ID_BYTE2_256  0x19
106  #define ISSI_ID_BYTE2_512  0x1a
107  
108  #define QSPIPSU_DEVICE_ID      XPAR_XQSPIPSU_0_DEVICE_ID
109  
110  //flash页的数量
111  #define PAGE_COUNT     32
112  
113  //页大小的最大值
114  #define MAX_PAGE_SIZE 1024
115  
116  #define TEST_ADDRESS       0x000000
117  
118  #define UNIQUE_VALUE       0x06
119  
120  /**************************** Type Definitions *******************************/
121  typedef struct{
122     u32 SectSize;         //扇区大小
123     u32 NumSect;          //扇区总个数
124     u32 PageSize;         //页大小
125     u32 NumPage;          //总页数
126     u32 FlashDeviceSize;  //一个存储器件的大小
127     u8 ManufacturerID;    //制造商ID
128     u8 DeviceIDMemSize;   //指出存储容量的器件ID
129     u32 SectMask;         //扇区开始地址掩码
130     u8 NumDie;            // No. of die forming a single flash
131  } FlashInfo;
132  
133  u8 ReadCmd;
134  u8 WriteCmd;
135  u8 StatusCmd;
136  u8 SectorEraseCmd;
137  u8 FSRFlag;
138  
139  /************************** Function Prototypes ******************************/
140  
141  int QspiPsuPolledFlashExample(XQspiPsu *QspiPsuInstancePtr, u16 QspiPsuDeviceId);
142  int FlashReadID(XQspiPsu *QspiPsuPtr);
143  int FlashErase(XQspiPsu *QspiPsuPtr, u32 Address, u32 ByteCount, u8 *WriteBfrPtr);
144  int FlashWrite(XQspiPsu *QspiPsuPtr, u32 Address, u32 ByteCount, u8 Command,
145                 u8 *WriteBfrPtr);
146  int FlashRead(XQspiPsu *QspiPsuPtr, u32 Address, u32 ByteCount, u8 Command,
147                 u8 *WriteBfrPtr, u8 *ReadBfrPtr);
148  u32 GetRealAddr(XQspiPsu *QspiPsuPtr, u32 Address);
149  int BulkErase(XQspiPsu *QspiPsuPtr, u8 *WriteBfrPtr);
150  int FlashEnableQuadMode(XQspiPsu *QspiPsuPtr);
151  /************************** Variable Definitions *****************************/
152  u8 TxBfrPtr;
153  u8 ReadBfrPtr[3];
154  FlashInfo Flash_Config_Table[] = {
155     {SECTOR_SIZE_64K, NUM_OF_SECTORS128, BYTES256_PER_PAGE,
156         0x8000, 0x800000, SPANSION_ID_BYTE0,
157         SPANSION_ID_BYTE2_64, 0xFFFF0000, 1}
158  };
159  
160  u32 FlashMake;
161  u32 FCTIndex;  //闪存配置表的索引
162  
163  //QSPI实例
164  static XQspiPsu QspiPsuInstance;
165  
166  static XQspiPsu_Msg FlashMsg[5];
167  
168  //测试变量 用于产生发送数据
169  int Test = 1;
170  
171  //用于存储读写数据的变量
172  u8 ReadBuffer[(PAGE_COUNT * MAX_PAGE_SIZE) + (DATA_OFFSET + DUMMY_SIZE)*8] __attribute__ ((aligned(64)));
173  u8 WriteBuffer[(PAGE_COUNT * MAX_PAGE_SIZE) + DATA_OFFSET];
174  u8 CmdBfr[8];
175  
176  u32 MaxData = PAGE_COUNT*256;
177  
178  //主函数
179  int main(void)
180  {
181     int Status;
182  
183     xil_printf("QSPIPSU Generic Flash Polled Example Test \r\n");
184  
185     //调用QspiPsu Polled example
186     Status = QspiPsuPolledFlashExample(&QspiPsuInstance, QSPIPSU_DEVICE_ID);
187     if (Status != XST_SUCCESS) {
188         xil_printf("QSPIPSU Generic Flash Polled Example Failed\r\n");
189         return XST_FAILURE;
190     }
191  
192     xil_printf("Successfully ran QSPIPSU Generic Flash Polled Example\r\n");
193     return XST_SUCCESS;
194  }

首先,本次实验的C程序是在官方提供的示例程序“xqspipsu_generic_flash_polled_example.c”的基础上修改得到的,该示例程序演示了如何使用轮询模式对QSPI Flash进行读写操作。
在程序的开头,我们定义了一系列的参数,包括Flash器件的指令、Flash BUFFER中各数据段的偏移量、Flash器件PAGE、SECTOR的数目和大小等信息。这些信息针对不同型号的Flash器件有所不同,需要通过查看器件的数据手册得到。
接下来在程序第141至150行声明了八个函数,这些函数是前面我们提到的示例程序中所提供的。我们对其中的函数QspiPsuPolledFlashExample(XQspiPsu *QspiPsuInstancePtr, u16 QspiPsuDeviceId)、FlashReadID(XQspiPsu *QspiPsuPtr)进行修改,从而简化读写测试过程。而其他的函数如擦除FlashErase( )、写操作FlashWrite( )、读操作FlashRead( )等,改动不大。
程序的主函数特别简单,就是通过调用修改之后的示例函数QspiPsuPolledFlashExample ( )来对Flash进行读写测试,并打印最终的测试结果。下面是该示例函数的代码:

198  int QspiPsuPolledFlashExample(XQspiPsu *QspiPsuInstancePtr, u16 QspiPsuDeviceId)
199  {
200     u8 UniqueValue;
201     int Count;
202     int Page;
203     XQspiPsu_Config *QspiPsuConfig;
204     int ReadBfrSize;
205  
206     ReadBfrSize = (PAGE_COUNT * MAX_PAGE_SIZE) +
207             (DATA_OFFSET + DUMMY_SIZE)*8;
208  
209     //根据ID查找Qspi配置信息
210     QspiPsuConfig = XQspiPsu_LookupConfig(QspiPsuDeviceId);
211     if (QspiPsuConfig == NULL) {
212         return XST_FAILURE;
213     }
214  
215     //初始化Qspi
216     XQspiPsu_CfgInitialize(QspiPsuInstancePtr, QspiPsuConfig,
217                     QspiPsuConfig->BaseAddress);
218  
219     //设置Options
220     XQspiPsu_SetOptions(QspiPsuInstancePtr, XQSPIPSU_MANUAL_START_OPTION);
221  
222     //为qspi时钟设置分频系数
223     XQspiPsu_SetClkPrescaler(QspiPsuInstancePtr, XQSPIPSU_CLK_PRESCALE_8);
224  
225     XQspiPsu_SelectFlash(QspiPsuInstancePtr,
226         XQSPIPSU_SELECT_FLASH_CS_LOWER,
227         XQSPIPSU_SELECT_FLASH_BUS_LOWER);
228  
229     //读Flash ID
230     FlashReadID(QspiPsuInstancePtr);
231  
232  
233     //Initialize MaxData according to page size.
234  
235     MaxData = PAGE_COUNT * (Flash_Config_Table[FCTIndex].PageSize);
236  
237     //使能flash quad模式
238     FlashEnableQuadMode(QspiPsuInstancePtr);
239  
242     //Address size and read command selection
243     ReadCmd = QUAD_READ_CMD;
244     WriteCmd = WRITE_CMD;
245     SectorEraseCmd = SEC_ERASE_CMD;
246  
247     /* Status cmd - SR or FSR selection */
248     if ((Flash_Config_Table[FCTIndex].NumDie > 1) &&
249             (FlashMake == MICRON_ID_BYTE0)) {
250         StatusCmd = READ_FLAG_STATUS_CMD;
251         FSRFlag = 1;
252     } else {
253         StatusCmd = READ_STATUS_CMD;
254         FSRFlag = 0;
255     }
256  
257     for (UniqueValue = UNIQUE_VALUE, Count = 0;
258             Count < Flash_Config_Table[FCTIndex].PageSize;
259             Count++, UniqueValue++) {
260         WriteBuffer[Count] = (u8)(UniqueValue + Test);
261     }
262  
263     for (Count = 0; Count < ReadBfrSize; Count++) {
264         ReadBuffer[Count] = 0;
265     }
266  
267     //擦除flash
268     FlashErase(QspiPsuInstancePtr, TEST_ADDRESS, MaxData, CmdBfr);
269  
270     for (Page = 0; Page < PAGE_COUNT; Page++) {
271         FlashWrite(QspiPsuInstancePtr,
272                 (Page * Flash_Config_Table[FCTIndex].PageSize) + TEST_ADDRESS,
273                 Flash_Config_Table[FCTIndex].PageSize,
274                 WriteCmd, WriteBuffer);
275     }
276  
277     //从flash中读出数据
278     FlashRead(QspiPsuInstancePtr, TEST_ADDRESS, MaxData, ReadCmd,
279                 CmdBfr, ReadBuffer);
280  
281     //读出的数据和写入的数据对比
282     for (UniqueValue = UNIQUE_VALUE, Count = 0; Count < MaxData;
283          Count++, UniqueValue++) {
284         if (ReadBuffer[Count] != (u8)(UniqueValue + Test)) {
285             return XST_FAILURE;
286         }
287     }
288  
289     return XST_SUCCESS;
290  }

在示例函数中,首先查找QSPI Flash控制器配置信息,接着对控制器驱动进行初始化,如代码的第210行至217行所示。向WriteBuffer中写入数据,然后将WriteBuffer中的数据写到Flash中,如代码第270行至第275行所示。注意在写Flash之前,调用FlashErase( )函数对Flash进行擦除,这是因为Flash写操作只能将1写成0,不能将0写成1,而擦除操作才能将0写成1。
最后,在程序的第282至287行,通过对比写入BUFFER的数据与读BUFFER中的数据是否一致,从而判断Flash读写测试实验是否成功。
程序的剩余部分是前面所声明的一系列操作Flash的函数的实现,因为我们将其当作库函数直接调用,因此代码就不再贴出来了。大家有兴趣的话也可以研究一下,这些函数是如何将读写指令和数据转换成QSPI Flash所要求的命令格式的。实际上,这些函数的功能也都是通过调用xqspipsu.h头文件中的库函数XQspiPsu_PolledTransfer( )来实现的。
13.5下载验证
首先我们将下载器与开发板上的JTAG接口连接,下载器另外一端与电脑连接。然后使用USB连接线将开发板的USB_UART接口(PS PORT)与电脑连接,用于串口通信。最后连接开发板的电源,给开发板供电。
打开Vitis Terminal终端,设置并连接串口。然后下载本次实验的程序,下载完成后,在下方的Terminal中可以看到应用程序打印的信息“Successfully ran QSPIPSU Generic Flash Polled Test”,如下图所示:
在这里插入图片描述

图 13.5.1 串口打印结果
从图 13.5.1中可以看出,本次实验所实现的QSPI Flash读写测试功能,在MPSOC开发板上面下载验证成功。

相关文章:

【正点原子FPGA连载】第十三章QSPI Flash读写测试实验 摘自【正点原子】DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南

1&#xff09;实验平台&#xff1a;正点原子MPSoC开发板 2&#xff09;平台购买地址&#xff1a;https://detail.tmall.com/item.htm?id692450874670 3&#xff09;全套实验源码手册视频下载地址&#xff1a; http://www.openedv.com/thread-340252-1-1.html 第十三章QSPI Fl…...

深入理解mysql的内核查询成本计算

MySql系列整体栏目 内容链接地址【一】深入理解mysql索引本质https://blog.csdn.net/zhenghuishengq/article/details/121027025【二】深入理解mysql索引优化以及explain关键字https://blog.csdn.net/zhenghuishengq/article/details/124552080【三】深入理解mysql的索引分类&a…...

LeetCode 141. 环形链表

原题链接 难度&#xff1a;easy\color{Green}{easy}easy 题目描述 给你一个链表的头节点 headheadhead &#xff0c;判断链表中是否有环。 如果链表中有某个节点&#xff0c;可以通过连续跟踪 nextnextnext 指针再次到达&#xff0c;则链表中存在环。 为了表示给定链表中的…...

git提交

文章目录关于数据库&#xff1a;桌面/vue-admin/vue_shop_api 的 git 输入 打开 phpStudy ->mySQL管理器 导入文件同时输入密码&#xff0c;和文件名 node app.js 错误区&#xff1a; $ git branch // git branch 查看分支 只有一个main分支不见master解决&#xff1a; gi…...

Java中常见的编码集问题

收录于热门专栏Java基础教程系列&#xff08;进阶篇&#xff09; 一、遇到一个问题 1、读取CSV文件 package com.guor.demo.charset;import java.io.BufferedReader; import java.io.FileReader; import java.util.ArrayList; import java.util.HashMap; import java.util.L…...

数据结构与算法(Java版) | 就让我们来看看几个实际编程中遇到的问题吧!

上一讲&#xff0c;我给大家简单介绍了一下数据结构&#xff0c;以及数据结构与算法之间的关系&#xff0c;照理来说&#xff0c;接下来我就应该要给大家详细介绍线性结构和非线性结构了&#xff0c;但是在此之前&#xff0c;我决定还是先带着大家看几个实际编程中遇到的问题&a…...

【C++算法】dfs深度优先搜索(上) ——【全面深度剖析+经典例题展示】

&#x1f483;&#x1f3fc; 本人简介&#xff1a;男 &#x1f476;&#x1f3fc; 年龄&#xff1a;18 &#x1f4d5; ps:七八天没更新了欸&#xff0c;这几天刚搞完元宇宙&#xff0c;上午一直练&#x1f697;&#xff0c;下午背四级单词和刷题来着&#xff0c;还在忙一些学弟…...

总结高频率Vue面试题

目录 什么是三次握手&#xff1f; 什么是四次挥手&#xff1f;&#xff08;close触发&#xff09; 什么是VUEX&#xff1f; 什么是同源----跨域&#xff1f; 什么是Promise&#xff1f; 什么是fexl布局&#xff1f; 数据类型 什么是深浅拷贝&#xff1f; 什么是懒加载&…...

IP协议详解

目录 前言&#xff1a; IP协议 提出问题 解决方案 地址管理 子网掩码 路由选择 小结&#xff1a; 前言&#xff1a; IP协议作为网络层知名协议。当数据经过传输层使用TCP或者UDP对数据进行封装&#xff0c;然后当数据到达网络层&#xff0c;基于TCP或UDP数据包继续进行…...

webpack5 基础配置

在开发中&#xff0c;我们会使用 vue、react、less、scss等语法进行开发项目&#xff0c;但是浏览器只能识别 js、css&#xff0c;或者说在js中使用了es6中的import 导入 这时候也需要打包工具去转换成浏览器可以识别的语句。 一、使用webpack 1.初始化package.json npm i…...

IDEA入门安装使用教程

一、背景 作为一个Java开发者&#xff0c;有非常多编辑工具供我们选择&#xff0c;比如Eclipse、IntelliJ IDEA、NetBeans、Visual Studio Code、Sublime Text等等&#xff0c;这些有免费也有收费的&#xff0c;但是就目前市场占比来说普遍使用Eclipse和IntelliJ IDEA这两款主…...

Lambda表达式使用及详解

一 Lambda表达式的简介 Lambda表达式&#xff08;闭包&#xff09;&#xff1a;java8的新特性&#xff0c;lambda运行将函数作为一个方法的参数&#xff0c;也就是函数作为参数传递到方法中。使用lambda表达式可以让代码更加简洁。 Lambda表达式的使用场景&#xff1a;用以简…...

JAVA练习52-打家劫舍

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 前言 一、题目-打家劫舍 1.题目描述 2.思路与代码 2.1 思路 2.2 代码 总结 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 2月16日练习内容 提…...

简单谈一谈幂等测试

1、什么是幂等测试 幂等是一个抽象的概念&#xff0c;在编程中一个幂等操作的特点是其任意多次执行所产生的影响均与一次执行的影响相同&#xff0c;即多次调用方法或者接口不会改变业务状态&#xff0c;可以保证重复调用的结果和单次调用的结果一致。幂等测试&#xff0c;则主…...

typescript复习笔记

数组类型-限定每一项的类型 //写法一 const arrNumber: number[] [1, 2, 3] const arrString: string[] [a, b, c] //写法二 const arrNumber2: Array<number> [1, 2, 3] const arrString2: Array<string> [a, b, c]联合类型 符号是 | //数组可以存放字符串或…...

webstorm开发electron,调试主进程方案

官网教程地址&#xff1a;https://www.electronjs.org/zh/docs/latest/tutorial/debugging-main-process 我只能说官网太看得起人了&#xff0c;整这么简易的教程…… 命令行开关 第一步还是要按要求在我们的package.json里加上端口监听&#xff1a;–inspect5858 我的命令…...

2W字正则表达式基础知识总结,这一篇就够了!!(含前端常用案例,建议收藏)

正则表达式 (Regular Expression&#xff0c;简称 RE 或 regexp ) 是一种文本模式&#xff0c;包括普通字符&#xff08;例如&#xff0c;a 到 z 之间的字母&#xff09;和特殊字符&#xff08;称为"元字符"&#xff09;正则表达式使用单个字符串来描述、匹配一系列匹…...

自学web前端觉得好难,可能你遇到了这些困境

好多人跟我说上学的时候也学过前端&#xff0c;毕业了想从事web前端开发的工作&#xff0c;但自学起来好难&#xff0c;快要放弃了&#xff0c;所以我总结了一些大家遇到的困境&#xff0c;希望对你会有所帮助。 目录 1. 意志是否坚定 2. 没有找到合适自己的老师 3. 为了找…...

ASEMI中低压MOS管18N20参数,18N20封装,18N20尺寸

编辑-Z ASEMI中低压MOS管18N20参数&#xff1a; 型号&#xff1a;18N20 漏极-源极电压&#xff08;VDS&#xff09;&#xff1a;200V 栅源电压&#xff08;VGS&#xff09;&#xff1a;30V 漏极电流&#xff08;ID&#xff09;&#xff1a;18A 功耗&#xff08;PD&#x…...

[NetBackup]客户端安装后server无法连通client

client name处填写客户端主机名&#xff0c;server to use for backups and restores处填写server端名字&#xff0c;与hosts文件内保持一致&#xff1b;source client for restores处填写client主机名&#xff0c;与server端hosts文件中保持一致&#xff0c;与主机实际名称保持…...

生成xcframework

打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式&#xff0c;可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...

【Linux】C语言执行shell指令

在C语言中执行Shell指令 在C语言中&#xff0c;有几种方法可以执行Shell指令&#xff1a; 1. 使用system()函数 这是最简单的方法&#xff0c;包含在stdlib.h头文件中&#xff1a; #include <stdlib.h>int main() {system("ls -l"); // 执行ls -l命令retu…...

STM32+rt-thread判断是否联网

一、根据NETDEV_FLAG_INTERNET_UP位判断 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…...

关于iview组件中使用 table , 绑定序号分页后序号从1开始的解决方案

问题描述&#xff1a;iview使用table 中type: "index",分页之后 &#xff0c;索引还是从1开始&#xff0c;试过绑定后台返回数据的id, 这种方法可行&#xff0c;就是后台返回数据的每个页面id都不完全是按照从1开始的升序&#xff0c;因此百度了下&#xff0c;找到了…...

Leetcode 3577. Count the Number of Computer Unlocking Permutations

Leetcode 3577. Count the Number of Computer Unlocking Permutations 1. 解题思路2. 代码实现 题目链接&#xff1a;3577. Count the Number of Computer Unlocking Permutations 1. 解题思路 这一题其实就是一个脑筋急转弯&#xff0c;要想要能够将所有的电脑解锁&#x…...

基于Uniapp开发HarmonyOS 5.0旅游应用技术实践

一、技术选型背景 1.跨平台优势 Uniapp采用Vue.js框架&#xff0c;支持"一次开发&#xff0c;多端部署"&#xff0c;可同步生成HarmonyOS、iOS、Android等多平台应用。 2.鸿蒙特性融合 HarmonyOS 5.0的分布式能力与原子化服务&#xff0c;为旅游应用带来&#xf…...

【HarmonyOS 5 开发速记】如何获取用户信息(头像/昵称/手机号)

1.获取 authorizationCode&#xff1a; 2.利用 authorizationCode 获取 accessToken&#xff1a;文档中心 3.获取手机&#xff1a;文档中心 4.获取昵称头像&#xff1a;文档中心 首先创建 request 若要获取手机号&#xff0c;scope必填 phone&#xff0c;permissions 必填 …...

Yolov8 目标检测蒸馏学习记录

yolov8系列模型蒸馏基本流程&#xff0c;代码下载&#xff1a;这里本人提交了一个demo:djdll/Yolov8_Distillation: Yolov8轻量化_蒸馏代码实现 在轻量化模型设计中&#xff0c;**知识蒸馏&#xff08;Knowledge Distillation&#xff09;**被广泛应用&#xff0c;作为提升模型…...

人工智能(大型语言模型 LLMs)对不同学科的影响以及由此产生的新学习方式

今天是关于AI如何在教学中增强学生的学习体验&#xff0c;我把重要信息标红了。人文学科的价值被低估了 ⬇️ 转型与必要性 人工智能正在深刻地改变教育&#xff0c;这并非炒作&#xff0c;而是已经发生的巨大变革。教育机构和教育者不能忽视它&#xff0c;试图简单地禁止学生使…...

(一)单例模式

一、前言 单例模式属于六大创建型模式,即在软件设计过程中,主要关注创建对象的结果,并不关心创建对象的过程及细节。创建型设计模式将类对象的实例化过程进行抽象化接口设计,从而隐藏了类对象的实例是如何被创建的,封装了软件系统使用的具体对象类型。 六大创建型模式包括…...