浅谈STM32堆栈与uCOS堆栈,其实是两码事

发布者:古泉痴迷者最新更新时间:2020-01-12 来源: eefocus关键字:STM32  堆栈  uCOS 手机看文章 扫描二维码
随时随地手机看文章

本博文分为3部分,分别为启动代码篇,C堆栈篇,和STM32堆栈和uCOS堆栈区别篇.


***********************************************①启动代码篇***********************************************


前年毕业时,去了意法半导体工作,所以结识了STM32,先后学习了STM32和uCOS,在后边的学习中突然有了一个疑惑,就是堆栈的问题,在STM32的启动文件里定义的堆栈其实是很小的,但是,我写的uCOS程序其实占用了很大的堆栈空间,超过了启动代码中定义的堆栈大小,我们首先来看一下STM32的启动代码,这里以startup_stm32f10x_hd.s为例进行说明:


参考:https://www.cnblogs.com/afeibfp/archive/2013/01/08/2850408.html


;先在RAM中分配系统使用的栈,RAM的起始地址为0x2000_0000

;然后在RAM中分配变量使用的堆

;然后在CODE区(flash)分配中断向量表,flash的起始地址为0x0800_0000,该中断向量表就从这个起始地址开始分配

;分配完成后,再定义和实现相应的中断函数,

;所有的中断函数全部带有[weak]特性,即弱定义,如果编译器发现在别处文件中定义了同名函数,在链接时用别处的地址进行链接。

;中断函数仅仅实现了Reset_Handler,其他要么是死循环,要么仅仅定义了函数名称

 

;STM32被设置为从内部FLASH启动时(这也是最常见的一种情况),当STM32遇到复位信号后,

;从0x0800_0000处取出栈顶地址存放于MSP寄存器,从0x0800_0004处取出复位中断服务入口地址放入PC寄存器,

;继而执行复位中断服务程序Reset_Handler,

;Reset_Handler仅仅执行了两个函数调用,一个是SystemInit,另一个__main,

;SystemInit定义在system_stm32f10x.c中,主要初始化了STM的时钟系统:HSI,HSE,LSI,LSE,PLL,SYSCLK,USBCLK,APECLK等等.

;__main函数由编译器生成,负责初始化栈、堆等,并在最后跳转到用户自定义的main()函数,来到C的世界。

 

 

Stack_Size      EQU     0x00000400  ;//定义堆栈大小

                AREA    STACK, NOINIT, READWRITE, ALIGN=3  ;//定义一个数据段 按8字节对齐    ;AREA 伪指令用于定义一个代码段或数据段 NOINIT:指定此数据段仅仅保留了内存单元,而没有将各初始值写入内存单元,或者将各个内存单元值初始化为0

Stack_Mem       SPACE   Stack_Size    ;//保留Stack_Size大小的堆栈空间 分 配连续 Stack_Size 字节的存储单元并初始化为 0

__initial_sp  ;//标号,代表堆栈顶部地址,后面有用

                                                  

; // Heap Configuration

; //    Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>

; //

Heap_Size       EQU     0x00000200    ;//定义堆空间大小

                AREA    HEAP, NOINIT, READWRITE, ALIGN=3  ;//定义一个数据段,8字节对齐

__heap_base      ;//标号,代表堆末底部地址,后面有用

Heap_Mem        SPACE   Heap_Size     ;//保留Heap_Size的堆空间  

__heap_limit     ;//标号,代表堆界限地址,后面有用

    ;//PRESERVE8 指令指定当前文件保持堆栈八字节对齐。 它设置 PRES8 编译属性以通知链接器。

    ;//链接器检查要求堆栈八字节对齐的任何代码是否仅由保持堆栈八字节对齐的代码直接或间接地调用。

                PRESERVE8 ;//指示编译器8字节对齐

                THUMB   ;//指示编译器以后的指令为THUMB指令 

 

;中断向量表定义

; Vector Table Mapped to Address 0 at Reset

                AREA    RESET, DATA, READONLY   ;//定义只读数据段,其实放在CODE区,位于0地址

                EXPORT  __Vectors    ;//EXPORT:在程序中声明一个全局的标号__Vectors,该标号可在其他的文件中引用

                EXPORT  __Vectors_End

                EXPORT  __Vectors_Size

__Vectors       DCD     __initial_sp               ; //Top of Stack  ;给__initial_sp分配4字节32位的地址0x0

                DCD     Reset_Handler              ; //Reset Handler ; 给标号Reset Handler分配地址为0x00000004

                DCD     NMI_Handler                ; //NMI Handler ; 给标号NMI Handler分配地址0x00000008

                DCD     HardFault_Handler          ; //Hard Fault Handler

                DCD     MemManage_Handler          ; //MPU Fault Handler

                DCD     BusFault_Handler           ; //Bus Fault Handler

                DCD     UsageFault_Handler         ; //Usage Fault Handler

                DCD     0                          ; //Reserved  ; 这种形式就是保留地址,不给任何标号分配

                DCD     0                          ; //Reserved

                DCD     0                          ; //Reserved

                DCD     0                          ; //Reserved

                DCD     SVC_Handler                ; //SVCall Handler

                DCD     DebugMon_Handler           ; //Debug Monitor Handler

                DCD     0                          ; //Reserved

                DCD     PendSV_Handler             ; //PendSV Handler

                DCD     SysTick_Handler            ; //SysTick Handler

                ; External Interrupts

                DCD     WWDG_IRQHandler            ; //Window Watchdog

                DCD     PVD_IRQHandler             ; //PVD through EXTI Line detect

                DCD     TAMPER_IRQHandler          ; //Tamper

                DCD     RTC_IRQHandler             ; //RTC

                DCD     FLASH_IRQHandler           ; //Flash

                DCD     RCC_IRQHandler             ; //RCC

                DCD     EXTI0_IRQHandler           ; //EXTI Line 0

                DCD     EXTI1_IRQHandler           ; //EXTI Line 1

                DCD     EXTI2_IRQHandler           ; //EXTI Line 2

                DCD     EXTI3_IRQHandler           ; //EXTI Line 3

                DCD     EXTI4_IRQHandler           ; //EXTI Line 4

                DCD     DMA1_Channel1_IRQHandler   ; //DMA1 Channel 1

                DCD     DMA1_Channel2_IRQHandler   ; //DMA1 Channel 2

                DCD     DMA1_Channel3_IRQHandler   ; //DMA1 Channel 3

                DCD     DMA1_Channel4_IRQHandler   ; //DMA1 Channel 4

                DCD     DMA1_Channel5_IRQHandler   ; //DMA1 Channel 5

                DCD     DMA1_Channel6_IRQHandler   ; //DMA1 Channel 6

                DCD     DMA1_Channel7_IRQHandler   ; //DMA1 Channel 7

                DCD     ADC1_2_IRQHandler          ; //ADC1 & ADC2

                DCD     USB_HP_CAN1_TX_IRQHandler  ; //USB High Priority or CAN1 TX

                DCD     USB_LP_CAN1_RX0_IRQHandler ; //USB Low  Priority or CAN1 RX0

                DCD     CAN1_RX1_IRQHandler        ; //CAN1 RX1

                DCD     CAN1_SCE_IRQHandler        ; //CAN1 SCE

                DCD     EXTI9_5_IRQHandler         ; //EXTI Line 9..5

                DCD     TIM1_BRK_IRQHandler        ; //TIM1 Break

                DCD     TIM1_UP_IRQHandler         ; //TIM1 Update

                DCD     TIM1_TRG_COM_IRQHandler    ; //TIM1 Trigger and Commutation

                DCD     TIM1_CC_IRQHandler         ; //TIM1 Capture Compare

                DCD     TIM2_IRQHandler            ; //TIM2

[1] [2] [3] [4]
关键字:STM32  堆栈  uCOS 引用地址:浅谈STM32堆栈与uCOS堆栈,其实是两码事

上一篇:stm32 堆和栈(stm32 Heap & Stack)
下一篇:STM32-systick系统定时器

推荐阅读最新更新时间:2024-11-09 17:02

STM32的USARTx中u3_printf函数解析
我们在STM32中常常使用printf来将信息打印至PC端控制台上。但是有这样一种函数,它可以把数据以我们指定的格式装进字符串中——sprinft和vsprintf。 ⑴ sprintf函数使用的方式如下: ① 将多个参数以指定格式写入字符串 int a=1,b=2; char s ; sprintf(s, a=%d,b=%d ,1,2); puts(s); 输出结果:a=1,b=2 ② 错误使用:在函数封装中使用 void Myprintf(const char* fmt,...) // 传递个数不定的参数 { char s ; sprintf(s,fmt); // 出现错误 puts
[单片机]
<font color='red'>STM32</font>的USARTx中u3_printf函数解析
STM32--Error: L6218E: Undefined symbol
STM32编译时出现:..OBJKEY.axf: Error: L6218E: Undefined symbol IWDG_WriteAccessCmd (referred from wdg.o).错误原因: 没有将相应的库函数包含进去。 方法:Project--右键--Manage Project Items--在Groups选择对应文件夹--Files中添加需要的库文件
[单片机]
STM32 Part number information
STM32 Part number information 如果是STM32F105xx和STM32F107xx,是Connectivity Line Devices,则宏定义选择的是STM32F10X_CL;如果是别的型号,则根据FLASH的容量来进行选择。可能文字写的有点不太清楚,还是以表格来说明:
[单片机]
<font color='red'>STM32</font> Part number information
STM32】DMA—直接存储器存取(原理篇)
一、DMA是什么? 直接存储器存取(DMA)用来提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。无须CPU干预,数据可以通过DMA快速地移动,这就节省了CPU的资源来做其他操作。两个DMA控制器有12个通道(DMA1有7个通道,DMA2有5个通道),每个通道专门用来管理来自于一个或多个外设对存储器访问的请求。还有一个仲裁器来协调各个DMA请求的优先权。FLASH、SRAM、外设的SRAM、APB1、APB2和AHB外设均可作为访问的源和目标! 二、DMA的工作原理是什么? 1.DMA的工作流程分析 在发生一个事件后,外设向DMA控制器发送一个请求信号。DMA控制器根据通道的优先权处理请求。当DMA控制器开始
[单片机]
STMCU应用过程中与电源相关的案例分享
我们在从事STM32单片机的应用开发及调试过程中,往往会碰到各类异常。其中有不少比例的问题跟电源有关。对于一个电子产品而言,电源部分很关键、很重要,但在实际开发调试中,我们偶尔会有意无意的忽视它。这里分享几个实际案例,以加强刺激,加深印象。 毕竟因为电源问题可能导致的异常很多很多,这里分享几个案例算是抛砖引玉,希望大家在调试中对电源方面加以重视。个人认为,往往电源出问题时导致的异常时并不太好分析。多数时候异常表现得更为诡异或没章法。 注:下面提到的案例中异常原因都与电源有关,但并不是说出现类似异常时一定是电源的原因。 下面主要分享五个基于STM32应用的案例。 案例1:STM32芯片的PLL无法正常工作。 有人使用STM3
[单片机]
STMCU应用过程中与电源相关的案例分享
stm32最小系统组成及作用
最小系统是单片机工作时的最低要求,不包含外设控制,原理比较简单,下面我们一起来看看stm32最小系统组成及作用。 stm32最小系统上电之后,能够让单片机正常运转以及下载程序,没有其他的功能。 stm32最小系统是由电源、复位、时钟、调试/下载接口、启动组成的。 电源 stm32单片机一般都是3.3V供电,电容起到滤波的作用。 复位 STM32复位引脚是低电平复位,正常工作状态,复位引脚是高电平。复位方式一共有三种,分别为上电复位、手动复位、程序自动复位。 时钟 晶振+起振电容 +(反馈电阻MΩ级) 能够让晶振两端的等效电容等于或接近于负载电容,可以起到一定的滤波作用,让晶振波形中的高频杂波消除。 调试/下
[单片机]
STM32 基础系列教程 8 - 互补PWM
前言 PWM及互补PWM是电机控制的基础,前面我们已经学习了PWM的产生,今天来学习一下互补PWM的产生,互补PWM就是两个互补的PWM的组合,用stm32 的高级定时器可以直接产生两路互补的PWM(即互补PWM)。 示例详解 基于硬件平台: STM32F10C8T6最小系统板, MCU 的型号是 STM32F103c8t6, 使用stm32cubemx 工具自动产生的配置工程,使用KEIL5编译代码。 本示例所用的最小系统板原理图: 从本节开始,关于CUBEMX工具及KEIL工具的操作将不再细讲,如果还有不熟悉的可以查看之前的教程文档。下面直接介绍工程配置: 系统时钟树 高级定时器TIM1配置
[单片机]
<font color='red'>STM32</font> 基础系列教程 8 - 互补PWM
RT-Thread 自动初始化机制
自动初始化机制是指初始化函数不需要被显式调用,只需要在函数定义处通过宏定义的方式进行申明,就会在系统启动过程中被执行。 在RTT的代码中,有rt_components_init()和rt_components_board_init();两个函数,用于实现自动初始化机制。 RTT官方文档的系统启动流程图中,6种注册分别于上述两个函数中实现自动初始化。 两个初始化函数也很简单,就是调用从__rt_init_rti_board_start到__rt_init_rti_board_end的函数执行一遍;__rt_init_rti_board_end到__rt_init_rti_end的函数执行一遍。 /** * RT-Thr
[单片机]
RT-Thread 自动初始化机制
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
  • 学习ARM开发(16)
    ARM有很多东西要学习,那么中断,就肯定是需要学习的东西。自从CPU引入中断以来,才真正地进入多任务系统工作,并且大大提高了工作效率。采 ...
  • 学习ARM开发(17)
    因为嵌入式系统里全部要使用中断的,那么我的S3C44B0怎么样中断流程呢?那我就需要了解整个流程了。要深入了解,最好的方法,就是去写程序 ...
  • 学习ARM开发(18)
    上一次已经了解ARM的中断处理过程,并且可以设置中断函数,那么它这样就可以工作了吗?答案是否定的。因为S3C44B0还有好几个寄存器是控制中 ...
  • 嵌入式系统调试仿真工具
    嵌入式硬件系统设计出来后就要进行调试,不管是硬件调试还是软件调试或者程序固化,都需要用到调试仿真工具。 随着处理器新品种、新 ...
  • 最近困扰在心中的一个小疑问终于解惑了~~
    最近在驱动方面一直在概念上不能很好的理解 有时候结合别人写的一点usb的例子能有点感觉,但是因为arm体系里面没有像单片机那样直接讲解引脚 ...
  • 学习ARM开发(1)
  • 学习ARM开发(2)
  • 学习ARM开发(4)
  • 学习ARM开发(6)
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved