AURIX TC397 Flash编程_data memory uint(dmu),2024年最新物联网嵌入式开发进阶学习资料

223 阅读8分钟
  • 数据存储单元(DMU, Data Memory Unit)控制执行在PFLASH和DFLASH上的命令序列, 连接FSI(Flash Standard Interface)和PFI(Programming Flash Interface).
  • FSI在所有闪存上执行擦除, 编程和验证操作.
  • PFI为每个PFLASH块与CPU提供唯一的点对点快速连接
  • TC39x 提供 6 Program Flash Banks(PFx) 和 2 Data Flash Banks(DFx)
  • TC3xx 具有相同扇区结构的PFLASH块PFx, PFx块大小可能不用: 3/2/1 Mbyte Program Flash Bank
  • TC39x 有5个3MB大小的PFx(PF0…PF4) 和 1个1MB大小的PF5. 每个PFx被划分为1024KB大小的物理扇区(Physical Sectors), 每个物理扇区又被划分为16KB大小的逻辑扇区(Logical Sectors)
  • TC39x具有两个数据闪存存储区DFLASH0和DFLASH1, 两者都包括多个通常用于EEPROM仿真的EEPROM扇区. 仅DFLASH0包含用于数据保护的用户配置块(UCBs, User Configuration Blocks)和1个配置扇区(CFS, Configuration Sector), 用户无法直接访问该配置扇区.
  • DFLASH EEPROM可以配置为单端模式(默认)或补码检测(incomplement sensing). 根据所选模式, 每个扇区的大小分别设置为4KB和2KB
  • 闪存中可以编程的最小数据量是页(Page), 程序闪存(Program Flash)页由32字节组成, 数据闪存(Data Flash)页由8字节组成
  • 仅在擦除操作后才能对页面进行编程
  • 可以执行擦除操作的最小单元是逻辑扇区(Logical Sector)

TC39x Program Flash Memeory:

在这里插入图片描述

TC39x Data Flash memory:

在这里插入图片描述

所有闪存操作均通过命令序列执行, DMU具有命令序列解释器(CSI, Command Sequence Interpreter)来处理命令序列, 用于对程序闪存或数据闪存进行编程的最小命令序列如下:

  • 擦除逻辑扇区待编程
  • 等待直到闪存就绪(不忙)
  • 进入页面模式
  • 等待直到闪存就绪(不忙)
  • 加载要写入页面的数据
  • 写页面
  • 等待直到闪存内存已准备就绪(不忙)

注:执行PFLASH编程或擦除的代码不应从同一PFLASH执行

PF0…PF5的地址映射为:

Address RangeSizeDescriptionReadWrite
A000 0000H - A02F FFFFH3 MbyteProgram Flash 0 (PF0)AccessSRIBE
A030 0000H - A05F FFFFH3 MbyteProgram Flash 1 (PF1)AccessSRIBE
A060 0000H - A08F FFFFH3 MbyteProgram Flash 2 (PF2)AccessSRIBE
A090 0000H - A0BF FFFFH3 MbyteProgram Flash 3 (PF3)AccessSRIBE
A0C0 0000H - A0EF FFFFH3 MbyteProgram Flash 4 (PF4)AccessSRIBE
A0F0 0000H - A0FF FFFFH1 MbyteProgram Flash 5 (PF5)AccessSRIBE

其中, SRIBE: A bus access is terminated with a bus error on the SRI(SRI上的总线错误终止总线访问)

DF0…DF1的地址映射为:

Address RangeSizeDescriptionReadWrite
AF00 0000H - AF0F FFFFH1 MbyteData Flash 0 EEPROM (DF0) Host Comd. Sequence InterpreterAccessAccess 1)
AF10 0000H - AF3F FFFFH3 MbyteReservedSRIBESRIBE
AF40 0000H - AF40 5FFFH24 KbyteData Flash 0 UCB (DF0)AccessSRIBE
AF40 6000H - AF7F FFFFH-ReservedSRIBESRIBE
AF80 0000H - AF80 FFFFH64 KbyteData Flash 0 CFS (DF0)AccessSRIBE
AF81 0000H - AFBF FFFFH-ReservedSRIBESRIBE
AFC0 0000H - AFC1 FFFFH128 KbyteData Flash 1 EEPROM (DF1) HSM Comd. Sequence InterpreterAccessAccess 2)

其中:

    1. Host Command Sequence Interpreter(主机命令序列解释器)
    1. HSM Command Sequence Interpreter(HSM命令序列解释器)

Flash Programming

直接搬运官方的例程来看, 此例中, 程序闪存(PFLASH)的64个字节随后被烧写并验证. 此外, 烧写并验证了64字节的数据闪存(DFLASH). 在进行任何写操作之前, 将擦除闪存, 如果闪存烧写并验证成功, 则将打开每个测试内存的LED.

闪存中可以编程的最小数据量是页(Page), 程序闪存(Program Flash)页由32字节组成, 数据闪存(Data Flash)页由8字节组成, 所以64字节对应PFLASH的2页, DFLASH的8页.

Cpu0_Main.c 代码如下:

#include "Ifx\_Types.h"
#include "IfxCpu.h"
#include "IfxScuWdt.h"

IFX\_ALIGN(4) IfxCpu_syncEvent g_cpuSyncEvent = 0;

#include <string.h>
#include "Ifx\_Types.h"
#include "IfxFlash.h"
#include "IfxCpu.h"

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 writeDataFlash(void);      /\* Function that flashes the Data Flash memory \*/
void verifyProgramFlash(void);  /\* Function that verifies the data written in the Program Flash memory \*/
void verifyDataFlash(void);     /\* Function that verifies the data written in the Data Flash memory \*/

#define PFLASH\_PAGE\_LENGTH IFXFLASH\_PFLASH\_PAGE\_LENGTH /\* 0x20 = 32 Bytes (smallest unit that can be
 \* programmed in the Program Flash memory (PFLASH)) \*/
#define DFLASH\_PAGE\_LENGTH IFXFLASH\_DFLASH\_PAGE\_LENGTH /\* 0x8 = 8 Bytes (smallest unit that can be
 \* programmed in the Data Flash memory (DFLASH)) \*/
#define FLASH\_MODULE 0 /\* Macro to select the flash (PMU) module \*/
#define PROGRAM\_FLASH\_0 IfxFlash\_FlashType\_P0 /\* Define the Program Flash Bank to be used \*/
#define DATA\_FLASH\_0 IfxFlash\_FlashType\_D0 /\* Define the Data Flash Bank to be used \*/

#define DATA\_TO\_WRITE 0x07738135 /\* Dummy data to be written into the Flash memories \*/

#define PFLASH\_STARTING\_ADDRESS 0xA00E0000 /\* Address of the PFLASH where the data is written \*/
#define DFLASH\_STARTING\_ADDRESS 0xAF000000 /\* Address of the DFLASH where the data is written \*/

#define PFLASH\_NUM\_PAGE\_TO\_FLASH 2 /\* Number of pages to flash in the PFLASH \*/
#define PFLASH\_NUM\_SECTORS 1 /\* Number of PFLASH sectors to be erased \*/
#define DFLASH\_NUM\_PAGE\_TO\_FLASH 8 /\* Number of pages to flash in the DFLASH \*/
#define DFLASH\_NUM\_SECTORS 1 /\* Number of DFLASH sectors to be erased \*/

/\* Reserved space for erase and program routines in bytes \*/
#define ERASESECTOR\_LEN (100)
#define WAITUNBUSY\_LEN (100)
#define ENTERPAGEMODE\_LEN (100)
#define LOADPAGE2X32\_LEN (100)
#define WRITEPAGE\_LEN (100)
#define ERASEPFLASH\_LEN (0x100)
#define WRITEPFLASH\_LEN (0x200)

/\* Relocation address for the erase and program routines: Program Scratch-Pad SRAM (PSPR) of CPU0 \*/
#define RELOCATION\_START\_ADDR (0x70100000U)

