【正点原子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)实验平台:正点原子MPSoC开发板 2)平台购买地址:https://detail.tmall.com/item.htm?id692450874670 3)全套实验源码手册视频下载地址: 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. 环形链表
原题链接 难度:easy\color{Green}{easy}easy 题目描述 给你一个链表的头节点 headheadhead ,判断链表中是否有环。 如果链表中有某个节点,可以通过连续跟踪 nextnextnext 指针再次到达,则链表中存在环。 为了表示给定链表中的…...
git提交
文章目录关于数据库:桌面/vue-admin/vue_shop_api 的 git 输入 打开 phpStudy ->mySQL管理器 导入文件同时输入密码,和文件名 node app.js 错误区: $ git branch // git branch 查看分支 只有一个main分支不见master解决: gi…...
Java中常见的编码集问题
收录于热门专栏Java基础教程系列(进阶篇) 一、遇到一个问题 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版) | 就让我们来看看几个实际编程中遇到的问题吧!
上一讲,我给大家简单介绍了一下数据结构,以及数据结构与算法之间的关系,照理来说,接下来我就应该要给大家详细介绍线性结构和非线性结构了,但是在此之前,我决定还是先带着大家看几个实际编程中遇到的问题&a…...
【C++算法】dfs深度优先搜索(上) ——【全面深度剖析+经典例题展示】
💃🏼 本人简介:男 👶🏼 年龄:18 📕 ps:七八天没更新了欸,这几天刚搞完元宇宙,上午一直练🚗,下午背四级单词和刷题来着,还在忙一些学弟…...
总结高频率Vue面试题
目录 什么是三次握手? 什么是四次挥手?(close触发) 什么是VUEX? 什么是同源----跨域? 什么是Promise? 什么是fexl布局? 数据类型 什么是深浅拷贝? 什么是懒加载&…...
IP协议详解
目录 前言: IP协议 提出问题 解决方案 地址管理 子网掩码 路由选择 小结: 前言: IP协议作为网络层知名协议。当数据经过传输层使用TCP或者UDP对数据进行封装,然后当数据到达网络层,基于TCP或UDP数据包继续进行…...
webpack5 基础配置
在开发中,我们会使用 vue、react、less、scss等语法进行开发项目,但是浏览器只能识别 js、css,或者说在js中使用了es6中的import 导入 这时候也需要打包工具去转换成浏览器可以识别的语句。 一、使用webpack 1.初始化package.json npm i…...
IDEA入门安装使用教程
一、背景 作为一个Java开发者,有非常多编辑工具供我们选择,比如Eclipse、IntelliJ IDEA、NetBeans、Visual Studio Code、Sublime Text等等,这些有免费也有收费的,但是就目前市场占比来说普遍使用Eclipse和IntelliJ IDEA这两款主…...
Lambda表达式使用及详解
一 Lambda表达式的简介 Lambda表达式(闭包):java8的新特性,lambda运行将函数作为一个方法的参数,也就是函数作为参数传递到方法中。使用lambda表达式可以让代码更加简洁。 Lambda表达式的使用场景:用以简…...
JAVA练习52-打家劫舍
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 目录 前言 一、题目-打家劫舍 1.题目描述 2.思路与代码 2.1 思路 2.2 代码 总结 前言 提示:这里可以添加本文要记录的大概内容: 2月16日练习内容 提…...
简单谈一谈幂等测试
1、什么是幂等测试 幂等是一个抽象的概念,在编程中一个幂等操作的特点是其任意多次执行所产生的影响均与一次执行的影响相同,即多次调用方法或者接口不会改变业务状态,可以保证重复调用的结果和单次调用的结果一致。幂等测试,则主…...
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,调试主进程方案
官网教程地址:https://www.electronjs.org/zh/docs/latest/tutorial/debugging-main-process 我只能说官网太看得起人了,整这么简易的教程…… 命令行开关 第一步还是要按要求在我们的package.json里加上端口监听:–inspect5858 我的命令…...
2W字正则表达式基础知识总结,这一篇就够了!!(含前端常用案例,建议收藏)
正则表达式 (Regular Expression,简称 RE 或 regexp ) 是一种文本模式,包括普通字符(例如,a 到 z 之间的字母)和特殊字符(称为"元字符")正则表达式使用单个字符串来描述、匹配一系列匹…...
自学web前端觉得好难,可能你遇到了这些困境
好多人跟我说上学的时候也学过前端,毕业了想从事web前端开发的工作,但自学起来好难,快要放弃了,所以我总结了一些大家遇到的困境,希望对你会有所帮助。 目录 1. 意志是否坚定 2. 没有找到合适自己的老师 3. 为了找…...
ASEMI中低压MOS管18N20参数,18N20封装,18N20尺寸
编辑-Z ASEMI中低压MOS管18N20参数: 型号:18N20 漏极-源极电压(VDS):200V 栅源电压(VGS):30V 漏极电流(ID):18A 功耗(PD&#x…...
[NetBackup]客户端安装后server无法连通client
client name处填写客户端主机名,server to use for backups and restores处填写server端名字,与hosts文件内保持一致;source client for restores处填写client主机名,与server端hosts文件中保持一致,与主机实际名称保持…...
黑马Java后端项目实战--在线聊天交友
【课程简介】 越来越多的系统都有消息推送的功能,如聊天室、邮件推送、系统消息推送等; 要实现消息推送就需要服务端在数据有变化时主动推送消息给客户端,本次课程将带大家使用websocket实现消息推送。 【主讲内容】 1.方法:如…...
【实战系列 2】Yapi接口管理平台Getshell-Linux后门权限维持与痕迹清除
文章目录 前言一、网站主页到Getshell二、SSH软链接后门三、Linux权限维持 --隐藏踪迹3.1 隐藏远程SSH登陆记录3.2、ssh软链接后门连接失败的原因以及解决办法3.3、隐藏踪迹-痕迹清楚3.3.1、隐藏历史操作命令3.3.2、隐藏文件/文件夹3.3.3、修改文件时间戳3.3.4、隐藏权限3.3.5、…...
设计模式之抽象工厂模式(C++)
作者:翟天保Steven 版权声明:著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处 一、抽象工厂模式是什么? 抽象工厂模式是一种创建型的软件设计模式,该模式相当于升级版的工厂模式。 如果…...
Kotlin新手教程一(Kotlin简介及环境搭建)
目录一、 什么是Kotlin?二、为什么要使用Kotlin?三、使用IntelliJ IDEA搭建Kotlin四、Kotlin使用命令行编译一、 什么是Kotlin? Kotlin 是一种在 Java 虚拟机上运行的静态类型编程语言,它也可以被编译成为 JavaScript 源代码&…...
【虚拟仿真】Unity3D打包WEBGL实现全屏切换
推荐阅读 CSDN主页GitHub开源地址Unity3D插件分享简书地址我的个人博客 大家好,我是佛系工程师☆恬静的小魔龙☆,不定时更新Unity开发技巧,觉得有用记得一键三连哦。 一、前言 今天实现Unity3D打包WEBGL后实现按钮点击全屏和退出 全屏的实现…...
java对象内存结构分析与大小计算
java对象内存结构Java对象保存在堆中时,由三部分组成:对象头(object header):包括了关于堆对象的布局、类型、GC状态、同步状态和标识哈希码的基本信息。所有java对象都有一个共同的对象头格实例数据(Insta…...
RabbitMQ学习(七):交换器
〇、前言在之前的内容中,我们创建了一个工作队列。我们假设的是工作队列背后,每个任务都恰好交付给一个消 费者(工作进程)。在今天的内容中,我们将做一些完全不同的事情——我们将消息传达给多个消费者。这种模式 称为 “发布/订阅”。为了说…...
cmd命令大全
文章目录变量输入输出逻辑命令符控制语句函数注释变量 在批处理中,变量全部是弱类型的,通常可以当做字符串处理 1.初始化定义 set varthis a var 2.获取变量值 %var% 3.链接 set varcat%var1%%var2% 4.截取 %var:~n,m% n是起点,m是长度&…...
Git的使用方法(保姆级)
一、安装git二、创建凭据 ①打开电脑的凭据管理器git:https://gitee.com是固定写法用户名、密码是你创建gitee的用户名、密码三、在gitee中创建一个仓库四、项目提交到仓库的方法①选择一个项目交由git管理按照步骤一中召唤小黑窗口输入 git init 就可以出现.git文件夹②右键选…...
TypeScript 学习之泛型
泛型使用 组件不仅能够支持当前的数据类型,同时也能支持未来的数据类型。就需要使用泛型。使用泛型就不会丢失类型信息,使用any会丢失类型信息。 function identity<T>(arg: T): T {return arg; }identity 添加了类型变量T, T 捕获用户传入的类型…...
商城类网站价格/百度搜索引擎竞价排名
Azure是微软的云平台,不仅支持Windows服务器,也深爱着开源世界。通过与开源社区之间的合作, Azure支持了大量的开源软件和框架,涵盖了包括Linux 服务器,Docker, chef, MySQL, WordPress, redis等大部分主流互联网开源软…...
wordpress新手/百度竞价推广是什么工作
当下电子阅读逐渐流行,但多限于纯文字类网文小说阅读。市面上主流的电子书阅读器多为8英寸以下的小屏产品,很多都不能很好地解决大版面的PDF文件阅读舒适度的问题,更没法满足读者批注写笔记的需求。一直走大屏路线的BOOX电纸书,在…...
青海网站建设价格低/seo工资水平
背景 一些软件系统需要根据组织做数据查看权限限制,比如可以设置张三能查看或管理1个或多个组织的数据。在对张三进行配置后,张三这个账号查询对应的业务数据表时需要带上数据权限有关的where条件。 一、主要表介绍 组织表的主要字段:ID、CODE、NAME、上级CODE、CODE全路…...
公司网站建设怎么规划比较好/百度搜索网址
目录 0 引言 1 为什么参加? 2 收获了什么? 3 结果怎么样? 0 引言 2020年博客之星2月4日发榜了,这是第一次参加CSDN博客之星大赛,这里做了简要的小回顾吧,现在变得比较怀旧了,多年以后再回首…...
专业网站制作公司名称/百度关键词优化大
<HTML> <HEAD> <TITLE>给数组增加元素</TITLE> </HEAD> <?$Cities[] "<B>北京</B>"; //等同于$Cities[0] "北京"$Cities[] "<B>天津</B>"; //等同于$Cities[1] "天津…...
航空网站建设/google官网下载
从dict开始说起 学python的时候,我们一定会接触到dict(字典)这个数据结构。 dict结构展示了数据间(key与value)一一对应的关系,key作为一个查询索引,是不允许有重复的,而不同key所…...