stm32堆栈的认知

2023-05-16

flash和SRAM的区别
flash可以像硬盘一样存数据,也可以直接像RAM运行,一般在里面放bootload,程序执行代码。

1、stm32中的堆栈
单片机是一种集成电路芯片,集成cpu、ram、rom、多种i/o口和中断系统、定时器/计数器等功能。cpu中包括了各种总线电路,计算电路,逻辑电路,还有各种寄存器。stm32有通用寄存器R0-R15以及一些特殊功能寄存器,其中包括了堆栈指针寄存器。当stm32正常运行程序的时候,来了一个中断,CPU就需要将寄存器中的值压栈到ram里,然后将数据所在的地址存放在堆栈寄存器中。等中断处理完成退出时,再将数据出栈到之前的寄存器中,这个在c语言中是自动完成的。

2、编程中的堆栈
在编程中,很多时候会提到堆栈这个东西,准确的说这个就是ram中的一个区域。我们先了解几个说明:
(1)程序中的所有内容最终只会出现在flash,ram里。
(2)段的划分,是将类似数据种类存储在一个区域里,方便管理,正如上面所说,不管什么段的数据,最终都是在flash和ram里面。
c语言上分为堆、栈、bss、data、code段。具体每个段具体是存储什么数据,直接百度。接下来重点分析stm32以及在MDK里面段的划分。
MDK下code、ro-data,rw-data,zi-data着几个段:
code:存储程序代码的。
ro-data:存储const常量和指令。
rw-data:存储初始化值不为0的全局变量。
zi-data:存储未初始化的全局变量或初始化值为0的全局变量。

flash=code+RO Data + RW Data;
RAM=rw-data+zi-data;

这个是MDK编译之后能够得到的每个段的大小,也就能够得到占用响应的flash和ram大小,但是还是有两个数据段也会占用RAM,但是是在程序运行的时候,才会占用,那就是堆和栈。 在stm32的启动文件.s文件里面,就有堆栈的设置,其实这个堆栈的内存占用就是在上面RAM分配给rw-data+zi-data之后的地址开始分配的。

堆:是编译器调用动态内存分配的内存区域。
栈:是程序运行的时候局部变量的地方,所有局部变量用数组太大了都有可能造成栈溢出。

堆栈的大小在编译器编译之后是不知道的,只有运行的时候才知道,所以需要注意一点,就是别造成堆栈溢出了,,,不然就会有hardfault。

2、如果查看map文件

例子:
Total RO Size (Code + RO Data) 2980 ( 2.91kB)
Total RW Size (RW Data + ZI Data) 104 ( 0.10kB)
Total ROM Size (Code + RO Data + RW Data) 2988 (2.92kB)

Total ROM Size (Code + RO Data + RW Data)这样所写的程序占用的ROM的字节总数,也就是说程序所下载到rom flash中的大小为什么rom中还要存rw,因为掉电之后ram中所有数据都丢失了,每次上电ram的数据是被重新赋值的,每次这些固定的值就是存储在rom中,为什么不包含zi段呢,是因为自数据都是0
,没必要包含,只要程序运行之前将zi数据所在的区域一律清零即可,包含进去反而浪费存储空间。
实际上,rom中的指令至少应该有这样的功能:
(1)将rw从rom中搬到ram中,因为rw是变量,变量不能存在rom中。
(2)将zi所在的ram区域全部清零,因为zi区域并不在lmage中,所以需要程序根据编译器给出的zi地址以及大小来讲相应的ram区域清零,zi中也是变量,同理,变量不能存在rom中。

在程序运行的最初阶段,ro中的指令完成了这两项工作后c程序才能正常访问变量,否则只能运行不含变量的代码。

一、已经了解的

MDK编译之后的信息:
在这里插入图片描述
从中知道占用的flash=code+ro-data+rw-data

stm32 flash的初始地址是0x80000000,当然也可以自定义起始地址,不过记得在main函数中sing一变量后加一句SCB->VTOR==FLASH_BASE | OFFSET;其中offset是想要偏移的量,可宏定义或者直接0xXX。
当然也可以调用库函数NVIC_SetVectorTable()进行偏移,效果一样。
占用的SRAM=rw-data+zi-data。
stm32 sram的起始地址是0x20000000。看MDK的魔法棒设置target选项也是可以设置RAM起始地址和大小的,不过一般都不会动RAM的。