/\* Definition of the addresses where to relocate the erase and program routines, given their reserved space \*/
#define ERASESECTOR\_ADDR (RELOCATION\_START\_ADDR)
#define WAITUNBUSY\_ADDR (ERASESECTOR\_ADDR + ERASESECTOR\_LEN)
#define ENTERPAGEMODE\_ADDR (WAITUNBUSY\_ADDR + WAITUNBUSY\_LEN)
#define LOAD2X32\_ADDR (ENTERPAGEMODE\_ADDR + ENTERPAGEMODE\_LEN)
#define WRITEPAGE\_ADDR (LOAD2X32\_ADDR + LOADPAGE2X32\_LEN)
#define ERASEPFLASH\_ADDR (WRITEPAGE\_ADDR + WRITEPAGE\_LEN)
#define WRITEPFLASH\_ADDR (ERASEPFLASH\_ADDR + ERASEPFLASH\_LEN)

/\* Definition of the LEDs port pins \*/
#define LED1 &MODULE\_P13,0 /\* LED connected to Port 13, Pin 0 \*/
#define LED2 &MODULE\_P13,1 /\* LED connected to Port 13, Pin 1 \*/

#define MEM(address) \*((uint32 \*)(address)) /\* Macro to simplify the access to a memory address \*/

/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
/\*------------------------------------------------Function Prototypes------------------------------------------------\*/
/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
void erasePFLASH(uint32 sectorAddr);
void writePFLASH(uint32 startingAddr);
void copyFunctionsToPSPR(void);

typedef struct
{
    void (\*eraseSectors)(uint32 sectorAddr, uint32 numSector);
    uint8 (\*waitUnbusy)(uint32 flash, IfxFlash_FlashType flashType);
    uint8 (\*enterPageMode)(uint32 pageAddr);
    void (\*load2X32bits)(uint32 pageAddr, uint32 wordL, uint32 wordU);
    void (\*writePage)(uint32 pageAddr);
    void (\*eraseFlash)(uint32 sectorAddr);
    void (\*writeFlash)(uint32 startingAddr);
} Function;

/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
/\*-------------------------------------------------Global variables--------------------------------------------------\*/
/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
Function g_commandFromPSPR;

/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
/\*---------------------------------------------Function Implementations----------------------------------------------\*/
/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
/\* Function to initialize the LEDs \*/
void initLEDs()
{
    /\* Configure LED1 and LED2 port pins \*/
    IfxPort\_setPinMode(LED1, IfxPort_Mode_outputPushPullGeneral);
    IfxPort\_setPinMode(LED2, IfxPort_Mode_outputPushPullGeneral);

    /\* Turn off the LEDs (LEDs are low-level active) \*/
    IfxPort\_setPinState(LED1, IfxPort_State_high);
    IfxPort\_setPinState(LED2, IfxPort_State_high);
}

/\* This function copies the erase and program routines to the Program Scratch-Pad SRAM (PSPR) of the CPU0 and assigns
 \* function pointers to them.
 \*/
void copyFunctionsToPSPR()
{
    /\* Copy the IfxFlash\_eraseMultipleSectors() routine and assign it to a function pointer \*/
    memcpy((void \*)ERASESECTOR_ADDR, (const void \*)IfxFlash_eraseMultipleSectors, ERASESECTOR_LEN);
    g_commandFromPSPR.eraseSectors = (void \*)ERASESECTOR_ADDR;

    /\* Copy the IfxFlash\_waitUnbusy() routine and assign it to a function pointer \*/
    memcpy((void \*)WAITUNBUSY_ADDR, (const void \*)IfxFlash_waitUnbusy, WAITUNBUSY_LEN);
    g_commandFromPSPR.waitUnbusy = (void \*)WAITUNBUSY_ADDR;

    /\* Copy the IfxFlash\_enterPageMode() routine and assign it to a function pointer \*/
    memcpy((void \*)ENTERPAGEMODE_ADDR, (const void \*)IfxFlash_enterPageMode, ENTERPAGEMODE_LEN);
    g_commandFromPSPR.enterPageMode = (void \*)ENTERPAGEMODE_ADDR;

    /\* Copy the IfxFlash\_loadPage2X32() routine and assign it to a function pointer \*/
    memcpy((void \*)LOAD2X32_ADDR, (const void \*)IfxFlash_loadPage2X32, LOADPAGE2X32_LEN);
    g_commandFromPSPR.load2X32bits = (void \*)LOAD2X32_ADDR;

    /\* Copy the IfxFlash\_writePage() routine and assign it to a function pointer \*/
    memcpy((void \*)WRITEPAGE_ADDR, (const void \*)IfxFlash_writePage, WRITEPAGE_LEN);
    g_commandFromPSPR.writePage = (void \*)WRITEPAGE_ADDR;

    /\* Copy the erasePFLASH() routine and assign it to a function pointer \*/
    memcpy((void \*)ERASEPFLASH_ADDR, (const void \*)erasePFLASH, ERASEPFLASH_LEN);
    g_commandFromPSPR.eraseFlash = (void \*)ERASEPFLASH_ADDR;

    /\* Copy the erasePFLASH() routine and assign it to a function pointer \*/
    memcpy((void \*)WRITEPFLASH_ADDR, (const void \*)writePFLASH, WRITEPFLASH_LEN);
    g_commandFromPSPR.writeFlash = (void \*)WRITEPFLASH_ADDR;
}

/\* This function erases a given sector of the Program Flash memory. The function is copied in the PSPR through
 \* copyFunctionsToPSPR(). Because of this, inside the function, only routines from the PSPR or inline functions
 \* can be called, otherwise a Context Type (CTYP) trap can be triggered.
 \*/
void erasePFLASH(uint32 sectorAddr)
{
    /\* Get the current password of the Safety WatchDog module \*/
    uint16 endInitSafetyPassword = IfxScuWdt\_getSafetyWatchdogPasswordInline();

    /\* Erase the sector \*/
    IfxScuWdt\_clearSafetyEndinitInline(endInitSafetyPassword);      /\* Disable EndInit protection \*/
    g_commandFromPSPR.eraseSectors(sectorAddr, PFLASH_NUM_SECTORS); /\* Erase the given sector \*/
    IfxScuWdt\_setSafetyEndinitInline(endInitSafetyPassword);        /\* Enable EndInit protection \*/

    /\* Wait until the sector is erased \*/
    g_commandFromPSPR.waitUnbusy(FLASH_MODULE, PROGRAM_FLASH_0);
}

/\* This function writes the Program Flash memory. The function is copied in the PSPR through copyFunctionsToPSPR().
 \* Because of this, inside the function, only routines from the PSPR or inline functions can be called,
 \* otherwise a Context Type (CTYP) trap can be triggered.
 \*/
void writePFLASH(uint32 startingAddr)
{
    uint32 page;                                                /\* Variable to cycle over all the pages \*/
    uint32 offset;                                              /\* Variable to cycle over all the words in a page \*/

    /\* Get the current password of the Safety WatchDog module \*/
    uint16 endInitSafetyPassword = IfxScuWdt\_getSafetyWatchdogPasswordInline();

    /\* Write all the pages \*/
    for(page = 0; page < PFLASH_NUM_PAGE_TO_FLASH; page++)              /\* Loop over all the pages \*/
    {
        uint32 pageAddr = startingAddr + (page \* PFLASH_PAGE_LENGTH);   /\* Get the address of the page \*/

        /\* Enter in page mode \*/
        g_commandFromPSPR.enterPageMode(pageAddr);

        /\* Wait until page mode is entered \*/
        g_commandFromPSPR.waitUnbusy(FLASH_MODULE, PROGRAM_FLASH_0);

        /\* Write 32 bytes (8 double words) into the assembly buffer \*/
        for(offset = 0; offset < PFLASH_PAGE_LENGTH; offset += 0x8)     /\* Loop over the page length \*/
        {
            g_commandFromPSPR.load2X32bits(pageAddr, DATA_TO_WRITE, DATA_TO_WRITE); /\* Load 2 words of 32 bits each \*/
        }

        /\* Write the page \*/
        IfxScuWdt\_clearSafetyEndinitInline(endInitSafetyPassword);      /\* Disable EndInit protection \*/
        g_commandFromPSPR.writePage(pageAddr);                          /\* Write the page \*/
        IfxScuWdt\_setSafetyEndinitInline(endInitSafetyPassword);        /\* Enable EndInit protection \*/

        /\* Wait until the page is written in the Program Flash memory \*/
        g_commandFromPSPR.waitUnbusy(FLASH_MODULE, PROGRAM_FLASH_0);
    }
}

/\* This function flashes the Program Flash memory calling the routines from the PSPR \*/
void writeProgramFlash()
{
    boolean interruptState = IfxCpu\_disableInterrupts(); /\* Get the current state of the interrupts and disable them\*/

    /\* Copy all the needed functions to the PSPR memory to avoid overwriting them during the flash execution \*/
    copyFunctionsToPSPR();

    /\* Erase the Program Flash sector before writing \*/
    g_commandFromPSPR.eraseFlash(PFLASH_STARTING_ADDRESS);

    /\* Write the Program Flash \*/
    g_commandFromPSPR.writeFlash(PFLASH_STARTING_ADDRESS);

    IfxCpu\_restoreInterrupts(interruptState);            /\* Restore the interrupts state \*/
}

/\* This function verifies if the data has been correctly written in the Program Flash \*/
void verifyProgramFlash()
{
    uint32 page;                                                /\* Variable to cycle over all the pages \*/
    uint32 offset;                                              /\* Variable to cycle over all the words in a page \*/
    uint32 errors = 0;                                          /\* Variable to keep record of the errors \*/

    /\* Verify the written data \*/
    for(page = 0; page < PFLASH_NUM_PAGE_TO_FLASH; page++)                          /\* Loop over all the pages \*/
    {
        uint32 pageAddr = PFLASH_STARTING_ADDRESS + (page \* PFLASH_PAGE_LENGTH);    /\* Get the address of the page \*/

        for(offset = 0; offset < PFLASH_PAGE_LENGTH; offset += 0x4)                 /\* Loop over the page length \*/
        {
            /\* Check if the data in the Program Flash is correct \*/
            if(MEM(pageAddr + offset) != DATA_TO_WRITE)
            {
                /\* If not, count the found errors \*/
                errors++;
            }
        }
    }

    /\* If the data is correct, turn on the LED1 \*/
    if(errors == 0)
    {
        IfxPort\_setPinState(LED1, IfxPort_State_low);
    }
}

/\* This function flashes the Data Flash memory.
 \* It is not needed to run this function from the PSPR, thus functions from the Program Flash memory can be called
 \* inside.
 \*/
void writeDataFlash()
{
    uint32 page;                                                /\* Variable to cycle over all the pages \*/

    /\* --------------- ERASE PROCESS --------------- \*/
    /\* Get the current password of the Safety WatchDog module \*/
    uint16 endInitSafetyPassword = IfxScuWdt\_getSafetyWatchdogPassword();

    /\* Erase the sector \*/


**收集整理了一份《2024年最新物联网嵌入式全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升的朋友。**
![img](https://p9-xtjj-sign.byteimg.com/tos-cn-i-73owjymdk6/f12e17bc7ec14128a8fa58ab47015941~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5py65Zmo5a2m5Lmg5LmL5b-DQUk=:q75.awebp?rk3s=f64ab15b&x-expires=1771856235&x-signature=nvAIVcs88TADwh68NyC1jVSBvGg%3D)
![img](https://p9-xtjj-sign.byteimg.com/tos-cn-i-73owjymdk6/c2c554049993488d8332fdbfe8e1a14d~tplv-73owjymdk6-jj-mark-v1:0:0:0:0:5o6Y6YeR5oqA5pyv56S-5Yy6IEAg5py65Zmo5a2m5Lmg5LmL5b-DQUk=:q75.awebp?rk3s=f64ab15b&x-expires=1771856235&x-signature=pmg5yuWJmU6nJRVcYoyBydFWP78%3D)

**[如果你需要这些资料,可以戳这里获取](https://gitee.com/vip204888)**

**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人**

**都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**