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 + -
显示快捷键?