This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] MSP430G2553:在内存中创建一个新段,用于在计算过程中进行读/写操作

Guru**** 2601195 points
Other Parts Discussed in Thread: MSP430G2553

请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/642901/msp430g2553-create-a-new-segment-in-memory-to-use-for-read-write-during-calculations

部件号:MSP430G2553

我有代码示例 msp430g2xxS 3_flashwrite_01.c正在运行并了解其中的大部分内容。 我不能使用现有的INFOA-D (每个64字节)内存段,因为我需要更大的空间。 因此,我尝试在INFOA结束(INFOA-D反向映射)和0xC000 (下一个项目(闪存)开始)之间的可用空间中创建新的句段。  

我尝试了几种不同的方法,但都不能使用,所以我把它变得非常简单:从0x1100开始,声明一个与INFOC相同大小的新段(64字节),并将 msp430g2xxS中的SegC地址位置3_flashwrite_01.c替换为0x1100地址。 仍然无法正常工作。 没有什么与原始工作示例不同,因此我得出结论,如果我选择"全部显示",我的新句段将显示在"内存分配"下,这是不可写的。 也许我只是错过了一个设置? 是否有人成功创建了已写入的新句段? 我可以在论坛上找到一些写动画的例子,但没有一个写新片段的例子。

在内存中创建新段:

内存

/*首先我们计算*/
SFR:原点= 0x0000,长度= 0x0010
Peripherals_8bit:原始= 0x0010,长度= 0x00F0
Peripherals_16BIT:原点= 0x0100,长度= 0x0100
RAM:原点= 0x0200,长度= 0x0200

/*然后我们倒计时。在INFOC和INFOD中,代码示例在其中工作*/
INFOA:原点= 0x10C0,长度= 0x0040
INFOB:原点= 0x1080,长度= 0x0040
INFOC:原点= 0x1040,长度= 0x0040
INFOD:原点= 0x1000,长度= 0x0040

/*这是我的新内容。 从0x1100 (INFOA结束)到0xC000 (RAM开始)似乎可用*/
XVSEG:原点= 0x1100,长度= 0x0040

/*这是原始资料*/
Flash:Origin = 0xC000,length = 0x3FDE

/*好的,但现在我们要倒计时了吗? */
BSLSIGNATURE:原点= 0xFFDE,长度= 0x0002,填充= 0xFFFF
INT00:原点= 0xFFE0,长度= 0x0002
INT01:原点= 0xFFE2,长度= 0x0002
INT02:原点= 0xFFE4,长度= 0x0002
INT03:原点= 0xFFE6,长度= 0x0002
INT04:原点= 0xFFE8,长度= 0x0002
INT05:原点= 0xFFEA,长度= 0x0002
INT06:原点= 0xFFEC,长度= 0x0002
INT07:原点= 0xFFEE,长度= 0x0002
INT08:Origin = 0xFFF0,length = 0x0002
INT09:原点= 0xFFF2,长度= 0x0002
INT10:原点= 0xFFF4,长度= 0x0002
INT11:原点= 0xFFF6,长度= 0x0002
INT12:原点= 0xFFF8,长度= 0x0002
INT13:原点= 0xFFFA,长度= 0x0002
INT14:原点= 0xFFFC,长度= 0x0002
重置:原点= 0xFFFE,长度= 0x0002
}

/******************************************************************************** /
/*指定分配给内存的部分*/
/******************************************************************************** /

章节

.bss :{}> RAM/*全局和静态vars */
数据:{}> RAM/*全局和静态vars */
.TI.noinit :{}> RAM /*用于#pragma noinit */
sysmem :{}> RAM/*动态内存分配区域*/
堆栈:{}> RAM (高)/*软件系统堆栈*/

text :{}> flash /* Code */
.cinit :{}> flash /* Initialization Tables */
const :{}> flash /*常量数据*/
.bslsignature :{}> BSLSIGNATURE /* BSL Signature */
CIO:{}> RAM/* C I/O Buffer */

.Pinit :{}> flash /* C++构造函数表*/
binit :{}> flash /* boot-time Initialization tables */
init_array :{}> flash /* C++构造函数表*/
.mspabi.exidx :{}> flash /* C++构造函数表*/
.mspabi.extab :{}> flash /* C++构造函数表*/
#ifdef __TI_Compiler_version__
#if __TI_Compiler_version__>= 1500.9万
#ifndef __larate_code_model__
.TI.ramfunc :{} load=flash, run=ram, table(BINIT)
#否则
.TI.ramfunc:{} load=flash | FLASH2,run=RAM,table (BINIT)
#endif
#endif
#endif

