⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fswrite.c

📁 ATMEL单片机可用的文件系统源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/***********************************************************************/
/*                                                                     */
/*   Module:  fswrite.c                                                */
/*   Release: 2004.5                                                   */
/*   Version: 2004.5                                                   */
/*   Purpose: Implements the function for writing bytes to a file      */
/*                                                                     */
/*---------------------------------------------------------------------*/
/*                                                                     */
/*               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

/***********************************************************************/
/* Global Function Definitions                                         */
/***********************************************************************/

/***********************************************************************/
/*  FlashWrite: Write len number of bytes to file                      */
/*                                                                     */
/*      Inputs: stream = pointer to file control block                 */
/*              buf    = buffer that holds the bytes to be written     */
/*              len    = number of bytes to be written                 */
/*                                                                     */
/*     Returns: Number of bytes successfully written, -1 on error      */
/*                                                                     */
/***********************************************************************/
int FlashWrite(FILE *stream, const ui8 *buf, ui32 len)
{
  int  skip_read, adjust_size, status, check_recycles = FALSE;
  ui32 remaining = len, num_sectors, i, space_left, sect_num;
  ui8  *sector, dirty_flag;
  FFIL_T *link_ptr = &((FFSEnt *)stream->handle)->entry.file;

#if QUOTA_ENABLED
  int adjust_quota = TRUE;
#endif /* QUOTA_ENABLED */

  /*-------------------------------------------------------------------*/
  /* If the file mode does not permit writing, return error.           */
  /*-------------------------------------------------------------------*/
  if ((link_ptr->comm->open_mode & (F_APPEND | F_WRITE)) == 0)
  {
    set_errno(EACCES);
    return -1;
  }

  /*-------------------------------------------------------------------*/
  /* If file is in append mode, writes are always at the end.          */
  /*-------------------------------------------------------------------*/
  if (link_ptr->comm->open_mode & F_APPEND)
    FlashPoint2End(&stream->curr_ptr, link_ptr->comm);

  /*-------------------------------------------------------------------*/
  /* Else if a seek past end was performed, validate it.               */
  /*-------------------------------------------------------------------*/
  else if (stream->curr_ptr.sector == FDRTY_SECT &&
           FlashSeekPastEnd((i32)(stream->curr_ptr.sect_off *
                            Flash->sect_sz + stream->curr_ptr.offset -
                            link_ptr->comm->size), stream, ADJUST_FCBs))
    return -1;

  /*-------------------------------------------------------------------*/
  /* If curr_ptr is valid, fill out either len bytes or what's left of */
  /* the current sector, whichever is smaller.                         */
  /*-------------------------------------------------------------------*/
  if (stream->curr_ptr.sector != (ui16)-1)
  {
    /*-----------------------------------------------------------------*/
    /* NAND/MLC creatn files should skip cache reads.                  */
    /*-----------------------------------------------------------------*/
    if (Flash->type != FFS_NOR && (link_ptr->comm->mode & S_CREATN))
      skip_read = TRUE;
    else
      skip_read = FALSE;

    /*-----------------------------------------------------------------*/
    /* If stream does not have a cache entry associated with it, get   */
    /* the sector from the cache.                                      */
    /*-----------------------------------------------------------------*/
    if (stream->cached == NULL)
    {
      status = GetSector(&Flash->cache, (int)stream->curr_ptr.sector,
                         skip_read, link_ptr->comm, &stream->cached);
      if (status != GET_OK)
      {
        if (stream->cached)
          FreeSector(&stream->cached, &Flash->cache);
        return -1;
      }
    }
    PfAssert(stream->cached->file_ptr == link_ptr->comm);

    /*-----------------------------------------------------------------*/
    /* For creatn() files, NOR always uses dirty new sectors, NAND uses*/
    /* dirty new if first time writing to sector, else uses dirty old. */
    /*-----------------------------------------------------------------*/
    if (link_ptr->comm->mode & S_CREATN)
    {
      /*---------------------------------------------------------------*/
      /* For NAND/MLC check it's truly empty because can't write over. */
      /*---------------------------------------------------------------*/
      if (Flash->type != FFS_NOR &&
          ((CacheEntry*)stream->cached)->dirty == CLEAN &&
          !Flash->empty_sect(stream->curr_ptr.sector))
      {
        --Flash->free_sects;
        ((CacheEntry *)stream->cached)->dirty = DIRTY_OLD;
        Flash->cache.dirty_old = TRUE;
        stream->flags |= FCB_MOD;

        /*-------------------------------------------------------------*/
        /* Check for recycles when writing over old data.              */
        /*-------------------------------------------------------------*/
        check_recycles = TRUE;
      }

      /*---------------------------------------------------------------*/
      /* Else creatn() files should not use new sectors.               */
      /*---------------------------------------------------------------*/
      else
      {
        ((CacheEntry *)stream->cached)->dirty = DIRTY_NEW;
        Flash->cache.dirty_new = TRUE;
      }
    }

    /*-----------------------------------------------------------------*/
    /* For normal files, if FlashWrprWr() uses new sector, keep track  */
    /* of it and set sector to dirty old because we're writing over it.*/
    /* Set the stream modified flag if we're using a free sector.      */
    /*-----------------------------------------------------------------*/
    else if (((CacheEntry *)stream->cached)->dirty == CLEAN)
    {
      --Flash->free_sects;
      ((CacheEntry *)stream->cached)->dirty = DIRTY_OLD;
      Flash->cache.dirty_old = TRUE;
      stream->flags |= FCB_MOD;

      /*---------------------------------------------------------------*/
      /* Check for recycles when writing over old data.                */
      /*---------------------------------------------------------------*/
      check_recycles = TRUE;
    }

    /*-----------------------------------------------------------------*/
    /* Get the pointer to the sector data.                             */
    /*-----------------------------------------------------------------*/
    sector = ((CacheEntry *)stream->cached)->sector;

    /*-----------------------------------------------------------------*/
    /* Figure out how much space is left in current sector.            */
    /*-----------------------------------------------------------------*/
    space_left = (ui32)(Flash->sect_sz - stream->curr_ptr.offset);

    /*-----------------------------------------------------------------*/
    /* If what has to be written fits in this sector, write it and     */
    /* set remaining to 0 so that we're done.                          */
    /*-----------------------------------------------------------------*/
    if (space_left >= remaining)
    {
      /*---------------------------------------------------------------*/
      /* Use memcpy to copy from buf to sector remaining bytes.        */
      /*---------------------------------------------------------------*/
      memcpy(&sector[stream->curr_ptr.offset], buf, remaining);

      /*---------------------------------------------------------------*/
      /* Adjust current offset.                                        */
      /*---------------------------------------------------------------*/
      stream->curr_ptr.offset += (ui16)remaining;

      /*---------------------------------------------------------------*/
      /* Adjust remaining to 0 because we're done writing everything.  */
      /*---------------------------------------------------------------*/
      remaining = 0;

      /*---------------------------------------------------------------*/
      /* If one past last needs to be updated, update it.              */
      /*---------------------------------------------------------------*/
      if (link_ptr->comm->one_past_last.sector ==
                                               stream->curr_ptr.sector &&
          link_ptr->comm->one_past_last.offset < stream->curr_ptr.offset)
      {
        /*-------------------------------------------------------------*/
        /* Adjust file size.                                           */
        /*-------------------------------------------------------------*/
        link_ptr->comm->size += (stream->curr_ptr.offset -
                                 link_ptr->comm->one_past_last.offset);
        link_ptr->comm->one_past_last.offset =
                                           (ui16)stream->curr_ptr.offset;
      }

      /*---------------------------------------------------------------*/
      /* If recycles need to be checked, free sector.                  */
      /*---------------------------------------------------------------*/
      if (check_recycles && FreeSector(&stream->cached, &Flash->cache))
        return -1;
    }

    /*-----------------------------------------------------------------*/
    /* Else the current sector has not enough room for all the bytes   */
    /* that need to be written. Write enough to fill this sector,      */
    /* adjust remaining and later continue writing sectors.            */
    /*-----------------------------------------------------------------*/
    else
    {
      /*---------------------------------------------------------------*/
      /* Use memcpy to copy from buf to sector space_left bytes.       */
      /*---------------------------------------------------------------*/
      memcpy(&sector[stream->curr_ptr.offset], buf, space_left);

      /*---------------------------------------------------------------*/
      /* Adjust number of bytes left to be written and buf pointer.    */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -