Part Number: LAUNCHXL-F280039C
Other Parts Discussed in Thread: C2000WARE
Tool/software:
Hi everyone,
I'm working with the F28003x series and using the Flash API. I have added the F021_API_F28003x_FPU32.lib library to my project,
However, when I call my own function fapi_init() (which includes Fapi_initializeAPI() inside), I get the following linker error:
- It seems like the linker does not recognize or include
Fapi_initializeAPI()
code below:
//
// Included Files
//
#include "driverlib.h"
#include "device.h"
#include "bl_commands.h"
#include "bl_dcan.h"
#include "EEPROM_Config.h"
#include <stdio.h>
#define RX_MSG_OBJ_ID 1
#define MSG_DATA_LENGTH 8
#define MSGCOUNT 10
#define TX_MSG_OBJ_ID 2
///
// Globals
//
volatile uint32_t rxMsgCount = MSGCOUNT;
uint16_t rxMsgData[4];
uint32_t msgID;
volatile unsigned long i;
volatile uint32_t errorFlag = 0;
CAN_MsgFrameType FrameType;
//
// Function Prototypes
//
__interrupt void canaISR(void);
//
// Main
//
void main(void)
{
//
// Initialize device clock and peripherals
//
Device_init();
//
// Initialize GPIO and configure GPIO pins for CANTX/CANRX
// on module A.
//
Device_initGPIO();
GPIO_setPinConfig(DEVICE_GPIO_CFG_CANRXA);
GPIO_setPinConfig(DEVICE_GPIO_CFG_CANTXA);
//
// Initialize the CAN controllers
//
CAN_initModule(CANA_BASE);
//
// Set up the CAN bus bit rate to 500kHz for each module
// Refer to the Driver Library User Guide for information on how to set
// tighter timing control. Additionally, consult the device data sheet
// for more information about the CAN module clocking.
//
CAN_setBitRate(CANA_BASE, DEVICE_SYSCLK_FREQ, 100000, 20);
//
// Enable interrupts on the CAN A peripheral.
//
CAN_enableInterrupt(CANA_BASE, CAN_INT_IE0 | CAN_INT_ERROR |
CAN_INT_STATUS);
//
// Initialize PIE and clear PIE registers. Disables CPU interrupts.
//
Interrupt_initModule();
//
// Initialize the PIE vector table with pointers to the shell Interrupt
// Service Routines (ISR).
//
Interrupt_initVectorTable();
//
// Enable Global Interrupt (INTM) and realtime interrupt (DBGM)
//
EINT;
ERTM;
//
// Interrupts that are used in this example are re-mapped to
// ISR functions found within this file.
// This registers the interrupt handler in PIE vector table.
//
Interrupt_register(INT_CANA0,&canaISR);
//
// Enable the CAN-A interrupt signal
//
Interrupt_enable(INT_CANA0);
CAN_enableGlobalInterrupt(CANA_BASE, CAN_GLOBAL_INT_CANINT0);
// Flash_initModule(FLASH0CTRL_BASE, FLASH0ECC_BASE, 5);
//
// oReturnCheck = Fapi_initializeAPI(F021_CPU0_BASE_ADDRESS, 120);
//
// if(oReturnCheck != Fapi_Status_Success)
// {
// // Check Flash API documentation for possible errors
// Sample_Error();
// }
fapi_init();
//
// Initialize the receive message object used for receiving CAN messages.
// Message Object Parameters:
CAN_setupMessageObject(CANA_BASE, RX_MSG_OBJ_ID, 0,
CAN_MSG_FRAME_STD, CAN_MSG_OBJ_TYPE_RX, 0,
CAN_MSG_OBJ_USE_ID_FILTER | CAN_MSG_OBJ_RX_INT_ENABLE,
MSG_DATA_LENGTH);
//
// Start CAN module A operations
//
CAN_startModule(CANA_BASE);
//
// Loop to keep receiving data from another CAN Controller.
//
while(1)
{
}
//
// Stop application after completion.
//
asm(" ESTOP0");
}
//
// CAN A ISR - The interrupt service routine called when a CAN interrupt is
// triggered on CAN module A.
//
__interrupt void
canaISR(void)
{
uint32_t status;
//
// Read the CAN-B interrupt status to find the cause of the interrupt
//
status = CAN_getInterruptCause(CANA_BASE);
//
// If the cause is a controller status interrupt, then get the status
//
if(status == CAN_INT_INT0ID_STATUS)
{
//
// Read the controller status. This will return a field of status
// error bits that can indicate various errors. Error processing
// is not done in this example for simplicity. Refer to the
// API documentation for details about the error status bits.
// The act of reading this status will clear the interrupt.
//
status = CAN_getStatus(CANA_BASE);
//
// Check to see if an error occurred.
//
#ifdef TRANSMIT
if(((status & ~(CAN_STATUS_TXOK)) != CAN_STATUS_LEC_MSK) &&
((status & ~(CAN_STATUS_TXOK)) != CAN_STATUS_LEC_NONE))
#else
if(((status & ~(CAN_STATUS_RXOK)) != CAN_STATUS_LEC_MSK) &&
((status & ~(CAN_STATUS_RXOK)) != CAN_STATUS_LEC_NONE))
#endif
{
//
// Set a flag to indicate some errors may have occurred.
//
errorFlag = 1;
}
}
else if(status == TX_MSG_OBJ_ID)
{
//
// Getting to this point means that the TX interrupt occurred on
// message object 1, and the message TX is complete. Clear the
// message object interrupt.
//
CAN_clearInterruptStatus(CANA_BASE, TX_MSG_OBJ_ID);
//
// Increment a counter to keep track of how many messages have been
// transmitted. In a real application this could be used to set flags to
// indicate when a message is transmitted.
//
//txMsgCount++;
//
// Since the message was transmitted, clear any error flags.
//
errorFlag = 0;
}
else if(status == RX_MSG_OBJ_ID)
{
//
// Get the received message
//
//CAN_readMessage(CANA_BASE, RX_MSG_OBJ_ID, rxMsgData);
CAN_readMessageWithID(CANA_BASE,RX_MSG_OBJ_ID,&FrameType,&msgID,rxMsgData);
UpdaterCAN(msgID);
//
// Getting to this point means that the RX interrupt occurred on
// message object 1, and the message RX is complete. Clear the
// message object interrupt.
//
CAN_clearInterruptStatus(CANA_BASE, RX_MSG_OBJ_ID);
//
// Decrement the counter after a message has been received.
//
//
// Since the message was received, clear any error flags.
//
errorFlag = 0;
//CAN_sendMessage(CANA_BASE, TX_MSG_OBJ_ID, MSG_DATA_LENGTH,txMsgData);
}
//
// If something unexpected caused the interrupt, this would handle it.
//
else
{
//
// Spurious interrupt handling can go here.
//
}
//
// Clear the global interrupt flag for the CAN interrupt line
//
CAN_clearGlobalInterruptStatus(CANA_BASE, CAN_GLOBAL_INT_CANINT0);
//
// Acknowledge this interrupt located in group 9
//
Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP9);
}
//
// End of File
//
//#############################################################################
//
// FILE: F28003x_EEPROM.c
//
//#############################################################################
#include "EEPROM_Config.h" // Include EEPROM Config
// Global Variables
uint16 *Bank_Pointer;
uint16 *Page_Pointer;
uint16 *Sector_End;
uint16 WE_Protection_Mask;
uint32 Bank_Size;
uint16 Bank_Counter = 0;
uint16 Page_Counter = 0;
uint16 Bank_Status[8] = {0};
uint16 Page_Status[8] = {0};
uint16 Erase_Inactive_Unit = 0;
uint16 Erase_Blank_Check = 0;
uint16 NUM_EEPROM_SECTORS;
uint16 Empty_EEPROM = 1;
uint32_t g_ulBankInitialized = 0;
// Edit this to select Flash Sector location for EEPROM Emulation
// NOTE: INSERT FIRST AND LAST SECTOR NUMBERS ONLY
// Example: To use sectors 1-10, insert {1,10}
// Example: To only use sector 1, insert {1,1}
uint16 FIRST_AND_LAST_SECTOR[2] = {1,1};
//######################### EEPROM_Config ############################
// The purpose of this function is to configure Write/Erase protection masks
// used by the Flash API and check inputs in EEPROM_Config.h for validity.
// If an invalid configuration is encountered, a non-zero code is returned.
int EEPROM_Config_Check(void){
// FATAL ERRORS
// Check if using Flash Bank 0 for EEPROM Emulation. If Flash API is
// running from Flash Bank 0, the code will not execute. User can
// change the linker command file as needed to do EEPROM on Flash Bank 0
if (FLASH_BANK_SELECT == FlashBank0StartAddress)
{
return 0xFFFF;
}
// If using Bank 1
else if (FLASH_BANK_SELECT == FlashBank1StartAddress) // If using Bank 1
{
#if !defined(F28003x) // Verify that appropriate device is being used
return 0xFFFF;
#endif
}
// If using Bank 2
else if (FLASH_BANK_SELECT == FlashBank2StartAddress) // If using Bank 2
{
#if !defined(F28003x) // Verify that appropriate device is being used
return 0xFFFF;
#endif
}
// Derive the number of Flash sectors for EEPROM emulation
NUM_EEPROM_SECTORS = FIRST_AND_LAST_SECTOR[1] - FIRST_AND_LAST_SECTOR[0] + 1;
// If invalid amount of EEPROM sectors defined, return error code
if (NUM_EEPROM_SECTORS > NUM_FLASH_SECTORS || NUM_EEPROM_SECTORS == 0)
{
return 0xEEEE;
}
if (NUM_EEPROM_SECTORS > 1)
{
// Check if SECTOR_NUMBERS is sorted in increasing order and doesn't have duplicates
if (FIRST_AND_LAST_SECTOR[1] <= FIRST_AND_LAST_SECTOR[0])
{
return 0xEEEE;
}
// Check if SECTOR_NUMBERS contains invalid sector
if (FIRST_AND_LAST_SECTOR[0] > NUM_FLASH_SECTORS - 1)
{
return 0xEEEE;
}
if (FIRST_AND_LAST_SECTOR[1] > NUM_FLASH_SECTORS - 1 || FIRST_AND_LAST_SECTOR[1] < 1)
{
return 0xEEEE;
}
} else // If only one sector, validate it is input properly
{
// Verify that the only sector is valid
if (FIRST_AND_LAST_SECTOR[0] > NUM_FLASH_SECTORS - 1) {
return 0xEEEE;
}
}
#ifdef PAGE_MODE
// Calculate size of each EEPROM Bank (16 bit words)
Bank_Size = 8 + ((EEPROM_PAGE_DATA_SIZE + 8) * NUM_EEPROM_PAGES);
// Calculate amount of available space (16 bit words)
uint32 Available_Words = NUM_EEPROM_SECTORS * FLASH_SECTOR_SIZE;
// Check if size of EEPROM Banks and Pages will fit in EEPROM sectors
if (Bank_Size * NUM_EEPROM_BANKS > Available_Words)
{
return 0xCCCC;
}
#endif
// WARNINGS (Not fatal errors)
uint16 Warning_Flags = 0;
#ifdef PAGE_MODE
// Notify for extra space (more than one bank leftover)
if (Available_Words - (Bank_Size * NUM_EEPROM_BANKS ) >= Bank_Size)
{
Warning_Flags += 1;
}
// Notify if Page is less than 8 16-bit words
// This wastes Flash space because the _64_BIT_MODE could be used to achieve the same effect; configuration should be optimized.
// However, emulation can continue.
if (EEPROM_PAGE_DATA_SIZE < 5)
{
Warning_Flags += 2;
}
#endif
// Reset Bank Pointer to beginning of EEPROM Unit
RESET_BANK_POINTER;
// Configure Write/Erase Protection Masks used by the Flash API
WE_Protection_Mask = Configure_Protection_Masks(FIRST_AND_LAST_SECTOR, NUM_EEPROM_SECTORS);
// Erase the EEPROM sectors before programming
EEPROM_Erase();
return Warning_Flags;
}
//######################### EEPROM_Config ############################
//######################### Configure_Protection_Masks ############################
// This function calculates the Write/Erase Protection masks needed by the Flash API.
// The masks are used to set CMDWEPROT register
// Bits 0-15 of CMDWEPROT is applicable for sectors 0-15, each bit represents a sector
uint16 Configure_Protection_Masks(uint16* Sector_Numbers, uint16 Num_EEPROM_Sectors)
{
// Initialize a variable to store the bits indicating which sectors need to have write/erase
// protection disabled.
uint16 Protection_Mask_Sectors = 0;
uint16 Unshifted_Sectors;
// If we have more than one Flash Sector
if (Num_EEPROM_Sectors > 1)
{
// Configure mask
Unshifted_Sectors = (uint16) 1 << Num_EEPROM_Sectors;
Unshifted_Sectors -= 1;
Protection_Mask_Sectors |= (Unshifted_Sectors << Sector_Numbers[0]);
} else { // If only using 1 Flash Sector
if(Sector_Numbers[0] < 16)
{
Unshifted_Sectors = (uint16) 1 << Sector_Numbers[0];
Protection_Mask_Sectors |= Unshifted_Sectors;
}
}
return Protection_Mask_Sectors;
}
//######################### Configure_Protection_Masks ############################
//######################### EEPROM_GET_VALID_BANK ############################
void EEPROM_GetValidBank(uint16 Read_Flag)
{
//Each page holds N Data Words
//Page size = 8 Page_Status Words + N Data Words = (8 + N) Words
//Bank Size = 8 Bank_Status words + NUM_EEPROM_PAGES * Page size = 8 + NUM_EEPROM_PAGES*(8 + N) Words
uint16 i;
RESET_BANK_POINTER; // Reset Bank Pointer to enable search for current Bank
RESET_PAGE_POINTER; // Reset Page Pointer to enable search for current Page
// Find Current Bank
for(i=0; i < NUM_EEPROM_BANKS; i++)
{
Bank_Status[0] = *(Bank_Pointer); // Read contents of Bank Pointer
Bank_Status[4] = *(Bank_Pointer + 4);
if(Bank_Status[0] == EMPTY_BANK) // Check for Unused Bank
{
Bank_Counter = i; // Set Bank Counter to number of current page
return; // If Bank is Unused, return as EEPROM is empty
}
if(Bank_Status[0] == CURRENT_BANK && Bank_Status[4] != CURRENT_BANK) // Check for Current Bank
{
Bank_Counter = i; // Set Bank Counter to number of current bank
Page_Pointer = Bank_Pointer + 8; // Set Page Pointer to first page in current bank
break; // Break from loop as current bank has been found
}
if(Bank_Status[0] == CURRENT_BANK && Bank_Status[4] == CURRENT_BANK) // Check for Used Bank
Bank_Pointer += Bank_Size; // If Bank has been used, set pointer to next bank
}
// Find Current Page
for(i=0; i < NUM_EEPROM_PAGES; i++)
{
Page_Status[0] = *(Page_Pointer); // Read contents of Page Pointer
Page_Status[4] = *(Page_Pointer + 4);
// Check for Blank Page or Current Page
if(Page_Status[0] == BLANK_PAGE)
{
Page_Counter = i; // Set Page Counter to number of current page
break; // Break from loop as current page has been found
}
if (Page_Status[0] == CURRENT_PAGE && Page_Status[4] != CURRENT_PAGE)
{
Page_Counter = i + 1;
break;
}
// Check for Used Page
if(Page_Status[0] == CURRENT_PAGE && Page_Status[4] == CURRENT_PAGE)
{
Page_Pointer += EEPROM_PAGE_DATA_SIZE + 8; // If page has been used, set pointer to next page
}
}
// Check for full EEPROM
if (!Read_Flag)
{
if (Bank_Counter == NUM_EEPROM_BANKS - 1 && Page_Counter == NUM_EEPROM_PAGES)
{
// Re-Configure Write/Erase Protection Masks used by the Flash API
WE_Protection_Mask ^= 0xFFFF;
Erase_Inactive_Unit = 1; // Set flag to erase inactive (full) Flash Bank
EEPROM_UpdatePageStatus(); // Update Page Status of previous page
EEPROM_UpdateBankStatus(); // Update Bank Status of previous page
Erase_Blank_Check = 1; // Set flag to perform blank check on inactive (full) Flash Bank
EEPROM_Erase(); // Erase flash sector being used as EEPROM
RESET_BANK_POINTER; // Reset Bank Pointer as EEPROM is empty
RESET_PAGE_POINTER; // Reset Page Pointer as EEPROM is empty
}
}
}
//######################### EEPROM_GET_VALID_BANK ############################
//############################# EEPROM_ERASE #################################
void EEPROM_Erase()
{
Fapi_StatusType oReturnCheck;
// Erase the EEPROM Bank
oReturnCheck = Fapi_issueBankEraseCommand((uint32*) FLASH_BANK_SELECT, WE_Protection_Mask);
// Wait for completion and check for any programming errors
EEPROM_CheckStatus(&oReturnCheck);
}
//############################# EEPROM_ERASE #################################
//############################# ERASE_BANK #################################
void Erase_Bank()
{
Fapi_StatusType oReturnCheck;
// Erase the EEPROM Bank
oReturnCheck = Fapi_issueBankEraseCommand((uint32*) FLASH_BANK_SELECT, WE_Protection_Mask);
// Wait for completion and check for any programming errors
EEPROM_CheckStatus(&oReturnCheck);
}
//############################# EEPROM_READ ##################################
void EEPROM_Read(uint16* Read_Buffer)
{
#ifdef PAGE_MODE
uint16 i;
// Check for empty EEPROM
if (Empty_EEPROM)
{
Sample_Error(); // Attempting to read data that hasn't been written
} else
{
// Find Current Bank and Current Page
EEPROM_GetValidBank(1);
// Increment page pointer to point at first data word
Page_Pointer += 8;
// Transfer contents of Current Page to Read Buffer
for(i=0;i<DATA_SIZE;i++)
{
Read_Buffer[i] = *(Page_Pointer++);
}
}
#else
uint16 i;
// Check for empty EEPROM
if (Empty_EEPROM)
{
Sample_Error(); // Attempting to read data that hasn't been written
} else
{
// Move the bank pointer backwards to read data
Bank_Pointer -= 4;
// Transfer contents of Current Page to Read Buffer
for(i=0;i<4;i++)
{
Read_Buffer[i] = *(Bank_Pointer++);
}
}
#endif
}
//############################# EEPROM_READ ##################################
//############################ EEPROM_WRITE ##################################
void EEPROM_Write(uint16* Write_Buffer)
{
EEPROM_GetValidBank(0); // Find Current Bank and Current Page
EEPROM_UpdatePageStatus(); // Update Page Status of previous page
EEPROM_UpdateBankStatus(); // Update Bank Status of current and previous bank
EEPROM_UpdatePageData(Write_Buffer); // Update Page Data of current page
}
//############################ EEPROM_WRITE ##################################
//###################### EEPROM_UPDATE_BANK_STATUS ###########################
void EEPROM_UpdateBankStatus()
{
// Variables needed for Flash API Functions
Fapi_StatusType oReturnCheck;
Bank_Status[0] = *(Bank_Pointer); // Read Bank Status from Bank Pointer
Page_Status[0] = *(Page_Pointer); // Read Page Status from Page Pointer
// Program Bank Status for Empty EEPROM
if (Bank_Status[0] == EMPTY_BANK)
{
// Set Bank Status to Current Bank
Bank_Status[0] = CURRENT_BANK;
Bank_Status[1] = CURRENT_BANK;
Bank_Status[2] = CURRENT_BANK;
Bank_Status[3] = CURRENT_BANK;
// Program Bank Status to current bank
oReturnCheck = Fapi_issueProgrammingCommand((uint32*) Bank_Pointer,
Bank_Status, 4, 0, 0,
Fapi_AutoEccGeneration);
// Wait for completion and check for any programming errors
EEPROM_CheckStatus(&oReturnCheck);
// Set Page Pointer to first page of current bank
Page_Counter = 0;
Page_Pointer = Bank_Pointer + 8;
}
// Program Bank Status of full bank and following bank
if (Bank_Status[0] == CURRENT_BANK && Page_Counter == NUM_EEPROM_PAGES)
{
// Set Bank Status to Used Bank
Bank_Status[0] = CURRENT_BANK;
Bank_Status[1] = CURRENT_BANK;
Bank_Status[2] = CURRENT_BANK;
Bank_Status[3] = CURRENT_BANK;
// Program Bank Status to full bank
oReturnCheck = Fapi_issueProgrammingCommand((uint32*) Bank_Pointer + 2,
Bank_Status, 4, 0, 0,
Fapi_AutoEccGeneration);
// Wait for completion and check for any programming errors
EEPROM_CheckStatus(&oReturnCheck);
// Increment Bank Pointer to next bank
Bank_Pointer += Bank_Size;
if (Bank_Counter == NUM_EEPROM_BANKS - 1 && Page_Counter == NUM_EEPROM_PAGES){
return;
}
else{
// Set Bank Status to Current Bank
Bank_Status[0] = CURRENT_BANK;
Bank_Status[1] = CURRENT_BANK;
Bank_Status[2] = CURRENT_BANK;
Bank_Status[3] = CURRENT_BANK;
// Program Bank Status to current bank
oReturnCheck = Fapi_issueProgrammingCommand((uint32*) Bank_Pointer,
Bank_Status, 4, 0, 0,
Fapi_AutoEccGeneration);
// Wait for completion and check for any programming errors
EEPROM_CheckStatus(&oReturnCheck);
// Set Page Pointer to first page of current bank
Page_Counter = 0;
Page_Pointer = Bank_Pointer + 8;
}
}
}
//###################### EEPROM_UPDATE_BANK_STATUS ###########################
//###################### EEPROM_UPDATE_PAGE_STATUS ###########################
void EEPROM_UpdatePageStatus()
{
Fapi_StatusType oReturnCheck;
Bank_Status[0] = *(Bank_Pointer); // Read Bank Status from Bank Pointer
Page_Status[0] = *(Page_Pointer); // Read Page Status from Page Pointer
// Check if Page Status is blank. If so return to EEPROM_WRITE.
if(Page_Status[0] == BLANK_PAGE)
return;
// Program previous page's status to Used Page
else
{
// Set Page Status to Used Page
Page_Status[0] = CURRENT_PAGE;
Page_Status[1] = CURRENT_PAGE;
Page_Status[2] = CURRENT_PAGE;
Page_Status[3] = CURRENT_PAGE;
// Program Bank Status to current bank
oReturnCheck = Fapi_issueProgrammingCommand((uint32*) Page_Pointer + 2,
Page_Status, 4, 0, 0,
Fapi_AutoEccGeneration);
// Wait for completion and check for any programming errors
EEPROM_CheckStatus(&oReturnCheck);
// Increment Page Pointer to next page
Page_Pointer += EEPROM_PAGE_DATA_SIZE + 8;
}
}
//###################### EEPROM_UPDATE_PAGE_STATUS ###########################
//###################### EEPROM_UPDATE_PAGE_DATA ###########################
void EEPROM_UpdatePageData(uint16* Write_Buffer)
{
// Variable for write incrementing
uint16 i;
// Variables needed for Flash API Functions
Fapi_StatusType oReturnCheck;
for (i = 0; i < EEPROM_PAGE_DATA_SIZE / 4; i++)
{
// Variable for page offset (first write position has offset of 2 (64 bits),
// second has offset of 4 (128 bits), etc.)
uint32 Page_Offset = 4 + (2 * i);
// Program data located in Write_Buffer to current page
oReturnCheck = Fapi_issueProgrammingCommand((uint32*) Page_Pointer + Page_Offset,
Write_Buffer + (i*4), 4, 0, 0,
Fapi_AutoEccGeneration);
// Wait for completion and check for any programming errors
EEPROM_CheckStatus(&oReturnCheck);
}
if(oReturnCheck == Fapi_Status_Success)
{
// Set Page Status to Current Page
Page_Status[0] = CURRENT_PAGE;
Page_Status[1] = CURRENT_PAGE;
Page_Status[2] = CURRENT_PAGE;
Page_Status[3] = CURRENT_PAGE;
oReturnCheck = Fapi_issueProgrammingCommand((uint32*) Page_Pointer,
Page_Status, 4, 0, 0,
Fapi_AutoEccGeneration);
// Wait for completion and check for any programming errors
EEPROM_CheckStatus(&oReturnCheck);
Empty_EEPROM = 0;
}
if (Erase_Inactive_Unit)
{
// Erase the inactive (full) EEPROM Bank
Erase_Inactive_Unit = 0;
// Re-configure Write/Erase Protection Masks for active EEPROM Bank
WE_Protection_Mask ^= 0xFFFF;
}
}
//###################### EEPROM_UPDATE_PAGE_DATA ###########################
//###################### EEPROM_CHECKSTATUS ###########################
void EEPROM_CheckStatus(Fapi_StatusType* oReturnCheck)
{
Fapi_FlashStatusType oFlashStatus;
Fapi_FlashStatusWordType oFlashStatusWord;
uint32_t sectorAddress = FLASH_BANK_SELECT + FIRST_AND_LAST_SECTOR[0] * FLASH_SECTOR_SIZE;
uint16_t sectorSize = (FIRST_AND_LAST_SECTOR[1] - FIRST_AND_LAST_SECTOR[0] + 1) * (FLASH_SECTOR_SIZE / 2);
// Wait until the Flash program operation is over
while(Fapi_checkFsmForReady() == Fapi_Status_FsmBusy);
if(*oReturnCheck != Fapi_Status_Success)
{
// Check Flash API documentation for possible errors
Sample_Error();
}
//
// Read FMSTAT register contents to know the status of FSM after
// program command to see if there are any program operation related
// errors
//
oFlashStatus = Fapi_getFsmStatus();
if (Erase_Inactive_Unit && Erase_Blank_Check){
*oReturnCheck = Fapi_doBlankCheck((uint32_t *) sectorAddress,
sectorSize, &oFlashStatusWord);
Erase_Blank_Check = 0;
}
if(*oReturnCheck != Fapi_Status_Success || oFlashStatus != 0)
{
//Check FMSTAT and debug accordingly
Sample_Error();
}
}
//###################### EEPROM_CHECKSTATUS ###########################
//###################### EEPROM_GET_FOUR_WORD_POINTER ###########################
// NOTE: This function expects that 0xFFFF is invalid data
void EEPROM_Get_64_Bit_Data_Address()
{
uint16 *End_Address;
End_Address = (uint16 *)END_OF_SECTOR; // Set End_Address for sector
if(Bank_Pointer > End_Address-3) // Test if EEPROM is full
{
// Re-Configure Write/Erase Protection Masks used by the Flash API
WE_Protection_Mask ^= 0xFFFF;
Erase_Inactive_Unit = 1; // Set flag to erase inactive (full) Flash Bank
Erase_Blank_Check = 1; // Set flag to perform blank check on inactive (full) Flash Bank
EEPROM_Erase(); // Erase flash Bank being used as EEPROM
Erase_Inactive_Unit = 0; // Reset flag for erasing inactive (full) Flash Bank)
RESET_BANK_POINTER; // Reset Bank Pointer as EEPROM is empty
}
}
//###################### EEPROM_GET_SINGLE_POINTER ###########################
//##################### EEPROM_PROGRAM_FOUR_WORDS ###########################
// NOTE: If Num_Words < 4, the missing missing words will be filled with 0xFFFF
// Example: EEPROM_Program_64_Bits(2, 1, 2, 3, 4)
// This results in [0x0001 0x0002 0xFFFF 0xFFFF] being programmed to Flash
void EEPROM_Program_64_Bits(uint16 Num_Words, uint16 * Write_Buffer)
{
// Variables needed for Flash API Functions
Fapi_StatusType oReturnCheck;
// Test for full sector
EEPROM_Get_64_Bit_Data_Address();
// Overwrite anything in first 4 Write_Buffer addresses with 0xFFFF if less than 4 words are to be written
int i;
for(i = Num_Words; i < 4; i++)
{
Write_Buffer[i] = 0xFFFF;
}
oReturnCheck = Fapi_issueProgrammingCommand((uint32*) Bank_Pointer,
Write_Buffer, 4, 0, 0,
Fapi_AutoEccGeneration);
// Wait for completion and check for any programming errors
EEPROM_CheckStatus(&oReturnCheck);
Empty_EEPROM = 0;
// Increment to next location
Bank_Pointer += 4;
}
//##################### EEPROM_PROGRAM_FOUR_WORDS ###########################
//##################### Fapi_init ###########################
Fapi_StatusType fapi_init(void)
{
Fapi_StatusType oReturnCheck;
Flash_initModule(FLASH0CTRL_BASE, FLASH0ECC_BASE, 5);
oReturnCheck = Fapi_initializeAPI(F021_CPU0_BASE_ADDRESS, 120);
if(oReturnCheck != Fapi_Status_Success)
{
// Check Flash API documentation for possible errors
Sample_Error();
}
return(oReturnCheck);
}
//##################### Fapi_Write_EEPROM ###########################
uint32_t Fapi_Write_EEPROM(uint32_t dest_address, uint32_t src_address, uint32_t SizeInBytes)
{
Fapi_StatusType status = Fapi_Status_Success;
register uint32_t src = src_address;
register uint32_t dst = dest_address;
uint32_t bytes;
// Out of Bank 3
if (dest_address < 0xA0000 || dest_address > 0xAFFFF)
return (2);
status = Fapi_setActiveFlashBank(Fapi_FlashBank2);
status = Fapi_setupBankSectorEnable();
while(Fapi_checkFsmForReady() == Fapi_Status_FsmBusy);
while(Fapi_checkFsmForReady() != Fapi_Status_Success);
//! Erase Bank7 - Sector0
status = Fapi_issueAsyncCommandWithAddress(Fapi_EraseSector, (uint32_t *)dst);
if (status != Fapi_Status_Success)
return (1);
while(Fapi_checkFsmForReady() == Fapi_Status_FsmBusy);
while(Fapi_checkFsmForReady() != Fapi_Status_Success);
if (SizeInBytes < 8)
bytes = SizeInBytes;
else
bytes = 8;
//! Write data to Bank7 - Sector0
while( SizeInBytes > 0)
{
status = Fapi_issueProgrammingCommand((uint32_t *)dst,
(uint8_t *)src,
(uint32_t) bytes,
0,
0,
Fapi_AutoEccGeneration);
while(Fapi_checkFsmForReady() == Fapi_Status_FsmBusy);
while(Fapi_checkFsmForReady() != Fapi_Status_Success);
src += bytes;
dst += bytes;
SizeInBytes -= bytes;
if ( SizeInBytes < 8){
bytes = SizeInBytes;
}
}
//! success
return (0);
}
uint32_t Fapi_Read_EEPROM(uint32_t dest_address, uint32_t src_address, uint32_t SizeInBytes)
{
memcpy((uint32_t *)dest_address, (uint32_t *)src_address, SizeInBytes);
//! success
return (0);
}
//##################### Fapi_Write_EEPROM ###########################
/* Below is the code for Flash_DisablePrefetch_SW_Workaround(). */
//*****************************************************************************
//
//! Disables flash prefetch mechanism and adds 7 cycle delay
//!
//! \param ctrlBase is the base address of the flash wrapper control registers.
//!
//! \return None.
//
//*****************************************************************************
#ifdef __cplusplus
#pragma CODE_SECTION(".TI.ramfunc");
#else
#pragma CODE_SECTION(Flash_DisablePrefetch_SW_Workaround, ".TI.ramfunc");
#endif
void Flash_DisablePrefetch_SW_Workaround(uint32_t ctrlBase)
{
//
// Check the arguments.
//
ASSERT(Flash_isCtrlBaseValid(ctrlBase));
//
// Disable flash prefetch
//
Flash_disablePrefetch(ctrlBase);
//
// Force a pipeline flush to ensure that the write to the last register
// configured occurs before returning.
//
FLASH_DELAY_CONFIG;
}
/* Below is the code for Flash_EnablePrefetch_SW_Workaround() */
//*****************************************************************************
//
//! Enables flash prefetch mechanism and adds 7 cycle delay
//!
//! \param ctrlBase is the base address of the flash wrapper control registers.
//!
//! \return None.
//
//*****************************************************************************
#ifdef __cplusplus
#pragma CODE_SECTION(".TI.ramfunc");
#else
#pragma CODE_SECTION(Flash_EnablePrefetch_SW_Workaround, ".TI.ramfunc");
#endif
void Flash_EnablePrefetch_SW_Workaround(uint32_t ctrlBase)
{
//
// Check the arguments.
//
ASSERT(Flash_isCtrlBaseValid(ctrlBase));
//
// Disable flash prefetch
//
Flash_enablePrefetch(ctrlBase);
//
// Force a pipeline flush to ensure that the write to the last register
// configured occurs before returning.
//
FLASH_DELAY_CONFIG;
}
//##################### SAMPLE_ERROR ###########################
// This is a sample error function, no error handling is implemented in this project,
void Sample_Error() {
asm(" ESTOP0");
}
//##################### EXAMPLE_DONE ###########################
// This is a sample function that signifies the end of program execution
void Example_Done() {
asm(" ESTOP0");
}