infoA :{}> INFOA /* MSP430信息闪存段*/
信息B:{}> INFOB.
INFoC :{}> INFOC.
信息D :{}> INFOD.

.xvseg :{}> XVSEG.

/* MSP430中断矢量*/
TRAPINT :{*(.int00)}> INT00类型= VECT_INIT
int01 :{}> INT01
端口1:{*(.int02)}> INT02类型= VECT_INIT
端口2:{*(.int03)}> INT03类型= VECT_INIT
int04:{}> INT04
ADC10 :{*(.int05)}> INT05类型= VECT_INIT
USCIAB0TX:{*(.int06)}> INT06类型= VECT_INIT
USCIAB0RX :{*(.int07)}> INT07类型= VECT_INIT
TIMER0_A1:{*(.int08)}> INT08类型= VECT_INIT
TIMER0_A0:{*(.int09)}> INT09类型= VECT_INIT
WDT:{*(.INT10)}> INT10类型= VECT_INIT
COMPARATORA :{*(.INT11)}> INT11 TYPE = VECT_INIT
Timer1_A1 :{*(.INT12)}> INT12类型= VECT_INIT
Timer1_A0 :{*(.INT13)}> INT13类型= VECT_INIT
NMI :{*(.INT14)}> INT14类型= VECT_INIT
.reset:{}> reset /* MSP430 Reset vector */
}

/******************************************************************************** /

/******************************************************************************** /

-l msp430g2553.cmd

修改的源代码:

//************************************************************************************************
// MSP430G2xx3演示-闪存系统内编程,将SegC复制到SegD
//
//说明:此程序首先擦除闪存设置C,然后全部递增
// seg C中的值,然后擦除seg D,然后将seg C复制到seg D
//假定MCLK 771kHz - 1428kHz。
////*在主循环中的NOP上设置断点,以避免对Flash *//造成压力
//
// MSP430G2xx3
//-----------
///|\\| Xin|-
//||||
//--|RST XOUT|-
//||
//
// D. Dang
//德州仪器(TI)
// 2010年12月
//使用CCS版本4.2 0和IAR嵌入式工作台版本:5.10 构建
//************************************************************************************************

#include <MSP4S.h>

字符值;//要写入A段的8位值
volatile char myTemp =0;

//函数原型
void write_SegC (字符值);
CHAR COPY_C2D (void);

内部主(无效)

WDTCTL = WDTPW + WDTHOLD;//停止看门狗计时器
IF (CALBC1_1MHz=0xFF)// If calibration constant erased

while (1);//不加载,捕获CPU!!
}
DCOCTL = 0;//选择最低DCOx和MODx设置
BCSCTL1 = CALC1_1MHz;//将DCO设置为1MHz
DCOCTL = CALDCO_1MHz;
FCTL2 = FWKEY + FSSEL0 + FN1;// MCLK/3,用于闪存定时发生器
值= 0;//初始化值

while (1)//永远重复

Write_SegC (value++);//写入段C,增量值
myTemp = COPY_C2D();//将段C复制到D
__no_operation();//在此处设置断点
}
}

void write_SegC (字符值)

CHAR *Flash_PTR;//闪存指针
无符号int I;

Flash_PTR =(CHAR *) 0x1100;//初始化闪存指针
FCTL1 = FWKEY + ERASE;//设置Erase bit
FCTL3 = FWKEY;//清除锁定位
*Flash_PTR =0;//虚拟写入以擦除闪存段

FCTL1 = FWKEY + WRT;//设置写入操作的WRT位

用于(i=0;i<64;i++)

*Flash_PTR++=值;//将值写入闪存
}

FCTL1 = FWKEY;//清除WRT位
FCTL3 = FWKEY + LOCK;//设置锁定位
}

CHAR COPY_C2D (无效)

CHAR *Flash_PTRC;//段C指针
char *Flash_ptrD;//段D指针
无符号int I;
字符温度;

FLASH_PTRC =(CHAR *) 0x1100;//初始化闪存段C指针
flash_ptrD =(char *) 0x1000;//初始化闪存段D指针
FCTL1 = FWKEY + ERASE;//设置Erase bit
FCTL3 = FWKEY;//清除锁定位
*Flash_ptrD = 0;//虚拟写入以擦除闪存段D
FCTL1 = FWKEY + WRT;//设置写入操作的WRT位

用于(i=0;i<64;i++)

*Flash_ptrD++=*Flash_PTRC+;//将值段C复制到段D
}

temp =*Flash_ptrD-;

FCTL1 = FWKEY;//清除WRT位
FCTL3 = FWKEY + LOCK;//设置锁定位

回流温度;
}

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    也许我误解了您的问题,但据我所知,在0x1100处的G2553中,除了可能从0x0C00开始的基于ROM的BSL代码的某些部分之外,没有任何内容。

    G2553的闪存为INFOA-D和0xC000 - 0xFF,其它任何地方都没有。  至少这就是数据表所说的。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您不能使用不存在的内存。 链接器命令文件只描述硬件;告诉链接器在某个地址有一些内存不会创建实现内存的晶体管。

    如果您想有一些新的段,您必须使其他段变小,以便有一些实际内存可以放置它:

    XVSEG : Origin = 0xC000,length = 0x0040
    
    flash : origin = 0xC040,length = 0x3F9E
    /* ^^ ^^*/*
    更高 较小*/ 
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    谢谢,我现在看到了。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    谢谢,我将缩小闪存并添加存储计算所需的新件。 我实际上有255个双倍(这就是为什么INFOA-D段还不够),所以我将从闪存的前端分离1024个字节,用于XVSEG。 我看到写入闪存的速度非常慢。 创建255个新段(每个段4个字节)与所有段(每个段1个字节)是否有任何优势?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    闪存段大小(即必须立即擦除的内容)为512字节。 这是硬件的属性;您不能更改它。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    XVSEG:原点= 0xC000,长度= 0x0400
    Flash:原始= 0xC400,长度= 0x3BFF

    如果按上述方式映射,我将有两个512段来写入我的计算。

    一个迭代的计算方法如下所示
    1)设置擦除位,并通过将0写入0xC000擦除第一个段;通过将0写入0xC200擦除第二个段
    2)设置解锁位以便写入
    3)在For循环I=0;I<255;I++中,计算255个双精度值并将其写入0xC000 + I*4
    4)重置锁
    5)通过检查是否关闭繁忙位来添加写入后的等待

    您认为这会奏效吗? 它与闪存写入示例不同,因为我在处理器执行其他操作(计算值)时保持未锁定内存。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    从闪存执行代码时,您无需等待忙线(请参阅《用户指南》中的7.3 Tm3部分)。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我已成功创建一个1024字节的新内存段来容纳我的255个双精度内存(具有4字节的可用空间)。

    XVSEG:原点= 0xC000,长度= 0x0400
    闪光:原点= 0xC400,长度= 0x3BDE

    由于 Clemens Ladisch指出一个数据段为512字节,因此我在写入前通过在0xc000和0xc200处写入零来擦除数据。

    我可以写一个值并读回,但只能读一个值。 我无法在下一次写入前擦除,因为我需要能够在将来使用上一个值。  

    我尝试擦除,然后解锁以写入,并将其解锁以执行连续写入,但这不起作用。 也没有擦除,然后解锁和锁定超过1个写入。

    这是这样吗?还是有什么事情可以让我一次擦除一次后一次反复写入? 随附的是一个独立测试程序,用于演示问题。 我已将NZEROS从254降低到4,但问题是一样的。

    e2e.ti.com/.../FIR_5F00_LPF_5F00_test.c

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    如果您解锁并启用每次写入的写入功能,它是否有效?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    是的,这很有效。

    我取得了一些进步:首先,我在 家庭指南的7.3 第3节中发现了这一关键句子,它回答了我的问题:“一个快速字(低字节和高字节)在擦除之间不能写超过两次。 否则可能会造成损坏。 "

    所以我认为我所要做的是不可能的。 但现在我看到了另一种可行的方法。 也就是说,如果我使用两个1024段(即四个512段),并交替对它们进行前后写入,则每次写入所有字节时,我可以擦除一次。  

    因此,一个迭代将是:

    1)擦除数据段A

    2)解锁以写入

    3)将段B的值2到N复制到地址的段A:base: I,其中I增加了4个字节,因为它们是双倍

    4)计算新的第N个值,并在(2)中写入的值末尾写入A段

    5)锁定写入(现在只需要读取)

    6)进行数据处理(所有N值的求和和加权)--这只需要读

    7)返回结果

    8)反复重复,在A段和B段以及源和目标之间切换

    唯一的缺点是使用2048字节的闪存进行此操作。 我会向大家报告这方面的进展。 到目前为止,我感到非常幸运的是,我的MSP430G2553没有因两次擦写之间的多次写入尝试而受损。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您的代码实际上是否多次写入同一个单词? 写入不同的地址应该没有问题。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    是的,每个ITER,因为值的“老化”,它会不断地写入。 它们沿着阵列的长度方向行进,直到从前面落下,每次结束时都会增加一个新的值。 我想把它变成一个循环缓冲区,但即使这样,我也需要一一一一再再再再再一再,加上新的价值。

    另外一点,我发现,擦除后,段中有NaN值,而不是我想要的零,所以我也必须写零,以便在数组仍在填满时不按总和拆分。 即,前N次迭代,数组未满。 每次添加一个值(到末尾),因此它需要N次迭代,直到前面有一个值-最早的值沿着第一个位置排列。 这就是我上面提到的“老龄化”。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    闪存擦除将所有位设置为1;闪存写入(编程)将某些位设置为零。

    您应该实施一些磨损平衡算法,即将数组索引与实际值一起写入下一个空闲的闪字,然后在读取时搜索最后一个有效(=不是全部)值。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    回复: 闪存擦除将所有位设置为1;闪存写入(编程)将某些位设置为零。

    擦除后,我在内存位置看到NaN。  请参阅屏幕截图:"Flash is initial"(最初是闪存)。 我正在将零写入每个512段的基本地址。 我应该写0xFF吗? 我已经看到过对其他MSP430型号执行此操作的代码,但此型号的闪存写示例写了一个零。

    然后,当我完成分配的设置时,它是4字节到0的两倍。它第一次工作(在地址0xC400处,但下一次通过时,它将0.0 设置为0xC404和0xC408。 请参阅所附的屏幕截图FIR归零太早。 如果I=2,I=3,则会再次出现这种情况。

    .

    Clemens Ladisch 说:
    您应该实施一些磨损平衡算法,即将数组索引与实际值一起写入下一个空闲的闪字,读取时搜索最后一个有效(=不是所有)值[/QUOT]

    您为什么建议我搜索这些值? 我不能只使用我知道的地址,然后阅读该地址吗? 例如:0xC400,0xC404,0xC408,...? 您是否说它不是在我给它的地址上写的?  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    写入0xFF无效;它不会更改已擦除值中的任何内容。

    擦除后,所有位均为1;对于浮点值,这被解释为NaN。

    双精度值的大小为八个字节。

    在进行磨损平衡时,您不再知道哪个地址的价值。 将该值的较新版本写入另一个地址(该地址仍被清除),因此在读取时,必须搜索该值的最新版本。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    啊,我读了 这个e2e.ti.com/.../23.7197万 ,从这个想法来看,Double是4字节,但是sizeof()说8! 我将切换为浮动以保留相同大小的分段。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    仅需澄清一点,一旦擦除了某个段,您可以启用写入,然后按顺序或随机将值写入该段中的任何或所有地址,而无需对每个地址执行写入操作。 但正如您所说,您只应向每个位置写一次。 嗯,我想你可以多次写一个词来说明,因为这样不会有什么影响,但是最好不要抓住这个机会。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    谢谢,是的,我是这样做的。 例如,擦除后,写入整个句段时仅解锁一次写入,然后将其锁定。 它运行良好。 我会在进一步测试后将其标记为已解决。 您能否评论等待到清除占线标志的想法。 克莱门斯说,我没有必要在闪光灯下做这项工作,但其他帖子说这是必要的。  

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    您的代码是从闪存执行的,因此您无需等待忙位(请参阅《用户指南》中的7.3 .2.1 和7.3 .3.2 部分)。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    [报价用户="Dayle Kotturi"]

    谢谢,是的,我是这样做的。 例如,擦除后,写入整个句段时仅解锁一次写入,然后将其锁定。 它运行良好。 我会在进一步测试后将其标记为已解决。 您能否评论等待到清除占线标志的想法。 克莱门斯说,我没有必要在闪光灯下做这项工作,但其他帖子说这是必要的。  

    [/引述]

    我从未等过忙,所以我认为没有必要。  我认为从RAM中的代码写入时可能需要它,但是如果您的代码在闪存中,或者在ROM中,处理器在写入完成之前不会返回到您的下一个指令。  我很确信BSL也不会选中"忙碌"。

    顺便说一下,此部分中确实有512字节的RAM。  堆栈可能只需要其中的几个字节。  剩余的RAM是否足以在处理数据时保存数据?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    代码无需等待忙碌时间即可工作,因此感谢Clemens和您的建议。 RAM不是一个选项,因为我有每个计算的255个浮点数组。