记忆小技巧:
前面3个是给flash,后面2个是给SRAM。
含义:
code:代码
ro-data:只读数据,字符串常量(经过const修饰的)
rw-data:可读可写数据,已经初始化的全局变量或者static修饰的变量(不管局部变量还是全局变量,没有显示的初始化的话,会初始化为0)
zi-data:没有进行初始化的全局变量。

二、基于map文件的分析
右边是.map文件放内容

const修饰的常量,不管在局部还是全局存放在flash 中,不占用RAM,所以为了节省RAM,把常量的字符串,数据等声明为const是推荐的一种做法
static修饰的变量,不管是在局部还是在全局存放于RAM 的.data段,就是已初始化变量区。static不显示初始化默认为初始化为0
初始化的全局变量存放在RAM 的.data段,就是已初始化变量区。static不显示初始化默认为初始化为0
未初始化的全局变量放在RAM的.bss段,也就是没有显示的进行初始化
HEAP 即堆区存放于RAM的HEAP段,堆区内存需要程序员用malloc和free进行动态分配和释放,注意不要丢失、改写了申请内存后得到的指针,以免释放不了,造成内存泄漏
STACK 即栈区存放于RAM 的STACK段,这部分是程序运行时函数局部变量使用的,使用完自动释放

在这里插入图片描述
PAD是“垫子、卫生巾”的意思。占用两个字节,姑且理解为”隔开各个段”吧。
宏定义、结构体、联合体、枚举类型等都属于代码。RAM值存放变量。但FLASH不止存放代码,还有变量,就是和RAM都有的交集,即MDK生成的RW-data(全局变量、static变量)。
疑问:这么多变量,它们是怎么排列在RAM中的呢?看上面的.map文件中的地址就知道了。就是一初始化的变量在前面,然后跟着是未初始化的全局变量,然后是堆,最后是栈。
也就是说栈和堆的起始地址是不可控的,是根据我们程序的全局变量多少计算出来的,一句话,吃剩下的。

三、裁剪栈和堆的大小
1、当我们程序运行到一个函数中莫名其妙的就崩了,进入HardFault_Handler,数组也没有越界啊?
可能的原因之一: 局部变量过多,栈溢出,不够用了,需要我们Tailor(裁剪)一下RAM。
ps: 数组越界也属于栈溢出。在启动文件中进行裁剪。HardFault_Handler在网上也有很多分析方法。

2、例如,如下启动文件我们可以把STACK_SIZE从0x400(1KB)改到0x800(2KB)一般就不会出现奔溃了,如果还崩,那要找找其他原因了(是不是函数使用了非法的指针,0xE0000000之类的MCU不认,不能访问的地址)等等。

3、当然有时候栈加上其他的,大小超过了RAM总大小,编译器就会提示不够,就要一点点加着试。

这时大小超过了RAM总大小,也能从一定程度说明程序设计存在不合理,几乎用光了RAM。比如全局变量设置的过大,世纪没用这么多,也设置这么多,一般多实际最大使用量加2个字节就没问题。大型的全局变量(即结构体全局变量、联合体全局变量)过多,重复繁杂,共用率不高。就要逐个文件删繁就简,砍掉能砍的全局变量, 缩小能缩的结构体,字节对齐,各种看家本领就要使用出来。如果砍到不能再砍的时候,只能砍功能或者换芯片了。

在这里插入图片描述

第三篇文章

1、查看:栈(stack)的问题
函数的局部变量,都是存放在“栈”里面,栈的英文是:STACK。STACK的大小我们可以在stm32的启动文件中设置,以战舰stm32开发板为例,在start_upstm32f10x_hd.s里面,开头就有:
stack_size EQU 0X00000800
表示栈大小是0x800,也就是2048字节,这样cpu处理任务的时候,函数局部变量最多可占用的大小就是2048字节。注意:是所有在处理的函数,包括函数嵌套、递归、等等,都是从“栈”里面分配的。
所有一个函数的局变量过多,比如在函数中定义一个u8 buf[512],这一下子就占用了1/4的栈大小了,再在其他函数里面来搞两下,程序奔溃是很容易的事了。这时候,一般就会进入hardfault…
这时初学者很容易犯的一个错误,切记不要在函数中放N多局部变量,尤其是有大数组的情况。
对于栈区,一般栈顶,也就是MSP,在程序刚运行的时候,指向程序所占用内存的最高地址,比如附件里面的这个程序,内存占用如图:

