AI嵌入式K210项目(11)-SPI Flash读写

文章目录

  • 前言
  • 一、K210的SPI
  • 二、Flash介绍
  • 三、实验过程
  • 总结


前言

这一章我们来学习下SPI及其应用,SPI 是一种高速的,全双工,同步的通信总线,由于其高速、同步和简单的特性,被广泛应用于各种微控制器和外围设备之间的通信场景,如:EEPROM和Flash存储器、实时时钟(RTC)、数模转换器(ADC)、网络控制器、数字信号处理(DSP)、数字信号解码器;

一、K210的SPI

串行外设接口有 4 组 SPI 接口,其中 SPI0、SPI1、SPI3 只能工作在 MASTER 模式,SPI2 只能工作在SLAVE 模式,他们有如下特性:
• 支持 1/2/4/8 线全双工模式
• SPI0、SPI1、SPI2 可支持 25MHz 时钟(待测更新)
• SPI3 最高可支持 100MHz 时钟(待测更新)
• 支持 32 位宽、32BYTE 深的 FIFO
• 独立屏蔽中断 - 主机冲突,发送 FIFO 溢出,发送 FIFO 空,接收 FIFO 满,接收 FIFO 下溢,接收 FIFO 溢出中断都可以被屏蔽独立
• 支持 DMA 功能
• 支持双沿的 DDR 传输模式
• SPI3 支持 XIP

对应的头文件 spi.h
为用户提供以下接口
• spi_init
• spi_init_non_standard
• spi_send_data_standard
• spi_send_data_standard_dma
• spi_receive_data_standard
• spi_receive_data_standard_dma
• spi_send_data_multiple
• spi_send_data_multiple_dma
• spi_receive_data_multiple
• spi_receive_data_multiple_dma
• spi_fill_data_dma
• spi_send_data_normal_dma
• spi_set_clk_rate
• spi_handle_data_dma

二、Flash介绍

FLASH 芯片是应用非常广泛的存储材料,与之对应的是RAM芯片,区别在于FLASH芯片断电后数据可以保存,而RAM芯片断电后数据不会保存。那么FLASH是如何工作的呢?计算机的储存方式是二进制,也就是0和1,在二进制中,0和1可以组成任何数。FLASH芯片对0和1的处理方式是用物质填充,1则填充,0则不填充,如下图所示,这样就算断电之后,物质的性质也不会因为没有电而改变,所以再次读取数据的时候数据依然不变,这样就可以做到断电保存。
在这里插入图片描述
开发板使用的flash芯片GD25LQ128C是通过SPI串行闪存的芯片,具有128M-bit(16兆字节MByte)空间,能够储存声音、文本和数据等,设备运行电源为2.7V~3.6V,低功耗模式电流低至1uA。

写数据,每次向GD25LQ128C写入数据都需要按照页或者扇区或者簇为单位进行,一页为256个字节,一个扇区为4K个字节(16页),一次最多写一页,也就是一次最多写256个字节,如果超过一页数据长度,则分多次完成。

读数据,可以从任何地址读出。

擦除数据,最小单位为一个扇区,也可以直接擦除整个flash芯片。

flash使用的是SPI的通讯方式,所以对应的头文件是spi.h,而由于各家flash芯片存在差异,往往导致适配起来会存在一定问题,所以kendryte官方对市面上常用的flash做了一些库,对应的头文件是w25qxx.h。

为用户提供以下接口:

• w25qxx_init:初始化flash芯片,主要是设置SPI的设备、通道和速率等。

• w25qxx_read_id:读取flash的ID。

• w25qxx_write_data:向flash写入数据。

• w25qxx_read_data:从flash读取数据。
这里可能部分同学会感觉很疑惑,为什么前面提供了SPI的接口,这里又提供了一些那?可以这样理解,这些接口是对上面那么多接口的封装,简化;这些接口最终还是会调用SPI的标准接口,这样做主要目的还是简化开发者的工作量;

硬件连接:
在这里插入图片描述
在这里插入图片描述

三、实验过程

这个实验我们实现对通过SPI接口对flash芯片进行读写操作,新建flash文件夹,新建main.c文件,然后将w25qxx.h和w25qxx.c放进去
w25qxx.c

/* Copyright 2018 Canaan Inc.** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at**     http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/
#include "w25qxx.h"
#include "fpioa.h"
#include "spi.h"
#include "sysctl.h"
#include "dmac.h"
#include <string.h>
#include <stdio.h>uint32_t spi_bus_no = 0;
uint32_t spi_chip_select = 0;static w25qxx_status_t w25qxx_receive_data(uint8_t *cmd_buff, uint8_t cmd_len, uint8_t *rx_buff, uint32_t rx_len)
{spi_init(spi_bus_no, SPI_WORK_MODE_0, SPI_FF_STANDARD, DATALENGTH, 0);spi_receive_data_standard(spi_bus_no, spi_chip_select, cmd_buff, cmd_len, rx_buff, rx_len);return W25QXX_OK;
}static w25qxx_status_t w25qxx_send_data(uint8_t *cmd_buff, uint8_t cmd_len, uint8_t *tx_buff, uint32_t tx_len)
{spi_init(spi_bus_no, SPI_WORK_MODE_0, SPI_FF_STANDARD, DATALENGTH, 0);spi_send_data_standard(spi_bus_no, spi_chip_select, cmd_buff, cmd_len, tx_buff, tx_len);return W25QXX_OK;
}static w25qxx_status_t w25qxx_receive_data_enhanced_dma(uint32_t *cmd_buff, uint8_t cmd_len, uint8_t *rx_buff, uint32_t rx_len)
{spi_receive_data_multiple_dma(DMAC_CHANNEL0, DMAC_CHANNEL1, spi_bus_no, spi_chip_select, cmd_buff, cmd_len, rx_buff, rx_len);return W25QXX_OK;
}static w25qxx_status_t w25qxx_send_data_enhanced_dma(uint32_t *cmd_buff, uint8_t cmd_len, uint8_t *tx_buff, uint32_t tx_len)
{spi_send_data_multiple_dma(DMAC_CHANNEL0, spi_bus_no, spi_chip_select, cmd_buff, cmd_len, tx_buff, tx_len);return W25QXX_OK;
}w25qxx_status_t w25qxx_read_id(uint8_t *manuf_id, uint8_t *device_id)
{uint8_t cmd[4] = {READ_ID, 0x00, 0x00, 0x00};uint8_t data[2] = {0};w25qxx_receive_data(cmd, 4, data, 2);*manuf_id = data[0];*device_id = data[1];return W25QXX_OK;
}static w25qxx_status_t w25qxx_write_enable(void)
{uint8_t cmd[1] = {WRITE_ENABLE};w25qxx_send_data(cmd, 1, 0, 0);return W25QXX_OK;
}static w25qxx_status_t w25qxx_write_status_reg(uint8_t reg1_data, uint8_t reg2_data)
{uint8_t cmd[3] = {WRITE_REG1, reg1_data, reg2_data};w25qxx_write_enable();w25qxx_send_data(cmd, 3, 0, 0);return W25QXX_OK;
}static w25qxx_status_t w25qxx_read_status_reg1(uint8_t *reg_data)
{uint8_t cmd[1] = {READ_REG1};uint8_t data[1] = {0};w25qxx_receive_data(cmd, 1, data, 1);*reg_data = data[0];return W25QXX_OK;
}static w25qxx_status_t w25qxx_read_status_reg2(uint8_t *reg_data)
{uint8_t cmd[1] = {READ_REG2};uint8_t data[1] = {0};w25qxx_receive_data(cmd, 1, data, 1);*reg_data = data[0];return W25QXX_OK;
}static w25qxx_status_t w25qxx_enable_quad_mode(void)
{uint8_t reg_data = 0;w25qxx_read_status_reg2(&reg_data);if (!(reg_data & REG2_QUAL_MASK)){reg_data |= REG2_QUAL_MASK;w25qxx_write_status_reg(0x00, reg_data);}return W25QXX_OK;
}static w25qxx_status_t w25qxx_is_busy(void)
{uint8_t status = 0;w25qxx_read_status_reg1(&status);if (status & REG1_BUSY_MASK)return W25QXX_BUSY;return W25QXX_OK;
}w25qxx_status_t w25qxx_sector_erase(uint32_t addr)
{uint8_t cmd[4] = {SECTOR_ERASE};cmd[1] = (uint8_t)(addr >> 16);cmd[2] = (uint8_t)(addr >> 8);cmd[3] = (uint8_t)(addr);w25qxx_write_enable();w25qxx_send_data(cmd, 4, 0, 0);return W25QXX_OK;
}static w25qxx_status_t w25qxx_quad_page_program(uint32_t addr, uint8_t *data_buf, uint32_t length)
{uint32_t cmd[2] = {0};cmd[0] = QUAD_PAGE_PROGRAM;cmd[1] = addr;w25qxx_write_enable();spi_init(spi_bus_no, SPI_WORK_MODE_0, SPI_FF_QUAD, 32/*DATALENGTH*/, 0);spi_init_non_standard(spi_bus_no, 8/*instrction length*/, 24/*address length*/, 0/*wait cycles*/,SPI_AITM_STANDARD/*spi address trans mode*/);w25qxx_send_data_enhanced_dma(cmd, 2, data_buf, length);while (w25qxx_is_busy() == W25QXX_BUSY);return W25QXX_OK;
}static w25qxx_status_t w25qxx_sector_program(uint32_t addr, uint8_t *data_buf)
{uint8_t index = 0;for (index = 0; index < w25qxx_FLASH_PAGE_NUM_PER_SECTOR; index++){w25qxx_quad_page_program(addr, data_buf, w25qxx_FLASH_PAGE_SIZE);addr += w25qxx_FLASH_PAGE_SIZE;data_buf += w25qxx_FLASH_PAGE_SIZE;}return W25QXX_OK;
}w25qxx_status_t w25qxx_write_data(uint32_t addr, uint8_t *data_buf, uint32_t length)
{uint32_t sector_addr = 0;uint32_t sector_offset = 0;uint32_t sector_remain = 0;uint32_t write_len = 0;uint32_t index = 0;uint8_t *pread = NULL;uint8_t *pwrite = NULL;uint8_t swap_buf[w25qxx_FLASH_SECTOR_SIZE] = {0};while (length){sector_addr = addr & (~(w25qxx_FLASH_SECTOR_SIZE - 1));sector_offset = addr & (w25qxx_FLASH_SECTOR_SIZE - 1);sector_remain = w25qxx_FLASH_SECTOR_SIZE - sector_offset;write_len = ((length < sector_remain) ? length : sector_remain);w25qxx_read_data(sector_addr, swap_buf, w25qxx_FLASH_SECTOR_SIZE);pread = swap_buf + sector_offset;pwrite = data_buf;for (index = 0; index < write_len; index++){if ((*pwrite) != ((*pwrite) & (*pread))){w25qxx_sector_erase(sector_addr);while (w25qxx_is_busy() == W25QXX_BUSY);break;}pwrite++;pread++;}if (write_len == w25qxx_FLASH_SECTOR_SIZE){w25qxx_sector_program(sector_addr, data_buf);}else{pread = swap_buf + sector_offset;pwrite = data_buf;for (index = 0; index < write_len; index++)*pread++ = *pwrite++;w25qxx_sector_program(sector_addr, swap_buf);}length -= write_len;addr += write_len;data_buf += write_len;}return W25QXX_OK;
}static w25qxx_status_t _w25qxx_read_data(uint32_t addr, uint8_t *data_buf, uint32_t length)
{uint32_t cmd[2] = {0};cmd[0] = FAST_READ_QUAL_IO;cmd[1] = addr << 8;spi_init(spi_bus_no, SPI_WORK_MODE_0, SPI_FF_QUAD, 32, 0);spi_init_non_standard(spi_bus_no, 8/*instrction length*/, 32/*address length*/, 4/*wait cycles*/,SPI_AITM_ADDR_STANDARD/*spi address trans mode*/);w25qxx_receive_data_enhanced_dma(cmd, 2, data_buf, length);return W25QXX_OK;
}w25qxx_status_t w25qxx_read_data(uint32_t addr, uint8_t *data_buf, uint32_t length)
{uint32_t v_remain = length % 4;if(v_remain != 0){length = length / 4 * 4;}uint32_t len = 0;while (length){len = ((length >= 0x010000) ? 0x010000 : length);_w25qxx_read_data(addr, data_buf, len);addr += len;data_buf += len;length -= len;}if(v_remain){uint8_t v_recv_buf[4];_w25qxx_read_data(addr, v_recv_buf, 4);memcpy(data_buf, v_recv_buf, v_remain);}return W25QXX_OK;
}w25qxx_status_t w25qxx_init(uint8_t spi_index, uint8_t spi_ss, uint32_t rate)
{spi_bus_no = spi_index;spi_chip_select = spi_ss;spi_init(spi_bus_no, SPI_WORK_MODE_0, SPI_FF_STANDARD, DATALENGTH, 0);spi_set_clk_rate(spi_bus_no, rate);w25qxx_enable_quad_mode();return W25QXX_OK;
}

