前言
在电机控制系统中我们需要处理许多数据,其中对于电机位置偏移量,PID参数等数据,我们要考虑数据的长期保存和掉电保存等问题,而TC275芯片中的DFLASH模块恰好能够满足这一条件,利用外扩的EEPROM特性来存储一些参数,保存一些掉电后需要保存的数据等。
1、存储器硬件分类
1.1 ROM存储器
Read Only Memory,只读存储器,最初代表一种出厂后只能读不能写、不掉电的设备。烧入数据后,无需外加电源来保存数据,且断电数据不丢失。
-
PROM
PROM,Programmable ROM,可编程ROM。这是一种可以用刻录机将资料写入的ROM内存,但只能写入一次。PROM在出厂时,存储的内容全为1,用户可以根据需要将其中的某些单元写入数据0, 以实现对其“编程”的目的。但是这种机会只有一次,一旦写入后也无法修改,若是出了错误,已写入的芯片只能报废。 -
EPROM
EPROM,Erasable Programmable ROM,可擦除可编程ROM。这是一种具有可擦除功能,擦除后即可进行再编程的ROM内存,写入前必须先把里面的内容用紫外线照射它的IC卡上的透明视窗的方式来清除掉。 -
EPPROM
EEPROM,Electrically Erasable Programmable ROM,电可擦除可编程ROM。功能与使用方式与EPROM一样,不同之处是清除数据的方式,EEPROM的擦除不需要借助于其它设备,它是以电子信号来修改其内容的,而且是以Byte为最小修改单位,不必将资料全部洗掉才能写入,彻底摆脱了EPROM Eraser和编程器的束缚。借助于EEPROM芯片的特性,可以使BIOS具有良好的防毒功能,在升级时,把跳线开关打至“ON”的位置,即给芯片加上相应的编程电压,就可以方便地升级;平时使用时,则把跳线开关打至“OFF”的位置,防止CIH类的病毒对BIOS芯片的非法修改。
EEPROM价格很高,而且写入时间很长,写入很慢。
-
FLASH
Flash Memory,快闪存储器,具有结构简单、控制灵活、编程可靠、加电擦写快捷的优点,而且集成度可以做得很高。它综合了前面的所有优点:不会断电丢失数据,快速读取,电可擦写可编程,并且很便宜,因此成功地获得了广泛的应用。
缺点是:FLASH必须以扇区为单位清除数据,而不是以Bit或者Byte为单位访问。在写入资料时必须先将原本的资料清除掉,然后才能再写入新的资料,写入资料的速度太慢。
擦除操作
将位0变为1称为擦除,擦除只能按照Flash的扇区进行写操作
将位1变为0称为写,写可以按地址进行 -
Flash Emulation EEPROM
EEPROM啥都好,就是太贵,于是人们想到了让便宜的Flash模仿EEPROM,让只能按扇区擦除的Flash具有按地址擦除的能力。综上,可以看出ROM存储器是不断地在发展进化的,最后有了Flash Emulation EEPROM这一类的存储器,而我们今天讲的TC275芯片的DFLASH就是这种存储器,集合了各种优点。对了,上述内容大多来自这篇文章: 深入了解存储器,对微控制器的存储介绍得太全面了,字字珠玑,大家可以参考一下这篇文章。
1.2 RAM存储器
Random Access Memory,随机存储器,代表了一种能读、能写、能改的设备。RAM这个词是因为可以按寻址读取和擦写,区别于早期的计算机曾经使用顺序读写的磁鼓和磁带作为内存。他的种类特别多,主要代表有硬件家族中的内存条、CPU的一二级缓冲,设备断电后,RAM中存储的数据就会丢失。
RAM则用来存取各种动态的输入输出数据、中间计算结果以及与外部存储器交换的数据和暂存数据。运行游戏、程序速度快慢看的是RAM,也就是动态内存,不是看ROM。
1.3 专业术语介绍
- Bank(存储单元):
Bank是DFLASH中较大的存储单元,一个DFLASH模块中可以包含多个Bank。每个Bank内部划分为更小的子单元和逻辑结构。
在DFLASH中,Bank进一步分为逻辑扇区(Logical Sector)和子扇区(Sub-Sector)。 - Sector(扇区):
Sector指的是逻辑扇区,是Bank中的一个部分。它由多个Page(页)组成。
扇区是可以进行擦除操作的基本单元,也就是说,擦除操作是以Sector为单位进行的。 - Page(页):
Page是Sector中的最小存储单元。在DFLASH中,一个Page通常是8字节大小。
Page是可以被编程和写入数据的基本单元。
本文讲的主要是DFLASH,它是Flash Emulation EEPROM,ROM存储器的一种,因此对于RAM存储器在此就不多做赘述了,想要深入了解的可以上面我提到的文章,讲得特别好。
2、TC275芯片存储器介绍
从图中可以看出,TC275芯片有PFlash和DFlash这两种FLASH,Pflash用于存储程序代码和只读数据;而Dflash则用于存储应用程序中的可变数据Dflash允许在运行时对数据进行擦除和编程,以满足应用的需求。其中PFlash有PF0和PF1,DFlash有DF0和DF1,今天我们着重介绍一下DFlash:
-
DF0:是所有CPU共用的数据区,一共400KB的空间。其中包含了EEPROM和UCB(User Configuration Block两个模块,其中UCB就是用户可以设置密码用来擦写的区域。
EEPROM一共分为48个Sector,每个Sector为8KB,一共384KB的空间,偏移地址为0xAF00 0000。
UCB一共分为16个Sector,每个Sector为1KB,一共16KB的空间,偏移地址为0xAF10 0000。
-
DF1:是Hardware Security Module的数据区, 分为8个Sector,每个Sector为8KB,一共64KB的空间,偏移地址为0xAF11 0000。
3.代码配置
这里我先在ADS编译环境中导入有关TC275芯片DFlash实现的例程,可以发现例程中它将DFlash和PFlash结合到一起的,我们可以先屏蔽调有关PFlash的代码。
- 可以先不用看以下函数:
void initLEDs(void); /* Function that initializes the LEDs */
void writeProgramFlash(void); /* Function that flashes the Program Flash memory calling the routines from the PSPR*/
void verifyProgramFlash(void); /* Function that verifies the data written in the Program Flash memory */
1.写入数据
代码如下:
void write_CURRENTPI_DataFlash(void)
{
uint16 endInitSafetyPassword = IfxScuWdt_getSafetyWatchdogPassword();
/* Erase the sector */
IfxScuWdt_clearSafetyEndinit(endInitSafetyPassword); /* Disable EndInit protection */
IfxFlash_eraseMultipleSectors(DFLASH_STARTING_ADDRESS_CURRENTPI, DFLASH_SECTORS_CLAERNUM); /* Erase the given sector DFLASH_NUM_SECTORS */
IfxScuWdt_setSafetyEndinit(endInitSafetyPassword); /* Enable EndInit protection */
/* Wait until the sector is erased */
IfxFlash_waitUnbusy(FLASH_MODULE, DATA_FLASH_0);
uint32 pageAddr = DFLASH_STARTING_ADDRESS_CURRENTPI + (page_Offeset_0 * DFLASH_PAGE_LENGTH); /* Get the address of the page */
/* Enter in page mode */
IfxFlash_enterPageMode(pageAddr);
/* Wait until page mode is entered */
IfxFlash_waitUnbusy(FLASH_MODULE, DATA_FLASH_0);
/* Load data to be written in the page */
IfxFlash_loadPage2X32(pageAddr, CURRENT_KP,CURRENT_KI); /* Load two words of 32 bits each */
/* Write the loaded page */
IfxScuWdt_clearSafetyEndinit(endInitSafetyPassword); /* Disable EndInit protection */
IfxFlash_writePage(pageAddr); /* Write the page */
IfxScuWdt_setSafetyEndinit(endInitSafetyPassword); /* Enable EndInit protection */
/* Wait until the data is written in the Data Flash memory */
IfxFlash_waitUnbusy(FLASH_MODULE, DATA_FLASH_0);
}
该处是用来写入电流PI参数的代码,其中需要注意以下几个函数接口的使用:
-
IfxFlash_eraseMultipleSectors(DFLASH_STARTING_ADDRESS_CURRENTPI, DFLASH_SECTORS_CLAERNUM)
在数据写入之前必须要先擦除该区域的数据,该例程中是按扇区来擦除的,其中
DFLASH_STARTING_ADDRESS_CURRENTPI
表示起始地址,根据上文的图片这里我选择的是0xAF006000
,DFLASH_SECTORS_CLAERNUM
表示擦除扇区的数目是1。这个函数实现的就是从起始地址0xAF006000开始擦除1个扇区。
-
uint32 pageAddr = DFLASH_STARTING_ADDRESS_CURRENTPI + (page_Offeset_0 * DFLASH_PAGE_LENGTH)
这里需要着重说的是
page_Offeset_0
和DFLASH_PAGE_LENGTH
,DFLASH_PAGE_LENGTH表示每次根据起始地址偏移的大小
,Page是Sector中的最小存储单元。在DFLASH中,一个Page通常是8字节大小,为了最大的利用DFlash的空间,这里我选择的是8个字节,而
page_Offeset_0
则表示偏移的次数,这里我选择的是1**。 -
IfxFlash_loadPage2X32(pageAddr, CURRENT_KP,CURRENT_KI)
这里是将CURRENT_KP,CURRENT_KI
两个32位的数据合并为64位的数据**存放在之前定义的地址当中。
2.读取数据
代码如下:
#define MEM(address) *((uint32 *)(address)) /* Macro to simplify the access to a memory address */
void ReadDataFlash_Calibration(void)
{
uint32 Addr_offset = 4; /* Variable to cycle over all the words in a page */
CurrentKP_Read = MEM(pageAddr_CurrentKPI);
CurrentKI_Read = MEM(pageAddr_CurrentKPI+Addr_offset);
}
由于是数据是两个32位合成的,因此利用定义的宏函数MEM
对相对应的地址进行解引用,同时每次读取4个字节的数据即可将每一个数据完整的读取出来了。
总结
TC275芯片拥有着丰富的存储空间,对于DFlash组件来说,我们仔细阅读手册,确定好起始地址,以及空间大小再根据相关例程便可以实现相关参数的存储,下图是我利用CAN总线在上位机进行参数的修改和存储,成功实现电流PI参数的掉电存储。