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

📄 flash.c

📁 开放源码实时操作系统源码.
💻 C
📖 第 1 页 / 共 5 页
字号:
//==========================================================================
//
//      flash.c
//
//      RedBoot - FLASH memory support
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004 Red Hat, Inc.
// Copyright (C) 2003, 2004 Gary Thomas
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s):    gthomas
// Contributors: gthomas, tkoeller
// Date:         2000-07-28
// Purpose:      
// Description:  
//              
// This code is part of RedBoot (tm).
//
//####DESCRIPTIONEND####
//
//==========================================================================

#include <redboot.h>
#include <cyg/io/flash.h>
#include <fis.h>
#include <sib.h>
#include <cyg/infra/cyg_ass.h>         // assertion macros

#ifdef CYGSEM_REDBOOT_FLASH_COMBINED_FIS_AND_CONFIG
// Note horrid intertwining of functions, to save precious FLASH
extern void conf_endian_fixup(void *p);
#endif

// Round a quantity up
#define _rup(n,s) ((((n)+(s-1))/s)*s)

#ifdef CYGOPT_REDBOOT_FIS
// Image management functions
local_cmd_entry("init",
                "Initialize FLASH Image System [FIS]",
                "[-f]",
                fis_init,
                FIS_cmds
    );
#ifdef CYGSEM_REDBOOT_FIS_CRC_CHECK
# define FIS_LIST_OPTS "[-c] [-d]"
#else
# define FIS_LIST_OPTS "[-d]"
#endif
local_cmd_entry("list",
                "Display contents of FLASH Image System [FIS]",
                FIS_LIST_OPTS,
                fis_list,
                FIS_cmds
    );
local_cmd_entry("free",
                "Display free [available] locations within FLASH Image System [FIS]",
                "",
                fis_free,
                FIS_cmds
    );
local_cmd_entry("delete",
                "Delete an image from FLASH Image System [FIS]",
                "name",
                fis_delete,
                FIS_cmds
    );

static char fis_load_usage[] = 
#ifdef CYGPRI_REDBOOT_ZLIB_FLASH
                      "[-d] "
#endif
                      "[-b <memory_load_address>] [-c] name";

local_cmd_entry("load",
                "Load image from FLASH Image System [FIS] into RAM",
                fis_load_usage,
                fis_load,
                FIS_cmds
    );
local_cmd_entry("create",
                "Create an image",
                "[-b <mem_base>] [-l <image_length>] [-s <data_length>]\n"
                "      [-f <flash_addr>] [-e <entry_point>] [-r <ram_addr>] [-n] <name>",
                fis_create,
                FIS_cmds
    );
#endif

// Raw flash access functions
local_cmd_entry("erase",
                "Erase FLASH contents",
                "-f <flash_addr> -l <length>",
                fis_erase,
                FIS_cmds
    );
#ifdef CYGHWR_IO_FLASH_BLOCK_LOCKING
local_cmd_entry("lock",
                "LOCK FLASH contents",
                "[-f <flash_addr> -l <length>] [name]",
                fis_lock,
                FIS_cmds
    );
local_cmd_entry("unlock",
                "UNLOCK FLASH contents",
                "[-f <flash_addr> -l <length>] [name]",
                fis_unlock,
                FIS_cmds
    );
#endif
local_cmd_entry("write",
                "Write raw data directly to FLASH",
                "-f <flash_addr> -b <mem_base> -l <image_length>",
                fis_write,
                FIS_cmds
    );

// Define table boundaries
CYG_HAL_TABLE_BEGIN( __FIS_cmds_TAB__, FIS_cmds);
CYG_HAL_TABLE_END( __FIS_cmds_TAB_END__, FIS_cmds);

extern struct cmd __FIS_cmds_TAB__[], __FIS_cmds_TAB_END__;

// CLI function
static cmd_fun do_fis;
RedBoot_nested_cmd("fis", 
            "Manage FLASH images", 
            "{cmds}",
            do_fis,
            __FIS_cmds_TAB__, &__FIS_cmds_TAB_END__
    );

// Local data used by these routines
void *flash_start, *flash_end;
int flash_block_size, flash_num_blocks;
#ifdef CYGOPT_REDBOOT_FIS
void *fis_work_block;
void *fis_addr;
#ifdef CYGOPT_REDBOOT_REDUNDANT_FIS
void *redundant_fis_addr;
#endif
int fisdir_size;  // Size of FIS directory.
#endif
#ifdef CYGSEM_REDBOOT_FLASH_CONFIG
extern void *cfg_base;   // Location in Flash of config data
extern int   cfg_size;   // Length of config data - rounded to Flash block size
extern struct _config *config;
#endif

static void
fis_usage(char *why)
{
    diag_printf("*** invalid 'fis' command: %s\n", why);
    cmd_usage(__FIS_cmds_TAB__, &__FIS_cmds_TAB_END__, "fis ");
}

static void        
_show_invalid_flash_address(CYG_ADDRESS flash_addr, int stat)
{
    diag_printf("Invalid FLASH address %p: %s\n", (void *)flash_addr, flash_errmsg(stat));
    diag_printf("   valid range is %p-%p\n", (void *)flash_start, (void *)flash_end);
}

#ifdef CYGOPT_REDBOOT_FIS