w25qxx.h

/* Copyright 2018 Canaan Inc.** Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at**     http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/
#ifndef _W25QXX_H
#define _W25QXX_H#include <stdint.h>/* clang-format off */
#define DATALENGTH                          8#define SPI_SLAVE_SELECT                    (0x01)#define w25qxx_FLASH_PAGE_SIZE              256
#define w25qxx_FLASH_SECTOR_SIZE            4096
#define w25qxx_FLASH_PAGE_NUM_PER_SECTOR    16
#define w25qxx_FLASH_CHIP_SIZE              (16777216 UL)#define WRITE_ENABLE                        0x06
#define WRITE_DISABLE                       0x04
#define READ_REG1                           0x05
#define READ_REG2                           0x35
#define READ_REG3                           0x15
#define WRITE_REG1                          0x01
#define WRITE_REG2                          0x31
#define WRITE_REG3                          0x11
#define READ_DATA                           0x03
#define FAST_READ                           0x0B
#define FAST_READ_DUAL_OUTPUT               0x3B
#define FAST_READ_QUAL_OUTPUT               0x6B
#define FAST_READ_DUAL_IO                   0xBB
#define FAST_READ_QUAL_IO                   0xEB
#define DUAL_READ_RESET                     0xFFFF
#define QUAL_READ_RESET                     0xFF
#define PAGE_PROGRAM                        0x02
#define QUAD_PAGE_PROGRAM                   0x32
#define SECTOR_ERASE                        0x20
#define BLOCK_32K_ERASE                     0x52
#define BLOCK_64K_ERASE                     0xD8
#define CHIP_ERASE                          0x60
#define READ_ID                             0x90
#define ENABLE_QPI                          0x38
#define EXIT_QPI                            0xFF
#define ENABLE_RESET                        0x66
#define RESET_DEVICE                        0x99#define REG1_BUSY_MASK                      0x01
#define REG2_QUAL_MASK                      0x02#define LETOBE(x)     ((x >> 24) | ((x & 0x00FF0000) >> 8) | ((x & 0x0000FF00) << 8) | (x << 24))
/* clang-format on *//*** @brief      w25qxx operating status enumerate*/
typedef enum _w25qxx_status
{W25QXX_OK = 0,W25QXX_BUSY,W25QXX_ERROR,
} w25qxx_status_t;/*** @brief      w25qxx read operating enumerate*/
typedef enum _w25qxx_read
{W25QXX_STANDARD = 0,W25QXX_STANDARD_FAST,W25QXX_DUAL,W25QXX_DUAL_FAST,W25QXX_QUAD,W25QXX_QUAD_FAST,
} w25qxx_read_t;w25qxx_status_t w25qxx_init(uint8_t spi_index, uint8_t spi_ss, uint32_t rate);
w25qxx_status_t w25qxx_read_id(uint8_t *manuf_id, uint8_t *device_id);
w25qxx_status_t w25qxx_write_data(uint32_t addr, uint8_t *data_buf, uint32_t length);
w25qxx_status_t w25qxx_read_data(uint32_t addr, uint8_t *data_buf, uint32_t length);#endif

main.c

/**
* @file         main.c
* @brief        flash实验
* @details      
* @par History  见如下说明
*                 
* version:	V1.0: 先向flash写入数据,然后读取出来,对比写入和读取的数据是否一致,
*                 如果不一致则打印错误信息。
*/
#include <stdio.h>
#include "fpioa.h"
#include "sysctl.h"
#include "w25qxx.h"
#include "uarths.h"
#include "spi.h"#define BUF_LENGTH (40 * 1024 + 5)
#define DATA_ADDRESS 0xB00000uint8_t write_buf[BUF_LENGTH];
uint8_t read_buf[BUF_LENGTH];/**
* Function       flash_init
* @brief         flash初始化
* @param[in]     void
* @param[out]    void
* @retval        void
* @par History   无
*/
int flash_init(void)
{uint8_t manuf_id, device_id;uint8_t spi_index = 3, spi_ss = 0;printf("flash init \n");w25qxx_init(spi_index, spi_ss, 60000000);/* 读取flash的ID */w25qxx_read_id(&manuf_id, &device_id);printf("manuf_id:0x%02x, device_id:0x%02x\n", manuf_id, device_id);if ((manuf_id != 0xEF && manuf_id != 0xC8) || (device_id != 0x17 && device_id != 0x16)){/* flash初始化失败 */printf("w25qxx_read_id error\n");printf("manuf_id:0x%02x, device_id:0x%02x\n", manuf_id, device_id);return 0;}else{return 1;} 
}/**
* Function       flash_write_data
* @brief         flash写入数据
* @param[in]     data_buf
* @param[in]     length
* @param[out]    void
* @retval        void
* @par History   无
*/
void flash_write_data(uint8_t *data_buf, uint32_t length)
{uint64_t start = sysctl_get_time_us();/* flash写入数据 */w25qxx_write_data(DATA_ADDRESS, data_buf, length);uint64_t stop = sysctl_get_time_us();/* 打印写入数据的时间(us) */printf("write data finish:%ld us\n", (stop - start));
}/**
* Function       flash_read_data
* @brief         flash读取数据
* @param[in]     data_buf
* @param[in]     length
* @param[out]    void
* @retval        void
* @par History   无
*/
void flash_read_data(uint8_t *data_buf, uint32_t length)
{uint64_t start = sysctl_get_time_us();/* flash读取数据 */w25qxx_read_data(DATA_ADDRESS, data_buf, length);uint64_t stop = sysctl_get_time_us();/* 打印读取数据的时间(us) */printf("read data finish:%ld us\n", (stop - start));
}/**
* Function       main
* @brief         主函数,程序的入口
* @param[in]     void
* @param[out]    void
* @retval        0
* @par History   无
*/
int main(void)
{/* 设置新PLL0频率 */sysctl_pll_set_freq(SYSCTL_PLL0, 800000000);uarths_init();/* 初始化flash */uint8_t res = 0;res = flash_init();if (res == 0) return 0;/* 给缓存写入的数据赋值 */for (int i = 0; i < BUF_LENGTH; i++)write_buf[i] = (uint8_t)(i);/* 清空读取的缓存数据 */for(int i = 0; i < BUF_LENGTH; i++)read_buf[i] = 0;printf("flash start write data\n");/* flash写入数据 */flash_write_data(write_buf, BUF_LENGTH);/*flash读取数据*/flash_read_data(read_buf, BUF_LENGTH);/* 比较数据,如果有不同则打印错误信息 */for (int i = 0; i < BUF_LENGTH; i++){if (read_buf[i] != write_buf[i]){printf("flash read error\n");return 0;}      }printf("spi3 flash master test ok\n");while (1);return 0;
}

