1. 简介

2. spi_nor_scan

2.1 检查结构体struct spi_nor是否合格,匹配支持的nor flash ID得到info

2.1.1 spi_nor_check

2.1.2 spi_nor_read_id

2.1.3 struct flash_info

2.2 初始化结构体struct spi_nor_flash_parameter变量params

2.3 设置保护bit、mtd相关的结构体

2.4 spi_nor_setup

2.5 设置地址宽度

2.6 s3an_nor_scan


1. 简介

前面已经介绍了spi-nor子系统的由来,现在我们来看看spi-nor子系统的代码。spi-nor的核心结构体是以下代码:

struct spi_nor {struct mtd_info      mtd;struct mutex        lock;struct device      *dev;u32            page_size;u8            addr_width;u8           erase_opcode;u8         read_opcode;u8          read_dummy;u8           program_opcode;enum spi_nor_protocol    read_proto;enum spi_nor_protocol    write_proto;enum spi_nor_protocol   reg_proto;bool          sst_write_second;u32            flags;u8            cmd_buf[SPI_NOR_MAX_CMD_SIZE];int (*prepare)(struct spi_nor *nor, enum spi_nor_ops ops);void (*unprepare)(struct spi_nor *nor, enum spi_nor_ops ops);int (*read_reg)(struct spi_nor *nor, u8 opcode, u8 *buf, int len);int (*write_reg)(struct spi_nor *nor, u8 opcode, u8 *buf, int len);ssize_t (*read)(struct spi_nor *nor, loff_t from,size_t len, u_char *read_buf);ssize_t (*write)(struct spi_nor *nor, loff_t to,size_t len, const u_char *write_buf);int (*erase)(struct spi_nor *nor, loff_t offs);int (*flash_lock)(struct spi_nor *nor, loff_t ofs, uint64_t len);int (*flash_unlock)(struct spi_nor *nor, loff_t ofs, uint64_t len);int (*flash_is_locked)(struct spi_nor *nor, loff_t ofs, uint64_t len);void *priv;
};

mtd:        指向mtd_info结构体,我们知道所有的存储设备,最终都有可以挂载到mtd子系统中。
lock:        读/写/擦除/锁定/解锁操作的锁定
dev:        指向spi设备或spi nor控制器设备。
page_size:        SPI NOR的页面大小
addr_width:        地址字节数
erase_opcode:    用于擦除扇区的操作码
read_opcode:    读操作码
read_dummy:        读取操作所需的dummy数
program_opcode:    program操作码
sst_write_second: used by the SST write operation
flags:              当前SPI-NOR的标志选项(SNOR\u F\ux*)。
read_proto:        用于读取操作的SPI协议
write_proto:    用于写操作的SPI协议
reg_proto        用于读\写\擦除操作的SPI协议
cmd_buf:        used by the write_reg

这里有一个enum spi_nor_protocol说明一下,如下所示。

enum spi_nor_protocol {SNOR_PROTO_1_1_1 = SNOR_PROTO_STR(1, 1, 1),SNOR_PROTO_1_1_2 = SNOR_PROTO_STR(1, 1, 2),SNOR_PROTO_1_1_4 = SNOR_PROTO_STR(1, 1, 4),SNOR_PROTO_1_1_8 = SNOR_PROTO_STR(1, 1, 8),SNOR_PROTO_1_2_2 = SNOR_PROTO_STR(1, 2, 2),SNOR_PROTO_1_4_4 = SNOR_PROTO_STR(1, 4, 4),SNOR_PROTO_1_8_8 = SNOR_PROTO_STR(1, 8, 8),SNOR_PROTO_2_2_2 = SNOR_PROTO_STR(2, 2, 2),SNOR_PROTO_4_4_4 = SNOR_PROTO_STR(4, 4, 4),SNOR_PROTO_8_8_8 = SNOR_PROTO_STR(8, 8, 8),SNOR_PROTO_1_1_1_DTR = SNOR_PROTO_DTR(1, 1, 1),SNOR_PROTO_1_2_2_DTR = SNOR_PROTO_DTR(1, 2, 2),SNOR_PROTO_1_4_4_DTR = SNOR_PROTO_DTR(1, 4, 4),SNOR_PROTO_1_8_8_DTR = SNOR_PROTO_DTR(1, 8, 8),
};

这个协议是该spi-nor所使用的协议,是1线、4线、8线等协议,初始值就是默认值。

查看include\linux\mtd\spi-nor.h文件,只有一个对外开放的函数spi_nor_scan,这个也是我们分析的重点。