// fis_endian_fixup() is used to swap endianess if required.
//
static inline void fis_endian_fixup(void *addr)
{
#ifdef REDBOOT_FLASH_REVERSE_BYTEORDER
    struct fis_image_desc *p = addr;
    int cnt = fisdir_size / sizeof(struct fis_image_desc);

    while (cnt-- > 0) {
        p->flash_base = CYG_SWAP32(p->flash_base);
        p->mem_base = CYG_SWAP32(p->mem_base);
        p->size = CYG_SWAP32(p->size);
        p->entry_point = CYG_SWAP32(p->entry_point);
        p->data_length = CYG_SWAP32(p->data_length);
        p->desc_cksum = CYG_SWAP32(p->desc_cksum);
        p->file_cksum = CYG_SWAP32(p->file_cksum);
        p++;
    }
#endif
}

void
fis_read_directory(void)
{
    void *err_addr;

    FLASH_READ(fis_addr, fis_work_block, fisdir_size, (void **)&err_addr);
    fis_endian_fixup(fis_work_block);
}

struct fis_image_desc *
fis_lookup(char *name, int *num)
{
    int i;
    struct fis_image_desc *img;

    fis_read_directory();

    img = (struct fis_image_desc *)fis_work_block;
    for (i = 0;  i < fisdir_size/sizeof(*img);  i++, img++) {
        if ((img->u.name[0] != (unsigned char)0xFF) &&
            (strcasecmp(name, img->u.name) == 0)) {
            if (num) *num = i;
            return img;
        }
    }
    return (struct fis_image_desc *)0;
}

int fis_start_update_directory(int autolock)
{
#ifdef CYGOPT_REDBOOT_REDUNDANT_FIS
#ifdef CYGHWR_IO_FLASH_BLOCK_LOCKING
#ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL
   // Ensure [quietly] that the directory is unlocked before trying to update and locked again afterwards
   int do_autolock=1;
#else
   int do_autolock=autolock;
#endif
#endif

   struct fis_image_desc* img=NULL;
   void* err_addr=NULL;
   void* tmp_fis_addr=NULL;

   /*exchange old and new valid fis tables*/
   tmp_fis_addr=fis_addr;
   fis_addr=redundant_fis_addr;
   redundant_fis_addr=tmp_fis_addr;

   //adjust the contents of the new fis table
   img=(struct fis_image_desc*)fis_work_block;

   memcpy(img->u.valid_info.magic_name, CYG_REDBOOT_RFIS_VALID_MAGIC, CYG_REDBOOT_RFIS_VALID_MAGIC_LENGTH);
   img->u.valid_info.valid_flag[0]=CYG_REDBOOT_RFIS_IN_PROGRESS;
   img->u.valid_info.valid_flag[1]=CYG_REDBOOT_RFIS_IN_PROGRESS;
   img->u.valid_info.version_count=img->u.valid_info.version_count+1;

   //ready to go....
#ifdef CYGHWR_IO_FLASH_BLOCK_LOCKING
   if (do_autolock)
      flash_unlock((void *)fis_addr, fisdir_size, (void **)&err_addr);
#endif

   flash_erase(fis_addr, fisdir_size, (void **)&err_addr);
   //now magic is 0xffffffff
   fis_endian_fixup(fis_work_block);
   flash_program(fis_addr, fis_work_block, flash_block_size, (void **)&err_addr);
   fis_endian_fixup(fis_work_block);
   //now magic is 0xff1234ff, valid is IN_PROGRESS, version_count is the old one +1

#else
   /* nothing to do here without redundant fis */
#endif
   return 0;

}

int
fis_update_directory(int autolock, int error)
{
   void* err_addr=0;

#ifdef CYGHWR_IO_FLASH_BLOCK_LOCKING
#ifdef CYGSEM_REDBOOT_FLASH_LOCK_SPECIAL
   // Ensure [quietly] that the directory is unlocked before trying to update and locked again afterwards
   int do_autolock=1;
#else
   int do_autolock=autolock;
#endif
#endif

#ifdef CYGOPT_REDBOOT_REDUNDANT_FIS

   struct fis_image_desc* img=(struct fis_image_desc*)fis_work_block;

   // called from invalid state
   if (img->u.valid_info.valid_flag[0]!=CYG_REDBOOT_RFIS_IN_PROGRESS)
      return -1;

   //if it failed, reset is0Valid to the state before startUpdateDirectory()
   //g_data.fisTable hasn't been changed yet, so it doesn't have to be reset now
   //then reread the contents from flash
   //setting the valid flag of the failed table to "INVALID" might also be not too bad
   //but IN_PROGRESS is also good enough I think
   if (error!=0)
   {
      void* swap_fis_addr=fis_addr;
      fis_addr=redundant_fis_addr;
      redundant_fis_addr=swap_fis_addr;
   }
   else //success
   {
      void* tmp_fis_addr=(void *)((CYG_ADDRESS)fis_addr+CYG_REDBOOT_RFIS_VALID_MAGIC_LENGTH);

      img->u.valid_info.valid_flag[0]=CYG_REDBOOT_RFIS_VALID;
      img->u.valid_info.valid_flag[1]=CYG_REDBOOT_RFIS_VALID;

      flash_program(tmp_fis_addr, img->u.valid_info.valid_flag, sizeof(img->u.valid_info.valid_flag), (void **)&err_addr);
   }
#ifdef CYGHWR_IO_FLASH_BLOCK_LOCKING
   if (do_autolock)
      flash_lock((void *)fis_addr, fisdir_size, (void **)&err_addr);
#endif

⌨️ 快捷键说明

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