在这里插入图片描述
图中我们可以看到,程序总共占用内存:20+2348字节=2368=0x940
那么程序刚开始运行的时候:MSP=0x2000 0000+0x940=0x200000940。
事实上,也是如此,如图:
在这里插入图片描述
图中,MSP就是0x20000 0940。
程序运行后,MSP就是从这个地址开始,往下给函数的局部变量分配地址。

再说说栈的增长方向,我们可以用如下代码测试:

//保存栈增长方向
//0,向下增长;1,向上增长.
static u8 stack_dir;

//查找栈增长方向,结果保存在stack_dir里面.
void find_stack_direction(void)
{
    static u8 *addr=NULL; //用于存放第一个dummy的地址。
    u8 dummy;               //用于获取栈地址
    if(addr==NULL)    //第一次进入
    {                         
        addr=&dummy;     //保存dummy的地址
        find_stack_direction ();  //递归
    }
    else                //第二次进入
 	{  
        if(&dummy>addr)stack_dir=1; //第二次dummy的地址大于第一次dummy,那么说明栈增长方向是向上的.
        else stack_dir=0;           //第二次dummy的地址小于第一次dummy,那么说明栈增长方向是向下的. 
 	}
}

这个代码不是我写的,是从网上抄的,思路很巧妙,利用递归,判断两次分配给dummy的地址,来比较栈是向下增长还是向上增长。
如果你在stm32测试这个函数,你会发现,使stm32的栈,是向下增长的,事实上,一般CPU的栈增长方向,都是向下的。

2、再来说说,堆(HEAP)的问题

全局变量,静态变量,以及内存管理所用的内容,都是“堆”区,英文名:“HEAP”。
和栈区不同,堆区是从内存区域的起始地址,开始分配给各个全局变量和静态变量。
堆的生长方向,都是向上的。在程序里面,所有的内存分为:堆+栈。只是他们各自的起始地址和增长方向不同,他们没有 一个固定的界限,所以一旦堆栈冲突,系统就会奔溃。
我们测试一下:
在这里插入图片描述
sack_dir的地址是0x20000004,也就是stm32的内存起始端的地址。
这里本来应该是从0x20000000开始分配的,,但是仿真后发现,0x20000000总是存放:0x20000398,这个目前不清楚,等后续再解决。待解决
其他的,全局变量,则依次递增,地址肯定大于0x20000004,比如,cpu_endian的地址就是0x20000005,这时stm32内部堆的分配规则。
3、再说说,大小端的问题
大端模式:地位字节存在高地址上,高位字节存在低地址上。
小段模式:高位字节存在高地址上,低位字节存在低地址上。

stm32属于小端模式,简单的说,比如u32 temp=0x12345678;
假设temp地址在0x2000 0010。
那么在内存里面,存放就变成了:

地址hex
0x2000 001078 56 34 12

cpu到底是小端还是大端,可以通过如下代码测试:

//CPU大小端
//0,小端模式;1,大端模式.
static u8 cpu_endian;

//获取CPU大小端模式,结果保存在cpu_endian里面
void find_cpu_endian(void)
{
 	int x=1;
 	if(*(char*)&x==1)
 		cpu_endian=0; //小端模式
 	else cpu_endian=1;    //大端模式 
}

以上测试,在stm32上,你会得到cpu_endian=0,也就是小端模式。

3、最后说说,stm32内存的问题
在前面第一个图,程序总共占用内存:20+2348字节,那么多内存,到底是怎么得来的呢?
我们直接双击“工程名字”就能弹出map文件,在这里面,我们就可以很清楚的知道这些内存到底是怎么来的,在map文件最后,image部分有:

Image component sizes

      Code (inc. data)   RO Data    RW Data    ZI Data      Debug   Object Name
       172         10          0          4          0        995   delay.o//delay.c里面,fac_us和fac_ms,共占用4字节
       112         12          0          0          0        427   led.o
        72         26        304          0       2048        828   startup_stm32f10x_hd.o  //启动文件,里面定义了Stack_Size为0X800,所以这里是2048.
       712         52          0          0          0       2715   sys.o
       348        154          0          6          0     208720   test.o//test.c里面,stack_dir和cpu_endian 以及*addr  ,占用6字节.
       384         24          0          8        200       3050   usart.o//usart.c定义了一个串口接收数组buffer,占用200字节.
    ----------------------------------------------------------------------
      1800        278        336         20       2248     216735   Object Totals //总共2248+20字节
         0          0         32          0          0          0   (incl. Generated)
         0          0          0          2          0          0   (incl. Padding)//2字节用于对其
    ----------------------------------------------------------------------
      Code (inc. data)   RO Data    RW Data    ZI Data      Debug   Library Member Name
         8          0          0          0          0         68   __main.o
       104          0          0          0          0         84   __printf.o
        52          8          0          0          0          0   __scatter.o
        26          0          0          0          0          0   __scatter_copy.o
        28          0          0          0          0          0   __scatter_zi.o
        48          6          0          0          0         96   _printf_char_common.o
        36          4          0          0          0         80   _printf_char_file.o
        92          4         40          0          0         88   _printf_hex_int.o
       184          0          0          0          0         88   _printf_intcommon.o
         0          0          0          0          0          0   _printf_percent.o
         4          0          0          0          0          0   _printf_percent_end.o
         6          0          0          0          0          0   _printf_x.o
        12          0          0          0          0         72   exit.o
         8          0          0          0          0         68   ferror.o
         6          0          0          0          0        152   heapauxi.o
         2          0          0          0          0          0   libinit.o
         2          0          0          0          0          0   libinit2.o
         2          0          0          0          0          0   libshutdown.o
         2          0          0          0          0          0   libshutdown2.o
         8          4          0          0         96         68   libspace.o          //库文件(printf使用),占用了96字节
        24          4          0          0          0         84   noretval__2printf.o
         0          0          0          0          0          0   rtentry.o
        12          0          0          0          0          0   rtentry2.o
         6          0          0          0          0          0   rtentry4.o
         2          0          0          0          0          0   rtexit.o
        10          0          0          0          0          0   rtexit2.o
        74          0          0          0          0         80   sys_stackheap_outer.o
         2          0          0          0          0         68   use_no_semi.o
         2          0          0          0          0         68   use_no_semi_2.o
       450          8          0          0          0        236   faddsub_clz.o
       388         76          0          0          0         96   fdiv.o
        62          4          0          0          0         84   ffixu.o
        38          0          0          0          0         68   fflt_clz.o
       258          4          0          0          0         84   fmul.o
       140          4          0          0          0         84   fnaninf.o
        10          0          0          0          0         68   fretinf.o
         0          0          0          0          0          0   usenofp.o
    ----------------------------------------------------------------------
      2118        126         42          0        100       1884   Library Totals  //调用的库用了100字节.
        10          0          2          0          4          0   (incl. Padding)   //用于对其多占用了4个字节
    ----------------------------------------------------------------------
      Code (inc. data)   RO Data    RW Data    ZI Data      Debug   Library Name
       762         30         40          0         96       1164   c_w.l
      1346         96          0          0          0        720   fz_ws.l
    ----------------------------------------------------------------------
      2118        126         42          0        100       1884   Library Totals
    ----------------------------------------------------------------------
==============================================================================

      Code (inc. data)   RO Data    RW Data    ZI Data      Debug  
      3918        404        378         20       2348     217111   Grand Totals
      3918        404        378         20       2348     217111   ELF Image Totals
      3918        404        378         20          0          0   ROM Totals
==============================================================================
    Total RO  Size (Code + RO Data)                 4296 (   4.20kB)
    Total RW  Size (RW Data + ZI Data)              2368 (   2.31kB)   //总共占用:2248+20+100=2368.
    Total ROM Size (Code + RO Data + RW Data)       4316 (   4.21kB)

通过这个文件,我们就可以分析整个内存,是怎么被占用的,具体到每个文件,占用多少.一目了然了。

4,最后,看看整个测试代码:

main.c代码如下,工程见附件.
#include "sys.h"
#include "usart.h"  
#include "delay.h" 
#include "led.h"
#include "beep.h"   
#include "key.h"   
//ALIENTEK战舰STM32开发板堆栈增长方向以及CPU大小端测试
//保存栈增长方向
//0,向下增长;1,向上增长.
static u8 stack_dir;
//CPU大小端
//0,小端模式;1,大端模式.
static u8 cpu_endian;
 