/*** spi_nor_scan() - scan the SPI NOR* @nor:   the spi_nor structure* @name:  the chip type name* @hwcaps:   the hardware capabilities supported by the controller driver** The drivers can use this fuction to scan the SPI NOR.* In the scanning, it will try to get all the necessary information to* fill the mtd_info{} and the spi_nor{}.** The chip type name can be provided through the @name parameter.** Return: 0 for success, others for failure.*/
int spi_nor_scan(struct spi_nor *nor, const char *name,const struct spi_nor_hwcaps *hwcaps);

可以看出,对于spi-nor子系统来说,结构体struct spi_nor和struct spi_nor_hwcaps是最主要的设置目标,这个先不管。spi-nor子系统会根据这两个结构体来进行设置一些东西。下面具体分析这个函数。

2. spi_nor_scan

这个函数比较长,我们分几段来看。

2.1 检查结构体struct spi_nor是否合格,匹配支持的nor flash ID得到info

int spi_nor_scan(struct spi_nor *nor, const char *name,const struct spi_nor_hwcaps *hwcaps)
{struct spi_nor_flash_parameter params;const struct flash_info *info = NULL;struct device *dev = nor->dev;struct mtd_info *mtd = &nor->mtd;struct device_node *np = spi_nor_get_flash_node(nor);int ret;int i;ret = spi_nor_check(nor);if (ret)return ret;/* Reset SPI protocol for all commands. */nor->reg_proto = SNOR_PROTO_1_1_1;nor->read_proto = SNOR_PROTO_1_1_1;nor->write_proto = SNOR_PROTO_1_1_1;if (name)info = spi_nor_match_id(name);/* Try to auto-detect if chip name wasn't specified or not found */if (!info)info = spi_nor_read_id(nor);if (IS_ERR_OR_NULL(info))return -ENOENT;........
}

检查结构体struct spi_nor是否合格,设置读写的协议为SNOR_PROTO_1_1_1,匹配支持的nor flash ID得到info。

2.1.1 spi_nor_check

static int spi_nor_check(struct spi_nor *nor)
{if (!nor->dev || !nor->read || !nor->write ||!nor->read_reg || !nor->write_reg) {pr_err("spi-nor: please fill all the necessary fields!\n");return -EINVAL;}return 0;
}

spi_nor_check函数主要检查上层函数传递下来的变量是否设置了必要的变量,这些是编写驱动必须要实现的部分。

2.1.2 spi_nor_read_id

static const struct flash_info *spi_nor_read_id(struct spi_nor *nor)
{int            tmp;u8          id[SPI_NOR_MAX_ID_LEN];const struct flash_info  *info;tmp = nor->read_reg(nor, SPINOR_OP_RDID, id, SPI_NOR_MAX_ID_LEN);if (tmp < 0) {dev_dbg(nor->dev, "error %d reading JEDEC ID\n", tmp);return ERR_PTR(tmp);}for (tmp = 0; tmp < ARRAY_SIZE(spi_nor_ids) - 1; tmp++) {info = &spi_nor_ids[tmp];if (info->id_len) {if (!memcmp(info->id, id, info->id_len))return &spi_nor_ids[tmp];}}dev_err(nor->dev, "unrecognized JEDEC id bytes: %02x, %02x, %02x\n",id[0], id[1], id[2]);return ERR_PTR(-ENODEV);
}

通过调用控制器提供的read_reg函数,读取flash的JEDEC ID,并且从spi_nor_ids匹配是否支持该flash。我们简单看看spi_nor_ids这个全局变量。

static const struct flash_info spi_nor_ids[] = {.........{"gd25q128", INFO(0xc84018, 0, 64 * 1024, 256,SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB)},......
};

宏INFO定义如下:

宏INFO定义如下。
#define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags)  \.id = {                           \((_jedec_id) >> 16) & 0xff,          \((_jedec_id) >> 8) & 0xff,           \(_jedec_id) & 0xff,                \((_ext_id) >> 8) & 0xff,         \(_ext_id) & 0xff,              \},                     \.id_len = (!(_jedec_id) ? 0 : (3 + ((_ext_id) ? 2 : 0))),    \.sector_size = (_sector_size),                \.n_sectors = (_n_sectors),                \.page_size = 256,                 \.flags = (_flags),

我们以gd25q128这个flash为例,最终的展开是:

