📄 flash.c
字号:
//==========================================================================================
// Filename: Flash.c
//
// Description: Routines for managing flash access and code images
//
// Copyright (C) 2001 - 2003 Texas Instruments Incorporated
// Texas Instruments Proprietary Information
// Use subject to terms and conditions of TI Software License Agreement
//
// The flash is partitioned into distinct areas for different purposes of operation.
//
// flash partitioning is:
// 0x000000 - 0x00007F => reserved
// 0x018000 - 0x01FFFF => active code image
// 0x028000 - 0x02FFFF => DSP code download image
// 0x038000 - 0x03FFFF => data logging space
//
// The DSP and MSP cannot have any ROM image existing at address zero so tags are placed
// there indicating status of images
// 0x010000 = DSP code tag address
//
// Tags are image status for active and erasable
// 0xFFFF => the image does not exist, set by default when an erasure occurs
// 0x1248 => the image has been downloaded and should be used to overwrite the current one
// 0x0000 => the image is unused and can be erased
// Note: Since writing to flash can only be done when bits are changed from a 1 to a 0,
// the tags are assigned values which allow each succesive value to be written on
// top of the previous tag value.
//
// The user code must have its entry point at 0x0080, NO EXCEPTIONS!
//
// Revision History:
//==========================================================================================
//==========================================================================================
// included files
//==========================================================================================
#include "ofdm_modem.h"
#include "ofdm_datatypes.h"
#include "ofdm_functions.h"
#include "intr.h"
#include "Flash.h"
//==========================================================================================
// local definitions for flash management
//==========================================================================================
#define FLASH_IMAGE_LOAD (0x1248u)
#define FLASH_IMAGE_PROG (0x028000ul)
#define FLASH_IMAGE_ACTIVE (0x018000ul)
#define FLASH_IMAGE_BOOT (0x00FF80ul)
#define FLASH_BOOT_CODE_TAG (0x3CA5u)
#define FLASH_IMAGE_PROG_TAG_OFFSET (2)
#define FLASH_BOOT_CODE_TAG_OFFSET (127)
#define FLASH_PROG_CODE_UPPER_LIMIT (0x7FFFul)
#define FLASH_PROG_CODE_LOWER_LIMIT (0x0080ul)
#define FLASH_LOG_BASE_ADDRESS (0x038000ul)
#define FLASH_LOG_MAX_SIZE (0x008000ul)
#define ERASED_FLASH_VALUE (0xFFFFu)
#define DOWN_LOAD_TIMEOUT (0x4000u)
#define LED_START (0X80)
#define LED_UPDATE_RATE (300)
//==========================================================================================
// exported global variables
//==========================================================================================
u16 FlashLEDMask = 0; // used to output flash status to LED's
u32 FlashLogSize; // indicates the current size of the data log in flash
//==========================================================================================
// Local function declarations
//==========================================================================================
void RunStateMachine(i16 Target, u32 Address, u16 Data, i16 Operation);
i16 GetBufferCharacter(i16 Position);
void DoEraseSector(i16 Target, u32 SectorAddress);
u16 ReadHexNumber(i16 Digits, i16* Position);
u16 Xlate(u16 Data);
u16 UnXlate(u16 Data);
i16 ValidateFlashModification(void);
void EnableFlashWriteAccess(void);
void DisableFlashWriteAccess(void);
i16 ValidateFlashComponent(void);
void WriteFlash(u32 Address, u16 Data);
u32 GetBaseAddress(i16 Target);
void UpdateStatus(i16 Target);
void ResetProcessor(void);
//==========================================================================================
// state machine function prototypes, each function is a different state
//==========================================================================================
void* SM_Idle(void);
void* CommandPolling(void);
void* EraseCommandPolling(void);
void* EraseFlash(void);
void* EraseSector(void);
void* WriteFlashData(void);
//==========================================================================================
// globals local to this file hence the static prefix
//==========================================================================================
static u16 StateMachineStatus = FLASH_STATUS_COMPLETE; // indicates status of the state machine
static void* CurrentState; // holds current state of the state machine
static i16 TranslationMap[] = {0, 2, 4, 6, 8, 10, 12, 14, 1, 3, 5, 7, 9, 11, 13, 15};// for Xlate() and UnXlate()
static i16 EnableFlashWrites; // a protection flag, must be set to do writes
static u16 FlashProgBuffer[16]; // buffer for DSP program image writes
static u16 FlashLogBuffer[FLASH_LOG_RECORD_MAX_SIZE + 2]; // buffer for flash log writes
static u16 FlashBootBuffer[1]; // the buffer for boot sector writes
static u16 FlashCopyBuffer[1]; // the buffer for copying flash to flash
static u16* FlashBuffer[FLASH_TARGET_COUNT] = { FlashProgBuffer, 0/* MSP placeholder */, FlashLogBuffer, FlashBootBuffer, FlashCopyBuffer };// pointers to the buffers
static i16 FlashSize[FLASH_TARGET_COUNT]; // size of data in buffers, zero indicates buffer is not busy, negative indicates erase
static i16 WriteTag[FLASH_TARGET_COUNT]; // flags to indicate needed update of tags for images
static i16 CurrentTarget; // points to the currently active target of the state machine
static u32 FlashLoadAddress[FLASH_TARGET_COUNT]; // current address for current buffer data
static u16 DownLoadActive;
static u16 DisplayMode;
static u16 Dir;
static u16 TargetStatus[FLASH_TARGET_COUNT];
static struct
{
u16 Data;
u32 Address;
} StateData;
//==========================================================================================
// Function: ResetProcessor()
//
// Description: Sets the PMST register similar to that of a hard reset and
// jumps to the reset vector at 0xFF80. This function never returns
//
// Revision History:
//==========================================================================================
void ResetProcessor(void)
{
INTR_GLOBAL_DISABLE(); // Disable Global Interrupts (if they were enabled)
asm(" STM 0xFFE0, 0x1D"); // reset the PMST register
asm(" NOP"); // wait for changed to take effect
asm(" NOP");
asm(" NOP");
asm(" NOP");
asm(" NOP");
asm(" B 0xFF80"); // jump to reset vector
}
//==========================================================================================
// Function: InitFlash()
//
// Description: initializes globals and initial state, checks for flash operation
// and updates MSP code if needed base on MSP tag value
//
// Revision History:
//==========================================================================================
void InitFlash(void)
{
u32 j;
i16 i;
u16 BootCode[] = { // the boot code, copies flash to RAM and executes
// /* 0xFF80 */ 0xF073u, // FF80: B FF80 ; branch to self, debug bring up
// /* 0xFF81 */ 0xFF80u,
/* 0xFF80 */ 0xF495u, // FF80: NOP ; non debug bring up
/* 0xFF81 */ 0xF495u, // FF81: NOP
/* 0xFF82 */ 0x771Du, // FF82: STM FFE8h, PMST ; set PMST to overlay RAM in program space
/* 0xFF83 */ 0xFFE8u,
/* 0xFF84 */ 0xF495u, // FF84: NOP
/* 0xFF85 */ 0xF495u, // FF85: NOP
/* 0xFF86 */ 0xF495u, // FF86: NOP
/* 0xFF87 */ 0xF495u, // FF87: NOP
/* 0xFF88 */ 0xF495u, // FF88: NOP
/* 0xFF89 */ 0xF495u, // FF89: NOP
/* 0xFF8A */ 0xF495u, // FF8A: NOP
/* 0xFF8B */ 0x7708u, // FF8B: STM 0, 8h ; point accumulator A to downloaded program image tag
/* 0xFF8C */ 0x0000u,
/* 0xFF8D */ 0x7709u, // FF8D: STM 0, 9h
/* 0xFF8E */ 0x0000u,
/* 0xFF8F */ 0x770Au, // FF8F: STM 0, ah
/* 0xFF90 */ 0x0000u,
/* 0xFF91 */ 0xF3C0u, // FF91: XOR B, B ; clear accumulator B
/* 0xFF92 */ 0x7E0Bu, // FF92: READA bh ; read the tag value into lower word of accumulator B
/* 0xFF93 */ 0xF310u, // FF93: SUB #0, B ; check tag for active download
/* 0xFF94 */ 0x0000u,
/* 0xFF95 */ 0xF84Du, // FF95: BC LOAD_NEW, BEQ ; if an active tag, load the new image
/* 0xFF96 */ 0xFF9Fu,
/* 0xFF97 */ 0x7708u, // FF97: STM 0, 8h ; load address of old image
/* 0xFF98 */ 0x0000u,
/* 0xFF99 */ 0x7709u, // FF99: STM 0, 9h
/* 0xFF9A */ 0x0000u,
/* 0xFF9B */ 0x770Au, // FF9B: STM 0, ah
/* 0xFF9C */ 0x0000u,
/* 0xFF9D */ 0xF073u, // FF9D: B DO_LOAD ; start loading the old image
/* 0xFF9E */ 0xFFA5u,
// LOAD_NEW
/* 0xFF9F */ 0x7708u, // FF9F: STM 0, 8h ; load address of new image
/* 0xFFA0 */ 0x0000u,
/* 0xFFA1 */ 0x7709u, // FFA1: STM 0, 9h
/* 0xFFA2 */ 0x0000u,
/* 0xFFA3 */ 0x770Au, // FFA3: STM 0, ah
/* 0xFFA4 */ 0x0000u,
// DO_LOAD
/* 0xFFA5 */ 0x7711u, // FFA5: STM #80h, AR1 ; initialize ar1 to point to beginning of ram too
/* 0xFFA6 */ 0x0080u,
/* 0xFFA7 */ 0xF495u, // FFA7: NOP ; stall for debugging
/* 0xFFA8 */ 0xF495u, // FFA8: NOP
/* 0xFFA9 */ 0xF070u, // FFA9: RPT #7F7Fh ; load number of words to copy from flash - 1
/* 0xFFAA */ 0x0000u,
/* 0xFFAB */ 0x7E91u, // FFAB: READA *AR1+ ; copy from flash (in acc a) to data space (in ar1)
/* 0xFFAC */ 0xF495u, // FFAC: NOP
/* 0xFFAD */ 0xF495u, // FFAD: NOP
/* 0xFFAE */ 0xF495u, // FFAE: NOP
/* 0xFFAF */ 0xF495u, // FFAF: NOP
/* 0xFFB0 */ 0xF495u, // FFB0: NOP
/* 0xFFB1 */ 0x771Du, // FFB1: STM 00E8h,PMST ; set PMST to execute from RAM also
/* 0xFFB2 */ 0x00E8u,
/* 0xFFB3 */ 0xF495u, // FFB3: NOP
/* 0xFFB4 */ 0xF495u, // FFB4: NOP
/* 0xFFB5 */ 0xF495u, // FFB5: NOP
/* 0xFFB6 */ 0xF495u, // FFB6: NOP
/* 0xFFB7 */ 0xF495u, // FFB7: NOP
/* 0xFFB8 */ 0xF495u, // FFB8: NOP
/* 0xFFB9 */ 0xF495u, // FFB9: NOP
/* 0xFFBA */ 0xF073u, // FFBA: B 0x0080 ; branch to user code at user reset vector
/* 0xFFBB */ 0x0080u };
u16 BootCodeLength = 0xFFBBu - 0xFF80u + 1; // number of instruction words in boot code
// patch the download image tag address into the assembly code
BootCode[12] = (u16)((FLASH_IMAGE_PROG + FLASH_IMAGE_PROG_TAG_OFFSET) & 0xFFFFul);
BootCode[14] = (u16)(((FLASH_IMAGE_PROG + FLASH_IMAGE_PROG_TAG_OFFSET) >> 16) & 0x007Ful);
BootCode[16] = 0u;
// patch the tag value for loading into the assembly code
BootCode[20] = (u16)(FLASH_IMAGE_LOAD);
// patch the active image base address into the assembly code
BootCode[24] = (u16)((FLASH_IMAGE_ACTIVE + FLASH_PROG_CODE_LOWER_LIMIT) & 0xFFFFul);
BootCode[26] = (u16)(((FLASH_IMAGE_ACTIVE + FLASH_PROG_CODE_LOWER_LIMIT) >> 16) & 0x007Ful);
BootCode[28] = 0u;
// patch the new image base address into the assembly code
BootCode[32] = (u16)((FLASH_IMAGE_PROG + FLASH_PROG_CODE_LOWER_LIMIT) & 0xFFFFul);
BootCode[34] = (u16)(((FLASH_IMAGE_PROG + FLASH_PROG_CODE_LOWER_LIMIT) >> 16) & 0x007Ful);
BootCode[36] = 0u;
// patch the download count
BootCode[42] = (u16)(FLASH_PROG_CODE_UPPER_LIMIT - FLASH_PROG_CODE_LOWER_LIMIT);
DownLoadActive = 0; // clear the downloading flag
Dir = 0; // initialize direction of indicators
FlashLEDMask = 0; // initialize the indicator
for(i = 0; i < FLASH_TARGET_COUNT; i++) // loop through all targets clearing state data
{
FlashLoadAddress[i] = 0;
FlashSize[i] = 0;
WriteTag[i] = 0;
TargetStatus[i] = 0;
}
CurrentTarget = 0; // initialize target counter
CurrentState = SM_Idle; // initialize the state machine state
if(ValidateFlashComponent() != 0) // a quick check to believe everything is OK
{
FlashLEDMask = 0xFF; // indicate failure
AssignLEDs(FlashLEDMask); // forces output
for(;;); // lock up the system
}
// FORCE ERASE -- if the following line of code is uncommented, the flash will be erased on boot
// RunStateMachine(FLASH_TARGET_BOOT, 0, ERASED_FLASH_VALUE, -1); // erase the flash
for(j = 0; j < BootCodeLength; j++) // loop through all boot code
{
if(BootCode[j] != ReadFlash(0xFF80u + j)) // if code word fails to compare with expected
{
RunStateMachine(FLASH_TARGET_BOOT, FLASH_BOOT_CODE_TAG_OFFSET, 0, 1); // invalidate the boot tag
break; // exit the loop
}
}
// if boot code appears corrupted or missing
if(ReadFlash(GetBaseAddress(FLASH_TARGET_BOOT) + FLASH_BOOT_CODE_TAG_OFFSET) != FLASH_BOOT_CODE_TAG)
{
RunStateMachine(FLASH_TARGET_BOOT, 0, ERASED_FLASH_VALUE, -2); // erase the boot sector
// copy the boot code to flash
for(j = 0; j < BootCodeLength; j++) // loop through all boot code
{ // copy this word of the boot code
RunStateMachine(FLASH_TARGET_BOOT, j, BootCode[j], 1);
}
// update the boot code tag
RunStateMachine(FLASH_TARGET_BOOT, FLASH_BOOT_CODE_TAG_OFFSET, FLASH_BOOT_CODE_TAG, 1);
}
// if need to update DSP code image
if(ReadFlash(GetBaseAddress(FLASH_TARGET_PROG) + FLASH_IMAGE_PROG_TAG_OFFSET) == FLASH_IMAGE_LOAD)
{
// erase the DSP active sector
RunStateMachine(FLASH_TARGET_COPY, 0, ERASED_FLASH_VALUE, -2); // erase this sector
// copy the DSP code to low flash
for(j = FLASH_PROG_CODE_LOWER_LIMIT; j <= FLASH_PROG_CODE_UPPER_LIMIT; j++) // loop through all code space
{ // copy this word of the code image
RunStateMachine(FLASH_TARGET_COPY, j, ReadFlash(GetBaseAddress(FLASH_TARGET_PROG) + j), 1);
}
// update the DSP code image tag
RunStateMachine(FLASH_TARGET_PROG, FLASH_IMAGE_PROG_TAG_OFFSET, 0, 1);
ResetProcessor(); // run the newly loaded code
}
// if need to update MSP code image
// by definition, the download image for the DSP will have been cleared by this point
// initialize flash log size variable by running through the linked list
FlashLogSize = 0; // point to beginning of log records list
do // loop through log records
{
j = ReadFlash(FlashLogSize + FLASH_LOG_BASE_ADDRESS); // get high word of succeeding record pointer
j <<= 16; // move it into the high word
j += ReadFlash(FlashLogSize + FLASH_LOG_BASE_ADDRESS + 1); // get low word of succeeding record pointer
if(j != 0xFFFFFFFFul) // if not at end of linked list
{
if(j <= FlashLogSize || j >= FLASH_LOG_MAX_SIZE) // if the linked list appears corrupt
{
uFlashLogStatus = FLASH_STATUS_TIMEOUT; // set the log status
break; // exit the loop
}
FlashLogSize = j; // move to the next record in the list
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -