Files
levelx/common/src/lx_nor_flash_simulator.c
T

253 lines
8.2 KiB
C

/***************************************************************************
* Copyright (c) 2024 Microsoft Corporation
* Copyright (c) 2026-present Eclipse ThreadX contributors
*
* This program and the accompanying materials are made available under the
* terms of the MIT License which is available at
* https://opensource.org/licenses/MIT.
*
* SPDX-License-Identifier: MIT
**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/** */
/** LevelX Component */
/** */
/** NOR Flash Simulator */
/** */
/**************************************************************************/
/**************************************************************************/
/* Include necessary files. */
#include "lx_api.h"
/* Define constants for the NOR flash simulation. */
/* This configuration is for one physical sector of overhead. */
#define TOTAL_BLOCKS 8
#define PHYSICAL_SECTORS_PER_BLOCK 16 /* Min value of 2, max value of 120 for 1 sector of overhead. */
#define WORDS_PER_PHYSICAL_SECTOR 128
#define FREE_BIT_MAP_WORDS ((PHYSICAL_SECTORS_PER_BLOCK-1)/32)+1
#define USABLE_SECTORS_PER_BLOCK (PHYSICAL_SECTORS_PER_BLOCK-1)
#define UNUSED_METADATA_WORDS_PER_BLOCK (WORDS_PER_PHYSICAL_SECTOR-(3+FREE_BIT_MAP_WORDS+USABLE_SECTORS_PER_BLOCK))
typedef struct PHYSICAL_SECTOR_STRUCT
{
unsigned long memory[WORDS_PER_PHYSICAL_SECTOR];
} PHYSICAL_SECTOR;
typedef struct FLASH_BLOCK_STRUCT
{
unsigned long erase_count;
unsigned long min_log_sector;
unsigned long max_log_sector;
unsigned long free_bit_map[FREE_BIT_MAP_WORDS];
unsigned long sector_metadata[USABLE_SECTORS_PER_BLOCK];
unsigned long unused_words[UNUSED_METADATA_WORDS_PER_BLOCK];
PHYSICAL_SECTOR physical_sectors[USABLE_SECTORS_PER_BLOCK];
} FLASH_BLOCK;
FLASH_BLOCK nor_memory_area[TOTAL_BLOCKS];
ULONG nor_sector_memory[WORDS_PER_PHYSICAL_SECTOR];
UINT _lx_nor_flash_simulator_initialize(LX_NOR_FLASH *nor_flash);
UINT _lx_nor_flash_simulator_erase_all(VOID);
#ifdef LX_NOR_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
UINT _lx_nor_flash_simulator_read(LX_NOR_FLASH *nor_flash, ULONG *flash_address, ULONG *destination, ULONG words);
UINT _lx_nor_flash_simulator_write(LX_NOR_FLASH *nor_flash, ULONG *flash_address, ULONG *source, ULONG words);
UINT _lx_nor_flash_simulator_block_erase(LX_NOR_FLASH *nor_flash, ULONG block, ULONG erase_count);
UINT _lx_nor_flash_simulator_block_erased_verify(LX_NOR_FLASH *nor_flash, ULONG block);
UINT _lx_nor_flash_simulator_system_error(LX_NOR_FLASH *nor_flash, UINT error_code, ULONG block, ULONG sector);
#else
UINT _lx_nor_flash_simulator_read(ULONG *flash_address, ULONG *destination, ULONG words);
UINT _lx_nor_flash_simulator_write(ULONG *flash_address, ULONG *source, ULONG words);
UINT _lx_nor_flash_simulator_block_erase(ULONG block, ULONG erase_count);
UINT _lx_nor_flash_simulator_block_erased_verify(ULONG block);
UINT _lx_nor_flash_simulator_system_error(UINT error_code, ULONG block, ULONG sector);
#endif
UINT _lx_nor_flash_simulator_initialize(LX_NOR_FLASH *nor_flash)
{
/* Setup the base address of the flash memory. */
nor_flash -> lx_nor_flash_base_address = (ULONG *) &nor_memory_area[0];
/* Setup geometry of the flash. */
nor_flash -> lx_nor_flash_total_blocks = TOTAL_BLOCKS;
nor_flash -> lx_nor_flash_words_per_block = sizeof(FLASH_BLOCK)/sizeof(ULONG);
/* Setup function pointers for the NOR flash services. */
nor_flash -> lx_nor_flash_driver_read = _lx_nor_flash_simulator_read;
nor_flash -> lx_nor_flash_driver_write = _lx_nor_flash_simulator_write;
nor_flash -> lx_nor_flash_driver_block_erase = _lx_nor_flash_simulator_block_erase;
nor_flash -> lx_nor_flash_driver_block_erased_verify = _lx_nor_flash_simulator_block_erased_verify;
/* Setup local buffer for NOR flash operation. This buffer must be the sector size of the NOR flash memory. */
nor_flash -> lx_nor_flash_sector_buffer = &nor_sector_memory[0];
/* Return success. */
return(LX_SUCCESS);
}
#ifdef LX_NOR_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
UINT _lx_nor_flash_simulator_read(LX_NOR_FLASH *nor_flash, ULONG *flash_address, ULONG *destination, ULONG words)
#else
UINT _lx_nor_flash_simulator_read(ULONG *flash_address, ULONG *destination, ULONG words)
#endif
{
#ifdef LX_NOR_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
LX_PARAMETER_NOT_USED(nor_flash);
#endif
/* Loop to read flash. */
while (words--)
{
/* Copy word. */
*destination++ = *flash_address++;
}
return(LX_SUCCESS);
}
#ifdef LX_NOR_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
UINT _lx_nor_flash_simulator_write(LX_NOR_FLASH *nor_flash, ULONG *flash_address, ULONG *source, ULONG words)
#else
UINT _lx_nor_flash_simulator_write(ULONG *flash_address, ULONG *source, ULONG words)
#endif
{
#ifdef LX_NOR_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
LX_PARAMETER_NOT_USED(nor_flash);
#endif
/* Loop to write flash. */
while (words--)
{
/* Copy word. */
*flash_address++ = *source++;
}
return(LX_SUCCESS);
}
#ifdef LX_NOR_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
UINT _lx_nor_flash_simulator_block_erase(LX_NOR_FLASH *nor_flash, ULONG block, ULONG erase_count)
#else
UINT _lx_nor_flash_simulator_block_erase(ULONG block, ULONG erase_count)
#endif
{
ULONG *pointer;
ULONG words;
#ifdef LX_NOR_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
LX_PARAMETER_NOT_USED(nor_flash);
#endif
LX_PARAMETER_NOT_USED(erase_count);
/* Setup pointer. */
pointer = (ULONG *) &nor_memory_area[block];
/* Loop to erase block. */
words = sizeof(FLASH_BLOCK)/sizeof(ULONG);
while (words--)
{
/* Erase word of block. */
*pointer++ = (ULONG) 0xFFFFFFFF;
}
return(LX_SUCCESS);
}
UINT _lx_nor_flash_simulator_erase_all(VOID)
{
ULONG *pointer;
ULONG words;
/* Setup pointer. */
pointer = (ULONG *) &nor_memory_area[0];
/* Loop to erase block. */
words = sizeof(nor_memory_area)/(sizeof(ULONG));
while (words--)
{
/* Erase word of block. */
*pointer++ = (ULONG) 0xFFFFFFFF;
}
return(LX_SUCCESS);
}
#ifdef LX_NOR_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
UINT _lx_nor_flash_simulator_block_erased_verify(LX_NOR_FLASH *nor_flash, ULONG block)
#else
UINT _lx_nor_flash_simulator_block_erased_verify(ULONG block)
#endif
{
ULONG *word_ptr;
ULONG words;
#ifdef LX_NOR_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
LX_PARAMETER_NOT_USED(nor_flash);
#endif
/* Determine if the block is completely erased. */
/* Pickup the pointer to the first word of the block. */
word_ptr = (ULONG *) &nor_memory_area[block].erase_count;
/* Calculate the number of words in a block. */
words = sizeof(FLASH_BLOCK)/sizeof(ULONG);
/* Loop to check if the block is erased. */
while (words--)
{
/* Is this word erased? */
if (*word_ptr++ != 0xFFFFFFFF)
return(LX_ERROR);
}
/* Return success. */
return(LX_SUCCESS);
}
#ifdef LX_NOR_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
UINT _lx_nor_flash_simulator_system_error(LX_NOR_FLASH *nor_flash, UINT error_code, ULONG block, ULONG sector)
#else
UINT _lx_nor_flash_simulator_system_error(UINT error_code, ULONG block, ULONG sector)
#endif
{
#ifdef LX_NOR_ENABLE_CONTROL_BLOCK_FOR_DRIVER_INTERFACE
LX_PARAMETER_NOT_USED(nor_flash);
#endif
LX_PARAMETER_NOT_USED(error_code);
LX_PARAMETER_NOT_USED(block);
LX_PARAMETER_NOT_USED(sector);
/* Custom processing goes here... all errors are fatal. */
return(LX_ERROR);
}