static const struct flash_info spi_nor_ids[] = {.........{"gd25q128", .id = {c8,40,18,0,0},.id_len = 3,.sector_size = 64 * 1024,.n_sectors = 256,.page_size = 256,.flag = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB},......
};

2.1.3 struct flash_info

从2.1.2小节我们可以看出,如果我们要写一个nor flash的驱动,我们必须把这个nor flash的基本信息填充到spi_nor_ids这个数组中。下面我们看一下这个结构体,具体的分析我们下面在做。

struct flash_info {char      *name;/** This array stores the ID bytes.* The first three bytes are the JEDIC ID.* JEDEC ID zero means "no ID" (mostly older chips).*/u8     id[SPI_NOR_MAX_ID_LEN];u8       id_len;/* The size listed here is what works with SPINOR_OP_SE, which isn't* necessarily called a "sector" by the vendor.*/unsigned  sector_size;u16     n_sectors;u16       page_size;u16       addr_width;u16      flags;
#define SECT_4K         BIT(0)  /* SPINOR_OP_BE_4K works uniformly */
#define SPI_NOR_NO_ERASE    BIT(1)  /* No erase command needed */
#define SST_WRITE       BIT(2)  /* use SST byte programming */
#define SPI_NOR_NO_FR       BIT(3)  /* Can't do fastread */
#define SECT_4K_PMC     BIT(4)  /* SPINOR_OP_BE_4K_PMC works uniformly */
#define SPI_NOR_DUAL_READ   BIT(5)  /* Flash supports Dual Read */
#define SPI_NOR_QUAD_READ   BIT(6)  /* Flash supports Quad Read */
#define USE_FSR         BIT(7)  /* use flag status register */
#define SPI_NOR_HAS_LOCK    BIT(8)  /* Flash supports lock/unlock via SR */
#define SPI_NOR_HAS_TB      BIT(9)  /** Flash SR has Top/Bottom (TB) protect* bit. Must be used with* SPI_NOR_HAS_LOCK.*/
#define SPI_S3AN        BIT(10) /** Xilinx Spartan 3AN In-System Flash* (MFR cannot be used for probing* because it has the same value as* ATMEL flashes)*/
#define SPI_NOR_4B_OPCODES  BIT(11) /** Use dedicated 4byte address op codes* to support memory size above 128Mib.*/
#define NO_CHIP_ERASE       BIT(12) /* Chip does not support chip erase */
#define SPI_NOR_SKIP_SFDP   BIT(13) /* Skip parsing of SFDP tables */
#define USE_CLSR        BIT(14) /* use CLSR command */
#define SPI_NOR_OCTAL_READ  BIT(15) /* Flash supports Octal Read */
};

2.2 初始化结构体struct spi_nor_flash_parameter变量params

int spi_nor_scan(struct spi_nor *nor, const char *name,const struct spi_nor_hwcaps *hwcaps)
{struct spi_nor_flash_parameter params;......../** Make sure the XSR_RDY flag is set before calling* spi_nor_wait_till_ready(). Xilinx S3AN share MFR* with Atmel spi-nor*/if (info->flags & SPI_S3AN)nor->flags |=  SNOR_F_READY_XSR_RDY;/* Parse the Serial Flash Discoverable Parameters table. */ret = spi_nor_init_params(nor, info, &params);if (ret)return ret;.......ret = spi_nor_setup(nor, info, &params, hwcaps);.......
}

根据2.1节得到的flash info信息,设置初始化params。

struct spi_nor_flash_parameter {u64              size;u32                page_size;struct spi_nor_hwcaps     hwcaps;struct spi_nor_read_command  reads[SNOR_CMD_READ_MAX];struct spi_nor_pp_command  page_programs[SNOR_CMD_PP_MAX];int (*quad_enable)(struct spi_nor *nor);
};static int spi_nor_init_params(struct spi_nor *nor,const struct flash_info *info,struct spi_nor_flash_parameter *params)
{/* Set legacy flash parameters as default. */memset(params, 0, sizeof(*params));/* Set SPI NOR sizes. */params->size = (u64)info->sector_size * info->n_sectors;params->page_size = info->page_size;/* (Fast) Read settings. */params->hwcaps.mask |= SNOR_HWCAPS_READ;spi_nor_set_read_settings(&params->reads[SNOR_CMD_READ],0, 0, SPINOR_OP_READ,SNOR_PROTO_1_1_1);if (!(info->flags & SPI_NOR_NO_FR)) {params->hwcaps.mask |= SNOR_HWCAPS_READ_FAST;spi_nor_set_read_settings(&params->reads[SNOR_CMD_READ_FAST],0, 8, SPINOR_OP_READ_FAST,SNOR_PROTO_1_1_1);}if (info->flags & SPI_NOR_DUAL_READ) {params->hwcaps.mask |= SNOR_HWCAPS_READ_1_1_2;spi_nor_set_read_settings(&params->reads[SNOR_CMD_READ_1_1_2],0, 8, SPINOR_OP_READ_1_1_2,SNOR_PROTO_1_1_2);}if (info->flags & SPI_NOR_QUAD_READ) {params->hwcaps.mask |= SNOR_HWCAPS_READ_1_1_4;spi_nor_set_read_settings(&params->reads[SNOR_CMD_READ_1_1_4],0, 8, SPINOR_OP_READ_1_1_4,SNOR_PROTO_1_1_4);}if (info->flags & SPI_NOR_OCTAL_READ) {params->hwcaps.mask |= SNOR_HWCAPS_READ_1_1_8;spi_nor_set_read_settings(&params->reads[SNOR_CMD_READ_1_1_8],0, 8, SPINOR_OP_READ_1_1_8,SNOR_PROTO_1_1_8);}/* Page Program settings. */params->hwcaps.mask |= SNOR_HWCAPS_PP;spi_nor_set_pp_settings(&params->page_programs[SNOR_CMD_PP],SPINOR_OP_PP, SNOR_PROTO_1_1_1);/* Select the procedure to set the Quad Enable bit. */if (params->hwcaps.mask & (SNOR_HWCAPS_READ_QUAD |SNOR_HWCAPS_PP_QUAD)) {switch (JEDEC_MFR(info)) {case SNOR_MFR_MACRONIX:params->quad_enable = macronix_quad_enable;break;case SNOR_MFR_MICRON:break;case SNOR_MFR_GIGADEVICE:params->quad_enable = spansion_read_cr_quad_enable;break;default:/* Kept only for backward compatibility purpose. */params->quad_enable = spansion_quad_enable;break;}}/* Override the parameters with data read from SFDP tables. */nor->addr_width = 0;nor->mtd.erasesize = 0;if ((info->flags & (SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_OCTAL_READ)) &&!(info->flags & SPI_NOR_SKIP_SFDP)) {struct spi_nor_flash_parameter sfdp_params;memcpy(&sfdp_params, params, sizeof(sfdp_params));if (spi_nor_parse_sfdp(nor, &sfdp_params)) {nor->addr_width = 0;nor->mtd.erasesize = 0;} else {memcpy(params, &sfdp_params, sizeof(*params));}}return 0;
}

这个比较简单,根据flag的标志,设置params中的变量,主要设置的是该nor flash的硬件能力集。例如,上面的例子中我们的flash info的flag为

.flag = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ |SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB

有一个地方需要注意的是,使能Quad Enable bit位。

 /* Select the procedure to set the Quad Enable bit. */if (params->hwcaps.mask & (SNOR_HWCAPS_READ_QUAD |SNOR_HWCAPS_PP_QUAD)) {switch (JEDEC_MFR(info)) {case SNOR_MFR_MACRONIX:params->quad_enable = macronix_quad_enable;break;case SNOR_MFR_MICRON:break;case SNOR_MFR_GIGADEVICE:params->quad_enable = spansion_read_cr_quad_enable;break;default:/* Kept only for backward compatibility purpose. */params->quad_enable = spansion_quad_enable;break;}}

read sfdp相关信息。

 /* Override the parameters with data read from SFDP tables. */nor->addr_width = 0;nor->mtd.erasesize = 0;if ((info->flags & (SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ | SPI_NOR_OCTAL_READ)) &&!(info->flags & SPI_NOR_SKIP_SFDP)) {struct spi_nor_flash_parameter sfdp_params;memcpy(&sfdp_params, params, sizeof(sfdp_params));if (spi_nor_parse_sfdp(nor, &sfdp_params)) {nor->addr_width = 0;nor->mtd.erasesize = 0;} else {memcpy(params, &sfdp_params, sizeof(*params));}}

2.3 设置保护bit、mtd相关的结构体

int spi_nor_scan(struct spi_nor *nor, const char *name,const struct spi_nor_hwcaps *hwcaps)
{...../** Atmel, SST, Intel/Numonyx, and others serial NOR tend to power up* with the software protection bits set*/if (JEDEC_MFR(info) == SNOR_MFR_ATMEL ||JEDEC_MFR(info) == SNOR_MFR_INTEL ||JEDEC_MFR(info) == SNOR_MFR_SST ||info->flags & SPI_NOR_HAS_LOCK) {write_enable(nor);write_sr(nor, 0);spi_nor_wait_till_ready(nor);}if (!mtd->name)mtd->name = dev_name(dev);mtd->priv = nor;mtd->type = MTD_NORFLASH;mtd->writesize = 1;mtd->flags = MTD_CAP_NORFLASH;mtd->size = params.size;mtd->_erase = spi_nor_erase;mtd->_read = spi_nor_read;/* NOR protection support for STmicro/Micron chips and similar */if (JEDEC_MFR(info) == SNOR_MFR_MICRON ||info->flags & SPI_NOR_HAS_LOCK) {nor->flash_lock = stm_lock;nor->flash_unlock = stm_unlock;nor->flash_is_locked = stm_is_locked;}if (nor->flash_lock && nor->flash_unlock && nor->flash_is_locked) {mtd->_lock = spi_nor_lock;mtd->_unlock = spi_nor_unlock;mtd->_is_locked = spi_nor_is_locked;}/* sst nor chips use AAI word program */if (info->flags & SST_WRITE)mtd->_write = sst_write;elsemtd->_write = spi_nor_write;if (info->flags & USE_FSR)nor->flags |= SNOR_F_USE_FSR;if (info->flags & SPI_NOR_HAS_TB)nor->flags |= SNOR_F_HAS_SR_TB;if (info->flags & NO_CHIP_ERASE)nor->flags |= SNOR_F_NO_OP_CHIP_ERASE;if (info->flags & USE_CLSR)nor->flags |= SNOR_F_USE_CLSR;if (info->flags & SPI_NOR_NO_ERASE)mtd->flags |= MTD_NO_ERASE;mtd->dev.parent = dev;nor->page_size = params.page_size;mtd->writebufsize = nor->page_size;if (np) {/* If we were instantiated by DT, use it */if (of_property_read_bool(np, "m25p,fast-read"))params.hwcaps.mask |= SNOR_HWCAPS_READ_FAST;elseparams.hwcaps.mask &= ~SNOR_HWCAPS_READ_FAST;} else {/* If we weren't instantiated by DT, default to fast-read */params.hwcaps.mask |= SNOR_HWCAPS_READ_FAST;}/* Some devices cannot do fast-read, no matter what DT tells us */if (info->flags & SPI_NOR_NO_FR)params.hwcaps.mask &= ~SNOR_HWCAPS_READ_FAST;....
}

2.4 spi_nor_setup

int spi_nor_scan(struct spi_nor *nor, const char *name,const struct spi_nor_hwcaps *hwcaps)
{...../** Configure the SPI memory:* - select op codes for (Fast) Read, Page Program and Sector Erase.* - set the number of dummy cycles (mode cycles + wait states).* - set the SPI protocols for register and memory accesses.* - set the Quad Enable bit if needed (required by SPI x-y-4 protos).*/ret = spi_nor_setup(nor, info, &params, hwcaps);.......
}

2.5 设置地址宽度

int spi_nor_scan(struct spi_nor *nor, const char *name,const struct spi_nor_hwcaps *hwcaps)
{.....if (nor->addr_width) {/* already configured from SFDP */} else if (info->addr_width) {nor->addr_width = info->addr_width;} else if (mtd->size > 0x1000000) {/* enable 4-byte addressing if the device exceeds 16MiB */nor->addr_width = 4;if (JEDEC_MFR(info) == SNOR_MFR_SPANSION ||info->flags & SPI_NOR_4B_OPCODES)spi_nor_set_4byte_opcodes(nor, info);elseset_4byte(nor, info, 1);} else {nor->addr_width = 3;}.......
}

如果nor flash的大小超过16M,那么必须使用4根地址线才能访问全部的flash空间。

2.6 s3an_nor_scan

int spi_nor_scan(struct spi_nor *nor, const char *name,const struct spi_nor_hwcaps *hwcaps)
{.....if (info->flags & SPI_S3AN) {ret = s3an_nor_scan(info, nor);if (ret)return ret;}.......
}

s3an_nor_scan后面再说。

