📄 fsintrnl.c
字号:
/***********************************************************************/
/* */
/* Module: fsintrnl.c */
/* Release: 2004.5 */
/* Version: 2004.15 */
/* Purpose: Implements the internal functions for the flash files */
/* */
/*---------------------------------------------------------------------*/
/* */
/* Copyright 2004, Blunk Microsystems */
/* ALL RIGHTS RESERVED */
/* */
/* Licensees have the non-exclusive right to use, modify, or extract */
/* this computer program for software development at a single site. */
/* This program may be resold or disseminated in executable format */
/* only. The source code may not be redistributed or resold. */
/* */
/***********************************************************************/
#include "flashfsp.h"
#if NUM_FFS_VOLS
#define TIMING FALSE
#if TIMING
#include "../../../include/libc/time.h"
clock_t TotWrCtrl = 0, PreWrCtrl = 0, TotRec = 0, RecWrCtrl = 0;
ui32 RecCount = 0, WrCtrlCount = 0;
#endif
#define DO_JMP_RECYCLE FALSE
#if DO_JMP_RECYCLE
extern int EnableCount;
#endif
/***********************************************************************/
/* Symbol Definitions */
/***********************************************************************/
#define SINGLE_USED 1 /* Flags for sector values on flash */
#define MULTIPLE_USED 2
#define SINGLE_FREE 3
#define MULTIPLE_FREE 4
#define SINGLE_DIRTY 5
#define MULTIPLE_DIRTY 6
#define BLOCK_INVALID 7
#define MAX_WDELTA 15 /* Maximum allowed wear count diff */
#define FLASH_CTRL_UI32s 13 /* Num of ui32s present in ctrl info */
#define WRITE_CTRL TRUE
#define SKIP_WRITE_CTRL FALSE
#define SKIP_SECTS TRUE
#define DONT_SKIP_SECTS FALSE
#define FFS_FAILED_POWER_UP 1
#define FFS_NORMAL_POWER_UP 2
#define FFS_SLOW_POWER_UP 3
/***********************************************************************/
/* Macro Definitions */
/***********************************************************************/
#if FFS_SWAP_ENDIAN
#define write_ctrl_ui32(v) \
v_ui32 = v; \
v_ui32 = ((v_ui32 & 0xFF) << 24) | ((v_ui32 & 0xFF00) << 8) | \
((v_ui32 & 0xFF0000) >> 8) | ((v_ui32 & 0xFF000000) >> 24);\
status = Flash->write_ctrl(&v_ui32, sizeof(ui32)); \
if (status) \
goto WrCtrl_exit;
#define write_ctrl_ui16(v) \
v_ui16 = v; \
v_ui16 = (ui16)(((v_ui16 & 0xFF) << 8) | ((v_ui16 & 0xFF00) >> 8)); \
status = Flash->write_ctrl(&v_ui16, sizeof(ui16)) \
if (status) \
goto WrCtrl_exit;
#else
#define write_ctrl_ui32(v) \
v_ui32 = v; \
status = Flash->write_ctrl(&v_ui32, sizeof(ui32)); \
if (status) \
goto WrCtrl_exit;
#define write_ctrl_ui16(v) \
v_ui16 = v; \
status = Flash->write_ctrl(&v_ui16, sizeof(ui16)); \
if (status) \
goto WrCtrl_exit;
#endif /* FFS_SWAP_ENDIAN */
#if FFS_DEBUG
int printf(const char *, ...);
#endif
/***********************************************************************/
/* Local Function Definitions */
/***********************************************************************/
/***********************************************************************/
/* read_ctrl: Read a chunk of control memory from flash */
/* */
/* Inputs: head = address to write to in RAM */
/* length = number of bytes the chunk has */
/* */
/* Returns: 0 on success, -1 on error */
/* */
/***********************************************************************/
static int read_ctrl(void *head, uint length)
{
static ui32 offset = 0;
ui8 *dst = head;
ui16 next_ctrl_block = 0xFFFF;
/*-------------------------------------------------------------------*/
/* If length is zero, reset offset and read first sector. */
/*-------------------------------------------------------------------*/
if (length == 0)
{
offset = 0;
if (Flash->read_sector(Flash->tmp_sect, Flash->ctrl_sect))
{
set_errno(EIO);
return -1;
}
return 0;
}
/*-------------------------------------------------------------------*/
/* Loop, reading one byte at a time. */
/*-------------------------------------------------------------------*/
do
{
/*-----------------------------------------------------------------*/
/* If needed, read new sector from flash. */
/*-----------------------------------------------------------------*/
if (offset == Flash->sect_sz)
{
/*---------------------------------------------------------------*/
/* If at block boundary, update using NextCtrlBlock. */
/*---------------------------------------------------------------*/
if ((++Flash->ctrl_sect % Flash->block_sects) == 0)
{
PfAssert(next_ctrl_block < Flash->num_blocks);
Flash->ctrl_sect = next_ctrl_block * Flash->block_sects +
Flash->hdr_sects;
}
/*---------------------------------------------------------------*/
/* Read whole sector in and reset the sector offset. */
/*---------------------------------------------------------------*/
if (Flash->read_sector(Flash->tmp_sect, Flash->ctrl_sect))
{
set_errno(EIO);
return -1;
}
offset = 0;
}
/*-----------------------------------------------------------------*/
/* If this is last sector in block, and we are down to last two */
/* bytes, read in next ctrl block. */
/*-----------------------------------------------------------------*/
if (offset == Flash->sect_sz - 2 &&
(Flash->ctrl_sect + 1) % Flash->block_sects == 0)
{
next_ctrl_block = (ui16)(Flash->tmp_sect[offset++] << 8);
next_ctrl_block |= Flash->tmp_sect[offset++];
}
else
{
/*---------------------------------------------------------------*/
/* Read one byte of control information and increment. */
/*---------------------------------------------------------------*/
*dst++ = Flash->tmp_sect[offset++];
--length;
}
}
while (length);
return 0;
}
/***********************************************************************/
/* read_ctrl_ui32: Read a ui32 from flash in big endian and convert to */
/* machine endianess */
/* */
/* Input: val = place to store the read ui32 */
/* */
/* Returns: 0 on success, -1 on failure */
/* */
/***********************************************************************/
static int read_ctrl_ui32(ui32 *val)
{
#if FFS_SWAP_ENDIAN
ui32 tmp;
#endif
if (read_ctrl(val, sizeof(ui32)))
return -1;
#if FFS_SWAP_ENDIAN
tmp = *val;
*val = ((tmp & 0xFF) << 24) | ((tmp & 0xFF00) << 8) |
((tmp & 0xFF0000) >> 8) | ((tmp & 0xFF000000) >> 24);
#endif
return 0;
}
/***********************************************************************/
/* read_ctrl_ui16: Read a ui16 from flash in big endian and convert to */
/* machine endianess */
/* */
/* Input: val = place to store the read ui16 */
/* */
/* Returns: 0 on success, -1 on failure */
/* */
/***********************************************************************/
static int read_ctrl_ui16(ui16 *val)
{
#if FFS_SWAP_ENDIAN
ui16 tmp;
#endif
if (read_ctrl(val, sizeof(ui16)))
return -1;
#if FFS_SWAP_ENDIAN
tmp = *val;
*val = (ui16)(((tmp & 0xFF) << 8) | ((tmp & 0xFF00) >> 8));
#endif
return 0;
}
/***********************************************************************/
/* readjust_set: Fill -1 slots in erase set with blocks */
/* */
/***********************************************************************/
static void readjust_set(void)
{
ui32 i, j, sect;
int b, max_f, f_b, max_b;
ui32 free_blck, last_in_free_block;
/*-------------------------------------------------------------------*/
/* First, shift all non -1 slots to the front. */
/*-------------------------------------------------------------------*/
for (i = 0; i < Flash->set_blocks; ++i)
if (Flash->erase_set[i] == -1)
{
for (j = i + 1; j < Flash->set_blocks; ++j)
if (Flash->erase_set[j] != -1)
break;
if (j >= Flash->set_blocks)
break;
Flash->erase_set[i] = Flash->erase_set[j];
Flash->erase_set[j] = -1;
}
for (j = 0; j < i; ++j)
Flash->blocks[Flash->erase_set[j]].bad_block = TRUE;
/*-------------------------------------------------------------------*/
/* Now fill all -1 slots with new blocks. */
/*-------------------------------------------------------------------*/
for (; i < Flash->set_blocks; ++i)
{
for (b = 0, max_f = -1; b < Flash->num_blocks; ++b)
{
/*---------------------------------------------------------------*/
/* If block is not bad, ctrl and has no free sects, candidate. */
/*---------------------------------------------------------------*/
if (!Flash->blocks[b].bad_block && !Flash->blocks[b].ctrl_block &&
Flash->sect_tbl[(b + 1) * Flash->block_sects - 1].prev !=
FFREE_SECT)
{
/*-------------------------------------------------------------*/
/* Sanity check. */
/*-------------------------------------------------------------*/
PfAssert(Flash->high_wear >= Flash->blocks[b].wear_count);
/*-------------------------------------------------------------*/
/* Compute the selector. */
/*-------------------------------------------------------------*/
f_b = (int)(16 * (Flash->block_sects -
Flash->blocks[b].used_sects) +
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -