我正在学习嵌入式 C 编程教程,然后意识到使用指针指向变量,然后使用它来取消引用可以使程序更快!
我有汇编的基本知识,但我不明白为什么将变量的地址分配给指针会更快,我们不是在谈论按引用或按指针或按值传递!
据我所知,
R0,就像带有指针的代码中发生的情况一样。p_int寄存器的别名R0,这如何帮助使程序更快?不使用指针的代码:
int counter = 0;
int main() {
while (counter < 6) {
++(counter);
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
相反,下面是带有指针的代码:
int counter = 0;
int main() {
int *p;
p = &counter;
while (*p < 6) {
++(*p);
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我联系了课程创建者,他很友善地为我重播并分解了它,为了帮助其他可能遇到同样问题的人,我将留下问题和答案
为了访问内存中的变量,CPU 需要该变量在寄存器之一中的地址。在最低级别的代码优化中,编译器在每次访问变量之前从代码存储器加载该地址。指针加快了速度,因为作为 main() 函数内的局部变量被分配到寄存器。这意味着该地址位于寄存器中(在本例中为 R0),不需要每次都加载并重新加载到寄存器中。在更高级别的优化下,编译器会生成更合理的代码,并且不带指针的代码与带指针的代码一样快。--彩信
我们正在使用 STM32F429I 并尝试通过不同的方式使用定时器(TIM2 和 TIM5)。在我们的代码中启用计时器并调用后;
HAL_TIM_Base_Start_IT(&htim5);
Run Code Online (Sandbox Code Playgroud)
我们可以通过调用TIM5_IRQHandler函数来更新变量。我们注意到HAL_TIM_PeriodElapsedCallback函数已完成相同的过程。
那么我们的问题是:这两个函数有什么区别吗?
我正在研究 esp32 MQTT。当我从云向微控制器发布消息时,我收到了一条基于 msg 程序的 MQTT 消息,在处理完成后,我使用 MQTT 发送确认。发送确认后,esp 崩溃了。所以我想知道这个错误是什么意思?我收到错误的可能原因是什么?
DEBUG: [mqtt.c:800:handleMqttPayload] ------------------------>line
DEBUG: [mqtt.c:472:_mqttSubscriptionCallback] ------------------------>line
Guru Meditation Error: Core 0 panic'ed (LoadProhibited). Exception was unhandled.
Core 0 register dump:
PC : 0x400957b6 PS : 0x00060933 A0 : 0x80085160 A1 : 0x3ffe2120
0x400957b6: is_free at /home/horsemann/Desktop/WorkSpace/TestingRepo/vendors/espressif/esp-idf/components/heap/multi_heap.c:380
(inlined by) multi_heap_malloc_impl at /home/horsemann/Desktop/WorkSpace/TestingRepo/vendors/espressif/esp-idf/components/heap/multi_heap.c:432
A2 : 0x3ffb9a20 A3 : 0x00000074 A4 : 0x3ffb9bc2 A5 : 0x3ffc24f4
A6 : 0x00000000 A7 : 0x3ffc1930 A8 : 0x62df42e6 A9 : 0x00003ffb
A10 : 0x00000001 A11 : …Run Code Online (Sandbox Code Playgroud) 在嵌入式系统中,挥发性用于让编译器不修改/优化变量,但是对于局部变量使用挥发性的意义是什么,当用于全局变量时它驻留在数据段中,如果用于局部变量的目的是什么它会在堆栈中吗?
我觉得这个问题可能有点蠢。。
由于我们存储位来指示数字,并且由于我们拥有整个 RAM,因此我们应该能够拥有一个无限大小(实际上是自定义大小)的数字,该数字可以占用整个 RAM(或其指定部分) )。
正确的?
例如,如果我们这样做:
mov ax, 0xFFFF
add ax, 1
jc custom_function ; if I remember correctly jc checks the carry flag
Run Code Online (Sandbox Code Playgroud)
custom_function 是一个标签/函数,它具有一种算法来设置下一个位以创建无限大小的数字。
问题
这可能吗?如果不是无限大小的数字,则指定自定义(比默认值更长或更短)
我怀疑,如果可能的话,它的性能会很差(即使数量更短)。你怎么认为?
你认为拥有这样的东西会很好吗?(也许在内存有限的旧系统或嵌入式系统中这会更有效?)
下面的代码没有给出正确的输出。
#include <stdio.h>
#define PI 22/7
#define AREA(r) PI * r * r
int main() {
printf("Pi: %d\n", PI);
printf("Area: %d\n", AREA(8));
return 0;
}
Run Code Online (Sandbox Code Playgroud)
而下面的代码给出了正确的(最接近的)输出。
#include <stdio.h>
#define PI 22/7
#define AREA(r) r * r * PI
int main() {
printf("Pi: %d\n", PI);
printf("Area: %d\n", AREA(8));
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这些代码究竟有何不同?
为什么会这样呢?我无法理解上述代码给出不同答案的区别。
以下代码使用 avolatile uint8_t而不是 avolatile sig_atomic_t作为 C 标准要求,因为在 avr 平台上该类型sig_atomic_t不可用。
这仍然是合法的代码吗?使用合法吗__SIG_ATOMIC_TYPE__?
是否需要包含cli()/sei()宏?
#include <stdint.h>
#include <signal.h>
#include <avr/interrupt.h>
volatile uint8_t flag;
//volatile sig_atomic_t flag; // not available in avr-gcc
//volatile __SIG_ATOMIC_TYPE__ flag; // ok?
void isr() __asm__("__vector_5") __attribute__ ((__signal__, __used__, __externally_visible__));
void isr() {
flag = 1;
}
void func(void) {
for (uint8_t i=0; i<20; i++) {
flag = !flag;
}
}
Run Code Online (Sandbox Code Playgroud) 我已经在 IAR IDE 中创建了组,并且添加了 .h 文件,但仍然显示错误,例如找不到源文件。如何在IAR中添加头文件?

我还尝试在预处理器中添加路径为 $PROJ_DIR$/hdr。但我仍然遇到同样的错误。
尝试将新值(0x00008000,设置 TSVREFE 位)写入 ADC 控制寄存器 2 (ADC_CR2)。没有效果。我在内存(地址 0x40012408)中看到未更改的值(重置后为 0x00000000)。我应该配置一些东西才能写入该寄存器吗?
为了测试我尝试了这个实验例程:
__main PROC
EXPORT __main
LDR R0, =ADC1_ADDR
ADD R0, #ADC_CR2_OFFSET
MOV R1, #0x00008000
STR R1, [R0]
B .
ENDP
ADC1_ADDR EQU 0x40012400
ADC_CR2_OFFSET EQU 0x08
END
Run Code Online (Sandbox Code Playgroud)
执行后内存窗口如下所示(断点在 B . 行)
0x40012400 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x40012410 ...
Run Code Online (Sandbox Code Playgroud)