F28335第十六篇——内部Flash操作

前言

本文主要介绍如何对DSP28335进行Flash操作。

本文主要参考资料:

  • TI.Flash2833x_API_Readme

DSP的Flash操作需要借助官方提供API。官方提供的API主要完成Flash的擦除,编写,校验三种功能。

Flash编写,只能将数据位由1变成0,而无法由0变成1。所以,在每次需要刷新程序时,需要对Flash进行先擦除,再编写。最后防止出现错误,还需要进行校验。而DSP的Flash擦除操作中,其最小的擦除单位为扇区。而编写的最小单位为字(16位)。编写操作不会改变之前已经编写过的数据位。例如,在Flash中,可以不需要擦除的情况下,将已经编写为0xFFFE的数据重写编写为0xFFFC。但是,相反的操作是不允许的。

配置方法

下面介绍如何使用Flash API。

  1. 到官网下载sprc539压缩包。

  2. 将Flash2833x_API_Library.h和Flash2833x_API_Config.h两个头文件添加到项目工程中。

  3. 添加Flash28335_API_V210.lib文件到项目中。首先,需要将lib文件添加到项目工程中。其次,需要在CCS中添加lib所在的路径。
    在这里插入图片描述

  4. 将Flash API函数复制到SARAM中。这主要有两点原因:一,Flash API需要严格的时间限制。将函数复制到SARAM中,函数调用是无延时的,能够保证函数每个步骤的时序是正确的。二,因为Flash API是用于操作Flash中的数据的。若将函数放置于Flash中,有可能在程序运行中,函数代码被修改,造成程序失控。

其具体操作如下:
在cmd文件中添加如下代码:

   /* The Flash API functions can be grouped together as shown below.
      The defined symbols _Flash28_API_LoadStart, _Flash28_API_LoadEnd
      and _Flash28_API_RunStart are used to copy the API functions out
      of flash memory and into SARAM */

   Flash28_API:
   {
        -lFlash28335_API_V210.lib(.econst) 
        -lFlash28335_API_V210.lib(.text)
   }                   LOAD = FLASHA, 
                       RUN = RAML0,  
                       LOAD_START(_Flash28_API_LoadStart),
                       LOAD_END(_Flash28_API_LoadEnd),
                       RUN_START(_Flash28_API_RunStart),
                       PAGE = 0

修改cmd文件,可以在SARAM和Flash中分配好存储程序的空间。但是,在程序下载过程中,程序数据只会烧写进Flash中。而在SARAM中,虽然分配好了存储空间,程序数据的拷贝还需要自己在代码中实现。在main函数中添加如下语句:

  MemCopy(&Flash28_API_LoadStart, &Flash28_API_LoadEnd, &Flash28_API_RunStart);

其中,Memcopy函数的定义如下:

void 
MemCopy(Uint16 *SourceAddr, Uint16* SourceEndAddr, Uint16* DestAddr)
{
    while(SourceAddr < SourceEndAddr)
    { 
        *DestAddr++ = *SourceAddr++;
    }
    return;
}

经过以上步骤的设置,Flash API就成功的添加到项目中了。但是,还是需要注意一下几点:

  1. 确保系统时钟的频率是正确的,一般设置为150M。
  2. 不要工作在limp模式中。
  3. 关闭中断和看门狗。

下面重点介绍常用函数的使用方法。

擦除函数

extern Uint16  Flash_Erase(Uint16 SectorMask, FLASH_ST *FEraseStat);

Flash_Eraseh函数用于擦除指定的扇区。

参数:

  1. SectorMask:需要被擦除的扇区。其参数在头文件中有定义,代码如下所示。选择对应的扇区,即可擦除其内容。当然可以同时选择多个扇区,主需要将他们位或即可。
#define SECTORA   (Uint16)0x0001
#define SECTORB   (Uint16)0x0002
#define SECTORC   (Uint16)0x0004
#define SECTORD   (Uint16)0x0008
#define SECTORE   (Uint16)0x0010
#define SECTORF   (Uint16)0x0020
#define SECTORG   (Uint16)0x0040
#define SECTORH   (Uint16)0x0080
#define SECTOR_F28335 (SECTORA|SECTORB|SECTORC|\
                       SECTORD|SECTORE|SECTORF|\
                       SECTORG|SECTORH)
  1. FeraseStat:为结构体。定义为:
typedef struct {
    Uint32  FirstFailAddr;//第一出错的地址
    Uint16  ExpectedData;//期望值
    Uint16  ActualData;//实际值
}FLASH_ST;

注意:
在本函数中,只有第一个成员FirstFailAddr有意义。

返回值:

返回值表示函数的状态,其具体的取值如下定义:

// Operation passed, no errors were flagged
#define STATUS_SUCCESS                        0   

// The CSM is preventing the function from performing its operation
#define STATUS_FAIL_CSM_LOCKED               10

// Device REVID does not match that required by the API
#define STATUS_FAIL_REVID_INVALID            11
    
// Invalid address passed to the API
#define STATUS_FAIL_ADDR_INVALID             12

// Incorrect PARTID
// For example the F2806 API was used on a F2808 device. 
#define STATUS_FAIL_INCORRECT_PARTID         13

// API/Silicon missmatch.  An old version of the
// API is being used on silicon it is not valid for
// Please update to the latest API. 
#define STATUS_FAIL_API_SILICON_MISMATCH     14

// ---- Erase Specific errors ---- 
#define STATUS_FAIL_NO_SECTOR_SPECIFIED      20
#define STATUS_FAIL_PRECONDITION             21
#define STATUS_FAIL_ERASE                    22
#define STATUS_FAIL_COMPACT                  23
#define STATUS_FAIL_PRECOMPACT               24

// ---- Program Specific errors ----  
#define STATUS_FAIL_PROGRAM                  30
#define STATUS_FAIL_ZERO_BIT_ERROR           31

// ---- Verify Specific errors ----
#define STATUS_FAIL_VERIFY                   40

// Busy is set by each API function before it determines
// a pass or fail condition for that operation.  
// The calling function will will not receive this 
// status condition back from the API
#define STATUS_BUSY                999    

编写和校验函数

extern Uint16  Flash_Program(Uint16 *FlashAddr, Uint16 *BufAddr, Uint32 Length, FLASH_ST *FProgStatus);
extern Uint16  Flash_Verify(Uint16 *StartAddr, Uint16 *BufAddr, Uint32 Length, FLASH_ST *FVerifyStat);

因为编写和校验函数使用方法基本一致,所以放置到一起讲解。编写函数就是将数据写入到Flash中,校验函数就是校验写入到Flash中的数据和预期数据是否一致。

参数:

  1. FlashAddr:16位数据地址,指向函数作用的Flash首地址。
  2. BufAddr:16为数据地址,指向将要被编写/校验数据的首地址。
  3. Length:16位数据,表示即将编写/校验数据的长度。
  4. FprogStatus:结构体,前文已经介绍。

返回值:

和前文一致,不再介绍。

### 关于 F28335 擦除 Flash 失败的原因分析 针对F28335擦除Flash失败的情况,通常涉及几个可能的因素。这些因素不仅限于硬件连接问题、配置不当以及保护机制触发等问题。 #### 硬件连接问题 确保目标板上的电源供应稳定可靠,并且编程器与微控制器之间的接口连线无误非常重要。任何物理层面上的接触不良都可能导致通信中断从而引发擦除操作失败[^1]。 #### 配置参数不匹配 检查所使用的开发环境中的设置是否正确至关重要。这包括但不限于时钟频率设定、等待状态数目以及其他影响访问速度的相关参数。错误的配置可能会使CPU无法正常工作在预期条件下完成必要的初始化过程,进而妨碍到后续的操作如擦除Flash等动作的成功执行[^2]。 #### 读取保护或写入锁定功能启用 某些情况下,MCU内部可能存在某种形式的安全措施用来防止非法修改程序代码区的内容;当此类特性处于激活状态下,则会阻止任何形式的数据更改尝试——无论是通过调试工具还是应用程序本身发起的动作都会遭到拒绝并返回相应的异常报告给用户界面显示出来作为警告信号提醒开发者注意当前状况的存在及其潜在风险所在之处[^3]。 为了验证这一点可以进入设备特定寄存器查看相应标志位的状态或者查阅官方文档了解如何禁用上述提到的功能以排除它们可能是造成此次事件发生背后隐藏着真正元凶的可能性之一。 ```c // 假设有一个函数用于清除所有扇区的选择状态 void unselectAllSectors(void){ // 清楚所有选中项... } ```
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值