MC9S12XEP100的Flash包含:
- 128KB的P-Flash 内存,由两个物理Flash block组成,用于存储非易失性代码。
- 32KB的D-Flash内存,由一个物理Flash block组成,可作为Flash内存存储非易失性数据,或用于支持内建的模拟EEPROM。
- 2KB的缓存RAM,由一个物理RAM block组成,可用作普通的RAM,或者用于支持内建的模拟EEPROM。
MC9S12(X)系列单片机的Flash内存可以在不加外部电压的情况下自我重编程(擦除/写入),这是通过FTM模块提供的一个内存控制器来完成的,内存控制器独立于内核运行,用户通过给内存控制器传递命令及参数以使内存控制器修改Flash内存内容或配置模拟EEPROM资源;控制过程如下图:
本驱动程序对这个控制过程进行了封装(即FTM_LaunchCommand函数),并进一步对所有可用的命令进行了封装,提供了用户友好的接口,方便各位使用。
下面上代码:
先是FTM.h文件
/*
*********************************************************************************************************
*
*
* FLASH TECHNOLOGY MODULE SUPPORT MODULE
* FREESCALE MC9S12XEP100
* 飞思卡尔单片机 FLASH模块(FTM) 支持包
*
* File : FTM.h
* By : Lin Shijun(http://blog.csdn.net/lin_strong)
* Date : 2018/04/12
* Version : V2.0
* Note : 1. this module is customized for MC9S12XEP100. If used for other derivation, it may need
* some modification according to the PARTID.
* History : 2018/03/12 v1.0 prototype of the package.
* 2018/03/31 v1.1 a little modification.
* 2018/04/12 v2.0 encapsulate all of the FLASH COMMON COMMAND into more user-friendly interface.
*********************************************************************************************************
*/
#ifndef _FTM_H
#define _FTM_H
/*
*********************************************************************************************************
* TYPE DEFINITION 类型定义
*********************************************************************************************************
*/
/*** FSTAT - Flash Status Register; ***/
typedef union {
unsigned char Byte;
struct {
unsigned int MGSTAT0 :1; /* Memory Controller Command Completion Status Flag 0 */
unsigned int MGSTAT1 :1; /* Memory Controller Command Completion Status Flag 1 */
unsigned int :1;
unsigned int MGBUSY :1; /* Memory Controller Busy Flag */
unsigned int FPVIOL :1; /* Flash Protection Violation Flag */
unsigned int ACCERR :1; /* Flash Access Error Flag */
unsigned int :1;
unsigned int CCIF :1; /* Command Complete Interrupt Flag */
} Bits;
} FTM_FSTAT;
#define FTM_FSTAT_MASK_MGSTAT0 1U
#define FTM_FSTAT_MASK_MGSTAT1 2U
#define FTM_FSTAT_MASK_MGBUSY 8U
#define FTM_FSTAT_MASK_FPVIOL 16U
#define FTM_FSTAT_MASK_ACCERR 32U
#define FTM_FSTAT_MASK_CCIF 128U
#define FTM_FSTAT_MASK_ANYERR (FTM_FSTAT_MASK_MGSTAT0 | FTM_FSTAT_MASK_MGSTAT1 | FTM_FSTAT_MASK_MGBUSY |\
FTM_FSTAT_MASK_FPVIOL | FTM_FSTAT_MASK_ACCERR)
/*** FERSTAT - Flash Error Status Register; ***/
typedef union {
unsigned char Byte;
struct {
unsigned int SFDIF :1; /* Single Bit Fault Detect Interrupt Flag */
unsigned int DFDIF :1; /* Double Bit Fault Detect Interrupt Flag */
unsigned int ERSVIF0 :1; /* EEE Error Type 0 Interrupt Flag */
unsigned int ERSVIF1 :1; /* EEE Error Type 1 Interrupt Flag */
unsigned int EPVIOLIF :1; /* EEE Protection Violation Interrupt Flag */
unsigned int :1;
unsigned int PGMERIF :1; /* EEE Program Error Interrupt Flag */
unsigned int ERSERIF :1; /* EEE Erase Error Interrupt Flag */
} Bits;
} FTM_FERSTAT;
#define FTM_FERSTAT_MASK_SFDIF 1U
#define FTM_FERSTAT_MASK_DFDIF 2U
#define FTM_FERSTAT_MASK_ERSVIF0 4U
#define FTM_FERSTAT_MASK_ERSVIF1 8U
#define FTM_FERSTAT_MASK_EPVIOLIF 16U
#define FTM_FERSTAT_MASK_PGMERIF 64U
#define FTM_FERSTAT_MASK_ERSERIF 128U
#define FTM_FERSTAT_MASK_ERSVIF 12U
#define FTM_FERSTAT_MASK_ANYERR (FTM_FERSTAT_MASK_SFDIF | FTM_FERSTAT_MASK_DFDIF | FTM_FERSTAT_MASK_ERSVIF0 | \
FTM_FERSTAT_MASK_ERSVIF1 | FTM_FERSTAT_MASK_EPVIOLIF | FTM_FERSTAT_MASK_PGMERIF | \
FTM_FERSTAT_MASK_ERSERIF)
typedef union{ //Used to copy and store Flash error status registers.
unsigned short Word;
struct{
FTM_FSTAT fstat;
FTM_FERSTAT ferstat;
} Regs;
} FTM_STATUS;
#define FTM_STATUS_WORD(status) ((status).Word)
#define FTM_STATUS_FSTAT_BYTE(status) ((status).Regs.fstat.Byte)
#define FTM_STATUS_FERSTAT_BYTE(status) ((status).Regs.ferstat.Byte)
typedef struct {
// values if prior to partitioning.
// dfPart = 0xffff, erPart = 0xffff, ECOUNT = 0xffff, deadCnt = 0x00, rdyCnt = 0x00
unsigned short dfPart; // the number of D-flash Sector for genernal use. 0 - 128.
unsigned short erPart; // the number of EEE RAM sections for the FTM (Flash module) to use as EEE. 0 - 16.
unsigned short ersCnt; // sector erase count.
unsigned char deadCnt; // dead sector count.
unsigned char rdyCnt; // ready sector count.
} FTM_EEE_STATUS,*pFTM_EEE_STATUS;
typedef struct {
unsigned short word0;
unsigned short word1;
unsigned short word2;
unsigned short word3;
} INT64U,FTM_KEYGEN;
/*
*********************************************************************************************************
* FLASH COMMON COMMAND FLASH通用命令
*********************************************************************************************************
*/
/**** P-Flash and D-Flash Commands ****/
#define ERASE_VERIFY_ALL_BLOCKS 0x01
// Verify that all program and data Flash blocks are erased.
// CCOBIX end = 0
// CCOB Params - NONE
// MGSTAT set if fault
#define ERASE_VERIFY_BLOCK 0x02
// Verify that a Flash block is erased.
// CCOBIX end = 0
// CCOB Params - gpage
// MGSTAT set if fault
#define ERASE_ALL_BLOCKS 0x08
// Erase all program and data Flash blocks.
// An erase of all Flash blocks is only possible when the FPLDIS, FPHDIS, and FPOPEN
// bits in the FPROT register and the EPDIS and EPOPEN bits in the EPROM register are
// set prior to launching the command.
// CCOBIX end = 0
// CCOB Params - NONE
// MGSTAT set if fault, FPVIOL / ACCERR set where appropriate
#define UNSECURE_FLASH 0x0B
// Supports a method of releasing MCU security by erasing all program and data Flash
// blocks and verifying that all program and data Flash blocks are erased.
// CCOBIX end = 0
// CCOB Params - NONE
// MGSTAT set if fault
#define SET_USER_MARGIN_LEVEL 0x0D
// Specifies a user margin read level for all program Flash blocks.
// CCOBIX end = 1
// CCOB Params - gpage, level setting (0-2) in CCOB[1]
// ACCERR set if invalid level
#define SET_FIELD_MARGIN_LEVEL 0x0E
// Specifies a field margin read level for all program Flash blocks (special modes only).
// CCOBIX end = 1
// CCOB Params - gpage, level setting (0-4) in CCOB[1]
// ACCERR set if invalid level
/* **** P-Flash Only Commands ****/
#define ERASE_VERIFY_P_FLASH_SECTION 0x03
// Verify that a given number of words starting at the address provided are erased.
// CCOBIX end = 2
// CCOB Params - global address, number of phrases in CCOB[2]
// MGSTAT set if fault
#define READ_ONCE 0x04
// Read a phrase from a dedicated 64 word area in a hidden region of a programFlash block
// that was previously programmed using the Program Once command.
// CCOBIX end = 1
// CCOB Params - read once index (0-3) in CCOB[1], phrase in CCOB [5:2]
// returns phrase in CCOB [4:1]
#define LOAD_DATA_FIELD 0x05
// Load data for simultaneous multiple program Flash block operations.
// CCOBIX end = 5
// CCOB Params - global address, phrase in CCOB [5:2]
#define PROGRAM_P_FLASH 0x06
// Program a phrase in a program Flash block and any previously loaded phrases for any
// other program Flash block (see Load Data Field command).
// CCOBIX end = 5
// CCOB Params - global address, phrase in CCOB [5:2]
// MGSTAT set if fault, FPVIOL / ACCERR set where appropriate
#define PROGRAM_ONCE 0x07
// Program a dedicated 64 word area in a hidden region of a program Flash block that is
// allowed to be programmed only once.
// CCOBIX end = 5
// CCOB Params - read once index (0-3) in CCOB[1], phrase in CCOB [5:2]
// MGSTAT set if fault
#define ERASE_P_FLASH_BLOCK 0x09
// Erase a program Flash block.
// An erase of the full program Flash block is only possible when FPLDIS, FPHDIS and
// FPOPEN bits in the FPROT register are set prior to launching the command.
// CCOBIX end = 1
// CCOB Params - global address
// MGSTAT set if fault, FPVIOL / ACCERR set where appropriate
#define ERASE_P_FLASH_SECTOR 0x0A
// Erase all bytes in a program Flash sector.
// CCOBIX end = 1
// CCOB Params - global address
// MGSTAT set if fault, FPVIOL / ACCERR set where appropriate
#define VERIFY_BACKDOOR_ACCESS_KEY 0x0C
// Supports a method of releasing MCU security by verifying a set of security keys.
// CCOBIX end = 4
// CCOB Params - backdoor key in CCOB [1:4]
// ACCERR set if not verified
/**** D-Flash Only Commands ****/
#define ENABLE_D_FLASH 0x0F
// Partition a section of D-Flash for user access and EEE.
// CCOBIX end = 2
// CCOB Params - number of sectors for D-Flash in CCOB[1], number of sectors for EEE in CCOB[2]
// ACCERR set if fault
#define FULL_PARTITION_D_FLASH 0x0F
// Partition a section of D-Flash for user access and EEE.
// CCOBIX end = 2
// CCOB Params - number of sectors for D-Flash in CCOB[1], number of sectors for EEE in CCOB[2]
// ACCERR set if fault
#define ERASE_VERIFY_D_FLASH_SECTION 0x10
// Verify that a given number of words starting at the address provided are erased.
// CCOBIX end = 2
// CCOB Params - global address of first word, number of words to verify CCOB[2]
// MGSTAT set if fault
#define PROGRAM_D_FLASH 0x11
// Program up to four words in the data Flash block (see Load Data Field command).
// CCOBIX end = 2
// CCOB Params - global address, up to 4 data words in CCOB [2:5]
// MGSTAT set if fault, EPVIOL / ACCERR set where appropriate
#define ERASE_D_FLASH_SECTOR 0x12
// Erase all bytes in a data Flash sector.
// CCOBIX end = 2
// CCOB Params - global address
// MGSTAT set if fault, EPVIOL set where appropriate
#define ENABLE_EEPROM_EMULATION 0x13
// Requests the FTMSM to enable EEPROM emulation.
// CCOBIX end = 0
// CCOB Params - NONE
#define DISABLE_EEPROM_EMULATION 0x14
// Requests the FTMSM to suspend all current erase and program activity related to
// EEPROM emulation but leave current EEE tags set.
// CCOBIX end = 0
// CCOB Params - NONE
//#define CANCEL_EEPROM_EMULATION 0x15 /* M22E mask only */
// Requests the FTMSM to suspend all current erase and program activity related to
// EEPROM emulation and clear all outstanding EEE tags.
// CCOBIX end = 0
// CCOB Params - NONE
#define EEPROM_QUERY 0x15
// Requests EEE status information.
// CCOBIX end = 0
// CCOB Return Params -
// CCOB[1] DFPART - size of D-Flash user partition (x256 bytes)
// CCOB[2] ERPART - size of EEE ram (x256 bytes)
// CCOB[3] ECOUNT - typical number of erase cycles for the EEE sectors
// CCOB[4] Dead sector count / Ready sector count
#define PARTITION_D_FLASH 0x20
// Partition a section of D-Flash for user access and EEE.
// CCOBIX end = 2
// CCOB Params - number of sectors for D-Flash in CCOB[1], number of sectors for EEE in CCOB[2]
// ACCERR set if fault
/*
*********************************************************************************************************
* CONFIGURATION 配置
*********************************************************************************************************
*/
//Define the FCLK_DIV value according to the oscillator crystal.
//This table is extracted from the MC9S12XE100 datasheet.
// | OSCCLK Frequency(MHz) | FDIV |
// | min | max | |
// | 1.60 | 2.10 | 0x01 |
// | 2.40 | 3.15 | 0x02 |
// | 3.20 | 4.20 | 0x03 |
// | 4.20 | 5.25 | 0x04 |
// | 5.25 | 6.30 | 0x05 |
// | 6.30 | 7.35 | 0x06 |
// | 7.35 | 8.40 | 0x07 |
// | 8.40 | 9.45 | 0x08 |
// | 9.45 | 10.50 | 0x09 |
// | 10.50 | 11.55 | 0x0A |
// | 11.55 | 12.60 | 0x0B |
// | 12.60 | 13.65 | 0x0C |
// | 13.65 | 14.70 | 0x0D |
// | 14.70 | 15.75 | 0x0E |
// | 15.75 | 16.80 | 0x0F |
// | 16.80 | 17.85 | 0x10 |
// | 17.85 | 18.90 | 0x11 |
// | 18.90 | 19.95 | 0x12 |
// | 19.95 | 21.00 | 0x13 |
// | 21.00 | 22.05 | 0x14 |
// | 22.05 | 23.10 | 0x15 |
// | 23.10 | 24.15 | 0x16 |
// | 24.15 | 25.20 | 0x17 |
// | 25.20 | 26.25 | 0x18 |
// | 26.25 | 27.30 | 0x19 |
// | 27.30 | 28.35 | 0x1A |
// | 28.35 | 29.40 | 0x1B |
// | 29.40 | 30.45 | 0x1C |
// | 30.45 | 31.50 | 0x1D |
// | 31.50 | 32.55 | 0x1E |
// | 32.55 | 33.60 | 0x1F |
// | 33.60 | 34.65 | 0x20 |
// | 34.65 | 35.70 | 0x21 |
// | 35.70 | 36.75 | 0x22 |
// | 36.75 | 37.80 | 0x23 |
// | 37.80 | 38.85 | 0x24 |
// | 38.85 | 39.90 | 0x25 |
// | 39.90 | 40.95 | 0x26 |
// | 40.95 | 42.00 | 0x27 |
// | 42.00 | 43.05 | 0x28 |
// | 43.05 | 44.10 | 0x29 |
// | 44.10 | 45.15 | 0x2A |
// | 45.15 | 46.20 | 0x2B |
// | 46.20 | 47.25 | 0x2C |
// | 47.25 | 48.30 | 0x2D |
// | 48.30 | 49.35 | 0x2E |
// | 49.35 | 50.40 | 0x2F |
#define FCLK_DIV 0x0F
//EEE SIZE SECTION
#define EEE_RAM 16 //Specify the # of EEE RAM sections for the FTM (Flash
//module) to use as EEE. The valid range is 0-16 sections.
/**** CALCULATES AMOUNT OF DATA FLASH FOR GENERAL USE ****/
#if(EEE_RAM == 1)
#define DFPART (128 - 12)
#else
#define DFPART (128 - (8 * EEE_RAM))
#endif
//uncomment below if you are not debugging!!!!!!!!!!!!!!!!!
#define NDEBUG
/*
*********************************************************************************************************
* CONSTANT 常量
*********************************************************************************************************
*/
#define FLASH_SECTOR_SIZE 0x400
// error code
#define FTM_ERR_NONE 0x00
#define FTM_ERR_UNKNOWN 0x01 // 未知错误
#define FTM_ERR_ACCERR 0x02 // ACCERR错误,不同命令的可能情况不一样
#define FTM_ERR_READERR 0x03 // 读取内存(FTM256K2)中遇到错误
#define FTM_ERR_READERR_FATAL 0x04 // 读取内存中遇到不可修正的错误
#define FTM_ERR_PROTECTED_PFLASH 0x05 // 如果尝试擦/写PFlash受保护的区域
#define FTM_ERR_WRITEERR 0x06 // 写内存(FTM256K2)时发生错误
#define FTM_ERR_WRITEERR_FATAL 0x07 // 写内存(FTM256K2)时发生不可修正的错误
#define FTM_ERR_PROTECTED_EEE 0x08 // 如果尝试擦/写EEE受保护的区域
#define FTM_ERR_EREASEERR 0x09 // 擦除内存(FTM256K2)时发生错误
#define FTM_ERR_EREASEERR_FATAL 0x0A // 擦除内存(FTM256K2)时发生不可修正的错误
// margin level
#define FTM_MARGINLEVEL_NORMAL 0x00
#define FTM_MARGINLEVEL_USER1 0x01 // Read margin to the erased state
#define FTM_MARGINLEVEL_USER0 0x02 // Read margin to the programmed state
#define FTM_MARGINLEVEL_FIELD1 0x03 // Read margin to the erased state
#define FTM_MARGINLEVEL_FIELD0 0x04 // Read margin to the programmed state
/*
*********************************************************************************************************
* FUNCTION DECLARATION 函数声明
*********************************************************************************************************
*/
void FTM_Init(void); // remember this!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
#define FTM_LaunchCommand_p0(ccobhigh,ccoblow) \
FTM_LaunchCommand(0,ccobhigh,ccoblow)
#define FTM_LaunchCommand_p1(ccobhigh,ccoblow,param1) \
FTM_LaunchCommand(1,ccobhigh,ccoblow,(unsigned short)(param1))
#define FTM_LaunchCommand_p2(ccobhigh,ccoblow,param1,param2) \
FTM_LaunchCommand(2,ccobhigh,ccoblow,(unsigned short)(param1),(unsigned short)(param2))
#define FTM_LaunchCommand_p3(ccobhigh,ccoblow,param1,param2,param3) \
FTM_LaunchCommand(3,ccobhigh,ccoblow,(unsigned short)(param1),(unsigned short)(param2),\
(unsigned short)(param3))
#define FTM_LaunchCommand_p4(ccobhigh,ccoblow,param1,param2,param3,param4) \
FTM_LaunchCommand(4,ccobhigh,ccoblow,(unsigned short)(param1),(unsigned short)(param2),\
(unsigned short)(param3),(unsigned short)(param4))
#define FTM_LaunchCommand_p5(ccobhigh,ccoblow,param1,param2,param3,param4,param5) \
FTM_LaunchCommand(5,ccobhigh,ccoblow,(unsigned short)(param1),(unsigned short)(param2),\
(unsigned short)(param3),(unsigned short)(param4),(unsigned short)(param5))
#define FTM_LaunchCommand_p6(ccobhigh,ccoblow,param1,param2,param3,param4,param5,param6) \
FTM_LaunchCommand(6,ccobhigh,ccoblow,(unsigned short)(param1),(unsigned short)(param2),\
(unsigned short)(param3),(unsigned short)(param4),(unsigned short)(param5),\
(unsigned short)(param6))
#define FTM_LaunchCommand_p7(ccobhigh,ccoblow,param1,param2,param3,param4,param5,param6,param7) \
FTM_LaunchCommand(7,ccobhigh,ccoblow,(unsigned short)(param1),(unsigned short)(param2),\
(unsigned short)(param3),(unsigned short)(param4),(unsigned short)(param5),\
(unsigned short)(param6),(unsigned short)(param7))
#pragma push
#pragma CODE_SEG RAM_CODE
FTM_STATUS FTM_LaunchCommand(unsigned char paramCnt, unsigned char ccob0high, unsigned char ccob0low ,...);
#pragma pop
void ErrorCheck(FTM_STATUS status, unsigned char statbits, unsigned char ferstatbits);
unsigned char FTM_anyErrHappened(FTM_STATUS status);
/****************************************************************************/
/**** 以下函数返回的是FTM_STATUS结构体(即两个寄存器的值) *****/
/****************************************************************************/
/******************************** BOTH ************************************/
#define _FTM_EraseVerifyAllBlocks() FTM_LaunchCommand_p0(ERASE_VERIFY_ALL_BLOCKS, 0)
#define _FTM_EraseVerifyBlock(gPage) FTM_LaunchCommand_p0(ERASE_VERIFY_BLOCK, gPage)
#define _FTM_EraseAllBlocks() FTM_LaunchCommand_p0(ERASE_ALL_BLOCKS, 0)
#define _FTM_Unsecure() FTM_LaunchCommand_p0(UNSECURE_FLASH, 0)
#define _FTM_VerifyBackdoorAccessKey(key0,key1,key2,key3) \
FTM_LaunchCommand_p4(VERIFY_BACKDOOR_ACCESS_KEY, 0,key0,key1,key2,key3)
#define _FTM_SetUserMarginLevel(gPage,MarginLevel) \
FTM_LaunchCommand_p1(SET_USER_MARGIN_LEVEL, gPage,MarginLevel)
#define _FTM_SetFieldMarginLevel(gPage,MarginLevel) \
FTM_LaunchCommand_p1(SET_FIELD_MARGIN_LEVEL, gPage,MarginLevel)
/******************************** PFlash ************************************/
#define _FTM_PFlash_Program(gPage,gAddrLow,w0,w1,w2,w3) \
FTM_LaunchCommand_p5(PROGRAM_P_FLASH,gPage,gAddrLow,w0,w1,w2,w3)
#define _FTM_PFlash_ProgramOnce(phraseIndex,w0,w1,w2,w3) \
FTM_LaunchCommand_p5(PROGRAM_ONCE,0,phraseIndex,w0,w1,w2,w3)
#define _FTM_EraseVerifyPFlashSection(gPage,gAddrLow,NumOfPhrase) \
FTM_LaunchCommand_p2(ERASE_VERIFY_P_FLASH_SECTION, gPage, gAddrLow, NumOfPhrase)
// 如果使用擦除扇区函数的话,整个函数调用过程中PC都必须在RAM中,否则会异常退出。
// 也就是说,如果使用了中断的话,整个中断函数,包括调用到的子函数都必须在RAM_CODE中。
#define _FTM_PFlash_EraseSector(gPage,gAddrLow) \
FTM_LaunchCommand_p1(ERASE_P_FLASH_SECTOR,gPage,gAddrLow)
#define _FTM_PFlash_EraseBlock(gPage,gAddrLow) \
FTM_LaunchCommand_p1(ERASE_P_FLASH_BLOCK,gPage,gAddrLow)
/******************************** DFlash/EEPROM ************************************/
// EEPROM full partition command, only valid in Debug mode.
// Call this function before the first time you use EEPROM or when reallocate EEPROM in developing.
#define _FTM_EEPROM_FullPartition() FTM_LaunchCommand_p2(FULL_PARTITION_D_FLASH, 0, DFPART, EEE_RAM)
#define _FTM_EEPROM_Partition() FTM_LaunchCommand_p2(PARTITION_D_FLASH, 0, DFPART, EEE_RAM)
// Enable the EEPROM. If you use EEPROM, you should enable EEPROM after each reset.
#define _FTM_EEPROM_Enable() FTM_LaunchCommand_p0(ENABLE_EEPROM_EMULATION, 0)
#define _FTM_EEPROM_Disable() FTM_LaunchCommand_p0(DISABLE_EEPROM_EMULATION, 0)
#define _FTM_DFlash_EraseVerifySection(gPage,gAddrLow,wordsCnt) \
FTM_LaunchCommand_p2(ERASE_VERIFY_D_FLASH_SECTION, gPage, gAddrLow, wordsCnt)
#define _FTM_DFlash_ProgramOneWord(gPage,gAddrLow,w0) \
FTM_LaunchCommand_p2(PROGRAM_D_FLASH, gPage, gAddrLow, w0)
#define _FTM_DFlash_ProgramTwoWords(gPage,gAddrLow,w0,w1) \
FTM_LaunchCommand_p3(PROGRAM_D_FLASH, gPage, gAddrLow, w0, w1)
#define _FTM_DFlash_ProgramThreeWords(gPage,gAddrLow,w0,w1,w2) \
FTM_LaunchCommand_p4(PROGRAM_D_FLASH, gPage, gAddrLow, w0, w1, w2)
#define _FTM_DFlash_ProgramFourWords(gPage,gAddrLow,w0,w1,w2,w3) \
FTM_LaunchCommand_p5(PROGRAM_D_FLASH, gPage, gAddrLow, w0, w1, w2, w3)
#define _FTM_DFlash_EraseSector(gPage,gAddrLow) \
FTM_LaunchCommand_p1(ERASE_D_FLASH_SECTOR,gPage,gAddrLow)
/****************************************************************************/
/**** more user-friendly interface 更加用户友好的接口 *****/
/****************************************************************************/
/******************************** BOTH ************************************/
// 验证所有P-Flash和D-Flash块都被擦除了
unsigned char FTM_EraseVerifyAllBlocks(void);
// 验证指定GPAGE页的P-Flash或D-Flash块被擦除了
unsigned char FTM_EraseVerifyBlock(unsigned char gPage);
// 擦除所有P-Flash和D-Flash内存,包括EEE非易失性信息寄存器
unsigned char FTM_EraseAllBlocks(void);
// 擦除所有P-Flash和D-Flash内存,如果成功则解密
unsigned char FTM_Unsecure(void);
// 如果给的秘钥与Flash配置字段中的匹配,则解密
unsigned char FTM_VerifyBackdoorAccessKey(FTM_KEYGEN *key);
// 设置指定P-Flash或D-Flash块的margin level
unsigned char FTM_SetUserMarginLevel(unsigned char gPage,unsigned char MarginLevel);
/******************************** PFlash ************************************/
// 验证P-Flash中的一个代码块被擦除了
unsigned char FTM_PFlash_EraseVerifySection(unsigned long globalAddr,unsigned char NumOfPhrase);
// 读取位于P-Flash block 0 非易失性信息寄存器的8个phrase(8字节)中的指定的一个
unsigned char FTM_PFlash_ReadOnce(unsigned char phraseIndex,INT64U *rst);
// 写P-Flash中一个擦除状态的phrase
unsigned char FTM_PFlash_Program(unsigned long globalAddr,INT64U *src);
// 写位于P-Flash block 0 非易失性信息寄存器的8个phrase(8字节)中的指定的一个,分别只能写1次,因为无法擦除
unsigned char FTM_PFlash_ProgramOnce(unsigned char phraseIndex,INT64U *src);
// 擦除给定地址所处的P-Flash block
unsigned char FTM_PFlash_EraseBlock(unsigned long globalAddr);
// 擦除给定地址所处的P-Flash sector
unsigned char FTM_PFlash_EraseSector(unsigned long globalAddr);
/******************************** DFlash/EEPROM ************************************/
// 对EEE进行全分区
unsigned char FTM_EEPROM_FullPartition(void);
// 对EEE进行分区
unsigned char FTM_EEPROM_Partition(void);
// 使能EEE,重置后默认是禁用状态
unsigned char FTM_EEPROM_Enable(void);
// 禁用EEE
unsigned char FTM_EEPROM_Disable(void);
// 查询EEE状态
unsigned char FTM_EEPROM_Query(pFTM_EEE_STATUS rst);
// 验证D-Flash的用户分区中的一个代码块是擦除状态
unsigned char FTM_DFlash_EraseVerifySection(unsigned long globalAddrStart,unsigned short wordsCnt);
// 编程D-Flash指定地址起的n个word
unsigned char FTM_DFlash_ProgramOneWord(unsigned long globalAddr,unsigned short w0);
unsigned char FTM_DFlash_ProgramTwoWords(unsigned long globalAddr,unsigned short w0,unsigned short w1);
unsigned char FTM_DFlash_ProgramThreeWords(unsigned long globalAddr,unsigned short w0,unsigned short w1,
unsigned short w2);
unsigned char FTM_DFlash_ProgramFourWords(unsigned long globalAddr,unsigned short w0,unsigned short w1,
unsigned short w2,unsigned short w3);
// 擦除指定地址所处的D-Flash用户分区
unsigned char FTM_DFlash_EraseSector(unsigned long globalAddr);
#endif
然后是FTM.c文件
/*
*********************************************************************************************************
*
*
* Flash Technology Module SUPPORT PACKAGE
* Freescale MC9S12XEP100
* 飞思卡尔单片机 FLASH模块(FTM) 支持包
*
* File : FTM.c
* By : Lin Shijun(http://blog.csdn.net/lin_strong)
* Date : 2018/04/12
* Version : V2.0
* Note :
*
*********************************************************************************************************
*/
/*
*********************************************************************************************************
* INCLUDE
*********************************************************************************************************
*/
#include "FTM.h"
#include <MC9S12XEP100.h>
#include <assert.h>
#include <stdarg.h>
/*
*********************************************************************************************************
* LOCAL FUNCTION DECLARATION
*********************************************************************************************************
*/
//Wait a while for CCIF to be set
#define _FTM_waitUntilReady() while((FSTAT & FSTAT_CCIF_MASK) == 0);
#define _FTM_EEPROM_Query() FTM_LaunchCommand_p0(EEPROM_QUERY, 0)
#define _FTM_anyErrHappened(status) ((FTM_STATUS_FSTAT_BYTE(status) & FTM_FSTAT_MASK_ANYERR) \
|| (FTM_STATUS_FERSTAT_BYTE(status) & FTM_FERSTAT_MASK_ANYERR))
#define _FTM_PFlash_ReadOnce(phraseIndex) FTM_LaunchCommand_p1(READ_ONCE,0,phraseIndex)
static unsigned char _getErrorCode(FTM_STATUS statusWord,unsigned char accerrCode,unsigned char fpviolCode,
unsigned char mgstat1Code,unsigned char mgstat0Code,unsigned char epviolifCode);
/*
*********************************************************************************************************
* FTM_Init()
*
* Description : This function is used to initialize the FTM module.you should call this function before
* using anyother function in FTM module.
*
* Return :
* Notes :
*********************************************************************************************************
*/
void FTM_Init(void){
_FTM_waitUntilReady(); //Wait for FTM to be ready
FCLKDIV = FCLK_DIV; //write FCLKDIV before using the FTM.
//if(FCLKDIV != (FCLK_DIV | 0x80)) //Check to make sure value is written.
// while(1);
}
/*
*********************************************************************************************************
* FTM_LaunchCommand()
*
* Description : This function is used to launch FTM command.
* Arguments : paramCnt(<= 7) the count of parameters used in this command, pass the parameters one by one
* after the ccob0low.
* ccob0high undicates the high byte command portion of the ccob0 word.
* ccob0low Forms the low byte of the ccob0 word parameter, if needed.
* ... the params in order.
* Return : Flash module status registers
* Notes : 1. the type of params is unsigned short(16 bits) !!!
* 2. the number of addtional params should be exactly same to the paramCnt.
* 3. this function will clears any error flags and uses parameters to initiate an FTM command.
* 4. this function does not check if the Flash is erased, and does not explicitely verify that
* data has been sucessfully programmed.
* 5. if you are programming PFLASH, this function should run in RAM
*********************************************************************************************************
*/
#pragma push
#pragma CODE_SEG RAM_CODE
FTM_STATUS FTM_LaunchCommand(unsigned char paramCnt, unsigned char ccob0high, unsigned char ccob0low ,...){
va_list ap;
FTM_STATUS status; //Used to copy and store Flash status registers.
assert(paramCnt <= 7);
va_start(ap,ccob0low);
_FTM_waitUntilReady();
FSTAT = 0x30; //Use store instruction to clear ACCERR, FPVIOL.
/**********SET UP THE FTM COMMAND AND PARAMETERS***********/
FCCOBIX = 0; //Set CCOB index to 0 to begin command setup.
FCCOBHI = ccob0high; //Write ccob0 high-byte command value.
FCCOBLO = ccob0low; //Write ccob0 low-byte parameter, if used.
//write parameters one by one to CCOB buffer.
while(paramCnt >= 1){
FCCOBIX++;
FCCOB = va_arg(ap,unsigned short);
paramCnt--;
}
va_end(ap);
FSTAT = 0x80; //Clear buffer-empty-flag to start FTM command.
_FTM_waitUntilReady(); //Now wait for the FTM command to complete.
//Copy FSTAT and FERSTAT register state for later comparison.
FTM_STATUS_FSTAT_BYTE(status) = FSTAT;
FTM_STATUS_FERSTAT_BYTE(status) = FERSTAT;
return(status); //After FTM command completed, return status.
}
#pragma pop
/*
*********************************************************************************************************
* FTM_anyErrHappened()
*
* Description : To quickly check whether there is an error.
* Arguments : status value returned by most functions in this module.
*
* Return : TRUE if any error happened.
* FALSE if every thing goes well.
* Notes :
*********************************************************************************************************
*/
unsigned char FTM_anyErrHappened(FTM_STATUS status){
return _FTM_anyErrHappened(status);
}
//Compare the copied FSTAT and FERSTAT register results against the selected
//error bits. A match indicates an error and loops forever.
void ErrorCheck(FTM_STATUS status, unsigned char statbits, unsigned char ferstatbits){
if((FTM_STATUS_FSTAT_BYTE(status) & statbits) || (FTM_STATUS_FERSTAT_BYTE(status) & ferstatbits))
{
asm BGND;
}
}
/*
*********************************************************************************************************
* FTM_EraseVerifyAllBlocks()
*
* Description : To verify that all P-Flash and D-Flash blocks have been erased.
*
* Arguments :
*
* Return : FTM_ERR_NONE if no err.
* FTM_ERR_UNKNOWN if known error encountered.
* FTM_ERR_ACCERR error most likely caused by uninitialized FCLKDIV.
* FTM_ERR_READERR if any errors have been encountered during the read
* FTM_ERR_READERR_FATAL if any non-correctable errors have been encountered during the read
*
* Notes : if return FTM_ERR_READERR, verify fail.
*********************************************************************************************************
*/
unsigned char FTM_EraseVerifyAllBlocks(void){
FTM_STATUS status;
status = _FTM_EraseVerifyAllBlocks();
return _getErrorCode(status,FTM_ERR_ACCERR,FTM_ERR_UNKNOWN,FTM_ERR_READERR,FTM_ERR_READERR_FATAL,FTM_ERR_UNKNOWN);
}
/*
*********************************************************************************************************
* FTM_EraseVerifyAllBlocks()
*
* Description : To verify that an entire P-Flash or D-Flash block has been erased.
* The FCCOB upper global address bits determine which block must be verified.
*
* Arguments : gPage Global address [22:16] of the Flash block(GPAGE) to be verified
*
* Return : FTM_ERR_NONE if no err.
* FTM_ERR_UNKNOWN if known error encountered.
* FTM_ERR_ACCERR if uninitialized FCLKDIV or an invalid global address [22:16]
* is supplied.
* FTM_ERR_READERR if any errors have been encountered during the read
* FTM_ERR_READERR_FATAL if any non-correctable errors have been encountered during the read
*
* Notes : if return FTM_ERR_READERR, verify fail.
*********************************************************************************************************
*/
unsigned char FTM_EraseVerifyBlock(unsigned char gPage){
FTM_STATUS status;
status = _FTM_EraseVerifyBlock(gPage);
return _getErrorCode(status,FTM_ERR_ACCERR,FTM_ERR_UNKNOWN,FTM_ERR_READERR,FTM_ERR_READERR_FATAL,FTM_ERR_UNKNOWN);
}
/*
*********************************************************************************************************
* FTM_PFlash_EraseVerifySection()
*
* Description : To verify that a section of code in the P-Flash memory is erased. The Erase Verify
* P-Flash Section command defines the starting point of the code to be verified and
* the number of phrases( <= 128).
*
* Arguments : globalAddr Global address [22:0] of the first phrase of a P-Flash block to be verified.
* NumOfPhrase Number of phrases to be verified
*
* Return : FTM_ERR_NONE if no err.
* FTM_ERR_UNKNOWN if known error encountered.
* FTM_ERR_ACCERR if uninitialized FCLKDIV
* or if command not available in current mode
* or if an invalid global address [22:0] is supplied
* or if a misaligned phrase address is supplied(global address [2:0] != 000)
* of if the requested section crosses a 128 Kbyte boundary
* FTM_ERR_READERR if any errors have been encountered during the read
* FTM_ERR_READERR_FATAL if any non-correctable errors have been encountered during the read
*
* Notes : if return FTM_ERR_READERR, verify fail.
*********************************************************************************************************
*/
unsigned char FTM_PFlash_EraseVerifySection(unsigned long globalAddr,unsigned char NumOfPhrase){
FTM_STATUS status;
status = _FTM_EraseVerifyPFlashSection(((unsigned char)(globalAddr >> 16) & 0x7F),
((unsigned short)globalAddr),NumOfPhrase);
return _getErrorCode(status,FTM_ERR_ACCERR,FTM_ERR_UNKNOWN,FTM_ERR_READERR,FTM_ERR_READERR_FATAL,FTM_ERR_UNKNOWN);
}
/*
*********************************************************************************************************
* FTM_PFlash_ReadOnce()
*
* Description : To provides read access to a reserved 64 byte field (8 phrases) located in the nonvolatile
* information register of P-Flash block 0. The Read Once field is programmed using the
* Program Once command.
*
* Arguments : phraseIndex Read Once phrase index (0x0000 - 0x0007)
* rst result of Read Once, if no error.
*
* Return : FTM_ERR_NONE if no err.
* FTM_ERR_UNKNOWN if known error encountered.
* FTM_ERR_ACCERR if uninitialized FCLKDIV
* or if command not available in current mode
* orif an invalid phrase index is supplied
* FTM_ERR_READERR if any errors have been encountered during the read
* FTM_ERR_READERR_FATAL if any non-correctable errors have been encountered during the read
*
* Notes : result is returned by argument rst.
*********************************************************************************************************
*/
unsigned char FTM_PFlash_ReadOnce(unsigned char phraseIndex,INT64U *rst){
unsigned char errCode;
FTM_STATUS status;
status = _FTM_PFlash_ReadOnce(phraseIndex);
errCode = _getErrorCode(status,FTM_ERR_ACCERR,FTM_ERR_UNKNOWN,FTM_ERR_READERR,FTM_ERR_READERR_FATAL,FTM_ERR_UNKNOWN);
if(errCode != FTM_ERR_NONE)
return errCode;
FCCOBIX = 2;
rst->word0 = FCCOB;
FCCOBIX++;
rst->word1 = FCCOB;
FCCOBIX++;
rst->word2 = FCCOB;
FCCOBIX++;
rst->word3 = FCCOB;
return FTM_ERR_NONE;
}
/*
*********************************************************************************************************
* FTM_PFlash_Program()
*
* Description : To program a previously erased phrase in the P-Flash memory using an embedded algorithm.
*
* Arguments : globalAddr Global address [22:0] of phrase location of P-Flash block to
* be programmed.
* src 4 words to be programmed.
*
* Return : FTM_ERR_NONE if no err.
* FTM_ERR_UNKNOWN if known error encountered.
* FTM_ERR_ACCERR if uninitialized FCLKDIV
* or if command not available in current mode
* or if an invalid global address [22:0] is supplied
* of if a misaligned phrase address is supplied (global address [2:0] != 000)
* FTM_ERR_PROTECTED_PFLASH if the global address [22:0] points to a protected area
* FTM_ERR_WRITEERR if any errors have been encountered during the verify operation
* FTM_ERR_WRITEERR_FATAL if any non-correctable errors have been encountered during the
* verify operation
*
* Notes : A P-Flash phrase must be in the erased state before being programmed.
* Cumulative programming of bits within a Flash phrase is not allowed.
*********************************************************************************************************
*/
unsigned char FTM_PFlash_Program(unsigned long globalAddr,INT64U *src){
FTM_STATUS status;
status = _FTM_PFlash_Program(((unsigned char)(globalAddr >> 16) & 0x7F),
((unsigned short)globalAddr),src->word0,src->word1,src->word2,src->word3);
return _getErrorCode(status,FTM_ERR_ACCERR,FTM_ERR_PROTECTED_PFLASH,FTM_ERR_WRITEERR,FTM_ERR_WRITEERR_FATAL,FTM_ERR_UNKNOWN);
}
/*
*********************************************************************************************************
* FTM_PFlash_ProgramOnce()
*
* Description : The Program Once command restricts programming to a reserved 64 byte field (8 phrases)
* in the nonvolatile information register located in P-Flash block 0. The Program Once
* reserved field can be read using the Read Once command.The Program Once command must
* only be issued once since the nonvolatile information register in P-Flash block 0 cannot
* be erased.
*
* Arguments : phraseIndex Program Once phrase index (0x0000 - 0x0007)
* src 4 words to be programmed.
*
* Return : FTM_ERR_NONE if no err.
* FTM_ERR_UNKNOWN if known error encountered.
* FTM_ERR_ACCERR if uninitialized FCLKDIV
* or if command not available in current mode
* or if an invalid phrase index is supplied
* of if the requested phrase has already been programmed
* FTM_ERR_PROTECTED_PFLASH if any area of the P-Flash memory is protected
* FTM_ERR_WRITEERR if any errors have been encountered during the verify operation
* FTM_ERR_WRITEERR_FATAL if any non-correctable errors have been encountered during the
* verify operation
*
* Notes : The reserved nonvolatile information register accessed by the Program Once command cannot
* be erased and any attempt to program one of these phrases a second time will not be allowed.
* Valid phrase index values for the Program Once command range from 0x0000 to 0x0007. During
* execution of the Program Once command, any attempt to read addresses within P-Flash block 0
* will return invalid data.
*********************************************************************************************************
*/
unsigned char FTM_PFlash_ProgramOnce(unsigned char phraseIndex,INT64U *src){
FTM_STATUS status;
status = _FTM_PFlash_ProgramOnce(phraseIndex,src->word0,src->word1,src->word2,src->word3);
return _getErrorCode(status,FTM_ERR_ACCERR,FTM_ERR_UNKNOWN,FTM_ERR_WRITEERR,FTM_ERR_WRITEERR_FATAL,FTM_ERR_UNKNOWN);
}
/*
*********************************************************************************************************
* FTM_EraseAllBlocks()
*
* Description : To erase the entire P-Flash and D-Flash memory space including the EEE nonvolatile
* information register.
*
* Arguments :
*
* Return : FTM_ERR_NONE if no err.
* FTM_ERR_UNKNOWN if known error encountered.
* FTM_ERR_ACCERR if uninitialized FCLKDIV
* or if command not available in current mode
* FTM_ERR_PROTECTED_PFLASH if any area of the P-Flash memory is protected
* FTM_ERR_WRITEERR if any errors have been encountered during the verify operation
* FTM_ERR_WRITEERR_FATAL if any non-correctable errors have been encountered during the
* verify operation
* FTM_ERR_PROTECTED_EEE if any area of the buffer RAM EEE partition is protected
*
* Notes : If the Memory Controller verifies that the entire Flash memory space was properly erased,
* security will be released.
*********************************************************************************************************
*/
unsigned char FTM_EraseAllBlocks(void){
FTM_STATUS status;
status = _FTM_EraseAllBlocks();
return _getErrorCode(status,FTM_ERR_ACCERR,FTM_ERR_PROTECTED_PFLASH,FTM_ERR_WRITEERR,
FTM_ERR_WRITEERR_FATAL,FTM_ERR_PROTECTED_EEE);
}
/*
*********************************************************************************************************
* FTM_PFlash_EraseBlock()
*
* Description : To erase all addresses in a P-Flash block.
*
* Arguments : globalAddr Global address [22:0] in the P-Flash block to be erased.
*
* Return : FTM_ERR_NONE if no err.
* FTM_ERR_UNKNOWN if known error encountered.
* FTM_ERR_ACCERR if uninitialized FCLKDIV
* or if command not available in current mode
* or if an invalid global address [22:16] is supplied
* FTM_ERR_PROTECTED_PFLASH if an area of the selected P-Flash block is protected
* FTM_ERR_WRITEERR if any errors have been encountered during the verify operation
* FTM_ERR_WRITEERR_FATAL if any non-correctable errors have been encountered during the
* verify operation
*
* Notes : 如果使用擦除扇区函数的话,整个函数调用过程中PC都必须在RAM中,否则会异常退出。也就是说,
* 如果使用了中断的话,整个中断函数,包括调用到的子函数都必须在RAM_CODE中。
*********************************************************************************************************
*/
unsigned char FTM_PFlash_EraseBlock(unsigned long globalAddr){
FTM_STATUS status;
status = _FTM_PFlash_EraseBlock(((unsigned char)(globalAddr >> 16) & 0x7F),((unsigned short)globalAddr));
return _getErrorCode(status,FTM_ERR_ACCERR,FTM_ERR_PROTECTED_PFLASH,FTM_ERR_WRITEERR,
FTM_ERR_WRITEERR_FATAL,FTM_ERR_UNKNOWN);
}
/*
*********************************************************************************************************
* FTM_PFlash_EraseSector()
*
* Description : To erase all addresses in a P-Flash sector.
*
* Arguments : globalAddr Global address [22:0] in the P-Flash sector to be erased.
*
* Return : FTM_ERR_NONE if no err.
* FTM_ERR_UNKNOWN if known error encountered.
* FTM_ERR_ACCERR if uninitialized FCLKDIV
* or if command not available in current mode
* or if an invalid global address [22:16] is supplied
* or if a misaligned phrase address is supplied (global address [2:0] != 000)
* FTM_ERR_PROTECTED_PFLASH if the selected P-Flash sector is protected.
* FTM_ERR_WRITEERR if any errors have been encountered during the verify operation
* FTM_ERR_WRITEERR_FATAL if any non-correctable errors have been encountered during the
* verify operation
*
* Notes : 如果使用擦除扇区函数的话,整个函数调用过程中PC都必须在RAM中,否则会异常退出。也就是说,
* 如果使用了中断的话,整个中断函数,包括调用到的子函数都必须在RAM_CODE中。
*********************************************************************************************************
*/
unsigned char FTM_PFlash_EraseSector(unsigned long globalAddr){
FTM_STATUS status;
status = _FTM_PFlash_EraseSector(((unsigned char)(globalAddr >> 16) & 0x7F),((unsigned short)globalAddr));
return _getErrorCode(status,FTM_ERR_ACCERR,FTM_ERR_PROTECTED_PFLASH,FTM_ERR_WRITEERR,
FTM_ERR_WRITEERR_FATAL,FTM_ERR_UNKNOWN);
}
/*
*********************************************************************************************************
* FTM_Unsecure()
*
* Description : The Unsecure Flash command will erase the entire P-Flash and D-Flash memory space and,
* if the erase is successful, will release security
*
* Arguments :
*
* Return : FTM_ERR_NONE if no err.
* FTM_ERR_UNKNOWN if known error encountered.
* FTM_ERR_ACCERR if uninitialized FCLKDIV
* or if command not available in current mode.
* FTM_ERR_PROTECTED_PFLASH if any area of the P-Flash memory is protected.
* FTM_ERR_EREASEERR if any errors have been encountered during the verify operation
* FTM_ERR_EREASEERR_FATAL if any non-correctable errors have been encountered during the
* verify operation
* FTM_ERR_PROTECTED_EEE if any area of the buffer RAM EEE partition is protected
*
* Notes : If the Memory Controller verifies that the entire Flash memory space was properly erased,
* security will be released. If the erase verify is not successful, the Unsecure Flash
* operation sets MGSTAT1(return FTM_ERR_EREASEERR) and terminates without changing the
* security state.
*********************************************************************************************************
*/
unsigned char FTM_Unsecure(void){
FTM_STATUS status;
status = _FTM_Unsecure();
return _getErrorCode(status,FTM_ERR_ACCERR,FTM_ERR_PROTECTED_PFLASH,FTM_ERR_EREASEERR,
FTM_ERR_EREASEERR_FATAL,FTM_ERR_PROTECTED_EEE);
}
/*
*********************************************************************************************************
* FTM_VerifyBackdoorAccessKey()
*
* Description : To releases security if user-supplied keys match those stored in the Flash security bytes
* of the Flash configuration field
*
* Arguments :
*
* Return : FTM_ERR_NONE if no err.
* FTM_ERR_UNKNOWN if known error encountered.
* FTM_ERR_ACCERR if uninitialized FCLKDIV
* or if an incorrect backdoor key is supplied
* or if backdoor key access has not been enabled
* or if the backdoor key has mismatched since the last power down
*
* Notes : The Verify Backdoor Access Key command will only execute if it is enabled by the KEYEN
* bits in the FSEC register
*********************************************************************************************************
*/
unsigned char FTM_VerifyBackdoorAccessKey(FTM_KEYGEN *key){
FTM_STATUS status;
status = _FTM_VerifyBackdoorAccessKey(key->word0,key->word1,key->word2,key->word3);
return _getErrorCode(status,FTM_ERR_ACCERR,FTM_ERR_UNKNOWN,FTM_ERR_UNKNOWN,
FTM_ERR_UNKNOWN,FTM_ERR_UNKNOWN);
}
/*
*********************************************************************************************************
* FTM_SetUserMarginLevel()
*
* Description : The Set User Margin Level command causes the Memory Controller to set the margin level
* for future read operations of a specific P-Flash or D-Flash block.
*
* Arguments : gPage Global address [22:16] to identify the Flash block
* MarginLevel Margin level setting,see FTM_MARGINLEVEL_XXXX
* FTM_MARGINLEVEL_NORMAL
* FTM_MARGINLEVEL_USER1
* FTM_MARGINLEVEL_USER0
*
* Return : FTM_ERR_NONE if no err.
* FTM_ERR_UNKNOWN if known error encountered.
* FTM_ERR_ACCERR if uninitialized FCLKDIV
* or if command not available in current mode
* or if an invalid global address [22:16] is supplied
* or if an invalid margin level setting is supplied
*
* Notes : User margin levels can be used to check that Flash memory contents have adequate margin
* for normal level read operations. If unexpected results are encountered when checking
* Flash memory contents at user margin levels, a potential loss of information has been
* detected.
*********************************************************************************************************
*/
unsigned char FTM_SetUserMarginLevel(unsigned char gPage,unsigned char MarginLevel){
FTM_STATUS status;
status = _FTM_SetUserMarginLevel(gPage,MarginLevel);
return _getErrorCode(status,FTM_ERR_ACCERR,FTM_ERR_UNKNOWN,FTM_ERR_UNKNOWN,
FTM_ERR_UNKNOWN,FTM_ERR_UNKNOWN);
}
/*
*********************************************************************************************************
* FTM_SetFieldMarginLevel()
*
* Description : The Set Field Margin Level command, valid in special modes only, causes the Memory
* Controller to set the margin level specified for future read operations of a specific
* P-Flash or D-Flash block.
*
* Arguments : gPage Global address [22:16] to identify the Flash block
* MarginLevel Margin level setting,see FTM_MARGINLEVEL_XXXX
* FTM_MARGINLEVEL_NORMAL
* FTM_MARGINLEVEL_USER1
* FTM_MARGINLEVEL_USER0
* FTM_MARGINLEVEL_FIELD1
* FTM_MARGINLEVEL_FIELD0
*
* Return : FTM_ERR_NONE if no err.
* FTM_ERR_UNKNOWN if known error encountered.
* FTM_ERR_ACCERR if uninitialized FCLKDIV
* or if command not available in current mode
* or if an invalid global address [22:16] is supplied
* or if an invalid margin level setting is supplied
*
* Notes : 1. Field margin levels must only be used during verify of the initial factory programming.
* 2. Field margin levels can be used to check that Flash memory contents have adequate
* margin for data retention at the normal level setting. If unexpected results are
* encountered when checking Flash memory contents at field margin levels, the Flash
* memory contents should be erased and reprogrammed.
*********************************************************************************************************
*/
unsigned char FTM_SetFieldMarginLevel(unsigned char gPage,unsigned char MarginLevel){
FTM_STATUS status;
status = _FTM_SetFieldMarginLevel(gPage,MarginLevel);
return _getErrorCode(status,FTM_ERR_ACCERR,FTM_ERR_UNKNOWN,FTM_ERR_UNKNOWN,
FTM_ERR_UNKNOWN,FTM_ERR_UNKNOWN);
}
/*
*********************************************************************************************************
* FTM_EEPROM_FullPartition()
*
* Description : To allows the user to allocate sectors within the D-Flash block for applications and a
* partition within the buffer RAM for EEPROM access. The D-Flash block consists of 128
* sectors with 256 bytes per sector.
*
* Arguments : set directly at EEE_RAM in CONFIGURATION in FTM.h
*
* Return : FTM_ERR_NONE if no err.
* FTM_ERR_UNKNOWN if known error encountered.
* FTM_ERR_ACCERR if uninitialized FCLKDIV
* or if command not available in current mode
* or if an invalid DFPART or ERPART selection is supplied
* FTM_ERR_READERR if any errors have been encountered during the read.
* FTM_ERR_READERR_FATAL if any non-correctable errors have been encountered during the read.
*
* Notes :
*
*********************************************************************************************************
*/
unsigned char FTM_EEPROM_FullPartition(){
FTM_STATUS status;
status = _FTM_EEPROM_FullPartition();
return _getErrorCode(status,FTM_ERR_ACCERR,FTM_ERR_UNKNOWN,FTM_ERR_READERR,
FTM_ERR_READERR_FATAL,FTM_ERR_UNKNOWN);
}
/*
*********************************************************************************************************
* FTM_EEPROM_Partition()
*
* Description : To allows the user to allocate sectors within the D-Flash block for applications and a
* partition within the buffer RAM for EEPROM access. The D-Flash block consists of 32
* sectors with 256 bytes per sector.
*
* Arguments : set directly at EEE_RAM in CONFIGURATION in FTM.h
*
* Return : FTM_ERR_NONE if no err.
* FTM_ERR_UNKNOWN if known error encountered.
* FTM_ERR_ACCERR if uninitialized FCLKDIV
* or if command not available in current mode
* or if partitions have already been defined
* or if an invalid DFPART or ERPART selection is supplied
* FTM_ERR_READERR if any errors have been encountered during the read.
* FTM_ERR_READERR_FATAL if any non-correctable errors have been encountered during the read.
*
* Notes : 1. The Erase All Blocks command must be run prior to launching the Partition D-Flash command.
* 2. Running the Partition D-Flash command a second time will result in the ACCERR bit within
* the FSTAT register being set.
*
*********************************************************************************************************
*/
unsigned char FTM_EEPROM_Partition(){
FTM_STATUS status;
status = _FTM_EEPROM_Partition();
return _getErrorCode(status,FTM_ERR_ACCERR,FTM_ERR_UNKNOWN,FTM_ERR_READERR,
FTM_ERR_READERR_FATAL,FTM_ERR_UNKNOWN);
}
/*
*********************************************************************************************************
* FTM_DFlash_EraseVerifySection()
*
* Description : To verify that a section of code in the D-Flash user partition is erased.
*
* Arguments : globalAddrStart Global address [15:0] of the first word to be verified in D-Flash block
* wordsCnt Number of words to be verified
*
* Return : FTM_ERR_NONE if no err.
* FTM_ERR_UNKNOWN if known error encountered.
* FTM_ERR_ACCERR if uninitialized FCLKDIV
* or if command not available in current mode
* or if an invalid global address [22:0] is supplied
* or if a misaligned word address is supplied (global address [0] != 0)
* or if the global address [22:0] points to an area of the D-Flash EEE
* partition
* or if the requested section breaches the end of the D-Flash block or
* goes into the D-Flash EEE partition
* FTM_ERR_READERR if any errors have been encountered during the read.
* FTM_ERR_READERR_FATAL if any non-correctable errors have been encountered during the read.
*
* Notes :
*
*********************************************************************************************************
*/
unsigned char FTM_DFlash_EraseVerifySection(unsigned long globalAddrStart,unsigned short wordsCnt){
FTM_STATUS status;
status = _FTM_DFlash_EraseVerifySection(((unsigned char)(globalAddrStart >> 16) & 0x7F),
((unsigned short)globalAddrStart),wordsCnt);
return _getErrorCode(status,FTM_ERR_ACCERR,FTM_ERR_UNKNOWN,FTM_ERR_READERR,
FTM_ERR_READERR_FATAL,FTM_ERR_UNKNOWN);
}
/*
*********************************************************************************************************
* FTM_DFlash_ProgramXXXXWords()
*
* Description : To programs one to four previously erased words in the D-Flash user partition. The Program
* D-Flash operation will confirm that the targeted location(s) were successfully programmed
* upon completion.
*
* Arguments : globalAddrStart Global address [15:0] of the words to be programmed in D-Flash block
* w(n) Word n program value
*
* Return : FTM_ERR_NONE if no err.
* FTM_ERR_UNKNOWN if known error encountered.
* FTM_ERR_ACCERR if uninitialized FCLKDIV
* or if command not available in current mode
* or if an invalid global address [22:0] is supplied
* or if a misaligned word address is supplied (global address [0] != 0)
* or if the global address [22:0] points to an area of the D-Flash EEE
* partition
* or if the requested group of words breaches the end of the D-Flash
* block or goes into the D-Flash EEE partition.
* FTM_ERR_WRITEERR if any errors have been encountered during the verify operation.
* FTM_ERR_WRITEERR_FATAL if any non-correctable errors have been encountered during the
* verify operation.
*
* Notes : No protection checks are made in the Program D-Flash operation on the D-Flash block,
* only access error checks
*
*********************************************************************************************************
*/
unsigned char FTM_DFlash_ProgramOneWord(unsigned long globalAddr,unsigned short w0){
FTM_STATUS status;
status = _FTM_DFlash_ProgramOneWord(((unsigned char)(globalAddr >> 16) & 0x7F),
((unsigned short)globalAddr),w0);
return _getErrorCode(status,FTM_ERR_ACCERR,FTM_ERR_UNKNOWN,FTM_ERR_WRITEERR,
FTM_ERR_WRITEERR_FATAL,FTM_ERR_UNKNOWN);
}
unsigned char FTM_DFlash_ProgramTwoWords(unsigned long globalAddr,unsigned short w0,unsigned short w1){
FTM_STATUS status;
status = _FTM_DFlash_ProgramTwoWords(((unsigned char)(globalAddr >> 16) & 0x7F),
((unsigned short)globalAddr),w0,w1);
return _getErrorCode(status,FTM_ERR_ACCERR,FTM_ERR_UNKNOWN,FTM_ERR_WRITEERR,
FTM_ERR_WRITEERR_FATAL,FTM_ERR_UNKNOWN);
}
unsigned char FTM_DFlash_ProgramThreeWords(unsigned long globalAddr,unsigned short w0,unsigned short w1,
unsigned short w2){
FTM_STATUS status;
status = _FTM_DFlash_ProgramThreeWords(((unsigned char)(globalAddr >> 16) & 0x7F),
((unsigned short)globalAddr),w0,w1,w2);
return _getErrorCode(status,FTM_ERR_ACCERR,FTM_ERR_UNKNOWN,FTM_ERR_WRITEERR,
FTM_ERR_WRITEERR_FATAL,FTM_ERR_UNKNOWN);
}
unsigned char FTM_DFlash_ProgramFourWords(unsigned long globalAddr,unsigned short w0,unsigned short w1,
unsigned short w2,unsigned short w3){
FTM_STATUS status;
status = _FTM_DFlash_ProgramFourWords(((unsigned char)(globalAddr >> 16) & 0x7F),
((unsigned short)globalAddr),w0,w1,w2,w3);
return _getErrorCode(status,FTM_ERR_ACCERR,FTM_ERR_UNKNOWN,FTM_ERR_WRITEERR,
FTM_ERR_WRITEERR_FATAL,FTM_ERR_UNKNOWN);
}
/*
*********************************************************************************************************
* FTM_DFlash_EraseSector()
*
* Description : To erase all addresses in a sector of the D-Flash user partition.
*
* Arguments : globalAddr Global address [22:0] anywhere in the D-Flash sector to be erased.
*
* Return : FTM_ERR_NONE if no err.
* FTM_ERR_UNKNOWN if known error encountered.
* FTM_ERR_ACCERR if uninitialized FCLKDIV
* or if command not available in current mode
* or if an invalid global address [22:0] is supplied
* or if a misaligned word address is supplied (global address [0] != 0)
* or if the global address [22:0] points to the D-Flash EEE partition
* FTM_ERR_EREASEERR if any errors have been encountered during the verify operation
* FTM_ERR_EREASEERR_FATAL if any non-correctable errors have been encountered during the
* verify operation
*
* Notes :
*********************************************************************************************************
*/
unsigned char FTM_DFlash_EraseSector(unsigned long globalAddr){
FTM_STATUS status;
status = _FTM_DFlash_EraseSector(((unsigned char)(globalAddr >> 16) & 0x7F),((unsigned short)globalAddr));
return _getErrorCode(status,FTM_ERR_ACCERR,FTM_ERR_UNKNOWN,FTM_ERR_EREASEERR,
FTM_ERR_EREASEERR_FATAL,FTM_ERR_UNKNOWN);
}
/*
*********************************************************************************************************
* FTM_EEPROM_Enable()
*
* Description : To enable EEE activity.
*
* Arguments :
*
* Return : FTM_ERR_NONE if no err.
* FTM_ERR_UNKNOWN if known error encountered.
* FTM_ERR_ACCERR if uninitialized FCLKDIV
* or if Full Partition D-Flash or Partition D-Flash command not
* previously run
*
* Notes : 1. EEE activity is disabled after any reset.
* 2. This command can be submitted many times.
*********************************************************************************************************
*/
unsigned char FTM_EEPROM_Enable(void){
FTM_STATUS status;
status = _FTM_EEPROM_Enable();
return _getErrorCode(status,FTM_ERR_ACCERR,FTM_ERR_UNKNOWN,FTM_ERR_UNKNOWN,
FTM_ERR_UNKNOWN,FTM_ERR_UNKNOWN);
}
/*
*********************************************************************************************************
* FTM_EEPROM_Disable()
*
* Description : To suspend current EEE activity.
*
* Arguments :
*
* Return : FTM_ERR_NONE if no err.
* FTM_ERR_UNKNOWN if known error encountered.
* FTM_ERR_ACCERR if uninitialized FCLKDIV.
*
* Notes : 1. EEE activity is disabled after any reset.
* 2. This command can be submitted many times.
*********************************************************************************************************
*/
unsigned char FTM_EEPROM_Disable(void){
FTM_STATUS status;
status = _FTM_EEPROM_Disable();
return _getErrorCode(status,FTM_ERR_ACCERR,FTM_ERR_UNKNOWN,FTM_ERR_UNKNOWN,
FTM_ERR_UNKNOWN,FTM_ERR_UNKNOWN);
}
/*
*********************************************************************************************************
* FTM_EEPROM_Query()
*
* Description : To query the status of EEPROM.
*
* Arguments : rst used to return the result of the query ,if success.
*
* Return : FTM_ERR_NONE if no err.
* FTM_ERR_UNKNOWN if known error encountered.
* FTM_ERR_ACCERR if uninitialized FCLKDIV
* or if command not available in current mode.
*
* Notes : 1. if any error happen(check return value), rst will not be changed.
*********************************************************************************************************
*/
unsigned char FTM_EEPROM_Query(pFTM_EEE_STATUS rst){
unsigned char errCode;
FTM_STATUS status;
status = _FTM_EEPROM_Query();
errCode = _getErrorCode(status,FTM_ERR_ACCERR,FTM_ERR_UNKNOWN,FTM_ERR_UNKNOWN,
FTM_ERR_UNKNOWN,FTM_ERR_UNKNOWN);
if(errCode != FTM_ERR_NONE){
return errCode;
}
FCCOBIX = 1;
rst->dfPart = FCCOB;
FCCOBIX++;
rst->erPart = FCCOB;
FCCOBIX++;
rst->ersCnt = FCCOB;
FCCOBIX++;
rst->rdyCnt = FCCOBLO;
rst->deadCnt = FCCOBHI;
return FTM_ERR_NONE;
}
/*
*********************************************************************************************************
* LOCAL FUNCTION
*********************************************************************************************************
*/
static unsigned char _getErrorCode(FTM_STATUS status,unsigned char accerrCode,unsigned char fpviolCode,
unsigned char mgstat1Code,unsigned char mgstat0Code,unsigned char epviolifCode){
if(_FTM_anyErrHappened(status)){
if((status).Regs.fstat.Bits.ACCERR == 1)
return accerrCode;
if((status).Regs.fstat.Bits.FPVIOL == 1)
return fpviolCode;
if((status).Regs.fstat.Bits.MGSTAT1 == 1)
return mgstat1Code;
if((status).Regs.fstat.Bits.MGSTAT0 == 1)
return mgstat0Code;
if((status).Regs.ferstat.Bits.EPVIOLIF == 1)
return epviolifCode;
return FTM_ERR_UNKNOWN;
}
return FTM_ERR_NONE;
}
有一点需要注意的,很多命令在运行时是不允许程序在P-flash区域跑的,即不允许P-flash区域的代码擦写P-flash,否则单片机会直接跑飞,如果开了中断的话,任何可能在命令运行期间发生的中断的对应代码也必须在RAM区域。下面简单说下把代码移到RAM区域的方法。
我的代码中已经把FTM_LaunchCommand定义在呢 RAM_CODE这个代码块了,所以要做的就是在prm文件中定义RAM_CODE这个代码块。
打开工程的prm文件。找到
SEGMENTS
......
ROM_C000 = READ_ONLY DATA_NEAR IBCC_NEAR 0xC000 TO 0xFEFF;
......
END
将其改成
SEGMENTS
......
RAM_CODE_SEG = READ_ONLY 0xFE00 TO 0xFEFF RELOCATE_TO 0x3E00;
ROM_C000 = READ_ONLY DATA_NEAR IBCC_NEAR 0xC000 TO 0xFDFF;
......
END
PLACEMENT
......
RAM_CODE INTO RAM_CODE_SEG;
......
END
这样FTM_LaunchCommand的代码就会被重定位到0x3E00开始的RAM区域了
但是编译器不会自动帮你复制代码过去,所以在程序中还得在使用这个驱动程序之前先调用次这个函数。
#include <string.h>
#define __SEG_START_REF(a) __SEG_START_ ## a
#define __SEG_END_REF(a) __SEG_END_ ## a
#define __SEG_SIZE_REF(a) __SEG_SIZE_ ## a
#define __SEG_START_DEF(a) extern char __SEG_START_REF (a) []
#define __SEG_END_DEF(a) extern char __SEG_END_REF (a) []
#define __SEG_SIZE_DEF(a) extern char __SEG_SIZE_REF (a) []
__SEG_START_DEF (RAM_CODE);
__SEG_END_DEF (RAM_CODE);
__SEG_SIZE_DEF (RAM_CODE);
void CopyCodeToRAM(void)
{
memcpy((unsigned char *)0x3E00,(unsigned char *)__SEG_START_REF(RAM_CODE),(unsigned short)__SEG_SIZE_REF(RAM_CODE));
}
然后就可以愉快地操作Flash内存了。