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

📄 nand_util.c

📁 ATMEL单片机可用的文件系统源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
    /*-----------------------------------------------------------------*/
    if (status == -1)
    {
      bad_block = sect_num / Flash->block_sects;

      /*---------------------------------------------------------------*/
      /* If part of current control info in this block, invalidate it. */
      /*---------------------------------------------------------------*/
      if (Flash->frst_ctrl_sect / Flash->block_sects == bad_block)
      {
        frst_ctrl_sect = Flash->frst_ctrl_sect;

        /*-------------------------------------------------------------*/
        /* Invalidate all the control sectors.                         */
        /*-------------------------------------------------------------*/
        if (frst_ctrl_sect != (ui32)-1)
        {
          /*-----------------------------------------------------------*/
          /* Invalidate a block at a time.                             */
          /*-----------------------------------------------------------*/
          for (j = frst_ctrl_sect; j != FLAST_SECT;)
          {
            /*---------------------------------------------------------*/
            /* Invalidate control block.                               */
            /*---------------------------------------------------------*/
            do
            {
              Flash->sect_tbl[i = j].prev = FDRTY_SECT;
              j = Flash->sect_tbl[j].next;
            } while (j != FLAST_SECT && (i + 1) % Flash->block_sects);

            /*---------------------------------------------------------*/
            /* Unmark control block flag.                              */
            /*---------------------------------------------------------*/
            Flash->blocks[i / Flash->block_sects].ctrl_block = FALSE;
          }
        }

        /*-------------------------------------------------------------*/
        /* If free control area in bad block, invalidate it.           */
        /*-------------------------------------------------------------*/
        if (Flash->free_ctrl_sect / Flash->block_sects == bad_block)
          Flash->free_ctrl_sect = (ui32)-1;
      }

      /*---------------------------------------------------------------*/
      /* Mark block as bad.                                            */
      /*---------------------------------------------------------------*/
      return mark_block_bad(sect_num);
    }
  }
  return 0;
}

/***********************************************************************/
/* FsNandWriteSect: Write a given sector to flash by calling driver    */
/*              write routine                                          */
/*                                                                     */
/*      Inputs: buffer = pointer to buffer containing sector data      */
/*              sect_num = the sector number                           */
/*              sect_type = sector type (data or control)              */
/*                                                                     */
/*     Returns: 0 on success, -1 on failure, RWR_CTRL_OK if control    */
/*              was rewritten succesfully                              */
/*                                                                     */
/***********************************************************************/
int FsNandWriteSect(void *buffer, ui32 sect_num, ui32 sect_type)
{
  int  i, status;
  ui32 addr = Flash->mem_base + sect_num * Flash->sect_sz;
  ui32 wear = Flash->blocks[sect_num / Flash->block_sects].wear_count;
  ui32 next_sect_num, bad_block = sect_num / Flash->block_sects;
  void *orig_buffer = buffer;
  FlashGlob *vol;

  /*-------------------------------------------------------------------*/
  /* Write sector to flash, a page at a time.                          */
  /*-------------------------------------------------------------------*/
  for (i = 0; i < Flash->pages_per_sect; ++i, addr += Flash->page_size)
  {
    /*-----------------------------------------------------------------*/
    /* Release exclusive access to the flash file system.              */
    /*-----------------------------------------------------------------*/
    vol = Flash;
    semPost(FlashSem);

    /*-----------------------------------------------------------------*/
    /* Write page.                                                     */
    /*-----------------------------------------------------------------*/
    status = vol->driver.nand.write_page(buffer, addr, (ui32)sect_type,
                                         wear, vol->vol);

    /*-----------------------------------------------------------------*/
    /* Acquire exclusive access to the flash file system.              */
    /*-----------------------------------------------------------------*/
    semPend(FlashSem, WAIT_FOREVER);
    Flash = vol;

    /*-----------------------------------------------------------------*/
    /* If write error, either program disturb or bad block.            */
    /*-----------------------------------------------------------------*/
    if (status)
    {
      /*---------------------------------------------------------------*/
      /* Data sector.                                                  */
      /*---------------------------------------------------------------*/
      if (sect_type == DATA_SECT)
      {
        /*-------------------------------------------------------------*/
        /* If bad, block, mark it.                                     */
        /*-------------------------------------------------------------*/
        if (status == -1 && mark_block_bad(bad_block))
          return -1;

        /*-------------------------------------------------------------*/
        /* Relocate bad sector.                                        */
        /*-------------------------------------------------------------*/
        if (FlashRelocSect(sect_num, Flash->free_sect, orig_buffer))
          return -1;

        /*-------------------------------------------------------------*/
        /* If bad block, invalidate sector that was just relocated.    */
        /*-------------------------------------------------------------*/
        if (status == -1)
          Flash->sect_tbl[sect_num].prev = FNVLD_SECT;

        return 0;
      }

      /*---------------------------------------------------------------*/
      /* Control sector.                                               */
      /*---------------------------------------------------------------*/
      else
      {
        /*-------------------------------------------------------------*/
        /* All control sectors up to and including current one become  */
        /* dirty.                                                      */
        /*-------------------------------------------------------------*/
        next_sect_num = invalidate_ctrl_sects_upto(sect_num);

        /*-------------------------------------------------------------*/
        /* If bad block, control sectors in current block become dirty.*/
        /*-------------------------------------------------------------*/
        if (status == -1)
        {
          /*-----------------------------------------------------------*/
          /* Mark all sectors in current block as dirty.               */
          /*-----------------------------------------------------------*/
          sect_num = bad_block * Flash->block_sects;
          for (i = 0; i < Flash->block_sects; ++i, ++sect_num)
            Flash->sect_tbl[sect_num].prev = FDRTY_SECT;

          /*-----------------------------------------------------------*/
          /* Mark block bad.                                           */
          /*-----------------------------------------------------------*/
          if (mark_block_bad(bad_block))
            return -1;

          /*-----------------------------------------------------------*/
          /* Also, invalidate first free control sector.               */
          /*-----------------------------------------------------------*/
          Flash->free_ctrl_sect = (ui32)-1;
        }

        /*-------------------------------------------------------------*/
        /* Else, invalidate all sectors in current block and the free  */
        /* control sector.                                             */
        /*-------------------------------------------------------------*/
        else
        {
            ++sect_num;
            Flash->free_ctrl_sect = (ui32)-1;
            for (; sect_num % Flash->block_sects; ++sect_num)
              Flash->sect_tbl[sect_num].prev = FDRTY_SECT;
        }

        /*-------------------------------------------------------------*/
        /* All control blocks past current one become free.            */
        /*-------------------------------------------------------------*/
        free_ctrl_blocks_from(next_sect_num);

        /*-------------------------------------------------------------*/
        /* No more valid control information left.                     */
        /*-------------------------------------------------------------*/
        Flash->frst_ctrl_sect = Flash->last_ctrl_sect = (ui32)-1;

        /*-------------------------------------------------------------*/
        /* Rewrite the control information.                            */
        /*-------------------------------------------------------------*/
        if (FlashWrCtrl(SKIP_ADJUST_ERASE))
          return -1;
        else
          return RWR_CTRL_OK;
      }
    }
    buffer = (ui8 *)buffer + Flash->page_size;
  }
  return 0;
}

/***********************************************************************/
/* FsNandWriteCtrl: Write a chunk of control memory to NAND            */
/*                                                                     */
/*      Inputs: head = pointer to the beginning of chunk in RAM        */
/*              length = number of bytes the chunk has                 */
/*                                                                     */
/*     Returns: 0 on success, -1 on failure, RWR_CTRL_OK in case the   */
/*              whole ctrl was rewritten because of bad block          */
/*                                                                     */
/***********************************************************************/
int FsNandWriteCtrl(const void *head, uint length)
{
  int i = 0, j, rc;
  ui32 next_block;
  static ui32 crc;
  static int offset;
  static ui32 tot_sects;

  /*-------------------------------------------------------------------*/
  /* Check if this call is just to initialize the static variables.    */
  /*-------------------------------------------------------------------*/
  if (head == Flash)
  {
    tot_sects = Flash->ctrl_sects;
    crc = CRC32_START;
    offset = 0;
    return 0;
  }

  /*-------------------------------------------------------------------*/
  /* Copy data from head to buffer, and as soon as 1 sector in the     */
  /* buffer gets filled, write it to flash.                            */
  /*-------------------------------------------------------------------*/
  while (i < length)
  {
    /*-----------------------------------------------------------------*/
    /* If a full sector worth of ctrl data has been written to buffer, */
    /* send it to flash.                                               */
    /*-----------------------------------------------------------------*/
    PfAssert(offset <= Flash->sect_sz);
    if (offset == Flash->sect_sz)
    {
      /*---------------------------------------------------------------*/
      /* Write the TmpBuf.data to flash.                               */
      /*---------------------------------------------------------------*/
      rc = FlashWriteCtrlSect();
      if (rc)
        return rc;

      /*---------------------------------------------------------------*/
      /* Update the state variables.                                   */
      /*---------------------------------------------------------------*/
      Flash->ctrl_sect = Flash->sect_tbl[Flash->ctrl_sect].next;
      --tot_sects;
      offset = 0;
    }

    /*-----------------------------------------------------------------*/
    /* If this is the last sector in a block and we are down to the    */
    /* last two bytes, write the next ctrl block.                      */
    /*-----------------------------------------------------------------*/
    if (offset == Flash->sect_sz - 2 &&
        (Flash->ctrl_sect + 1) % Flash->block_sects == 0)
    {
      next_block = Flash->sect_tbl[Flash->ctrl_sect].next /
                   Flash->block_sects;
      Flash->tmp_sect[offset++] = (ui8)((next_block & 0xFF00) >> 8);
      Flash->tmp_sect[offset++] = (ui8)(next_block & 0xFF);
      crc = CRC_UPDATE(crc, Flash->tmp_sect[offset - 2]);
      crc = CRC_UPDATE(crc, Flash->tmp_sect[offset - 1]);
    }
    else
    {
      /*---------------------------------------------------------------*/
      /* Copy one byte at a time from head into buffer.                */
      /*---------------------------------------------------------------*/
      Flash->tmp_sect[offset++] = ((ui8 *)head)[i];

      /*---------------------------------------------------------------*/
      /* Update the CRC with the new ctrl info byte.                   */
      /*---------------------------------------------------------------*/
      crc = CRC_UPDATE(crc, ((ui8 *)head)[i++]);
    }
  }

  /*-------------------------------------------------------------------*/
  /* If it's last write, add the CRC at the end of the ctrl info.      */
  /*-------------------------------------------------------------------*/
  if (length == 0)
  {
    /*-----------------------------------------------------------------*/
    /* Fill out the rest of ctrl sectors with 0xFF, except for last    */
    /* ctrl sector.                                                    */
    /*-----------------------------------------------------------------*/
    PfAssert(tot_sects > 0);
    for (; tot_sects > 1; --tot_sects)
    {
      for (j = offset; j < Flash->sect_sz - 2; ++j)
      {
        Flash->tmp_sect[j] = 0xFF;
        crc = CRC_UPDATE(crc, 0xFF);
      }

      /*---------------------------------------------------------------*/
      /* If on block boundary, save next block in last two bytes, else */
      /* use 0xFF.                                                     */
      /*---------------------------------------------------------------*/
      if ((Flash->ctrl_sect + 1) % Flash->block_sects == 0)
      {
        next_block = Flash->sect_tbl[Flash->ctrl_sect].next /
                     Flash->block_sects;
        Flash->tmp_sect[j++] = (ui8)((next_block & 0xFF00) >> 8);
        Flash->tmp_sect[j++] = (ui8)(next_block & 0xFF);

⌨️ 快捷键说明

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