Cortex-M3学习调试之系统初始化

           在刚开始接触Cortex-M3的时候,对所有未知的东西都进行刨根问底的最后,从而达到从细节掌握知识要点。为了到到真正弄懂,所有决定从程序调试入手:


函数例程如下:

int main(void)
{
SystemInit();//系统初始化函数,由ST公司编写的库文件函数实现,所以我们进入该函数进行分析;
}

void SystemInit (void)
{
  RCC->CR |= (uint32_t)0x00000001;
}

  进入系统初始化函数后,我们看到的第一条语句,会觉得简单,然而具体实现了什么功能,不知道......所以继续跟踪如下....


#define RCC     ((RCC_TypeDef *) RCC_BASE)


对于以上一个宏定义:真正要明白该宏定义的含义,需要掌握以下三个方面的知识点:

预处理命令

    预处理的概念:在编译前的处理, 预处理命令以符号“#”开头。 C语言的预处理主要有三个方面的内容: 1.宏定义; 2.文件包含; 3.条件编译

宏定义

1.不带参数的宏定义:

如:#define 标识符 字符串;其中的标识符就是所谓的符号常量,也称为“宏名”。预处理(预编译)工作也叫做宏展开:将宏名替换为字符串。

说明:
(1)宏名一般用大写
(2)使用宏可提高程序的通用性和易读性,减少不一致性,减少输入错误和便于修改。例如: 数组大小常用 宏定义
(3)预处理是在编译之前的处理,而编译工作的任务之一就是语法检查,预处理不做语法检查。
(4) 宏定义末尾不加分号;
(5) 宏定义写在函数的花括号外边, 作用域为其后的程序,通常在文件的最开头。
(6)可以用#undef命令终止 宏定义作用域
(7) 宏定义可以嵌套
(8)字符串" "中永远不包含宏
(9) 宏定义不分配内存, 变量定义分配内存。

2、带参数的宏定义

#define 宏名(参数表) 字符串
例如: #define S(a,b) a*b
area=S(3,2);第一步被换为area=a*b; ,第二步被换为area=3*2;
类似于 函数调用,有一个哑实结合的过程:
(1) 实参如果是 表达式容易出问题
#define S(r) r*r
area=S(a+b);第一步换为area=r*r;,第二步被换为area=a+b*a+b;
正确的 宏定义#define S(r) (r)*(r)
(2)宏名和参数的括号间不能有空格
(3)宏替换只作替换,不做计算,不做 表达式求解
(4) 函数调用在编译后程序运行时进行,并且分配内存。宏替换在编译前进行,不分配内存
(5)宏的哑实结合不存在类型,也没有类型转换。
(6)函数只有一个返回值,利用宏则可以设法得到多个值
(7)宏展开使源程序变长, 函数调用不会
(8)宏展开不占运行时间,只占 编译时间函数调用占运行时间(分配内存、保留现场、值传递、返回值)
本文目前只涉及到了不带参数的宏定义,所以针对预处理部分就止于此吧,继续回到宏定义分析.....

类型转换

概念:在赋值和混合表达式中会出现隐式转化,除了隐式转换外,还有显示的转换成为类型转换。
其一般形式为: (类型说明符) ( 表达式 ) 其功能是把表达式的运算结果 强制转换 成类型说明符所表示的类型。
((RCC_TypeDef *) RCC_BASE)
在使用 强制转换时应注意以下问题:
1.类型说明符和 表达式都必须加括号(单个 变量可以不加括号),如把(int)(x+y)写成(int)x+y则成了把x转换成int型之后再与y相加了。
2.无论是 强制转换或是自动转换,都只是为了本次运算的需要而对 变量的数据长度进行的临时性转换,而不改变数据说明时对该 变量定义的类型。
在该表达式中RCC_BASE指向了0x4002 1000RCC寄存器的基地址空间:如下图所示:


所以可以知道该表达式实现了把RCC寄存器的基地址转换为RCC_TyoeDef *指针类型的数据类型。


用户自定义数据类型typedef

用途一:

定义一种类型的别名,而不只是简单的宏替换。可以用作同时声明指针型的多个对象。比如:

char* pa, pb; // 这多数不符合我们的意图,它只声明了一个指向字符变量的指针,

// 和一个字符变量;

以下则可行:

typedef char* PCHAR;

PCHAR pa, pb;  

这种用法很有用,特别是char* pa, pb的定义,初学者往往认为是定义了两个字符型指针,其实不是,而用typedef char* PCHAR就不会出现这样的问题,减少了错误的发生。

用途二:
      用在旧的C代码中,帮助struct。以前的代码中,声明struct新对象时,必须要带上
struct,即形式为: struct 结构名对象名,如:

struct tagPOINT1

 {
      int x;

    int y; 
};

struct tagPOINT1 p1;

而在C++中,则可以直接写:结构名对象名,即:tagPOINT1 p1;

typedef struct tagPOINT
{
    int x;

     int y;
}POINT;

POINT p1; // 这样就比原来的方式少写了一个struct,比较省事,尤其在大量使用的时候,或许,在C++中,typedef的这种用途二不是很大,但是理解了它,对掌握以前的旧代码还是有帮助的,毕竟我们在项目中有可能会遇到较早些年代遗留下来的代码。

用途三:

用typedef来定义与平台无关的类型。

比如定义一个叫 REAL 的浮点类型,在目标平台一上,让它表示最高精度的类型为:

typedef long double REAL;

在不支持 long double 的平台二上,改为:

typedef double REAL;

在连 double 都不支持的平台三上,改为:

typedef float REAL;

也就是说,当跨平台时,只要改下 typedef 本身就行,不用对其他源码做任何修改。

标准库就广泛使用了这个技巧,比如size_t。另外,因为typedef是定义了一种类型的新别名,不是简单的字符串替换,所以它比宏来得稳健。
     这个优点在我们写代码的过程中可以减少不少代码量哦!

用途四:

为复杂的声明定义一个新的简单的别名。方法是:在原来的声明里逐步用别名替换一部

分复杂声明,如此循环,把带变量名的部分留到最后替换,得到的就是原声明的最简化

版。举例: 

 原声明:void (*b[10]) (void (*)());

变量名为b,先替换右边部分括号里的,pFunParam为别名一:

typedef void (*pFunParam)();

再替换左边的变量b,pFunx为别名二:

typedef void (*pFunx)(pFunParam);

原声明的最简化版:

pFunx b[10];
 
      原声明:doube(*)() (*e)[9];

变量名为e,先替换左边部分,pFuny为别名一:

typedef double(*pFuny)();

再替换右边的变量e,pFunParamy为别名二

typedef pFuny (*pFunParamy)[9];

原声明的最简化版:

pFunParamy e;

理解复杂声明可用的“右左法则”:从变量名看起,先往右,再往左,碰到一个圆括号

就调转阅读的方向;括号内分析完就跳出括号,还是按先右后左的顺序,如此循环,直

到整个声明分析完。举例:

int (*func)(int *p);

首先找到变量名func,外面有一对圆括号,而且左边是一个*号,这说明func是一个指针

;然后跳出这个圆括号,先看右边,又遇到圆括号,这说明(*func)是一个函数,所以

func是一个指向这类函数的指针,即函数指针,这类函数具有int*类型的形参,返回值

类型是int。

int (*func[5])(int *);

func右边是一个[]运算符,说明func是具有5个元素的数组;func的左边有一个*,说明

func的元素是指针(注意这里的*不是修饰func,而是修饰func[5]的,原因是[]运算符

优先级比*高,func先跟[]结合)。跳出这个括号,看右边,又遇到圆括号,说明func数

组的元素是函数类型的指针,它指向的函数具有int*类型的形参,返回值类型为int。

这种用法是比较复杂的,出现的频率也不少,往往在看到这样的用法却不能理解,相信以上的解释能有所帮助。


在这里用到了用法二,源定义如下:

typedef struct
{
  __IO uint32_t CR; //_IO 是宏定义volatile,表示在程序运行中,该值是变化的。uint_32_t unsiged int型数据,即32位ARM 
  __IO uint32_t CFGR;
  __IO uint32_t CIR;
  __IO uint32_t APB2RSTR;
  __IO uint32_t APB1RSTR;
  __IO uint32_t AHBENR;
  __IO uint32_t APB2ENR;
  __IO uint32_t APB1ENR;
  __IO uint32_t BDCR;
  __IO uint32_t CSR;
#ifdef STM32F10X_CL  
  __IO uint32_t AHBRSTR;
  __IO uint32_t CFGR2;
#endif /* STM32F10X_CL */ 
} RCC_TypeDef;


到此 我们今晚要分析的第一个语句即将完成了,还差最后一步,通过查看STM32F10X的数据手册,如下:


可以看出实现RCC_RC寄存器的bit0位写1,即 使能内部高速时钟。Internal high-speed clock enable


至此,STM32F10X的System_init()函数就可以十分清楚的知道实现了什么功能了。











  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Cortex-M3中文手册是一本关于ARM架构中Cortex-M3处理器的详细说明书,它提供了有关该处理器的完整规格信息和相关应用指南,以帮助用户更好地理解和应用此处理器。 首先,Cortex-M3中文手册首先介绍了Cortex-M3处理器的基本特性,包括处理器的架构、指令集和寄存器架构等方面。这部分内容可以帮助用户了解处理器的工作原理和基本操作,为后续深入应用打下基础。 接着,手册详细描述了Cortex-M3处理器的内存管理单元(MMU)和保护机制。它介绍了如何配置和管理处理器的内部存储器和外部存储器,以及如何利用硬件保护机制确保系统的安全性和稳定性。 在应用方面,Cortex-M3中文手册提供了丰富的实例和案例,帮助用户了解如何在不同应用场景下使用Cortex-M3处理器。从简单的嵌入式系统到复杂的实时操作系统,手册中涵盖了各种常见的应用示例,包括数据处理、通信、控制和网络等领域。 此外,手册还提供了关于开发工具和调试技术的详细指导,帮助用户熟悉和掌握开发Cortex-M3处理器的工具和环境。它涵盖了开发软件、调试器和仿真器的使用方法,以及与其他外设和模块的集成。 总之,Cortex-M3中文手册是一本全面详细的说明书,它为用户提供了Cortex-M3处理器的基本知识和应用指导,帮助他们更好地理解和应用该处理器。无论是初学者还是有经验的开发者,都可以从中获得有用的参考和指导。 ### 回答2: Cortex-M3 中文手册是一本详细介绍 ARM 公司推出的 Cortex-M3 处理器的指南文档。Cortex-M3 是一种高性能、低功耗的嵌入式微控制器处理器,广泛应用于各种嵌入式系统中。 这本手册首先介绍了 Cortex-M3 处理器的基本架构和特性。Cortex-M3 采用了三级流水线结构,支持 Thumb-2 指令集,具有高效的指令执行能力和低功耗特性。手册详细介绍了 Cortex-M3 的寄存器组织、内存映射、异常处理、中断控制等方面的信息,帮助读者全面了解该处理器的体系结构。此外,手册还介绍了 Cortex-M3 处理器的电源管理、时钟控制、睡眠模式等低功耗特性的配置和使用方法。 Cortex-M3 中文手册还包含了大量关于 Cortex-M3 指令和编程模型的详细说明。它介绍了 Cortex-M3 的指令集特点、寻址模式、数据处理指令、控制指令等内容,帮助读者编写高效、可靠的嵌入式软件。手册还介绍了 Cortex-M3调试模式、断点功能等调试工具的使用方法,方便开发人员进行调试和测试。 此外,Cortex-M3 中文手册还深入介绍了 Cortex-M3 处理器的外设接口和功能模块。它详细描述了 GPIO、UART、SPI、I2C、定时器和中断控制器等外设的寄存器配置和使用方法,使读者能够充分发挥 Cortex-M3 处理器的扩展能力。 综上所述,Cortex-M3 中文手册是一本全面介绍 Cortex-M3 处理器体系结构、指令集和外设接口的指南文档。它对于嵌入式系统开发人员深入了解和应用 Cortex-M3 处理器具有重要的参考价值。 ### 回答3: Cortex-M3中文手册是一份详细介绍Cortex-M3微控制器架构和相关功能的文档。Cortex-M3ARM公司推出的一种广泛应用于嵌入式系统的32位内核处理器。 首先,Cortex-M3中文手册包含了对Cortex-M3架构的全面描述。它详细介绍了Cortex-M3内核的工作原理,包括指令集、寄存器和存储管理单元等关键组件。通过阅读手册,用户可以了解Cortex-M3如何处理指令,管理内存和访问外设。 其次,手册还介绍了Cortex-M3的特性和功能。它包括了对Cortex-M3内核的低功耗设计和高性能特性的说明,例如睡眠模式、中断处理和内核片上总线等。此外,手册还介绍了Cortex-M3支持的外设和调试接口。 此外,Cortex-M3中文手册还提供了一系列例程和代码片段,用于说明如何使用Cortex-M3进行编程和开发。示例代码可以帮助用户理解如何配置和初始化Cortex-M3的各种外设,并展示如何编写程序来实现不同的功能。 总的来说,Cortex-M3中文手册是一本重要的参考资料,对于开发者和嵌入式系统工程师而言至关重要。通过阅读手册,用户可以全面了解Cortex-M3的架构和功能,掌握使用Cortex-M3进行编程和开发的技术。这将有助于他们更好地利用Cortex-M3的强大功能,设计和开发高性能的嵌入式系统

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值