fdi_spll.c
来自「FDI Intel开发的FLASH文件系统,功能很强大」· C语言 代码 · 共 1,964 行 · 第 1/5 页
C
1,964 行
### DESCRIPTION:
### Verifies compatibility with flash support by the user application.
### If the function determines that the component is incompatible, it
### returns an error.
###
### PARAMETERS:
### IN: address (DWORD) - The absolute address of the window in flash
### to scan.
### size (DWORD) - The size of the window in flash to scan.
### OUT:
###
### RETURNS:
### If the flash type is supported, the function returns HW_ERR_NONE. If
### the flash type is not supported or if there was an error clearing
### the status register, the function returns HW_ERR_COMPAT.
###
*/
HW_ERROR FlashDevCompatCheck(DWORD address, DWORD size)
{
volatile FLASH_DATA_PTR flash_ptr = (FLASH_DATA_PTR) ALIGN_ADDRESS(address);
FLASH_DATA status_reg;
HW_ERROR compat;
DWORD key0, key1;
/*
* Since a status command will be issued to the flash, find a location
* where the ready bit(s) is (are) not set.
*/
for (*flash_ptr = FLASH_COMMAND_READ; (DWORD) flash_ptr < (address + size);
flash_ptr++)
{
if (*flash_ptr != FLASH_STATUS_READY)
{
break;
}
}
/*
* If our search took us to the end of the window, exit
* with success. This window will be checked in a future init,
* when the flash has been formatted.
*/
if ((DWORD) flash_ptr >= (address + size))
{
compat = HW_ERR_NONE;
}
/*
* Clear the status and obtain it. If not ready, a
* major problem happened. Exit with a failure.
*/
else
{
DISABLE_INTERRUPTS(key0, key1);
PtrLowLvlClearStat(flash_ptr);
status_reg = PtrLowLvlReadStat(flash_ptr);
ENABLE_INTERRUPTS(key0, key1);
if (status_reg == FLASH_STATUS_READY)
{
compat = HW_ERR_NONE;
}
else
{
compat = HW_ERR_COMPAT;
}
}
return compat;
}
#if (BUFFER_SIZE > 0)
/*#############################################################################
### FlashDevWrite
###
### DESCRIPTION:
### This function writes 'size' bytes of data from a specified buffer to
### the destination addresss within the device(s). The Background Manager,
### Reclaim Task, and Code Manager determine the relative address by
### using the FDI mapping structures. This function translates the
### relative address into a physical system addres and verifies the
### address range. After aligning the source and destination buffers,
### the function takes the flash write semaphore and calls the low-level
### function LowLvlWrite() via its function pointer. Upon completion
### of the write, the function releases the flash write semaphore and
### returns the appropriate value.
###
### PARAMETERS:
### IN: buffer_ptr (BYTE_PTR) - A pointer to the start address of the
### data to be written.
### address (DWORD) - The destination address within the flash
### device(s).
### size (DWORD) - The amount of data, in bytes, to write.
###
### RETURNS:
### If any portion of the data being written does not fall within the
### data managed area (or the code managed area if DAV is enabled), the
### function returns HW_ERR_PARAM. If an error occurred while writing
### the data to flash, HW_ERR_WRITE is returned. Finally, if all the
### parameters are within the appropriate ranges and the data was
### written successfully, the function returns HW_ERR_NONE.
###
*/
HW_ERROR FlashDevWrite(BYTE_PTR buffer_ptr, DWORD address, DWORD size)
{
BYTE_PTR dst_byte_ptr, src_byte_ptr;
FLASH_DATA_PTR dst_data_ptr;
FLASH_DATA temp_buffer[BUFFER_SIZE / sizeof(FLASH_DATA)];
DWORD dst_offset;
DWORD byte_size, data_size;
DWORD key0, key1;
HW_ERROR status = HW_ERR_NONE;
/* power loss simulation for testing purposes */
mDEBUG_PLR_SIMULATION(size);
/* address validation */
address += LOWLVL_FLASH_START_ADDRESS;
VALIDATE_ADDRESS(address, size);
/* if size is 0, return */
if (size == 0)
{
return HW_ERR_NONE;
}
/* align addresses & determine buffer offset */
dst_data_ptr = (FLASH_DATA_PTR) ALIGN_ADDRESS(address);
dst_offset = UNALIGNED_BYTES(address);
dst_byte_ptr = (BYTE_PTR) temp_buffer + dst_offset;
data_size = BUFFER_SIZE - dst_offset;
src_byte_ptr = buffer_ptr;
/* take flash write mutex and perform hardware precondition */
SEM_MTX_WAIT(SEM_FlashWrite);
HARDWARE_PRECONDITION;
while ((size > 0) && (status == HW_ERR_NONE))
{
/**/
byte_size = GET_MIN(data_size, size);
data_size = (byte_size + dst_offset + sizeof(FLASH_DATA) - 1) /
sizeof(FLASH_DATA);
/**/
if (byte_size != BUFFER_SIZE)
{
/*temp_buffer[0] = ALL_F;*/
/*temp_buffer[data_size] = ALL_F;*/
MemorySet((BYTE_PTR) temp_buffer, 0xff, BUFFER_SIZE);
}
MemoryMove(dst_byte_ptr, src_byte_ptr, (WORD) byte_size);
/* data_size = (byte_size + dst_offset + sizeof(FLASH_DATA) - 1) /
sizeof(FLASH_DATA); */
/* write buffer */
do
{
#if (TIME_MONITOR_ENABLED == TRUE)
TIME_MONITOR(key0, key1);
#else
DISABLE_INTERRUPTS(key0, key1);
#endif
status = PtrLowLvlWrite(dst_data_ptr, temp_buffer, data_size);
ENABLE_INTERRUPTS(key0, key1);
} while ((status == HW_ERR_SUSPEND) || (status == HW_ERR_ABORT));
/* update pointers/variables */
dst_data_ptr += data_size;
dst_byte_ptr = (BYTE_PTR) temp_buffer;
src_byte_ptr += byte_size;
size -= byte_size;
data_size = BUFFER_SIZE;
dst_offset = 0;
}
mDEBUG_PLR_SIMULATION_MLC_STATUS();
/* perform hardware postcondition, post flash write mutex, and return */
HARDWARE_POSTCONDITION;
SEM_MTX_POST(SEM_FlashWrite);
return status;
}
#else /* BUFFER_SIZE == 0 */
/*#############################################################################
### FlashDevWrite
###
### DESCRIPTION:
### This function writes 'size' bytes of data from a specified buffer to
### the destination addresss within the device(s). The Background Manager,
### Reclaim Task, and Code Manager determine the relative address by
### using the FDI mapping structures. This function translates the
### relative address into a physical system addres and verifies the
### address range. After aligning the source and destination buffers,
### the function takes the flash write semaphore and calls the low-level
### function LowLvlWrite() via its function pointer. Upon completion
### of the write, the function releases the flash write semaphore and
### returns the appropriate value.
###
### PARAMETERS:
### IN: buffer_ptr (BYTE_PTR) - A pointer to the start address of the
### data to be written.
### address (DWORD) - The destination address within the flash
### device(s).
### size (DWORD) - The amount of data, in bytes, to write.
###
### RETURNS:
### If any portion of the data being written does not fall within the
### data managed area (or the code managed area if DAV is enabled), the
### function returns HW_ERR_PARAM. If an error occurred while writing
### the data to flash, HW_ERR_WRITE is returned. Finally, if all the
### parameters are within the appropriate ranges and the data was
### written successfully, the function returns HW_ERR_NONE.
###
*/
HW_ERROR FlashDevWrite(BYTE_PTR buffer_ptr, DWORD address, DWORD size)
{
FLASH_DATA_PTR src_data_ptr, dst_data_ptr;
BYTE_PTR src_byte_ptr, dst_byte_ptr;
DWORD src_offset, dst_offset;
DWORD init_unaligned_bytes;
DWORD key0, key1;
FLASH_DATA temp_data;
HW_ERROR status = HW_ERR_NONE;
/* power loss simulation for testing purposes */
mDEBUG_PLR_SIMULATION(size);
/* address validation */
address += LOWLVL_FLASH_START_ADDRESS;
VALIDATE_ADDRESS(address, size);
/* return if nothing to write */
if (size == 0)
{
return HW_ERR_NONE;
}
/* align addresses & determine address offset */
dst_data_ptr = (FLASH_DATA_PTR) ALIGN_ADDRESS(address);
src_offset = UNALIGNED_BYTES((DWORD) buffer_ptr);
dst_offset = UNALIGNED_BYTES(address);
dst_byte_ptr = (BYTE_PTR) &temp_data + dst_offset;
/* calculate the number of initial unaligned bytes */
if (src_offset == dst_offset)
{
if (dst_offset == 0)
{
init_unaligned_bytes = 0;
}
else
{
init_unaligned_bytes = GET_MIN(size, sizeof(FLASH_DATA) - dst_offset);
}
}
else
{
init_unaligned_bytes = size;
}
size -= init_unaligned_bytes;
/* take flash write mutex and perform hardware precondition */
SEM_MTX_WAIT(SEM_FlashWrite);
HARDWARE_PRECONDITION;
/*
* write initial unaligned data, or all data if source and destination
* addresses do not have the same offset
*/
src_byte_ptr = (BYTE_PTR) buffer_ptr;
while ((init_unaligned_bytes > 0) && (status == HW_ERR_NONE))
{
/* fill temp buffer with data */
temp_data = ALL_F;
while ((dst_offset < sizeof(FLASH_DATA)) && (init_unaligned_bytes > 0))
{
*dst_byte_ptr = *src_byte_ptr;
dst_byte_ptr++;
src_byte_ptr++;
init_unaligned_bytes--;
dst_offset++;
}
/* write to flash */
do
{
#if (TIME_MONITOR_ENABLED == TRUE)
TIME_MONITOR(key0, key1);
#else
DISABLE_INTERRUPTS(key0, key1);
#endif
status = PtrLowLvlWrite(dst_data_ptr, &temp_data);
ENABLE_INTERRUPTS(key0, key1);
} while (status == HW_ERR_SUSPEND);
/* update pointers */
dst_data_ptr++;
dst_offset = 0;
dst_byte_ptr = (BYTE_PTR) &temp_data;
}
/* write aligned data */
src_data_ptr = (FLASH_DATA_PTR) src_byte_ptr;
while ((size >= sizeof(FLASH_DATA)) && (status == HW_ERR_NONE))
{
/* write to flash */
do
{
#if (TIME_MONITOR_ENABLED == TRUE)
TIME_MONITOR(key0, key1);
#else
DISABLE_INTERRUPTS(key0, key1);
#endif
status = PtrLowLvlWrite(dst_data_ptr, src_data_ptr);
ENABLE_INTERRUPTS(key0, key1);
} while (status == HW_ERR_SUSPEND);
/* update pointers */
dst_data_ptr++;
src_data_ptr++;
size -= sizeof(FLASH_DATA);
}
/* write remaining unaligned bytes */
if ((size > 0) && (status == HW_ERR_NONE))
{
src_byte_ptr = (BYTE_PTR) src_data_ptr;
dst_byte_ptr = (BYTE_PTR) &temp_data;
temp_data = ALL_F;
/* fill temp buffer with data */
while (size > 0)
{
*dst_byte_ptr = *src_byte_ptr;
dst_byte_ptr++;
src_byte_ptr++;
size--;
}
/* write to flash */
do
{
#if (TIME_MONITOR_ENABLED == TRUE)
TIME_MONITOR(key0, key1);
#else
DISABLE_INTERRUPTS(key0, key1);
#endif
status = PtrLowLvlWrite(dst_data_ptr, &temp_data);
ENABLE_INTERRUPTS(key0, key1);
} while (status == HW_ERR_SUSPEND);
}
mDEBUG_PLR_SIMULATION_MLC_STATUS();
/* perform hardware postcondition, post flash write mutex, and return */
HARDWARE_POSTCONDITION;
SEM_MTX_POST(SEM_FlashWrite);
return status;
}
#endif /* BUFFER_SIZE */
/*#############################################################################
### FlashDevEraseBlock
###
### DESCRIPTION:
### This function erases a single flash erase-block beginning at the
### address specified. The Reclaim Task and Code Manager determine the
### relative address by using the FDI mapping structures. This function
### performs several actions before calling LowLvlEraseBlock() to perform
### the actual erase. First, the function translates the relative address
### into a physical system address and verifies the address range. After
### taking the flash erase semaphore, it calls the low-level function
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?