Linux内核4.14版本——SPI NOR子系统(2)——spi-nor.c分析相关推荐

  1. Linux内核4.14版本:ARM64的内核启动过程(二)——start_kernel

    目录 1. rest_init 2. init 进程(kernel_init) 2.1 kernel_init_freeable 2.1.1 do_basic_setup 2.1.2 prepare_ ...

  2. Linux内核4.14版本——watchdog看门狗框架分析

    目录 0 简介 1. 设备的注册 1.1 dw_wdt_drv_probe 1.2 watchdog_register_device 1.3 __watchdog_register_device 1. ...

  3. Linux内核4.14版本——DMA Engine框架分析(6)-实战(测试dma驱动)

    1. dw-axi-dmac驱动 2. dma的测试程序 2.1 内核程序 2.2 用户测试程序 1. dw-axi-dmac驱动 dw-axi-dmac驱动4.14版本没有,是从5.4版本移植的,基 ...

  4. Linux内核4.14版本——alsa框架分析(1)—alsa简介

    目录 一,ALSA声音编程介绍 二,ALSA历史 三,数字音频基础 四,ALSA基础 五,ALSA体系结构 六,设备命名 七,声音缓存和数据传输 八,Over and Under Run 九,一个典型 ...

  5. Linux内核4.14版本——drm框架分析(1)——drm简介

    目录 1. DRM简介(Direct Rendering Manager) 1.1 DRM发展历史 1.2 DRM架构对比FB架构优势 1.3 DRM图形显示框架 1.4 DRM图形显示框架涉及元素 ...

  6. Linux内核4.14版本——SPI NOR子系统(3)——cadence-quadspi.c分析

    目录 1. 芯片简介 1.1 模块与接口 1.2 访问模式 2. DTS 2.1 reg 2.2 cdns,trigger-address 2.3 匹配DTS的驱动程序入口 3. cqspi_prob ...

  7. Linux内核4.14版本——GPIO子系统(1)——gpiolib分析

    目录 1.简述 2.Gpiolib 相关数据结构分析 2.1 gpio_chip 结构 2.2 gpio_desc 结构 2.3 gpio_device 结构 3 Gpiolib 对接芯片底层 3.1 ...

  8. Linux内核4.14版本——Nand子系统(1)——hisi504_nand.c分析

    1. 简介 2. DTS 3. hisi_nfc_probe函数 3.1 获取dts中的资源 3.2 设置nand-chip结构体中必要的字段 3.3 nand_scan_ident扫描识别nand控 ...

  9. Linux内核4.14版本——mmc框架_软件总体架构

    目录 1. 前言 2. 软件架构 3. 工作流程 4. mmc设备 4.1 mmc type card 4.2 sd type card 4.3 sdio type card 5. mmc协议 5.1 ...

最新文章

  1. 第一次用写一个3d轮播
  2. Oracle AWR 报告中 No data exists for this section of the report 说明
  3. 罗斯霍曼理工学院计算机毕业生,全美最强STEM大学,了解一下?
  4. 恒驰机器人_恒大汽车基地:2545台机器人为恒驰“效力”
  5. 【Object类、日期、StringBuilder】
  6. Spring Boot 单元测试详解+实战教程
  7. 【PAT甲级最新题解】PAT甲级2020.7月春季考试满分题解(附代码)
  8. Redis3.2.5部署(单节点)
  9. LeetCode 1992. 找到所有的农场组(BFS)
  10. MATLAB 【学习视频推荐】——新手必备
  11. Java排序算法-桶排序
  12. python3x菜鸟教程_菜鸟教程python3
  13. 实战 用Python放一场浪漫的烟花秀
  14. SQL 触发器 简记
  15. mount挂载不上,不提示任何信息
  16. TMS320C5509A 控制DDS AD9854芯片进行AM幅度调制时的FIR滤波处理
  17. 奈奎斯特定理和香农定理解释
  18. 10天精读掌握:计算机组成与设计COAD:Patterson and Hennessy 第7天 2018/11.1
  19. Xilinx SDK编译Microblaze时出错
  20. 配置了Maven环境变量后,cmd中mvn -v一直报“mvn不是内部命令”

热门文章

  1. MATLAB与DSP(C6657)的TCP/IP通信实现
  2. 【TIC6657 DSP学习笔记】01 工程创建与代码编写——以点亮LED为例
  3. TensorFlow深度学习:3.API示范
  4. html5不断切换的场景,HTML5场景: 沉舟侧畔千帆过(漂浮和沉没的帆船)
  5. 轻松解决夜神逍遥模拟器模拟器等模拟器无法连接问题
  6. div做表格 html5,div+css制作表格
  7. bcb6 连接mysql_BCB6常见问题
  8. ENGLISH资料收集(3)-英语日期的正确表达
  9. 卡方分布(Chi-Squared Distribution)
  10. android应用市场汇总