F0存储器映射和启动文件分析,使用cubmax创建第一个工程

目录

一、STM32cubMax

二、F0存储器映射

三、启动文件


一、STM32cubMax

直观的选择STM32微控制器
微控制器图形化配置
–自动处理引脚冲突
–动态设置确定的时钟树
–可以动态确定参数设置的外围和中间件模式和初始化
–功耗预测
C代码工程生成器覆盖了STM32微控制器初始化编译软件,如IAR,KEIL,GCC可以独立使用,作为Eclipse插件使用

 现在新的32已经不支持标准库开发了,所以我决定学习cubmax导出hal库来开发32的方式。

官网地址: http://www.st.com/en/development-tools/stm32cubemx.html

l  安装JAVA运行环境,JavaSetup8u151.exe
l  解压stm32cubemx.zip,安装SetupSTM32CubeMX-4.22.0.exe,最好不要有中文路径
l  解压stm32cube_fw_f0_v180.zip到STM32CubeMX的安装路径中

 new project

选用的就行,我选个主流的便宜的c8t6

点这个产生源码

 

 

 

 翻译了一下

 生成后打开

二、F0存储器映射

 

注:被控单元的FLASHRAMAHBAPB的桥(即片上外设),这些功能部件共同排列在一个 4GB 的地址空间内。我们在编程的时候,可以通过他们的地址找到他们,然后来操作他们 

l  存储器本身没有地址,给存储器分配地址的过程叫存储器映射

32其实也是一款SOC,把CPU和外设集成到一块芯片中,这个东西就是片上系统。

 

l § 可寻址 4GB 字节空间
l § 多达 64KB 片上闪存
l § 多达 8K SRAM

GPIOA寄存器组为例、如何读写ODR寄存器?

以知GPIOA的起始地址为0x48000000

各寄存器的偏移地址如下:

MODER;           /*Address offset: 0x00 */

OTYPER;   /*Address offset: 0x04 */

OSPEEDR;   /*Address offset: 0x08 */

PUPDR;    /*Address offset: 0x0C */

IDR;   /*Address offset: 0x10 */

ODR;   /*Address offset: 0x14 */

BSRR;   /*Address offset: 0x18 */

LCKR;   /*Address offset: 0x1C */

 

 对地址进行宏定义

l

#define     GPIOA_BASE        ( (unsigned int ) 0x48000000 )

#define     GPIOA_ODR         ( GPIOA_BASE  +  0x14 )

读操作

val  = *(unsigned int *) GPIOA_ODR  ;

写操作

*(unsigned int *)  GPIOA_ODR = val  ;

  改进

#define     GPIOA_ODR    *(unsigned int *) ( GPIOA_BASE  +  0x14 )

val  = GPIOA_ODR  ;    //

GPIOA_ODR = val  ;     //

       用上面的方法去定义地址,还是稍显繁琐、根据我们每一类外设对应的寄存器组地址都是连续增长的特点,我们引入 C 语言中的结构体语法对寄存器进行封装、

    typedef struct {
uint32_t		MODER;        	 /*Address offset: 0x00 */
uint32_t		OTYPER; 	/*Address offset: 0x04 */
uint32_t		OSPEEDR; 	/*Address offset: 0x08 */
uint32_t		PUPDR;	 	/*Address offset: 0x0C */
uint32_t		IDR; 		/*Address offset: 0x10 */
uint32_t		ODR; 		/*Address offset: 0x14 */
uint32_t		BSRR; 		/*Address offset: 0x18 */
uint32_t		LCKR; 		/*Address offset: 0x1C */
} GPIO_TypeDef;

#define     GPIOA_BASE        ( (unsigned int ) 0x48000000 )
#define     GPIOA	 ((GPIO_TypeDef *) GPIOA_BASE)

很眼熟吧,裸机开发4412的时候就是这样写的。其实所有的裸机开发都是这种方式,可能不绝对,但是我玩过三款51,好多款32,和一款A9都是这样开发的。但是裸机开发对于功能丰富的SOC很不友好,于是就有了各种库。 

注:我们访问GPIOA的控制寄存器组时、直接使用宏定义好 GPIO_TypeDef 类型的指针,而且指针指向 GPIOA端口的首地址,这样我们直接用宏GPIOA访问改外设的任意一个寄存器

GPIOA->MODER     =  0x20 ;

GPIOA->OSPEEDR  =  0x16 ;

因为时钟的频率不一样所以需要不同的总线,同速的外设挂载到一条总线上

我们的cpu和外设交互需要一个仲裁,这个仲裁我感觉就类似于之前学习驱动时的那种总线控制器

只是这里是利用总线矩阵来仲裁

三、启动文件

注:Cortex-M0 的程序映像通常是从地址 0x00000000 开始的、系统复位后,处理器首先读取向量表中的前两个字(8 个字节),第一个字存入 MSP,第二个字为复位向量,它表示程序执行的起始地址(复位处理)

 

我们的主闪存其实就是Flash 

系统存储器里是厂家内置的bootloader(ISP)

根据启动模式的不同,用户闪存、系统闪存和SRAM都

可以映射到0x0的低端地址;

我们的板子boot0直接接地,因此启动区域为flash启动

注:

       栈的作用是用于局部变量,函数调用,函数形参等的开销

       堆主要用来动态内存的分配

;******************** (C) COPYRIGHT 2016 STMicroelectronics ********************
;* File Name          : startup_stm32f051x8.s
;* Author             : MCD Application Team
;* Description        : STM32F051x4/STM32F051x6/STM32F051x8 devices vector table for MDK-ARM toolchain.
;*                      This module performs:
;*                      - Set the initial SP
;*                      - Set the initial PC == Reset_Handler
;*                      - Set the vector table entries with the exceptions ISR address
;*                      - Branches to __main in the C library (which eventually
;*                        calls main()).
;*                      After Reset the CortexM0 processor is in Thread mode,
;*                      priority is Privileged, and the Stack is set to Main.
;* <<< Use Configuration Wizard in Context Menu >>>
;*******************************************************************************
;*
;* Redistribution and use in source and binary forms, with or without modification,
;* are permitted provided that the following conditions are met:
;*   1. Redistributions of source code must retain the above copyright notice,
;*      this list of conditions and the following disclaimer.
;*   2. Redistributions in binary form must reproduce the above copyright notice,
;*      this list of conditions and the following disclaimer in the documentation
;*      and/or other materials provided with the distribution.
;*   3. Neither the name of STMicroelectronics nor the names of its contributors
;*      may be used to endorse or promote products derived from this software
;*      without specific prior written permission.
;*
;* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
;* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
;* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
;* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
;* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
;* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
;* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
;* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
;* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
;* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
;
;*******************************************************************************

; Amount of memory (in bytes) allocated for Stack
; Tailor this value to your application needs
; <h> Stack Configuration
;   <o> Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>
; </h>

Stack_Size	 EQU     0x400									;定义栈的大小1K

                AREA    STACK, NOINIT, READWRITE, ALIGN=3	;AREA 是定义一个段,此处定义的是栈段,没有初始化的段,可读可写,align是说段的起始地址应该是8的倍数
Stack_Mem       SPACE   Stack_Size							;SPACE 是为栈分配空间,开辟栈空间大小为0x400
__initial_sp												;__initial_sp是个标号,这个标号指向栈的栈顶


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

Heap_Size      EQU     0x200								;定义堆的大小 512B

                AREA    HEAP, NOINIT, READWRITE, ALIGN=3
__heap_base													;堆的起始地址
Heap_Mem        SPACE   Heap_Size							;堆的大小
__heap_limit												;堆的结束地址

                PRESERVE8
                THUMB


; Vector Table Mapped to Address 0 at Reset
                AREA    RESET, DATA, READONLY		;此处定义的数据段,数据段放的是中断向量表,只读
                EXPORT  __Vectors					;EXPORT在程序中声明一个全局的标号__Vectors,该标号可在其它的文件中引用
                EXPORT  __Vectors_End
                EXPORT  __Vectors_Size
											;DCD指令以字为单位分配内存,要求4字节对齐,并要求初始化这些内存。
											;在向量表中,DCD 分配了一堆内存,并且以 ESR 的入口地址初始化它们。
												
												
__Vectors       DCD     __initial_sp                   ; Top of Stack    存放__initial_sp,也就是堆栈栈顶的地址
                DCD     Reset_Handler                  ; Reset Handler
                DCD     NMI_Handler                    ; NMI Handler
                DCD     HardFault_Handler              ; Hard Fault Handler
                DCD     0                              ; Reserved
                DCD     0                              ; Reserved
                DCD     0                              ; Reserved
                DCD     0                              ; Reserved
                DCD     0                              ; Reserved
                DCD     0                              ; Reserved
                DCD     0                              ; Reserved
                DCD     SVC_Handler                    ; SVCall Handler
                DCD     0                              ; Reserved
                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     RTC_IRQHandler                 ; RTC through EXTI Line
                DCD     FLASH_IRQHandler               ; FLASH
                DCD     RCC_IRQHandler                 ; RCC
                DCD     EXTI0_1_IRQHandler             ; EXTI Line 0 and 1
                DCD     EXTI2_3_IRQHandler             ; EXTI Line 2 and 3
                DCD     EXTI4_15_IRQHandler            ; EXTI Line 4 to 15
                DCD     TSC_IRQHandler                 ; TS
                DCD     DMA1_Channel1_IRQHandler       ; DMA1 Channel 1
                DCD     DMA1_Channel2_3_IRQHandler     ; DMA1 Channel 2 and Channel 3
                DCD     DMA1_Channel4_5_IRQHandler     ; DMA1 Channel 4 and Channel 5
                DCD     ADC1_COMP_IRQHandler           ; ADC1, COMP1 and COMP2 
                DCD     TIM1_BRK_UP_TRG_COM_IRQHandler ; TIM1 Break, Update, Trigger and Commutation
                DCD     TIM1_CC_IRQHandler             ; TIM1 Capture Compare
                DCD     TIM2_IRQHandler                ; TIM2
                DCD     TIM3_IRQHandler                ; TIM3
                DCD     TIM6_DAC_IRQHandler            ; TIM6 and DAC
                DCD     0                              ; Reserved
                DCD     TIM14_IRQHandler               ; TIM14
                DCD     TIM15_IRQHandler               ; TIM15
                DCD     TIM16_IRQHandler               ; TIM16
                DCD     TIM17_IRQHandler               ; TIM17
                DCD     I2C1_IRQHandler                ; I2C1
                DCD     I2C2_IRQHandler                ; I2C2
                DCD     SPI1_IRQHandler                ; SPI1
                DCD     SPI2_IRQHandler                ; SPI2
                DCD     USART1_IRQHandler              ; USART1
                DCD     USART2_IRQHandler              ; USART2
                DCD     0                              ; Reserved
                DCD     CEC_IRQHandler                 ; CEC

__Vectors_End

__Vectors_Size  EQU  __Vectors_End - __Vectors

                AREA    |.text|, CODE, READONLY		 ;text  一般代表代码段

; Reset handler routine
Reset_Handler    PROC
                 EXPORT  Reset_Handler                 [WEAK]     ;“[WEAK]”是一个弱符号声明,就是告诉编译器,我这里声明的标号的优先权低于其它同名的标号,也就是说如果在工程中还有别的函数和我同名,那么你就调用和我同名的其它函数,如果没有同名的,那你就调用我。
        IMPORT  __main									 ;IMPORT则表明后面标号所代表的函数是调用其它文件的
        IMPORT  SystemInit  
                 LDR     R0, =SystemInit			;复位子程序是系统上电后第一个执行的程序,调用 SystemInit 函数初始化系统时钟
                 BLX     R0
                 LDR     R0, =__main                   ;__main 是一个标准的 C 库函数,主要作用是初始化用户堆栈,并在函数的最后调用main 函数去到 C 的世界
                 BX      R0
                 ENDP

; Dummy Exception Handlers (infinite loops which can be modified)

NMI_Handler     PROC
                EXPORT  NMI_Handler                    [WEAK]  
                B       .
                ENDP
HardFault_Handler\
                PROC
                EXPORT  HardFault_Handler              [WEAK]
                B       .
                ENDP
SVC_Handler     PROC
                EXPORT  SVC_Handler                    [WEAK]
                B       .
                ENDP
PendSV_Handler  PROC
                EXPORT  PendSV_Handler                 [WEAK]
                B       .
                ENDP
SysTick_Handler PROC
                EXPORT  SysTick_Handler                [WEAK]
                B       .
                ENDP

Default_Handler PROC

                EXPORT  WWDG_IRQHandler                [WEAK]
                EXPORT  PVD_IRQHandler                 [WEAK]
                EXPORT  RTC_IRQHandler                 [WEAK]
                EXPORT  FLASH_IRQHandler               [WEAK]
                EXPORT  RCC_IRQHandler                 [WEAK]
                EXPORT  EXTI0_1_IRQHandler             [WEAK]
                EXPORT  EXTI2_3_IRQHandler             [WEAK]
                EXPORT  EXTI4_15_IRQHandler            [WEAK]
                EXPORT  TSC_IRQHandler                 [WEAK]
                EXPORT  DMA1_Channel1_IRQHandler       [WEAK]
                EXPORT  DMA1_Channel2_3_IRQHandler     [WEAK]
                EXPORT  DMA1_Channel4_5_IRQHandler     [WEAK]
                EXPORT  ADC1_COMP_IRQHandler           [WEAK]
                EXPORT  TIM1_BRK_UP_TRG_COM_IRQHandler [WEAK]
                EXPORT  TIM1_CC_IRQHandler             [WEAK]
                EXPORT  TIM2_IRQHandler                [WEAK]
                EXPORT  TIM3_IRQHandler                [WEAK]
                EXPORT  TIM6_DAC_IRQHandler            [WEAK]
                EXPORT  TIM14_IRQHandler               [WEAK]
                EXPORT  TIM15_IRQHandler               [WEAK]
                EXPORT  TIM16_IRQHandler               [WEAK]
                EXPORT  TIM17_IRQHandler               [WEAK]
                EXPORT  I2C1_IRQHandler                [WEAK]
                EXPORT  I2C2_IRQHandler                [WEAK]
                EXPORT  SPI1_IRQHandler                [WEAK]
                EXPORT  SPI2_IRQHandler                [WEAK]
                EXPORT  USART1_IRQHandler              [WEAK]
                EXPORT  USART2_IRQHandler              [WEAK]
                EXPORT  CEC_IRQHandler                 [WEAK]


WWDG_IRQHandler
PVD_IRQHandler
RTC_IRQHandler
FLASH_IRQHandler
RCC_IRQHandler
EXTI0_1_IRQHandler
EXTI2_3_IRQHandler
EXTI4_15_IRQHandler
TSC_IRQHandler
DMA1_Channel1_IRQHandler
DMA1_Channel2_3_IRQHandler
DMA1_Channel4_5_IRQHandler
ADC1_COMP_IRQHandler
TIM1_BRK_UP_TRG_COM_IRQHandler
TIM1_CC_IRQHandler
TIM2_IRQHandler
TIM3_IRQHandler
TIM6_DAC_IRQHandler
TIM14_IRQHandler
TIM15_IRQHandler
TIM16_IRQHandler
TIM17_IRQHandler
I2C1_IRQHandler
I2C2_IRQHandler
SPI1_IRQHandler
SPI2_IRQHandler
USART1_IRQHandler
USART2_IRQHandler
CEC_IRQHandler

                B       .

                ENDP

                ALIGN

;*******************************************************************************
; User Stack and Heap initialization
;*******************************************************************************
                 IF      :DEF:__MICROLIB       ;检查是否定义了__MICROLIB,如果定义了则条件成立。用户可以在配置软件中勾选。
									  ;用户栈和堆初始化,由C库函数_main来完成
                 EXPORT  __initial_sp		  ;栈顶地址
                 EXPORT  __heap_base		  ;堆起始地址
                 EXPORT  __heap_limit          ;堆结束地址

                 ELSE					

                 IMPORT  __use_two_region_memory 	  
                 EXPORT  __user_initial_stackheap   ;用户自己来初始化堆栈

__user_initial_stackheap

                 LDR     R0, =  Heap_Mem
                 LDR     R1, = (Stack_Mem + Stack_Size)
                 LDR     R2, = (Heap_Mem +  Heap_Size)
                 LDR     R3, =  Stack_Mem
                 BX      LR

                 ALIGN

                 ENDIF

                 END

;************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE*****

其实32的启动文件都大同小异

先分配栈空间,这里是可读可写1KB,和8内存对齐

分配完栈指针在顶部,随着使用逐步往下走

然后分配了一个512k的堆

分配了一篇只读的空间,是我们的数据段,里面都是向量表

DCD是分配一个字的空间四个字节

复位子程序是系统上电后第一个执行的程序,调用 SystemInit 函数初始化系统时钟

;__main 是一个标准的 C 库函数,主要作用是初始化用户堆栈,并在函数的最后调用main 函数去到 C 的世界

这个微型C库我们一般都是勾选的

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

宇努力学习

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值