标签: avr

c/c ++优化调用函数中的常量变量

只有在使用-Os,-O1和-O2时,C/C++编译器才能使用常量参数(编译时已知)优化单层函数.他们没有优化所有层.只有-O3可以做到这一点.gcc是WinAVR 4.3.3,它不支持属性"optimize".

void inner(double value)
{
    //operations using value
    //...
}

void outer(double value)
{
    //few operations using value
    //...
    inner(value);
}

int main()
{
    inner(1); //optimize
    outer(1); //only optimize by using -O3
}
Run Code Online (Sandbox Code Playgroud)

除以下之外,有哪些可能的解决方案?

  1. -O3保存程序或文件(误用会炸掉大小)
  2. 属性优化-O3为函数(4.3.3不支持)
  3. 宏(容易出错)

更新:

//inner function
static inline void _delay_us(double __us) __attribute__((always_inline));
//outer function
void f(double);
inline f1(double);
static inline f2(double);
static f3(double);
Run Code Online (Sandbox Code Playgroud)

f1已经过优化,但发出警告'_delay_us'是静态的,但在内联函数'f1'中使用,由于静态函数问题,它不是静态的.其他人没有优化.


解:

static inline void outer(double) __attribute__((always_inline));
Run Code Online (Sandbox Code Playgroud)

内联是关键.我的外部函数对于内联来说太大了.属性always_inline强制函数内联.这允许编译器以比编写优化更少的编译成本来优化函数.-O3足够聪明,可以进行优化但不是-Os.-Os可能需要一些编译器选项.(关键字static是必需的,因为内部函数也是静态内联的.)

c c++ optimization avr constants

6
推荐指数
1
解决办法
1912
查看次数

使用带有AVR-G ++的Arduino库

是否有一种简单的方法可以使用用于Arduino IDE的库以及我为AVR-G ++/AVR-GCC编写的C和汇编代码?

我正在尝试使用Adafruit Wave Shield库,但只是包含头文件和cpp文件并没有太大的帮助.我可以以某种方式编译它并将其链接到我的C代码?或者也许只是找到一种方法来使用我的C代码进行编译.

目前,当我尝试做一些简单的事情时:

#include "WaveHC/WaveHC.h"    
SdReader card;
card.init();
Run Code Online (Sandbox Code Playgroud)

我受到了欢迎:

70: undefined reference to `SdReader::init(unsigned char)'
Run Code Online (Sandbox Code Playgroud)

c c++ avr arduino avrdude

6
推荐指数
1
解决办法
6081
查看次数

void*用于维持状态...(C编程)

目前我们正在学习如何编程AVR微控制器(仅限Ansi C89标准).部分包含的驱动程序是一个标题,用于处理调度,即以不同的速率运行任务.我的问题是与文档中的引用有关:

"每个任务必须通过使用静态局部 变量来维护自己的状态."

那是什么意思呢?他们似乎传递void*给维持状态的功能但是不使用它?

看一下我收集的文件中的代码,这就是他们的意思:

{.func = led_flash_task, .period = TASK_RATE / LED_TASK_RATE, .data = 0} 
/* Last term the pointer term */
Run Code Online (Sandbox Code Playgroud)

有一个函数在数组中使用上述参数运行,但它只作为调度程序.然后功能led_flash_task

static void led_flash_task (__unused__ void *data)
{
    static uint8_t state = 0;

    led_set (LED1, state); /*Not reall important what this task is */
    state = !state; /*Turn the LED on or off */
}
Run Code Online (Sandbox Code Playgroud)

并从标题

#define  __unused__ __attribute__ ((unused))
Run Code Online (Sandbox Code Playgroud)

而传递void *data是为了维持任务的状态?这是什么意思?

谢谢您的帮助

c microcontroller avr void

6
推荐指数
1
解决办法
445
查看次数

为什么我的Arduino上没有可用的串行数据?

我在我的Arduino Uno上运行了简单的串行程序,它只是回显你输入的内容.在Arduino Sketch IDE(v22)中运行时,这非常有效.

int incomingByte = 0;   // for incoming serial data

void setup() {
    Serial.begin(115200);   // opens serial port, sets data rate
}

void loop() {
    // send data only when you receive data:
    if (Serial.available() > 0) {
        // read the incoming byte:
        incomingByte = Serial.read();

        // say what you got:
        Serial.print("I received: ");
        Serial.println(incomingByte, DEC);
    }
}
Run Code Online (Sandbox Code Playgroud)

(代码来自http://arduino.cc/en/Serial/Available)

但是,我不想使用Arduino IDE而宁愿使用avr-g ++编译我的C++代码,所以我写了这个,它应该与上面完全相同:

extern "C" {
#include <avr/io.h>
}
#include <HardwareSerial.h>

extern …
Run Code Online (Sandbox Code Playgroud)

c++ avr arduino

6
推荐指数
1
解决办法
3229
查看次数

初始化变量并同时指定存储地址:是否可能?

例如,在Atmel处理器的codevision编译器中,可以指定全局变量的存储地址

int a @0x100; // will place the variable at the address 0x100 in RAM
Run Code Online (Sandbox Code Playgroud)

当然,根据标准C,变量可以在声明时初始化

int a=42;
Run Code Online (Sandbox Code Playgroud)

但是,我没有发现任何可能同时做到这两点.int a @0x100 = 42或者int a = 42 @0x100;不工作,它们会导致编译器错误.

你可能会问为什么这么做很重要,因为人们可以这样做

int a @0x100;

int main()
{
    a = 42;
    //...
}
Run Code Online (Sandbox Code Playgroud)

但是,如果我在EEPROM中有变量,我需要初始化它们,因为这是自动生成带有值的eeprom文件的唯一方法.我以后不能分配这些值,因为在这种情况下,它实际上会在程序的每个开始时将值写入eeprom.

c embedded avr

6
推荐指数
1
解决办法
7625
查看次数

GCC在ISR中生成无用的代码

我有一个非常简单的中断服务程序(ISR)为atmega328编写,并使用AVR工作室使用avrgcc(使用-Os)编译.

ISR (TIMER0_OVF_vect) { 
    txofcnt++;  //count overflows and store in uint16_t 
}
Run Code Online (Sandbox Code Playgroud)

如果你注意到生成的程序集(如下),它使用r24,r25来获取增加易失性uint16_t txofcnt的作业,但它也是push-write-pop r1,r28,r29而没有读取它们.它还有一个额外的r0推/弹,而不会在它们之间使用它.

我不知道为什么r1被推,清除然后最终poped.但是为什么gcc觉得需要将EIMSK和GPIOR0加载到寄存器中然后不使用它们.如果你能告诉我GPIOR0的用途是什么,那么数据表说它存在但没有描述.

00000258 <__vector_16>:

ISR (TIMER0_OVF_vect) {
 258:   1f 92           push    r1
 25a:   0f 92           push    r0
 25c:   00 90 5f 00     lds r0, 0x005F
 260:   0f 92           push    r0
 262:   11 24           eor r1, r1
 264:   8f 93           push    r24
 266:   9f 93           push    r25
 268:   cf 93           push    r28
 26a:   df 93           push    r29
 26c:   cd b7           in  r28, 0x3d   ; 61 reads register …
Run Code Online (Sandbox Code Playgroud)

c gcc avr interrupt

6
推荐指数
1
解决办法
1318
查看次数

只更改SD卡扇区中的一个字节

我正在使用Atmega328在SD卡上实现FAT16.

我经常需要更改扇区中的一个或两个字节(512B区域).

我知道Flash是如何工作的,它需要立刻覆盖整个扇区,但我想知道是否有一些特殊的命令可以使卡本身处理它?

关键是,atmega只有2k RAM,而且只为读取 - 修改 - 写入SD卡缓冲区分配512是非常不利的.没有其他办法吗?

(PS.AFAIK atmega本身不能有外部ram)

c embedded avr

6
推荐指数
1
解决办法
765
查看次数

C:用一个#define传递两个逗号分隔的值

问题

为微控制器编程可重用模块(在我的情况下为AVR)需要一般IO引脚的灵活性.每个引脚由字母(AG)和数字(0-7)定义.然而,它由三个寄存器中相同位置的一位控制.因此配置文件需要包含四个条目(指向寄存器的3个指针+ 1个位置),这不是那么优雅.

简单的解决方法是简单地接受这个,但由于这是一个常见的问题,它至少应该得到一点关注.


想法

让预编译器像这样重复工作会很好:

//CONFIGURATION
#define IO_NAME B5

//MACRO
#define PORT_(ID)
#define PIN_(ID)
#define DDR_(ID)
#define BIT_(ID)
Run Code Online (Sandbox Code Playgroud)

结果应如下所示

PORT_(IO_NAME)   =>  PORTB
PIN_(IO_NAME)    =>  PINB
DDR_(IO_NAME)    =>  DDRB
BIT_(IO_NAME)    =>  5
Run Code Online (Sandbox Code Playgroud)

结果表达式在AVR Studio中定义.


我试过的

我无法弄清楚如何忽略字母而不是数字,所以我尝试了连接:

#define PORT_(REG, BIT)             PORT_2(REG, BIT)
#define PIN_(REG, BIT)              PIN_2(REG, BIT)
#define DDR_(REG, BIT)              DDR_2(REG, BIT)

#define PORT_2(REG, BIT)            (PORT ## REG)
#define PIN_2(REG, BIT)             (PIN ## REG)
#define DDR_2(REG, BIT)             (DDR ## REG)

#define BIT(REG, BIT)               (BIT)
Run Code Online (Sandbox Code Playgroud)

额外的层需要使用任何#defined值作为REG或BIT.

以下代码按预期工作:

#define IO_NAME_REG B
#define IO_NAME_BIT …
Run Code Online (Sandbox Code Playgroud)

c macros avr concatenation

6
推荐指数
1
解决办法
610
查看次数

snprintf与avr-gcc无法正常工作

在调试会话期间,我发现snprintf在使用avr-gcc编译代码时无法按预期工作.示例代码应该简单地将浮点值3999.9f转换为其字符表示形式.

这是一个最小的测试用例:

    int TestSnprintf(void)
    {
       const float inputValue = 3999.9f;
       /* Print with a fixed width of 6 characters (5 numbers and 1 dot).
       The buffer must have a length of 7, because snprintf appends a '\0' at the end. */
       char buf[7U] = {0, 0, 0, 0, 0, 0, 0};
       const uint8_t bufferSize = 7U;
       if(6 != snprintf(buf, bufferSize, "%06.1f", inputValue))
       {
          return -1;
       }
       if( buf[0] != '3'
            || buf[1] != '9'
            || buf[2] …
Run Code Online (Sandbox Code Playgroud)

c avr avr-gcc atmel atmelstudio

6
推荐指数
1
解决办法
499
查看次数

avr-gcc :(貌似)简单功能中不需要的序言/结尾

尝试寻址时uint64,AVR gcc?¹?中的各个字节。给了我一个奇怪的序言/结尾,而使用编写的同一函数uint32_t给了我一个ret(示例函数为NOP)。

为什么gcc这样做?我该如何删除?

您可以在此处在Compiler Explorer中查看代码

???来自Arduino 1.8.9发行版的gcc 5.4.0,parameters = -O3 -std=c++11

源代码:

#include <stdint.h>

uint32_t f_u32(uint32_t x) {
  union y {
    uint8_t p[4];
    uint32_t w;
  };
  return y{ .p = {
    y{ .w = x }.p[0],
    y{ .w = x }.p[1],
    y{ .w = x }.p[2],
    y{ .w = x }.p[3]
  } }.w;
}

uint64_t f_u64(uint64_t x) {
  union y {
    uint8_t p[8];
    uint64_t w;
  };
  return y{ .p = {
    y{ …
Run Code Online (Sandbox Code Playgroud)

c++ avr arduino compiler-optimization avr-gcc

6
推荐指数
1
解决办法
199
查看次数