您好StackOverflow社区,
我正在尝试在Assembler中编写我的旧Arduino Duemilanove Board(Atmega 168V-10PU).我之前尝试了几次,但每次都没有执行代码.所以我试着在C中编写一个等效的测试程序,并且它有效.这里是:
// file led.c
#include <avr/io.h>
int main(void)
{
DDRB = 0xFF;
PORTB = 0xFF;
while (1) {
asm("nop\n");
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
编译器的asm转储导致(缩短),
ldi r24,lo8(-1) ; tmp44,
out 0x4,r24 ; MEM[(volatile uint8_t *)36B], tmp44
out 0x5,r24 ; MEM[(volatile uint8_t *)37B], tmp44
Run Code Online (Sandbox Code Playgroud)
它可以在Arduino Pin 13(AVR引脚PB5)上工作并激活LED.
但是当我使用这个asm文件时,
// file led.S
#include "avr/io.h"
.global main
main:
ldi r24, 0xFF
out DDRB, r24
out PORTB, r24
end:
jmp end
Run Code Online (Sandbox Code Playgroud)
编译器转储导致(缩短),
ldi r24, 0xFF
out ((0x04) + 0x20), r24
out …Run Code Online (Sandbox Code Playgroud) 我正在使用avr-gcc作为atmega-328p微控制器.代码构建为:
avr-gcc -g -Wall -Os -mmcu=atmega328p -D__AVR_ATmega3280__ -DARCH_AVR -I/usr/avr/include -DF_CPU=16000000 -c -o heap.o heap.c
avr-gcc -g -Wall -Os -mmcu=atmega328p -D__AVR_ATmega3280__ -DARCH_AVR -I/usr/avr/include -DF_CPU=16000000 -c -o kerneltimer.o kerneltimer.c
avr-gcc -g -Wall -Os -mmcu=atmega328p -D__AVR_ATmega3280__ -DARCH_AVR -I/usr/avr/include -DF_CPU=16000000 -c -o message.o message.c
avr-gcc -g -Wall -Os -mmcu=atmega328p -D__AVR_ATmega3280__ -DARCH_AVR -I/usr/avr/include -DF_CPU=16000000 -c -o driver.o driver.c
avr-gcc -g -Wall -Os -mmcu=atmega328p -D__AVR_ATmega3280__ -DARCH_AVR -I/usr/avr/include -DF_CPU=16000000 -c -o watchdog.o watchdog.c
avr-gcc -g -Wall -Os -mmcu=atmega328p -D__AVR_ATmega3280__ -DARCH_AVR -I/usr/avr/include -DF_CPU=16000000 -c -o mutex.o mutex.c
avr-gcc …Run Code Online (Sandbox Code Playgroud) 我在调试AVR微控制器时遇到了这个问题:我有一个带有大量变量定义的main.c文件,其中有一个结构数组,如下所示:
struct mystruct mystruct_array[COUNT];
Run Code Online (Sandbox Code Playgroud)
在另一个.c文件中,我将此数组称为外部,但是我放弃了数组括号和大小,所以我不会重复自己,只是将变量声明为指针(因为数组本质上是指针,不是吗?) :
extern struct mystruct *mystruct_array;
Run Code Online (Sandbox Code Playgroud)
但是,当我检查使用数组的地址printf("%p\n", mystruct_array);我得到了一个空指针,而不是在存储阵列的位置.另外,如果我将访问后续项目数组中,喜欢printf("%p\n", &(mystruct_array[n]));将打印地址0加n倍sizeof(struct mystruct).
只有在我将定义更改为
extern struct mystruct mystruct_array[COUNT];
Run Code Online (Sandbox Code Playgroud)
(与main.c完全相同),我得到了数组的真实地址.
我的问题:为什么这会对编译器产生影响(在我的例子中是avr-gcc)?
I'm trying to write a macro which simplifies setting multiple bits in an integer. This commonly occurs in microcontroller code when initializing configuration registers. For example, one might configure an 8-bit timer by setting 3 bits in the register TCCR0A like this:
// WGM01, WGM00 and COM0A1 are constants between 0 and 7
// There are hundreds of these constants defined in avr-libc
TCCR0A |= (1<<WGM01) | (1<<WGM00) | (1<<COM0A1);
// Another way to write this:
#define _BV(bit) (1 << …Run Code Online (Sandbox Code Playgroud) 我正在研究的delay_ms功能avr-gcc。在delay.h我发现它的定义:
void _delay_ms(double __ms)
{
double __tmp ;
#if __HAS_DELAY_CYCLES && defined(__OPTIMIZE__) && \
!defined(__DELAY_BACKWARD_COMPATIBLE__) && \
__STDC_HOSTED__
uint32_t __ticks_dc;
extern void __builtin_avr_delay_cycles(unsigned long);
__tmp = ((F_CPU) / 1e3) * __ms;
#if defined(__DELAY_ROUND_DOWN__)
__ticks_dc = (uint32_t)fabs(__tmp);
#elif defined(__DELAY_ROUND_CLOSEST__)
__ticks_dc = (uint32_t)(fabs(__tmp)+0.5);
#else
//round up by default
__ticks_dc = (uint32_t)(ceil(fabs(__tmp)));
#endif
__builtin_avr_delay_cycles(__ticks_dc);
#else
...
}
Run Code Online (Sandbox Code Playgroud)
我对__builtin_avr_delay_cycles函数的内部外观和定义位置感兴趣吗?在哪里可以找到来源?
我正在使用这个Makefile来编译我的Arduino草图,其中包含CPP和C的以下标志
CPPFLAGS += -mmcu=$(MCU) -DF_CPU=$(F_CPU) -DARDUINO=$(ARDUINO_VERSION) \
-I. -I$(ARDUINO_CORE_PATH) -I$(ARDUINO_VAR_PATH)/$(VARIANT) \
$(SYS_INCLUDES) $(USER_INCLUDES) -g -Os -w -Wall \
-ffunction-sections -fdata-sections
CFLAGS = -std=gnu99
CXXFLAGS = -fno-exceptions
Run Code Online (Sandbox Code Playgroud)
当我编译一个cpp文件时,如果函数在声明之前被使用,我会收到一个致命的错误.我浏览了avr g ++选项,发现选项-Wimplicit-function-declaration可以启用它.此外,它还通过-Wall选项启用,该选项在make文件中使用.
我想启用-Wall选项(因为它启用了很多其他警告)但只禁用-Wimplicit-function-declaration选项.
我检查了文档,但无法弄清楚如何做到这一点.有人可以告诉我该怎么做吗?
所以我被分配了为AVR编译编写自定义reset()函数的任务.
我得到了这个信息 - "Atmega128和Pic24e在程序地址0x0处有复位中断.写一个函数reset()来复位程序.我也听说过强制系统重启的一种简单方法就是发送它进入无限循环.
叫我疯了,但这就像写作一样简单:
function reset(){
goto 0x00000000;
}
Run Code Online (Sandbox Code Playgroud)
不确定你是否可以这样做,而不是寻找复杂的解释,因为我很确定这是一个通用的问题.简短而甜蜜,如果你能:)
我试图从 C++ 调用一个汇编函数,链接器说我试图调用的函数不存在。这是错误:
avr-gcc -mmcu=atmega328 -Wall -o main.elf hello.S main.cpp
/tmp/ccS7uaAX.o: In function `main':
main.cpp:(.text+0x14): undefined reference to `hello(char, char, char, char, char)'
collect2: error: ld returned 1 exit status
Run Code Online (Sandbox Code Playgroud)
这是我的来源:
//Somewhere in hello.S
.global hello
hello:
ret
//In main.cpp
extern void hello(char, char, char, char, char);
int main(){
hello(1, 2, 3, 4, 5);
}
Run Code Online (Sandbox Code Playgroud)
如果这有帮助,以下是我将它们编译成目标文件后对文件的反汇编:
这是 main.o:
00000000 <main>:
0: 0f 93 push r16
2: cf 93 push r28
4: df 93 push r29
6: cd b7 in r28, …Run Code Online (Sandbox Code Playgroud) 我正在编译一个8位AVR微控制器(AVR-GCC)的应用程序.为了减少微控制器中的闪存使用,链接器必须仅链接应用程序代码使用的函数.我正在编写自己的库,我发现了以下声明.
"为每个代码模块编写一个函数.这将编译为每个对象模块一个函数" - 来源:http://nongnu.org/avr-libc/user-manual/library.html
这是什么意思?如何为每个函数创建单独的目标文件?现在我的库中只有一个.h文件和一个.c文件.
我正在查看编译后编写的一些代码的生成程序集avr-gcc。具体来说,我是用-Os选项编译的。总的来说,输出是我所期望的,但我无法理解的是push r1正在发出的指令。更奇怪的是,函数末尾的补充指令是pop r0. 所以 的值r1正在被保存但它似乎被恢复到r0
根据此处的文档:
https://gcc.gnu.org/wiki/avr-gcc#Register_Layout
寄存器r1始终包含零,但函数可以在恢复寄存器时使用该寄存器。恢复它将是ldi r1, 0x0,不需要推动,从我的理解中弹出。
下面是编译版本的 C 代码和反汇编示例。它是用-Os. 它有点长,但我必须制作一个大函数才能让编译器发出它。
代码:
void mqtt_create_connect(mqtt_parser *p, mqtt_connect_config *cfg){
uint8_t idx = 0;
p->buffer[idx++] = MQTT_CTRL_CONNECT << 4;
idx++; // skip remaining length for now
p->buffer[idx++] = 0x0;
p->buffer[idx++] = 0x4;
p->buffer[idx++] = 'M';
p->buffer[idx++] = 'Q';
p->buffer[idx++] = 'T';
p->buffer[idx++] = 'T';
p->buffer[idx++] = 0x04; // protocol level 3.1.1
p->buffer[idx++] = …Run Code Online (Sandbox Code Playgroud)