代码写好后,我们开始编译,注意:如果你编译过程中出现错误,可以先make clean掉之前生成的过程文件,重新生成

cd build
//注意这里的目标文件目录改成flash,和刚才新建的文件夹名称一致
cmake .. -DPROJ=flash  -G "MinGW Makefiles"
make

编译完成后,在build文件夹下会生成flash.bin文件。

使用type-C数据线连接电脑与K210开发板,打开kflash,选择对应的设备,再将程序固件烧录到K210开发板上。
在这里插入图片描述

实验结果如下:
该处使用的url网络请求的数据。


总结

本章介绍了SPI相关内容,开发板使用的Flash芯片GD25LQ128C的一款存储空间为16MB的FLASH芯片,总共有4096个扇区,每个扇区有16页,每页是256字节,FLASH是能够断电保存数据的一种储存方式。

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

统计学R语言实验7 方差分析

统计学R语言实验7 方差分析 一、实验目的 1. 掌握理解方差分析的相关概念。 2. 掌握理解方差分析的相关方法。 3. 熟悉R语言等语言的集成开发环境。 二、实验分析与内容 完成教材P117的第4题 本题采用单因素方差分析来解题&#xff1a; &#xff08;1&#xff09;分析三…

2023年全球软件架构师峰会(ArchSummit深圳站):核心内容与学习收获(附大会核心PPT下载)

本次峰会是一次重要的技术盛会&#xff0c;旨在为全球软件架构师提供一个交流和学习的平台。本次峰会聚焦于软件架构的最新趋势、最佳实践和技术创新&#xff0c;吸引了来自世界各地的软件架构师、技术专家和企业领袖。 在峰会中&#xff0c;与会者可以了解到数字化、AIGC、To…

电梯节能落座-智慧停车场️,电梯不仅可载人也可以载汽车!

电梯不仅可载人也可以载汽车哦&#xff01; 在北京市丰台区&#xff0c;有这么一个智慧停车场&#x1f17f;️ &#xff0c;共298个停车位&#xff0c;全部智能一体化&#xff0c;简直是“豪华” “智能” 的象征。 523能源&#xff1a;小伍&#xff0c;你跑题了... 小伍&am…

【牛客周赛Round 27】题目讲解

题目一 小红的二进制删数字&#xff1a; 小红拿到了一个二进制字符串 s&#xff0c;她可以删掉其中的一些字符&#xff0c;使得最终该字符串为一个2的幂&#xff08;即可以表示为 2^k 形式的数&#xff09;。小红想知道&#xff0c;自己最少删几个字符可以达成&#xff1f;请你…

【GAMES101】Lecture 07 着色(shading)

目录 着色 Blinn-Phong反射模型 漫反射 光衰减 着色 这个着色&#xff08;shading&#xff09;就是将不同的材质应用到不同的物体上&#xff0c;像一个物体&#xff0c;它可以是木头的、金属的、塑料的…… Blinn-Phong反射模型 我们来看一个简单的着色模型&#xff0c;…

大文件的断点续传如何实现

断点续传 断点续传是一种数据恢复技术&#xff0c;主要用于在读取或发送数据时&#xff0c;因为网络问题、磁盘问题等原因导致数据传输中断。断点续传技术允许你在已经传输的数据基础上继续传输&#xff0c;从而节省数据传输时间。 断点续传通常用于文件传输过程中&#xff0c;…

C语言基本概念——正确理解C,不要被错误的题目误导

在进行C语言训练或做题时&#xff0c;我们可能会遇到一些看似简单但实则错误的题目。这些题目可能会误导我们对C语言基本概念的认识。因此&#xff0c;正确理解C语言并辨别题目中的错误至关重要。下面&#xff0c;举例说明题目错在哪。 1. 写出下列程序的运行结果。 #include…

vue3自定义按钮点击变颜色(切换)

实现效果图&#xff1a; 默认选中第一个按钮&#xff0c;未选中按钮为粉色&#xff0c;点击时颜色变为红色 利用动态类名&#xff0c;当定义isChange数值和下标index相同时&#xff0c;赋予act类名&#xff0c;实现变色效果 <template><view class"page"&g…

Find -name详解

Linux find命令的基本语法如下&#xff1a; find [path] [expression] path&#xff1a;要查找的目录路径。 expression&#xff1a;查找表达式&#xff0c;指定要查找的文件类型、名称、大小等条件 例子&#xff1a;find /etc -name passwd 这个表达式&#xff0c;指定条件为…

进阶Docker4:网桥模式、主机模式与自定义网络

目录 网络相关 子网掩码 网关 规则 docke网络配置 bridge模式 host模式 创建自定义网络(自定义IP) 网络相关 IP 子网掩码 网关 DNS 端口号 子网掩码 互联网是由许多小型网络构成的&#xff0c;每个网络上都有许多主机&#xff0c;这样便构成了一个有层次的结构。 IP 地…

【踩坑日志】SpringBoot读取nacos配置信息并提取信息中的IP地址(配置属性解析异常+排错记录)

缘起 &#xff1a;项目需读取nacos中动态的TDengine数据库连接信息并提取IP&#xff0c;一个并不复杂的操作&#xff0c;但作为一个nacos知识浅薄的菜鸡&#xff0c;我愣是捯饬了几个小时……惭愧惭愧…… 异常代码 Data Component public class TaosLink { // Value("…

ICC2:channel power plan/power switch的添加方法

更多学习内容请关注「拾陆楼」知识星球 拾陆楼知识星球入口 往期文章链接: low power与pg strategy (lib cell pin connect) low power与pg strategy(pg mesh) low power与pg