嵌入式C ++ 11 code - 我需要的挥发性? [英] Embedded C++11 code — do I need volatile?

查看:229
本文介绍了嵌入式C ++ 11 code - 我需要的挥发性?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用的Cortex M3的MCU(STM32F1)嵌入式设备。它的嵌入式闪存(64K)。
MCU固件可以重新在运行时闪存部门;这是由闪存控制器(FMC)寄存器来实现(所以它不是一个容易= B)。 FMC得到缓冲区指针和灼伤数据来一些闪光部门。

我想用最后的闪存部门的设备配置参数。
参数存储在阵列与一个拥挤的结构和包含一些自定义类。

参数可以在运行时改变(复制到RAM,变化和烧退使用FMC闪烁)。

因此​​,有关于一些问题:


  1. 状态参数结构的(按位)由FMC硬件改变。
    C ++编译器不知道它是否改变与否。
    这是否意味着我应该声明所有结构成员挥发?
    我想是的。


  2. 结构体应该被静态初始化(默认参数)在编译的时候。结构应该是POD(TriviallyCopyable并具有标准配置)。请记住,有一些自定义类在那里,所以我记住这些类应该是POD了。
    但也存在一些问题:
    CP preference.com


      

    只有平凡拷贝的类型是标量类型,拷贝的平凡
      类和这些类型/类阵列(可能是const限定,
      但不是volatile限定)。



这意味着我不能让我的课都POD和挥发性?
所以,我将如何解决这个问题?

有可能的参​​数结构只使用标量类型,但它可能会导致周围配置的处理更清洁code ...

P.S。
它的工作原理,即使没有波动,但恐怕有一天,一些精明的LTO编译器会看到初始化静态的,而不是(用C ++)结构变化和优化了一些访问底层内存不会忽略。这意味着新的编程参数将不适用,因为它们是由编译器内联。

编辑:可以不使用挥发性来解决问题。它似乎更正确。

您需要定义在不同的翻译单元(.cpp文件)的配置结构变量,不初始化变量,以避免LTO中值替换。如果不使用LTO - 因为优化是在一个翻译单元在同一时间完成的,因此具有静态存储时间和专用转换单元中定义的外部链接的变量不应被优化掉所有被确定。只有LTO可以把它扔掉或作出值替换,而不会发出存储器中取出。特别是定义变量时为常量。我认为这是确定的,如果不使用LTO来初始化变量。


解决方案

重新编程闪存,你改变底层对象的再presentation。在挥发性预选赛对于合适的解决方案
情况,以确保数据的更改不会优化掉。

您想声明为: const volatile的设置设置;

其缺点是,挥发性 prevents你的对象的静态初始化。这阻止你使用链接器把初始化的对象在其相应的内存地址。

您想定义为:常量设置设置= {...};

幸运的是,你可以初始化一个常量对象和访问它作为一个 const的挥发


  //头文件
结构设置{...};
的extern const volatile的设置和放大器;设置;


  //源文件
静态常量设置init_settings = {...};
const volatile的设置和放大器;设置= init_settings;


init_settings 对象静态初始化,但所有访问,通过设置引用被视为不稳定。

请注意,但是,修改定义为常量是未定义行为的对象。

Embedded device with Cortex M3 MCU(STM32F1). It has embedded flash(64K). MCU firmware can reprogram flash sectors at runtime; this is done by Flash Memory Controller(FMC) registers (so it's not as easy as a=b). FMC gets buffer pointer and burns data to some flash sector.

I want to use the last flash sector for device configuration parameters. Parameters are stored in a packed struct with arrays and contain some custom classes.

Parameters can be changed at runtime (copy to RAM, change and burn back to flash using FMC).

So there are some questions about that:

  1. State (bitwise) of parameters struct is changed by FMC hardware. C++ compiler does not know if it was changed or not. Does this mean I should declare all struct members as volatile? I think YES.

  2. Struct should be statically initialized (default parameters) at compile time. Struct should be POD (TriviallyCopyable and has standard layout). Remember, there are some custom classes in there, so I keep in mind these classes should be POD too. BUT there are some problems: cppreference.com

    The only trivially copyable types are scalar types, trivially copyable classes, and arrays of such types/classes (possibly const-qualified, but not volatile-qualified).

That means I can't keep my class both POD and volatile? So how would I solve the problem?

It is possible to use only scalar types in parameters struct but it may result in much less clean code around config processing...

P.S. It works even without volatile, but I am afraid someday, some smart LTO compiler will see static initialized, not changing (by C++) struct and optimize out some access to underlying memory adresses. That means fresh programmed parameters will not be applied because they were inlined by the compiler.

EDIT: It is possible to solve problem without using volatile. And it seems to be more correct.

You need define config struct variable in separate translation unit(.cpp file) and do not initialize variable to avoid values substitution during LTO. If not using LTO - all be OK because optimizations are done in one translation unit at a time, so variables with static storage duration and external linkage defined in dedicated translation unit should not be optimized out. Only LTO can throw it away or make values substitution without issuing memory fetches. Especially when defining variable as a const. I think it is OK to initialize variable if not using LTO.

解决方案

By reprogramming the flash, you are changing the underlying object's representation. The volatile qualifier is the appropriate solution for the situation to ensure the changes in data are not optimized away.

You would like a declaration to be: const volatile Settings settings;

The drawback is that volatile prevents static initialization of your object. This stops you from using the linker to put the initialized object in its appropriate memory address.

You would like the definition to be: const Settings settings = { ... };

Luckily, you can initialize a const object and access it as a const volatile.


// Header file
struct Settings { ... };
extern const volatile Settings& settings;


// Source file
static const Settings init_settings = { ... };
const volatile Settings& settings = init_settings;


The init_settings object is statically initialized, but all accesses through the settings reference are treated as volatile.

Please note, though, modifying an object defined as const is undefined behavior.

这篇关于嵌入式C ++ 11 code - 我需要的挥发性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