C - 在闪存中存储全局变量?
C - Store global variables in flash?
正如标题所暗示的,我目前在我的程序中缺少 SRAM,我找不到减少全局变量的方法。是否可以将全局变量带到闪存中?由于这些变量是频繁读取和写入的,因此nand flash
是否会因为它们的read/write循环次数有限而对nand flash
不利?
如果闪光灯无法解决这个问题,EEPROM
会是一个不错的选择吗?
编辑:
对不起,模棱两可的家伙。我正在使用 Atmel AVR ATmega32HVB,它具有:
2K字节的SRAM,
1K字节的EEPROM
32K字节的FLASH
编译器:AVR C/C++
平台:IAR 嵌入式 AVR
我要去掉的全局变量是:
uint32_t capacityInCCAccumulated[TOTAL_CELL];
和
int32_t AccumulatedCCADCvalue[TOTAL_CELL];
代码片段:
int32_t AccumulatedCCADCvalue[TOTAL_CELL];
void CCGASG_AccumulateCCADCMeasurements(int32_t ccadcMeasurement, uint16_t slowRCperiod)
{
uint8_t cellIndex;
// Sampling period dependant on configuration of CCADC sampling..
int32_t temp = ccadcMeasurement * (int32_t)slowRCperiod;
bool polChange = false;
if(temp < 0) {
temp = -temp;
polChange = true;
}
// Add 0.5*divisor to get proper rounding
temp += (1<<(CCGASG_ACC_SCALING-1));
temp >>= CCGASG_ACC_SCALING;
if(polChange) {
temp = -temp;
}
for (cellIndex = 0; cellIndex < TOTAL_CELL; cellIndex++)
{
AccumulatedCCADCvalue[cellIndex] += temp;
}
// If it was a charge, update the charge cycle counter
if(ccadcMeasurement <= 0) {
// If it was a discharge, AccumulatedCADCvalue can be negative, and that
// is "impossible", so set it to zero
for (cellIndex = 0; cellIndex < TOTAL_CELL; cellIndex++)
{
if(AccumulatedCCADCvalue[cellIndex] < 0)
{
AccumulatedCCADCvalue[cellIndex] = 0;
}
}
}
}
还有这个
uint32_t capacityInCCAccumulated[TOTAL_CELL];
void BATTPARAM_InitSramParameters() {
uint8_t cellIndex;
// Active current threshold in ticks
battParams_sram.activeCurrentThresholdInTicks = (uint16_t) BATTCUR_mA2Ticks(battParams.activeCurrentThreshold);
for (cellIndex = 0; cellIndex < TOTAL_CELL; cellIndex++)
{
// Full charge capacity in CC accumulated
battParams_sram.capacityInCCAccumulated[cellIndex] = (uint32_t) CCGASG_mAh2Acc(battParams.fullChargeCapacity);
}
// Terminate discharge limit in CC accumulated
battParams_sram.terminateDischargeLimit = CCGASG_mAh2Acc(battParams.terminateDischargeLimit);
// Values for remaining capacity calibration
GASG_CalculateRemainingCapacityValues();
}
would it be bad for the nand flash because they have limited number of
read/write cycle?
是的,频繁修改数据时使用闪存不是一个好主意。
只读闪存不会减少闪存的使用寿命。擦写会减少flash的寿命。
与传统内存相比,从闪存读取和写入速度要慢得多。
要写入一个字节,必须擦除整个块并重新写入闪存。
任何类型的 Flash 都不是用于频繁更改值的好主意:
- erase/write 循环次数有限,请参阅数据表。
- 非常慢 erase/write(擦除大约需要 1 秒),请参阅数据表。
- 您需要一个特殊的顺序来先擦后写(无语言支持)。
- 虽然最多阻止对闪存的擦除或写入访问,但有些要求根本不访问闪存(未定义的行为)。
- 闪存单元不能自由写入per-byte/word。大多数必须按页写入(例如 64 字节)并以更大的单位擦除大部分时间 (segments/blocks/sectors)。
对于NAND Flash来说,与NOR Flash相比,耐久性更差,而且单元的可靠性也更差(位可能偶尔会翻转或有缺陷),所以你必须添加错误检测和纠正。这很可能是你不应该去的方向。
真正的 EEPROM 共享大多数问题,但它们可能被写入 byte/word-wise(内部擦除)。
请注意,现代 MCU 集成 "EEPROM" 大多数时候也是闪存。一些实现只是使用稍微更可靠的单元(比程序闪存多 erase/write 周期大约十年)和允许任意 byte/word 写入(自动擦除)的额外硬件。但这对于频繁更改仍然不够。
但是,您首先应该验证您的应用程序是否可以容忍如此长的 write/erase 次。你能接受一个阻塞那么长时间的进程,或者相应地重写你的程序吗?如果答案是"no",你甚至应该停止对该方向的进一步调查。否则,您应该计算预期生命周期内的更新次数,并与数据表中的信息进行比较。也有减少擦除次数的方法,但是太过分了。
如果可以选择外部设备 (I2C/SPI),则可以使用串行 SRAM。尽管更好(并且可能更便宜)的方法是更大的 MCU 或考虑更有效(即更少的 RAM,更多的代码)的方法来将数据存储在 SRAM 中。
正如标题所暗示的,我目前在我的程序中缺少 SRAM,我找不到减少全局变量的方法。是否可以将全局变量带到闪存中?由于这些变量是频繁读取和写入的,因此nand flash
是否会因为它们的read/write循环次数有限而对nand flash
不利?
如果闪光灯无法解决这个问题,EEPROM
会是一个不错的选择吗?
编辑: 对不起,模棱两可的家伙。我正在使用 Atmel AVR ATmega32HVB,它具有: 2K字节的SRAM, 1K字节的EEPROM 32K字节的FLASH
编译器:AVR C/C++
平台:IAR 嵌入式 AVR
我要去掉的全局变量是:
uint32_t capacityInCCAccumulated[TOTAL_CELL];
和
int32_t AccumulatedCCADCvalue[TOTAL_CELL];
代码片段:
int32_t AccumulatedCCADCvalue[TOTAL_CELL];
void CCGASG_AccumulateCCADCMeasurements(int32_t ccadcMeasurement, uint16_t slowRCperiod)
{
uint8_t cellIndex;
// Sampling period dependant on configuration of CCADC sampling..
int32_t temp = ccadcMeasurement * (int32_t)slowRCperiod;
bool polChange = false;
if(temp < 0) {
temp = -temp;
polChange = true;
}
// Add 0.5*divisor to get proper rounding
temp += (1<<(CCGASG_ACC_SCALING-1));
temp >>= CCGASG_ACC_SCALING;
if(polChange) {
temp = -temp;
}
for (cellIndex = 0; cellIndex < TOTAL_CELL; cellIndex++)
{
AccumulatedCCADCvalue[cellIndex] += temp;
}
// If it was a charge, update the charge cycle counter
if(ccadcMeasurement <= 0) {
// If it was a discharge, AccumulatedCADCvalue can be negative, and that
// is "impossible", so set it to zero
for (cellIndex = 0; cellIndex < TOTAL_CELL; cellIndex++)
{
if(AccumulatedCCADCvalue[cellIndex] < 0)
{
AccumulatedCCADCvalue[cellIndex] = 0;
}
}
}
}
还有这个
uint32_t capacityInCCAccumulated[TOTAL_CELL];
void BATTPARAM_InitSramParameters() {
uint8_t cellIndex;
// Active current threshold in ticks
battParams_sram.activeCurrentThresholdInTicks = (uint16_t) BATTCUR_mA2Ticks(battParams.activeCurrentThreshold);
for (cellIndex = 0; cellIndex < TOTAL_CELL; cellIndex++)
{
// Full charge capacity in CC accumulated
battParams_sram.capacityInCCAccumulated[cellIndex] = (uint32_t) CCGASG_mAh2Acc(battParams.fullChargeCapacity);
}
// Terminate discharge limit in CC accumulated
battParams_sram.terminateDischargeLimit = CCGASG_mAh2Acc(battParams.terminateDischargeLimit);
// Values for remaining capacity calibration
GASG_CalculateRemainingCapacityValues();
}
would it be bad for the nand flash because they have limited number of read/write cycle?
是的,频繁修改数据时使用闪存不是一个好主意。 只读闪存不会减少闪存的使用寿命。擦写会减少flash的寿命。
与传统内存相比,从闪存读取和写入速度要慢得多。
要写入一个字节,必须擦除整个块并重新写入闪存。
任何类型的 Flash 都不是用于频繁更改值的好主意:
- erase/write 循环次数有限,请参阅数据表。
- 非常慢 erase/write(擦除大约需要 1 秒),请参阅数据表。
- 您需要一个特殊的顺序来先擦后写(无语言支持)。
- 虽然最多阻止对闪存的擦除或写入访问,但有些要求根本不访问闪存(未定义的行为)。
- 闪存单元不能自由写入per-byte/word。大多数必须按页写入(例如 64 字节)并以更大的单位擦除大部分时间 (segments/blocks/sectors)。
对于NAND Flash来说,与NOR Flash相比,耐久性更差,而且单元的可靠性也更差(位可能偶尔会翻转或有缺陷),所以你必须添加错误检测和纠正。这很可能是你不应该去的方向。
真正的 EEPROM 共享大多数问题,但它们可能被写入 byte/word-wise(内部擦除)。
请注意,现代 MCU 集成 "EEPROM" 大多数时候也是闪存。一些实现只是使用稍微更可靠的单元(比程序闪存多 erase/write 周期大约十年)和允许任意 byte/word 写入(自动擦除)的额外硬件。但这对于频繁更改仍然不够。
但是,您首先应该验证您的应用程序是否可以容忍如此长的 write/erase 次。你能接受一个阻塞那么长时间的进程,或者相应地重写你的程序吗?如果答案是"no",你甚至应该停止对该方向的进一步调查。否则,您应该计算预期生命周期内的更新次数,并与数据表中的信息进行比较。也有减少擦除次数的方法,但是太过分了。
如果可以选择外部设备 (I2C/SPI),则可以使用串行 SRAM。尽管更好(并且可能更便宜)的方法是更大的 MCU 或考虑更有效(即更少的 RAM,更多的代码)的方法来将数据存储在 SRAM 中。