当前位置:网站首页>【RTOS训练营】站在更高的角度学习C语言
【RTOS训练营】站在更高的角度学习C语言
2022-07-26 00:38:00 【韦东山】
一. 前言
C语言基础,有些同学基础扎实,有同学能用但是理解不深,这个训练营的重点在于RTOS和芯片架构,对C语言的要求也不算高. 结构体、指针、链表,掌握这三点就可以,基本不涉及复杂的语法,基础弱的同学,可以看唐老师的C语言视频,免费的。
我们并不需要停下来单独去学习C语言,C语言可以在RTOS的学习过程中再慢慢精进,不用担心。
唐老师的C语言课程在我们官网(www.100ask.net):
现在,我们一起来站在更高角度学习C语言
二. 代码引入
int a;
volatile unsigned int *p;
void main()
{
a = 123;
p = (volatile unsigned int *)(0x40010800 + 0x0c); /* GPIOA_ODR寄存器的地址 */
*p = 1;
}
1. 从这段代码可以引出几个问题:
①这段代码涉及哪些硬件?
- Flash、RAM、GPIO、CPU
②程序保存在哪里?
- Flash
③变量a、p保存在哪里?
- RAM
④操作p时,操作哪里?
- GPIO
⑤谁来执行这个程序?
- CPU
- 硬件方面,至少涉及这4部分:Flash、RAM、GPIO、CPU。
1.1 大家先看这个动图(图中的地址是假设的):

2. 全局变量a、p:
int a;
volatile unsigned int *p;
这两行代码,会在RAM中分配空间给这2个变量(图中的地址是假设的)
变量a、p的地址,你是控制不了的,编译器分配的地址
3. 执行main函数的代码:a = 123;是怎么进行的呢?
代码保存在Flash;
CPU读取Flash得到代码;
CPU根据代码指示,写变量a;
4. p = (volatile unsigned int *)(0x40010800 + 0x0c);的执行
代码保存在Flash;
CPU读取Flash得到代码;
CPU根据代码指示,写变量p;
执行完下面两行代码后:
a = 123;
p = (volatile unsigned int *)(0x40010800 + 0x0c); /* GPIOA_ODR寄存器的地址 */
内存情况如下图(图中的地址是假设的):

大家可以看到:
假设CPU将地址
0x2000 0000分配给了a,0x2000 1000分配给了p;对变量a和变量p的写操作都是在写RAM(在STM32F103中地址
0x2000 0000开始的一片内存是映射的是RAM空间);当对变量a进行赋值时,CPU就在a所在的地址空间 ,即从地址
0x2000 0000开始的一小段空间(根据a的类型和cpu的位数决定a占用多少长度的空间)写入数据;对于变量p的写操作也是类似的;
执行那两行代码a = 123;``p = (volatile unsigned int *)(0x40010800 + 0x0c);的结果就是:
在RAM地址0x2000 0000处写入了一个数据是123;
在RAM地址0x2000 1000处写入了一个数据是
(0x40010800 + 0x0c)即0x4001 080C;又根据指针的定义, 我们对
p = (volatile unsigned int *)(0x40010800 + 0x0c);这个操作就得到了一个信息: 指针p指向的地址是0x4001 080C。
5. *p = 1
*p = 1;
我们刚才已经知道, 指针p指向的地址是0x4001 080C,所以这一行代码的作用就是让CPU在p指向的地址写入一个数据1,即在地址0x4001 080C处写入数据1。我们在前面以STM32F103的内存空间举例得知地址0x2000 0000开始的一片内存映射的是RAM空间,那么地址0x4001 080C也是RAM空间嘛?不是的。根据STM32的手册我们可以发现地址0x4001 080C处映射的其实是STM32F103的引脚GPIOA(GPIO:通用输入输出)的输出寄存器ODR。
也就是说, *p = 1就是让地址0x4001 080C保存的数据变成了1,对于STM32F103而言,完成的功能就是让GPIOA的寄存器ODR的最低位bit0 = 1,最终表现出来的结果我们放在后面的课程说。
在整个过程中,最重要的是:地址
CPU读Flash得到指令
- 怎么读Flash?用地址
- 得到什么?得到指令,也就是Flash上的数据

CPU这个大爷,向外面发出地址,读到Flash上的数据。这些数据就是指令,然后CPU执行指令
6. 深入CPU的指令执行
6.1 指令a = 123?
怎么写变量a?用地址
做了什么?把数值123写到了内存里

6.2 指令p = (volatile unsigned int *)(0x40010800 + 0x0c)
CPU得到这条指令后,怎么执行?
- 怎么写变量p?用地址
- 做了什么?把数值0x4001080c写到了内存里
6.3 指令*p = 1
CPU得到这条指令后,怎么执行?
- 怎么写GPIO寄存器?用地址;
- 做了什么?把数值1写到了地址0x4001080c上,就是写到了GPIOA_ODR寄存器,导致LED变亮或熄灭;

7. 程序核心
这个程序的核心是什么?写地址!
最核心是什么:地址!
我们以葫芦娃举例:
这位大爷,怎么使唤葫芦娃?
- 叫名字, 7个葫芦娃都编号1234567;
- 使唤
在电子系统中,CPU也是大爷,外面的RAM、GPIO、Flash就是儿子。CPU要访问RAM、GPIO、Flash,也要先点名:发出地址:
7.1 地址和内存
RAM很大,CPU读写数据时,是不是要发出地址给RAM,再收发数据?假设我们有个这样的硬件框图:
我们说RAM、GPIO、Flash,是兄弟,是平等的,都给CPU大爷使唤,那么CPU大爷是如何访问这多个平等关系的设备的呢?
大家看,设备1、设备2都需要地址线,都需要数据线。CPU大爷发出地址,同时到达设备1、设备2;CPU大爷发出数据,同时到达设备1,设备2;那么问题来了:这数据给谁的啊?
所以,这些连线不够!还需要一个叫做片选信号的信号线和一个内存管理器,如图所示:
CPU大爷,和它的儿子之间,需要插入一个传话人,这个传话人叫:内存管理器/内存控制器。因为RAM、GPIO、FLASH都是同类的设备,都有地址,都能读、写。都 “类似” 内存。假设设备1的地址范围是XXX-YYY,假设设备2的地址范围是AAA-BBB,访问它们的过程是这样的:
- CPU大爷发出地址 addr;
- 内存管理器/内存控制器发现addr 处于 XXX-YYY之间,就知道了,哦,你要访问设备1;
- 内存管理器/内存控制器就把cs1设置为有效值,表示说:CPU大爷选中你了;同时,cs2保持无效值,也就是设备2没被选中,设备2就保持沉默;
- 所以,CPU发出的addr、数据,只会影响到设备1
根源在于:传话人,根据大爷发出的地址,判断要访问哪个设备,就去选中设备。地址!地址!地址!非常重要!
7.2 深入地址
什么叫地址?
在一栋安居房里,政府故意把房子设计得很小,每个房间都是单独的。
- 单身汉只有1房:
char c; - 夫妻有2房:
short a; - 有娃的家庭有4房:
int b; - 大家庭有8房:
char buf[8];
变量在内存哪个位置?我们一般无法决定,链接时确定的。
每个单间,都有一个地址。char c;占据一个字节,有一个地址;short a;占据2字节,有2个地址值;int b;占据4字节,有4个地址值;但是,我们去拜访这些居民时,只使用一个地址:首地址。
在同一栋楼里,大家的地址都是类似的:XX街道XXX小区XXX栋XXX房。在C语言里,就是:char, short, int, struct 、字符串,它们的首地址都是类似的:位数都一样。对于32位CPU,地址都是32位的。用一段伪代码来表示的话,就是这样一个结果:
边栏推荐
- 【RTOS训练营】GPIO知识和预习安排 + 晚课提问
- 独家下载|《阿里云MaxCompute百问百答》 解锁SaaS模式云数据仓库尽在本电子手册!
- 【RTOS训练营】课程学习方法和结构体知识复习 + 链表知识
- Getting started with D3D calculation shaders
- ZABBIX monitoring host and resource alarm
- 数据库工具对决:HeidiSQL 与 Navicat
- [oops framework] interface management
- jupyter更改主界面并且导入数据集
- Hcip day 11
- 2022/7/25 exam summary
猜你喜欢

独家下载|《阿里云MaxCompute百问百答》 解锁SaaS模式云数据仓库尽在本电子手册!
![[RTOS training camp] ring buffer, at instruction, preview arrangement and evening class questions](/img/cb/de38e9f4186c4392ef8832659422ff.jpg)
[RTOS training camp] ring buffer, at instruction, preview arrangement and evening class questions
![[zero based BLDC series] brushless DC motor control principle based on the zero crossing detection method of back EMF](/img/1d/00165635452245a4d1b557fba17c94.png)
[zero based BLDC series] brushless DC motor control principle based on the zero crossing detection method of back EMF

What is the difference between request forwarding and request redirection?

分布式事务和Seata的AT模式原理

ZABBIX monitoring host and resource alarm

Jmeter之用户自定义变量和抽离公共变量

南姐的糗事

HCIP第十三天

109. Upload local files using SAP ui5 fileuploader control
随机推荐
Hcip - republish
ASP. Net core configuration
开放下载!《阿里巴巴 DevOps 实践手册》
参数解析器HandlerMethodArgumentResolver分析与实战
【MATLAB appdesigner】27_ How to debug and view variables in appdesigner? (examples + skills)
Travel + strategy accelerated landing, jietu new product matrix exposure
Leetcode notes 121. the best time to buy and sell stocks
2022/7/19 exam summary
【RTOS训练营】作业讲解、队列和环形缓冲区、队列——传输数据、队列——同步任务和晚课提问
D3D计算着色器入门
Tarjan finds the strongly connected component o (n+m), shrinking point
Using questpdf operation to generate PDF is faster and more efficient!
[RTOS training camp] ring buffer, at instruction, preview arrangement and evening class questions
JDBC实现MySQL8.0数据库的增删改查
【IJCAI 2022】参数高效的大模型稀疏训练方法,大幅减少稀疏训练所需资源
pip install --upgrade can‘t find Rust compiler
[array creation in numpy]
[IJCAI 2022] parameter efficient large model sparse training method, which greatly reduces the resources required for sparse training
109. Upload local files using SAP ui5 fileuploader control
P4047 [jsoi2010] tribal Division