//查找栈增长方向,结果保存在stack_dir里面.
void find_stack_direction(void)
{
    static u8 *addr=NULL; //用于存放第一个dummy的地址。
    u8 dummy;               //用于获取栈地址
    if(addr==NULL)    //第一次进入
    {                         
        addr=&dummy;     //保存dummy的地址
        find_stack_direction ();  //递归
    }
    else                //第二次进入
 	{  
        if(&dummy>addr)
        	stack_dir=1; //第二次dummy的地址大于第一次dummy,那么说明栈增长方向是向上的.
        else 
        	stack_dir=0;           //第二次dummy的地址小于第一次dummy,那么说明栈增长方向是向下的. 
 	}
}
//获取CPU大小端模式,结果保存在cpu_endian里面
void find_cpu_endian(void)
{
	 int x=1;
	 if(*(char*)&x==1)
 		cpu_endian=0; //小端模式
	 else 
 		cpu_endian=1;    //大端模式 
}
int main(void)
{   
	 Stm32_Clock_Init(9); //系统时钟设置
	 uart_init(72,9600);   //串口初始化为9600
	 delay_init(72);       //延时初始化
	 LED_Init();      //初始化与LED连接的硬件接口 
   	 printf("stack_dir:%x\r\n",&stack_dir);
   	 printf("cpu_endian:%x\r\n",&cpu_endian);
 
 	find_stack_direction(); //获取栈增长方式
	 find_cpu_endian();  //获取CPU大小端模式
 	 while(1)
	 {
 		 if(stack_dir)
 		 	printf("STACK DIRCTION:向上生长\r\n\r\n");
  		else 
  			printf("STACK DIRCTION:向下生长\r\n\r\n");
 		if(cpu_endian)
 			printf("CPU ENDIAN:大端模式\r\n\r\n");
 		 else 
 		 	printf("CPU ENDIAN:小端模式\r\n\r\n");
  		delay_ms(500);
  		LED0=!LED0; 
 	} 
}

测试结果如图:
在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

