cpu设计和实现(总结篇)

news2024/9/21 18:33:42

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】

        学习cpu,主要还是因为自己对它的原理和实现还有很多不明白、不清楚的地方,本着追根溯源的精神,正好借助于verilog开源代码一窥究竟。和十年、二十年前相比较,现在数字电路学习、verilog学习、ip学习、开发板的购买方面要便捷很多。记得,最早的时候,市面上只有一本关于cpu设计的书,那就是《CPU源代码分析与芯片设计及Linux移植》。这本书上面不光谈了cpu设计,还谈到了怎么让gcc适配新的cpu、怎么把linux移植到新的cpu上面。坦白说,这些内容对于刚入门的新手来说,其实是非常艰困的,学习的曲线未免太陡峭了。

        后面随着网络的普及,特别是github这样的网站出现,大家已经可以接触到很多的开源cpu代码了。你可以说,这些代码良莠不齐,但是至少说大家发现,原来一个人也是可以做cpu、写os、完成一个小编译器的。曾经很高大上的东西,自己也是可以掌握的,而不再是纸上谈兵的内容。

        最近这一段时间,在网上忽然看到一个tinyriscv的代码,是一位cpu爱好者写的一个完整的mcu。整个代码非常简洁,还移植了freertos,支持jtag烧入,个人觉得非常建议拿来学习。

1、开源代码的地址

https://gitee.com/liangkangnan/tinyriscv

2、开源代码的架构

  

        整个mcu是有四个master,六个slave组成的。图中,master的部分都是蓝色。slave的部分都是绿色。其中riscv作为cpu,有两个master口,一个是指令,一个是数据。download是带有下载功能的uart口。jtag是调试口。slave的部分,这个比较正常,就是一般的rom、ram、gpio、uart、timer和spi,都是常用的一些外设。

3、mcu的接口

// tinyriscv soc顶层模块
module tinyriscv_soc_top(

    input wire clk,
    input wire rst,

    output reg over,         // 测试是否完成信号
    output reg succ,         // 测试是否成功信号

    output wire halted_ind,  // jtag是否已经halt住CPU信号

    input wire uart_debug_pin, // 串口下载使能引脚

    output wire uart_tx_pin, // UART发送引脚
    input wire uart_rx_pin,  // UART接收引脚
    inout wire[1:0] gpio,    // GPIO引脚

    input wire jtag_TCK,     // JTAG TCK引脚
    input wire jtag_TMS,     // JTAG TMS引脚
    input wire jtag_TDI,     // JTAG TDI引脚
    output wire jtag_TDO,    // JTAG TDO引脚

    input wire spi_miso,     // SPI MISO引脚
    output wire spi_mosi,    // SPI MOSI引脚
    output wire spi_ss,      // SPI SS引脚
    output wire spi_clk      // SPI CLK引脚

    );

        mcu的接口就类似于大家正常看到的那些chip的接口一样。其中over、succ、halted_ind很明显是为了调试用的。clk是时钟,rst是复位,uart_debug_pin是下载,uart_tx_pin&uart_rx_pin是串口,gpio是通用口,jtag是调试口,spi是协议口。之前谈到的rom、ram很明显用片上资源实现了。timer也是内部资源实现,对外扇出的就是以上这些端口。

4、总线

 /*                                                                      
 Copyright 2020 Blue Liang, liangkangnan@163.com
                                                                         
 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 "defines.v"


// RIB总线模块
module rib(

    input wire clk,
    input wire rst,

    // master 0 interface
    input wire[`MemAddrBus] m0_addr_i,     // 主设备0读、写地址
    input wire[`MemBus] m0_data_i,         // 主设备0写数据
    output reg[`MemBus] m0_data_o,         // 主设备0读取到的数据
    input wire m0_req_i,                   // 主设备0访问请求标志
    input wire m0_we_i,                    // 主设备0写标志

    // master 1 interface
    input wire[`MemAddrBus] m1_addr_i,     // 主设备1读、写地址
    input wire[`MemBus] m1_data_i,         // 主设备1写数据
    output reg[`MemBus] m1_data_o,         // 主设备1读取到的数据
    input wire m1_req_i,                   // 主设备1访问请求标志
    input wire m1_we_i,                    // 主设备1写标志

    // master 2 interface
    input wire[`MemAddrBus] m2_addr_i,     // 主设备2读、写地址
    input wire[`MemBus] m2_data_i,         // 主设备2写数据
    output reg[`MemBus] m2_data_o,         // 主设备2读取到的数据
    input wire m2_req_i,                   // 主设备2访问请求标志
    input wire m2_we_i,                    // 主设备2写标志

    // master 3 interface
    input wire[`MemAddrBus] m3_addr_i,     // 主设备3读、写地址
    input wire[`MemBus] m3_data_i,         // 主设备3写数据
    output reg[`MemBus] m3_data_o,         // 主设备3读取到的数据
    input wire m3_req_i,                   // 主设备3访问请求标志
    input wire m3_we_i,                    // 主设备3写标志

    // slave 0 interface
    output reg[`MemAddrBus] s0_addr_o,     // 从设备0读、写地址
    output reg[`MemBus] s0_data_o,         // 从设备0写数据
    input wire[`MemBus] s0_data_i,         // 从设备0读取到的数据
    output reg s0_we_o,                    // 从设备0写标志

    // slave 1 interface
    output reg[`MemAddrBus] s1_addr_o,     // 从设备1读、写地址
    output reg[`MemBus] s1_data_o,         // 从设备1写数据
    input wire[`MemBus] s1_data_i,         // 从设备1读取到的数据
    output reg s1_we_o,                    // 从设备1写标志

    // slave 2 interface
    output reg[`MemAddrBus] s2_addr_o,     // 从设备2读、写地址
    output reg[`MemBus] s2_data_o,         // 从设备2写数据
    input wire[`MemBus] s2_data_i,         // 从设备2读取到的数据
    output reg s2_we_o,                    // 从设备2写标志

    // slave 3 interface
    output reg[`MemAddrBus] s3_addr_o,     // 从设备3读、写地址
    output reg[`MemBus] s3_data_o,         // 从设备3写数据
    input wire[`MemBus] s3_data_i,         // 从设备3读取到的数据
    output reg s3_we_o,                    // 从设备3写标志

    // slave 4 interface
    output reg[`MemAddrBus] s4_addr_o,     // 从设备4读、写地址
    output reg[`MemBus] s4_data_o,         // 从设备4写数据
    input wire[`MemBus] s4_data_i,         // 从设备4读取到的数据
    output reg s4_we_o,                    // 从设备4写标志

    // slave 5 interface
    output reg[`MemAddrBus] s5_addr_o,     // 从设备5读、写地址
    output reg[`MemBus] s5_data_o,         // 从设备5写数据
    input wire[`MemBus] s5_data_i,         // 从设备5读取到的数据
    output reg s5_we_o,                    // 从设备5写标志

    output reg hold_flag_o                 // 暂停流水线标志

    );


    // 访问地址的最高4位决定要访问的是哪一个从设备
    // 因此最多支持16个从设备
    parameter [3:0]slave_0 = 4'b0000;
    parameter [3:0]slave_1 = 4'b0001;
    parameter [3:0]slave_2 = 4'b0010;
    parameter [3:0]slave_3 = 4'b0011;
    parameter [3:0]slave_4 = 4'b0100;
    parameter [3:0]slave_5 = 4'b0101;

    parameter [1:0]grant0 = 2'h0;
    parameter [1:0]grant1 = 2'h1;
    parameter [1:0]grant2 = 2'h2;
    parameter [1:0]grant3 = 2'h3;

    wire[3:0] req;
    reg[1:0] grant;


    // 主设备请求信号
    assign req = {m3_req_i, m2_req_i, m1_req_i, m0_req_i};

    // 仲裁逻辑
    // 固定优先级仲裁机制
    // 优先级由高到低:主设备3,主设备0,主设备2,主设备1
    always @ (*) begin
        if (req[3]) begin
            grant = grant3;
            hold_flag_o = `HoldEnable;
        end else if (req[0]) begin
            grant = grant0;
            hold_flag_o = `HoldEnable;
        end else if (req[2]) begin
            grant = grant2;
            hold_flag_o = `HoldEnable;
        end else begin
            grant = grant1;
            hold_flag_o = `HoldDisable;
        end
    end

    // 根据仲裁结果,选择(访问)对应的从设备
    always @ (*) begin
        m0_data_o = `ZeroWord;
        m1_data_o = `INST_NOP;
        m2_data_o = `ZeroWord;
        m3_data_o = `ZeroWord;

        s0_addr_o = `ZeroWord;
        s1_addr_o = `ZeroWord;
        s2_addr_o = `ZeroWord;
        s3_addr_o = `ZeroWord;
        s4_addr_o = `ZeroWord;
        s5_addr_o = `ZeroWord;
        s0_data_o = `ZeroWord;
        s1_data_o = `ZeroWord;
        s2_data_o = `ZeroWord;
        s3_data_o = `ZeroWord;
        s4_data_o = `ZeroWord;
        s5_data_o = `ZeroWord;
        s0_we_o = `WriteDisable;
        s1_we_o = `WriteDisable;
        s2_we_o = `WriteDisable;
        s3_we_o = `WriteDisable;
        s4_we_o = `WriteDisable;
        s5_we_o = `WriteDisable;

        case (grant)
            grant0: begin
                case (m0_addr_i[31:28])
                    slave_0: begin
                        s0_we_o = m0_we_i;
                        s0_addr_o = {{4'h0}, {m0_addr_i[27:0]}};
                        s0_data_o = m0_data_i;
                        m0_data_o = s0_data_i;
                    end
                    slave_1: begin
                        s1_we_o = m0_we_i;
                        s1_addr_o = {{4'h0}, {m0_addr_i[27:0]}};
                        s1_data_o = m0_data_i;
                        m0_data_o = s1_data_i;
                    end
                    slave_2: begin
                        s2_we_o = m0_we_i;
                        s2_addr_o = {{4'h0}, {m0_addr_i[27:0]}};
                        s2_data_o = m0_data_i;
                        m0_data_o = s2_data_i;
                    end
                    slave_3: begin
                        s3_we_o = m0_we_i;
                        s3_addr_o = {{4'h0}, {m0_addr_i[27:0]}};
                        s3_data_o = m0_data_i;
                        m0_data_o = s3_data_i;
                    end
                    slave_4: begin
                        s4_we_o = m0_we_i;
                        s4_addr_o = {{4'h0}, {m0_addr_i[27:0]}};
                        s4_data_o = m0_data_i;
                        m0_data_o = s4_data_i;
                    end
                    slave_5: begin
                        s5_we_o = m0_we_i;
                        s5_addr_o = {{4'h0}, {m0_addr_i[27:0]}};
                        s5_data_o = m0_data_i;
                        m0_data_o = s5_data_i;
                    end
                    default: begin

                    end
                endcase
            end
            grant1: begin
                case (m1_addr_i[31:28])
                    slave_0: begin
                        s0_we_o = m1_we_i;
                        s0_addr_o = {{4'h0}, {m1_addr_i[27:0]}};
                        s0_data_o = m1_data_i;
                        m1_data_o = s0_data_i;
                    end
                    slave_1: begin
                        s1_we_o = m1_we_i;
                        s1_addr_o = {{4'h0}, {m1_addr_i[27:0]}};
                        s1_data_o = m1_data_i;
                        m1_data_o = s1_data_i;
                    end
                    slave_2: begin
                        s2_we_o = m1_we_i;
                        s2_addr_o = {{4'h0}, {m1_addr_i[27:0]}};
                        s2_data_o = m1_data_i;
                        m1_data_o = s2_data_i;
                    end
                    slave_3: begin
                        s3_we_o = m1_we_i;
                        s3_addr_o = {{4'h0}, {m1_addr_i[27:0]}};
                        s3_data_o = m1_data_i;
                        m1_data_o = s3_data_i;
                    end
                    slave_4: begin
                        s4_we_o = m1_we_i;
                        s4_addr_o = {{4'h0}, {m1_addr_i[27:0]}};
                        s4_data_o = m1_data_i;
                        m1_data_o = s4_data_i;
                    end
                    slave_5: begin
                        s5_we_o = m1_we_i;
                        s5_addr_o = {{4'h0}, {m1_addr_i[27:0]}};
                        s5_data_o = m1_data_i;
                        m1_data_o = s5_data_i;
                    end
                    default: begin

                    end
                endcase
            end
            grant2: begin
                case (m2_addr_i[31:28])
                    slave_0: begin
                        s0_we_o = m2_we_i;
                        s0_addr_o = {{4'h0}, {m2_addr_i[27:0]}};
                        s0_data_o = m2_data_i;
                        m2_data_o = s0_data_i;
                    end
                    slave_1: begin
                        s1_we_o = m2_we_i;
                        s1_addr_o = {{4'h0}, {m2_addr_i[27:0]}};
                        s1_data_o = m2_data_i;
                        m2_data_o = s1_data_i;
                    end
                    slave_2: begin
                        s2_we_o = m2_we_i;
                        s2_addr_o = {{4'h0}, {m2_addr_i[27:0]}};
                        s2_data_o = m2_data_i;
                        m2_data_o = s2_data_i;
                    end
                    slave_3: begin
                        s3_we_o = m2_we_i;
                        s3_addr_o = {{4'h0}, {m2_addr_i[27:0]}};
                        s3_data_o = m2_data_i;
                        m2_data_o = s3_data_i;
                    end
                    slave_4: begin
                        s4_we_o = m2_we_i;
                        s4_addr_o = {{4'h0}, {m2_addr_i[27:0]}};
                        s4_data_o = m2_data_i;
                        m2_data_o = s4_data_i;
                    end
                    slave_5: begin
                        s5_we_o = m2_we_i;
                        s5_addr_o = {{4'h0}, {m2_addr_i[27:0]}};
                        s5_data_o = m2_data_i;
                        m2_data_o = s5_data_i;
                    end
                    default: begin

                    end
                endcase
            end
            grant3: begin
                case (m3_addr_i[31:28])
                    slave_0: begin
                        s0_we_o = m3_we_i;
                        s0_addr_o = {{4'h0}, {m3_addr_i[27:0]}};
                        s0_data_o = m3_data_i;
                        m3_data_o = s0_data_i;
                    end
                    slave_1: begin
                        s1_we_o = m3_we_i;
                        s1_addr_o = {{4'h0}, {m3_addr_i[27:0]}};
                        s1_data_o = m3_data_i;
                        m3_data_o = s1_data_i;
                    end
                    slave_2: begin
                        s2_we_o = m3_we_i;
                        s2_addr_o = {{4'h0}, {m3_addr_i[27:0]}};
                        s2_data_o = m3_data_i;
                        m3_data_o = s2_data_i;
                    end
                    slave_3: begin
                        s3_we_o = m3_we_i;
                        s3_addr_o = {{4'h0}, {m3_addr_i[27:0]}};
                        s3_data_o = m3_data_i;
                        m3_data_o = s3_data_i;
                    end
                    slave_4: begin
                        s4_we_o = m3_we_i;
                        s4_addr_o = {{4'h0}, {m3_addr_i[27:0]}};
                        s4_data_o = m3_data_i;
                        m3_data_o = s4_data_i;
                    end
                    slave_5: begin
                        s5_we_o = m3_we_i;
                        s5_addr_o = {{4'h0}, {m3_addr_i[27:0]}};
                        s5_data_o = m3_data_i;
                        m3_data_o = s5_data_i;
                    end
                    default: begin

                    end
                endcase
            end
            default: begin

            end
        endcase
    end

endmodule

        这个总线为什么叫rib,不是很清楚。不过从代码上看,内容非常简单,就是将命令和数据从master传递给slave。并且根据grant的逻辑,一次只能有一个master参与操作。等选定了master之后, 再根据设备地址的[31:28]位,决定把这个请求发给哪一个slave设备。

5、jtag代码

module jtag_top #(
    parameter DMI_ADDR_BITS = 6,
    parameter DMI_DATA_BITS = 32,
    parameter DMI_OP_BITS = 2)(

    input wire clk,
    input wire jtag_rst_n,

    input wire jtag_pin_TCK,
    input wire jtag_pin_TMS,
    input wire jtag_pin_TDI,
    output wire jtag_pin_TDO,

    output wire reg_we_o,
    output wire[4:0] reg_addr_o,
    output wire[31:0] reg_wdata_o,
    input wire[31:0] reg_rdata_i,
    output wire mem_we_o,
    output wire[31:0] mem_addr_o,
    output wire[31:0] mem_wdata_o,
    input wire[31:0] mem_rdata_i,
    output wire op_req_o,

    output wire halt_req_o,
    output wire reset_req_o

    );

        很多做嵌入式的同学虽然不知道jtag是怎么实现,不过大多数应该用过jtag。如果程序代码跑在ram里面,用软件断点就可以了。但是如果调试的代码保存在rom、flash当中,那么这个时候就只能用jtag来设置硬件断点了。上面这个,就描述了jtag有哪些接口需要处理。

        tck、tms、tdi、tdo,这些都是芯片外部接口数据,主要连接jlink这些工具。reg_we_o、reg_addr_o、reg_wdata_o、reg_rdata_i这些都是对cpu的寄存器进行读写。mem_we_o、mem_addr_o、mem_wdata_o、mem_rdata_i、op_req_o则是和rib总线的对接,这样一来就可以借助于bus访问所有的外设设备了。

6、download模块

module uart_debug(

    input wire clk,                // 时钟信号
    input wire rst,                // 复位信号

    input wire debug_en_i,         // 模块使能信号

    output wire req_o,
    output reg mem_we_o,
    output reg[31:0] mem_addr_o,
    output reg[31:0] mem_wdata_o,
    input wire[31:0] mem_rdata_i

    );

        这个download模块比较特殊,主要就是为了mcu可以正常的把版本烧入到flash里面去。大家可以想一下,自己用的mcu里面,是不是有的芯片也添加了类似这样的功能。

7、简单的一个ram slave代码

module ram(

    input wire clk,
    input wire rst,

    input wire we_i,                   // write enable
    input wire[`MemAddrBus] addr_i,    // addr
    input wire[`MemBus] data_i,

    output reg[`MemBus] data_o         // read data

    );

    reg[`MemBus] _ram[0:`MemNum - 1];


    always @ (posedge clk) begin
        if (we_i == `WriteEnable) begin
            _ram[addr_i[31:2]] <= data_i;
        end
    end

    always @ (*) begin
        if (rst == `RstEnable) begin
            data_o = `ZeroWord;
        end else begin
            data_o = _ram[addr_i[31:2]];
        end
    end

endmodu

        这是一份slave代码,主要是负责数据的读取和写入。从代码上看,内容也简单,如果是读取,那么组合逻辑直接给出;如果是写入,那么需要等时钟上升沿的时候才写入。

8、riscv cpu

        riscv的内容和我们正常的cpu设计差不多,也要处理逻辑运损、移位运算、数学运算、跳转、异常、中断这些内容。只不过,这里的riscv是三级流水线,省去了访存和写回这两级。整体上虽然效率略有降低,不过代码上更加简单和整齐。有兴趣的同学可以利用iverilog+gtkwave来仿真测试下。

9、其他的话

        至此,关于cpu和mcu设计的部分就结束了,有兴趣的同学可以继续拓展。总之,还是要多练习、多实践,才能加深印象。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

项目接入腾讯云短信服务SMS实现向用户发送手机验证码

1、自述 早在18年的时候&#xff0c;我就在项目中使用过阿里云的短信服务&#xff0c;现在我上阿里云短信控制台看&#xff0c;还能看到当时创建的短信签名&#xff0c;如下图所示。 出于某种原因&#xff0c;我现在想重新申请一个新的签名&#xff0c;却审批失败了&#xf…

HashMap和Hashtable的详细区别

HashMap和Hashtable的详细区别 一、简述&#xff1a; 1.安全性 Hashtable是线程安全&#xff0c;HashMap是非线程安全。HashMap的性能会高于Hashtable&#xff0c;我们平时使用时若无特殊需求建议使用HashMap&#xff0c;在多线程环境下若使用HashMap需要使用Collections.sy…

MyBatisPlus的使用入门

一、简介 官网&#xff1a;http://mp.baomidou.com/ 参考教程&#xff1a;http://mp.baomidou.com/guide/ MyBatis-Plus&#xff08;简称 MP&#xff09;是一个 MyBatis 的增强工具&#xff0c;在 MyBatis 的基础上只做增强不做改变&#xff0c;为简化开发、提高效率而生。 二、…

(ICLR-2019)DARTS:可微分架构搜索

DARTS&#xff1a;可微分架构搜索 paper题目&#xff1a;DARTS: DIFFERENTIABLE ARCHITECTURE SEARCH paper是CMU发表在ICLR 2019的工作 paper链接&#xff1a;地址 ABSTRACT 本文通过以可微分的方式制定任务来解决架构搜索的可扩展性挑战。与传统的在离散的、不可微分的搜索空…

【Android App】实战项目之使用OpenCV人脸识别实现找人功能(附源码和演示 超详细)

需要全部代码请点赞关注收藏后评论区留言私信~~~ 人脸识别自古有之&#xff0c;每当官府要捉拿某人时&#xff0c;便在城墙贴出通缉告示并附上那人的肖像。只是该办法依赖人们的回忆与主观判断&#xff0c;指认结果多有出入&#xff0c;算不上什么先进。 如今利用监控摄像头结合…

E3--FPGA实现LVDS收发实例和原理2022-12-03

1.什么是LVDS 一个新东西来的时候&#xff0c;人们总是希望能够宏观的定性的认识它。一个问题是&#xff0c;手机上用的“软件”该如何定义呢&#xff1f;来自百度百科的定义是&#xff0c;软件是指一系列按照特定顺序组织的计算机数据和指令的集合&#xff0c;如果你是非专业…

【Android App】给App集成WebRTC实现视频发送和接受实战(附源码和演示 超详细)

需要源码请点赞关注收藏后评论区留言私信~~~ 一、引入WebRTC开源库 WebRTC开源库的集成步骤如下&#xff1a; &#xff08;1&#xff09;给App模块的build.gradle添加WebRTC的依赖库配置&#xff1b; &#xff08;2&#xff09;App得申请录音和相机权限&#xff0c;还得申请…

[附源码]计算机毕业设计springboot自行车租赁管理系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

K-means聚类算法及Python代码实现

K-means聚类算法&#xff08;事先数据并没有类别之分&#xff01;所有的数据都是一样的&#xff09; 1、概述 K-means算法是集简单和经典于一身的基于距离的聚类算法 采用距离作为相似性的评价指标&#xff0c;即认为两个对象的距离越近&#xff0c;其相似度就越大。 该算法…

享元设计模式

一、享元模式 1、定义 享元模式&#xff08;Flyweight Pattern&#xff09;又称作轻量级模式&#xff0c;是指提供减少对象数量从而改善应用所需的对象结构的方式。其宗旨是共享细粒度的对象&#xff0c;将多个对同一对象的访问集中起来&#xff0c;不必为每个访问者都创建一个…

C++智能指针shared_ptr用法

目录shared_ptr功能介绍shared_ptr提供的接口shared_ptr初始化shared_ptr管理指针的构造和析构shared_ptr获取原始指针shared_ptr的线程安全shared_ptr应用之enable_shared_from_this写在前面的总结&#xff1a;一个shared_ptr对象管理一个指针&#xff08;new T&#xff0c;在…

TCP/IP五层协议栈(3)

1.网络层 1.1.IP协议 IP协议格式:报头数据 4位版本 :IP协议的版本号.当前只有两个取值,4和6(0100 0110).( 这里讨论IPv4 )4位首部长度 :IP报头和TCP类似,都是可变的,带有选项.8位TOS :只有4位有效,那四位TOS分别表示( 最小延时,最大吞吐量,最高可靠性,最小成本 )(同一时刻只能…

使用 Qt for Android 获取并利用手机传感器数据(下篇)使用C++实现功能

在上一篇&#xff0c;我们搭建了开发环境。本篇&#xff0c;使用C代码真正实现功能。我们使用UDP协议从手机上指定发送的目的地、端口。效果如下图&#xff0c;完整工程参考https://gitcode.net/coloreaglestdio/qtcpp_demo/-/tree/master/android/sensors2pc&#xff1a; 移动…

全志T3 ARM+Ethercat+Codesys工业控制器设计方案

目前codesys EtherCAT驱动 做运动控制很有优势。现在总线式运动控制基本都是这种配置。 Codesys 号称PLC界的安卓&#xff0c;国内造PLC的 基本都用Codesys内核了。 如&#xff1a;汇川 &#xff0c;合信&#xff0c; 和利时 &#xff0c;英威腾&#xff0c; 台达。 包…

原子范数初探:以到达角估计为例

到达方向&#xff08;Direction-of-arrival, DOA&#xff09;估计是指从形成传感器阵列的多个接收天线的输出中检索若干电磁波/源的方向信息的过程。DOA估计是阵列信号处理中的一个主要问题&#xff0c;在雷达、声纳、无线通信中有着广泛的应用。 基本数学模型 考虑KKK个窄带…

Java项目:ssm流浪猫狗救助管理系统

作者主页&#xff1a;源码空间站2022 简介&#xff1a;Java领域优质创作者、Java项目、学习资料、技术互助 文末获取源码 项目介绍 流浪猫狗救助管理系统。该项目分为前后台&#xff1b; 前台主要功能包括&#xff1a;会员的注册登陆,流浪猫狗知识&#xff0c;领养中心&#…

[附源码]计算机毕业设计JAVA学生实习管理系统

[附源码]计算机毕业设计JAVA学生实习管理系统 项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybati…

80W美团架构师整理分享出了Spring5企业级开发实战文档

前言 都说程序员工资高、待遇好&#xff0c; 2022 金九银十到了&#xff0c;你的小目标是 30K、40K&#xff0c;还是 16薪的 20K&#xff1f;作为一名 Java 开发工程师&#xff0c;当能力可以满足公司业务需求时&#xff0c;拿到超预期的 Offer 并不算难。然而&#xff0c;提升…

U盘插入提示格式化才能使用,但里面有数据无法复制出来怎么解决?

U盘作为移动储存硬盘&#xff0c;避免不了出现各种问题&#xff0c;特别是莫名提示格式化&#xff0c;无法打开&#xff0c;要使用的话只能先将其格式化。 只要电脑还能正常识别出U盘&#xff0c;那都是有概率恢复出来数据的。先不要点“格式化”&#xff01; 如果一旦出现点…

4.JVM垃圾收集机制

1. 垃圾收集算法 1.1 分代收集理论 当前虚拟机的垃圾收集都采用分代收集算法&#xff0c;这种算法&#xff0c;没有什么新的思想&#xff0c;只是根据对象存活周期的不同将内存分成几块。一般将JAVA堆分为新生代、老年代&#xff0c;这样我们就可以根据各个年代的特点选择合适…