stm32堆栈的认知 的相关文章

  • qemu镜像转化

    qemu img convert f raw redhat6 7 kvm postgresql9 2 3 8disk pulsar2 2 O qcow2 redhat6 7 kvm postgresql9 2 3 8disk pulsar2
  • brew install 慢的解决方法

    brew install 慢的原因 brew install 会先去执行 brew update 而 brew update xff0c 会依次更新 brew homebrew core homebrew cask 而以上三个的来源都在 g
  • 在linux ubuntu18.04版本中安装ceres solver

    在linux ubuntu18 04版本中安装ceres solver 本文是参照ceres solver的官方网站的按照教程来写的 xff0c 并对其做了适当的修改以便能成功安装 ceres官方教程链接为http www ceres so
  • KITTI Odometry dataset中00-21系列的相机内参设置

    一些声明 见data odometry calib文件夹中的calib txt文件 xff0c 其中P0表示左边灰度相机的3 4内参矩阵 xff0c P1表示右边灰度相机的3 4内参矩阵 依据这两个矩阵 xff0c 求解 f x f x f
  • CMakeLists.txt模板+常用库头文件添加和库文件链接+调用头文件

    CMakeLists txt模板 声明要求的cmake最低版本 span class token function cmake minimum required span span class token punctuation span
  • CLion 乱码 中文编码设置(UTF8、GBK)(Windows、WSL)——持续更新ing

    目录 问题描述解决方案一 xff1a CLion的简单设置见证奇迹 博主使用CLion如果里面有中文经常会遇到输出乱码问题 xff0c 本篇博文将告诉你多种问题的解决方案 问题描述 我们新建一个CLion工程 xff1a span clas
  • GRUB(bootloader)

    GRUB grub legacy版本 grub 0 x xff1a grub legacy Centos 5 6 stage2及内核等通常放置于一个基本磁盘分区 boot分区 配置文件 xff1a boot grub grub conf g
  • ROS实践(1)-环境搭建

    一 介绍 ROS官网 xff1a http www ros org ROS中文社区 xff1a http www robotos net forum php ROS版本 xff1a ROS的版本名称是按字母顺序E F G H I J排列的
  • ROS实践(6)-自建示例

    一 单topic 1 初始化环境 创建路径 dev mytest xff0c 并加入环境变量 xff1a root 64 yangkai04 Inspiron 3650 dev pwd root dev vim bashrc export
  • Python Django之密码的加密和解密

    通过django自带的类库 xff0c 来加密解密很方便 xff0c 下面来简单介绍下 xff1b 导入包 xff1a code class sourceCode python hljs span class im span class h
  • KCU105 XDMA 测试

    rdf0307 kcu105 trd03 2017 3 kcu105 axis dataplane hardware vivado scripts ug920 kcu105 pcie streaming data plane trd pdf
  • Ubuntu 配置 boa 服务器

    原文 xff1a http www linuxidc com Linux 2011 08 39780p3 htm Ubuntu上编译使用boa服务器的教程文章 xff0c 已经有很多了 xff0c 博客上也有很多人写了 xff0c 我就不赘
  • 阿里云docker方式搭建CAS服务端-最新版

    现在网上查到的CAS服务端搭建方式都比较老 xff0c 坑也很多 docker镜像直接使用官方的 xff0c 便于今后无缝升级 cas现时点最新版本为6 3 1 创建工作目录 mkdir home cas 以下操作都在该目录下执行 2 生成
  • 0、清华大学开源软件镜像站linux系统镜像下载地址

    https mirrors tuna tsinghua edu cn
  • 使用SSH公钥(id_dsa.pub)实现免密码登录

    使用SSH公钥 id dsa pub 实现免密码登录 博客分类 xff1a linux shell ssh 免密码 公钥 首先 xff0c 在本地机器上产生公钥 xff1a Java代码 root 64 localhost ssh ssh
  • 6.1、startx命令怎么不能进入图形界面

    命令行界面输入startx命令怎么不能进入图形界面 复制链接 发表于 2010 1 29 12 55 来自 51CTO网页 只看他 楼主 我在虚拟机 xff08 vmware xff09 上新安装的red hat linux 9 0在命令行
  • 7.1、mysql mha 主从自动切换 高可用

    是这个博主写的 xff0c 但是找不到地址了 写了他的另一个MHA地址 感谢原创的贡献 mysql mha 主从自动切换 高可用 mha xff08 Master High Availability xff09 目前在MySQL多服务器 x
  • 7.3、mysql主主循环备份数据库

    绿色部分是我根据需要自己写的 mysql 主主互备 双机热备的概念简单说一下 xff0c 就是要保持两个数据库的状态自动同步 对任何一个数据库的操作都自动应用到另外一个数据库 xff0c 始终保持两个数据库数据一致 这样做的好处多 1 可以
  • 7.4、Slave_SQL_Running: No mysql同步故障解决方法

    Slave SQL Running No mysql同步故障解决方法 2010 02 21 16 31 30 标签 xff1a mysql 数据库 同步 双机 休闲 原创作品 xff0c 允许转载 xff0c 转载时请务必以超链接形式标明文
  • 7.5、mysql破解密码

    找不到原创了 xff0c 百度了一下 xff0c 这个比较像 感谢原创的贡献 vi etc my cnf 在配置文件中加入 s kip grant tables mysqld safe skip grant tables amp 最佳答案

随机推荐

  • Scrum实践系列之三--敏捷教练的修炼之路

    敏捷教练与项目经理 在被奉为 项目管理圣经 的PMBOK中 xff0c 对项目经理在各阶段的职责有着清晰的界定 xff0c 比如项目经理制定规则 安排进度 监控执行中的各项风险并实时汇报状态 xff0c 等等 然而在敏捷的世界里 xff0c
  • 知识图谱_概述:课程PPT+个人理解

    2019 05 08 一 概念 xff08 是什么 xff09 1 知识 xff1a 有不同的解释 xff0c 可以是 不变的真理 经验 背景 解释 交工的信息 xff08 1 xff09 分类 陈述性知识 gt 描述客观事物的性状和关系等
  • chatgpt

    transformer GitHub Topics GitHub
  • Apollo:source cyber/setup.bash的作用

    source cyber setup bash 是在使用Apollo开发过程中 xff0c 用于加载Apollo软件的配置以及环境变量的脚本 Apollo是一款自动驾驶开发平台 xff0c cyber是其中的一个核心模块 xff0c 提供了
  • 什么样的人当不好程序员?

    什么样的人当不好程序员 xff1f 2016 01 21 程序员之家 来源 xff1a 36Kr 译文 xff1a http 36kr com p 5042433 html 原文 xff1a https goo gl jLfUFq 软件蚕食
  • java基础语法(顺便回顾cpp语法并比较与java的异同)

    变量 标识符 关键字与数据类型 1 标识符命名风格约定 xff1a 不能以数字开头 xff0c 也不能有 等符号 可以有 和 但不用作开头 方法名 变量名首单词小写 xff0c 其余单词首字母大写 如anyVariableName 类名 接
  • 刷leetcode,锻炼编程能力(c++)

    力扣20 xff0c 有效的括号 xff0c 栈 span class token macro property span class token directive keyword include span span class toke
  • 华为笔试题库之困难--难度

    题记 xff1a 若立志投身算法研究 xff0c 可精研理论算法 xff1a 动态规划 递归 深度搜索等 xff1b 若以解决问题为目的 xff0c 主要为了工作内容 xff0c 当尝试快而简单的方法 xff0c 这该是学习的本意 1 素数
  • C++ - opencv应用实例之矩形框检测

    C opencv应用实例之矩形框检测 现阶段下 目标检测在实际应用场景中的表现颇为重要 工业质检 移动机器人视觉伺服 作业 交通监控 安防领域等均需要通过目标检测来实现对目标的定位 测量或者统计 辅助控制等 目前目标检测主要分为两个方向的发
  • cpp-5 : Depends: gcc-5-base (= 5.3.1-14ubuntu2) but 5.4.0-6ubuntu1~16.04.11 is to be installed

    在5 4 0 6ubuntu1 16 04 11 cpp 5 amd64 Xenial 16 04 Ubuntu上下载对应的版本 xff0c 国 内源的版本都是5 4 0 6ubuntu1 16 04 12 xff0c 最后一位是12 xf
  • Questasim SystemC 指令sccom

    QuestaSim sccom 10 6c 1 compiler 2017 09 Sep 15 2017 Usage sccom options CPP compiler options lt CPP files gt General Op
  • MacOS 安装curl和wget

    目录 1 什么是curl和wget1 1 curl1 2 wget1 3 curl和wget的区别 2 安装curl2 1 利用wget安装curl2 2 直接下载curl源码编译安装 推荐 3 安装wget3 1 利用Homebrew安装
  • linux tty core 源码分析__tty_read,__tty_write,__tty_poll,

    转载 xff1a http blog csdn net sirzjp article details 6134489 前面分析了open操作 xff0c 现在分析读操作tty read tty read直接调用线路规程中的读操作从tty g
  • D触发器二分频电路

    D触发器二分频电路 有时真的要感慨一下自己电路学的够烂的 xff0c 啥都不会 xff0c 做示波器要学习分频电路 xff0c 学呗 将D触发器的Q非端接到数据输入端D即可实现二分频 xff0c 说白了就是CLK时钟信号的一个周期Q端电平反
  • 自动驾驶系列(十)编写电动车ROS节点(刹车)

    一 硬件控制协议 对于不同的设备 xff0c 底层的通讯方式都不一致 xff0c 因此需要根据具体硬件具体分析 本系统 采用了1个CAN盒子控制转向 xff0c 1路DA控制油门 xff0c 另外一路DA控制刹车 1 xff0c 转向协议
  • 【Mapreduce】利用单表关联在父子关系中求解爷孙关系

    首先是有如下数据 xff0c 设定左边是右边的儿子 xff0c 右边是左边的父母 Tom Lucy Tom Jack Jone Lucy Jone Jack Lucy Mary Lucy Ben Jack Alice Jack Jesse
  • 【C++】Split

    如果要将类似 aa ss ff 的字符串按空格分割成一个个字符 xff0c Java C PHP或者python等其它语言写多的人 xff0c 就会认为split一个理应存在的方法 xff0c 实际上C 43 43 中并没有这个方法 xff
  • TX2模组镜像备份与刷机

    1 环境搭建 1 1 下载驱动包和根文件系统 进入https developer nvidia com embedded linux tegra r3251下载两个文件 xff0c L4T Driver Package BSP 和Sampl
  • STM32——Keil5的编译警告和错误订正

    这是第一次写博客 xff0c 这里都是我在修改stm32代码遇到的一些警告和错误的改正 xff0c 其中有很多解决方法都是在网上找的 xff0c 也有一些还没解决的 xff0c 望指点 513 D HARDWARE 1U src Uart
  • stm32堆栈的认知

    flash和SRAM的区别 flash可以像硬盘一样存数据 xff0c 也可以直接像RAM运行 xff0c 一般在里面放bootload xff0c 程序执行代码 1 stm32中的堆栈 单片机是一种集成电路芯片 xff0c 集成cpu r