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

📄 nf_loader.c

📁 mp3播放器
💻 C
📖 第 1 页 / 共 2 页
字号:
//! @file nf_loader.c,v
//!
//! Copyright (c) 2004 Atmel.
//!
//! Please read file license.txt for copyright notice.
//!
//! @brief This file is the header file for the management of PHYSICAL access of the nand flash memory devices.
//!
//! @version 1.37 snd3-refd1-1_9_5 $Id: nf_loader.c,v 1.37 2007/03/30 12:15:29 sguyon Exp $
//!
//! @todo SG !!!WARNING!!!it must be no bad block in the first block (3 or 24)
//! @bug
#ifndef _nf_loader_c_
#define _nf_loader_c_


//_____  I N C L U D E S ___________________________________________________

#include "config.h"
#include "conf\conf_nf.h"
#include "conf\conf_access.h"
#include "conf\conf_update.h"
#include "lib_mcu\nfc\nfc_drv.h"
#include "lib_mem\nand_flash\nf_mngt.h"
#include "modules\audio\audio.h"             // Player module definition
#include "modules\update\update_file.h"      // for Zone_info structure definition
#include "modules\update\nf_update.h"
#if (FUNC_UPDATE == ENABLE) 
#  if (UPDATE_DO_FW_COPY == ENABLE)
#     include "lib_mcu\dfc\dfc_drv.h"
#  endif
#  if (UPDATE_DO_CODEC_COPY == ENABLE)
#     include "modules\control_access\ctrl_access.h"
#  endif
#endif
#include "nf_loader.h"


//_____ M A C R O S ________________________________________________________

// Data zone size of a NF 512Bytes/page
#define  NF512_DATA_SIZE         512   // in bytes

// Spare zone size of a NF 512Bytes/page.
#define  NF512_SPAREZONE_SIZE    16    // in bytes



//_____ R E F E R E N C E S ________________________________________________

#if (NF_GENERIC_DRIVER==TRUE)
extern _MEM_TYPE_FAST_ U8   g_shift_page_byte  ; // Defined in nf_mngt.c
#endif

#if (FUNC_UPDATE == ENABLE) 
#  if ((UPDATE_DO_FW_COPY == ENABLE) || (UPDATE_DO_CODEC_COPY == ENABLE))
      extern _MEM_TYPE_SLOW_ Zone_info g_zone_info;
#  endif
#endif

//_____ P R I V A T E   D E C L A R A T I O N S ____________________________

// Pattern table to identify zones
// The storage order of these patterns must have matched 
// with the enumeration Zones defined in "nf_loader.h"
U8 code zone_patterns[NB_ZONES][SZ_PATTERN_IN_BYTE] =
{
   { PATTERN_FIRMWARE }
,  { PATTERN_FIRMWARE }
,  { PATTERN_CODEC    }
,  { PATTERN_CODEC    }
,  { PATTERN_PICTURE  }
,  { PATTERN_FONT     }
};


U32  _MEM_TYPE_SLOW_ s_zone_page_addr[NB_ZONES];
static U8                _MEM_TYPE_SLOW_    s_curr_module_id = 0xFF;
static U8                _MEM_TYPE_SLOW_    s_curr_zone_id   = 0xFF;
static Module_struct     _MEM_TYPE_SLOW_    s_module;
Module_hdl_struct _MEM_TYPE_SLOW_ s_mod_hdl;


//static Zones nfloader_get_zone( U8 module_id ); //old version
#if (FUNC_UPDATE == ENABLE) 
# if (UPDATE_DO_FW_COPY == ENABLE)
   extern   Bool  g_b_update_copy_fw;
   Bool     nfloader_ckeck_fw_crc( void );
   Bool     nfloader_check_bank_crc ( void );
# endif
# if (UPDATE_DO_CODEC_COPY == ENABLE)
   extern   Bool g_b_update_copy_codec;
   Bool nfloader_check_codec_crc( void );
   Bool nfloader_is_codec_crc_is_good( U16 u16_crc );
# endif   
   // Global variable that holds the bank id of the currently active bank.
   // Global shared with the l51_bank.a51 assembly file.
   extern U8 data g_current_bank;   // Initialized to 0(i.e. bank0) in l51_bank.a51.      
   extern U8 Bank_load(void);
#endif


//_____ D E F I N I T I O N S ______________________________________________

//! Loads in RAM table "zone_page_addr" the page addresses of the zone stored in NF memory.
//!
//! The location of these zone are retrieved by scanning their unique patterns through the NF.
//! The zones always begins at page 0 in blocks in the device 0.
//!
void nfloader_init( void )
{
   _MEM_TYPE_FAST_ U32 u32_page_addr;
   _MEM_TYPE_FAST_ U16 u16_nb_blocks;
   _MEM_TYPE_FAST_ U8  code* ptr_pattern_data;
   _MEM_TYPE_FAST_ U8  i,j;


   for( i=0; i<NB_ZONES; i++)
   {
      Nfc_action(NFC_ACT_DEV_SELECT, 0);
      // Zone patterns always located at page 0 in blocks
      u32_page_addr = 0;                   
      ptr_pattern_data = &zone_patterns[i];

      // Scan the NF to detect a zone pattern
      for( u16_nb_blocks = G_N_BLOCKS; u16_nb_blocks != 0; u16_nb_blocks-- )
      {
         // Do not find twice the same zone for the two copy of FW zone
         if ( ((ZONE_FIRMWARE_COPY != i) || ( s_zone_page_addr[ZONE_FIRMWARE] != u32_page_addr) )
         &&   ((ZONE_CODEC_COPY != i) || ( s_zone_page_addr[ZONE_CODEC] != u32_page_addr)       ))
         {
            nfc_open_page_read( u32_page_addr , 0 );
            // "j" makes it possible here a required dummy read
            j = Nfc_rd_data_fetch_next(); 
            if (ZONE_FIRMWARE_COPY>=i)             
            {  // Firmware zone
               U8 u8_pattern3, u8_pattern4, u8_pattern5;
               j = 0;
               if((ptr_pattern_data[0] == Nfc_rd_data_fetch_next())
               && (ptr_pattern_data[1] == Nfc_rd_data_fetch_next()) )
               {
                  u8_pattern3 = Nfc_rd_data_fetch_next();
                  u8_pattern4 = Nfc_rd_data_fetch_next();
                  u8_pattern5 = Nfc_rd_data_fetch_next();
               
                  if((Nfc_rd_data_fetch_next() == ~u8_pattern3)
                  && (Nfc_rd_data_fetch_next() == ~u8_pattern4)
                  && (Nfc_rd_data_fetch_next() == ~u8_pattern5))
                  {
                     j = SZ_PATTERN_IN_BYTE;
                  }
               }
            }
            else
            {
               for( j=0; j<SZ_PATTERN_IN_BYTE; j++ )
               {
                  if( ptr_pattern_data[j] != Nfc_rd_data_fetch_next() )    { break; }
               }
            }         
            // If success in pattern location, shorten the loop
            if( SZ_PATTERN_IN_BYTE == j )    { break; }
         }
         // Else try the next block
         u32_page_addr += (U32)NF_NB_PAGE_PER_BLOCK;
      }

      if( SZ_PATTERN_IN_BYTE == j )
         { s_zone_page_addr[i] = u32_page_addr; }
      else
         { s_zone_page_addr[i] = UNFOUND_PATTERN; }
   }
#if (UPDATE_DO_FW_COPY == ENABLE)                              // FW update is implemented
   g_b_update_copy_fw = !nfloader_ckeck_fw_crc();      
#endif   //#if ((FUNC_UPDATE == ENABLE) && (UPDATE_DO_FW_COPY = ENABLE)) 

#if (UPDATE_DO_CODEC_COPY == ENABLE)                           // Codec update is implemented
   g_b_update_copy_codec = !nfloader_check_codec_crc();
#endif   //#if ((FUNC_UPDATE == ENABLE) && (UPDATE_DO_CODEC_COPY = ENABLE)) 
}

//! Fills the dedicated module structure "s_module" from the module header data stored in NF 
//!
//! @param  id_module : id of the module
//!         id_zone   : id of the zone in which this module is stored
//! @return status PASS or FAIL
//!
U8 nfloader_init_load_module( U8 id_module, Zone id_zone )
{
   _MEM_TYPE_FAST_   U8   i;
   _MEM_TYPE_FAST_   U8   device_number;
   _MEM_TYPE_FAST_   U16  nb_pages_remaining;
   _MEM_TYPE_FAST_   U16  contiguous_block_addr;
   _MEM_TYPE_FAST_   U16  u16_nb_pages;
   _MEM_TYPE_FAST_   U16  u16_block_addr;
   Bool b_first_block;

   union
   {
      U16 offset;
      U8  dummy;
   } _MEM_TYPE_SLOW_ v0;

   union
   {
      U8 header_size;
      U8 nb_blocks;
   } _MEM_TYPE_SLOW_ v1;


                          
   if( (id_module == s_curr_module_id) && (id_zone == s_curr_zone_id) )
      { return PASS; }
   else
   {
      // Loading of the zone header's data from the NF in the RAM structure "s_mod_hdl"   
      Mcu_set_sfr_page_nfc();
      Nfc_action(NFC_ACT_DEV_SELECT, 0);

      if ( s_zone_page_addr[id_zone] != UNFOUND_PATTERN)
      {
         s_mod_hdl.page_addr = s_zone_page_addr[id_zone];
      }
      else { return FAIL; }

      v0.offset = SZ_PATTERN_IN_BYTE;

      // Scan the zone to search the module with the help of its id
      do
      {
         nfc_open_page_read( s_mod_hdl.page_addr, v0.offset );
         i = Nfc_rd_data_fetch_next();                         // Dummy read required when manual reads

         v1.header_size = Nfc_rd_data_fetch_next();                  // Read of the module header size 
         if (0 == v1.header_size)   { return FAIL; }                 // Structure searched not found => RETURN FAIL
         else                       { v0.offset += v1.header_size +1; } // Point the next structure
                                                                     // NOTE: we add +1 to take into account the 
                                                                     // size information Byte itself.
      } while( id_module != Nfc_rd_data_fetch_next() );              // Module searched has been found?
   
      s_curr_module_id = id_module;
      s_curr_zone_id   = id_zone;
   
      #if (UPDATE_DO_FW_COPY == ENABLE)                              // FW update & FW copy is implemented  
         s_module.option = Nfc_rd_data_fetch_next();                 // Read option value 
      #else
         v0.dummy = Nfc_rd_data_fetch_next();                        // Option value discarded but dummy read required
      #endif
      MSB0(s_module.data_amount) = Nfc_rd_data_fetch_next();         // Size in 32 bits
      MSB1(s_module.data_amount) = Nfc_rd_data_fetch_next();   
      MSB2(s_module.data_amount) = Nfc_rd_data_fetch_next();
      MSB3(s_module.data_amount) = Nfc_rd_data_fetch_next();
      s_module.true_size = s_module.data_amount;
      // This amount of data is aligned on the sector size ...
      // DANGER If fw size gets close to the prog zone size and (prog zone size)%512 != 0
#if (defined ATMEL_WARNING)
#  warning: the code zone size of the chip(cf. MEMCSX) must be a multiple of 512.
#endif
      s_module.data_amount = Align_up(s_module.data_amount, 512); 
      // and gives the number of NF pages used to store the data
      nb_pages_remaining   = s_module.data_amount / (U16)NF_NB_BYTE_PER_PAGE; 
      if( 0 != s_module.data_amount % (U16)NF_NB_BYTE_PER_PAGE )
         { nb_pages_remaining++; }

      v0.dummy             = Nfc_rd_data_fetch_next();         // CRC (32 bits)
      v0.dummy             = Nfc_rd_data_fetch_next();         //   only the LSW is read
      MSB(s_module.CRC)    = Nfc_rd_data_fetch_next();
      LSB(s_module.CRC)    = Nfc_rd_data_fetch_next();
      v0.dummy             = Nfc_rd_data_fetch_next();         // Total number of blocks for firmware zone,
      v1.nb_blocks         = Nfc_rd_data_fetch_next();         // fragments for other zones
                                                               // ( only defined in 8 bits in our application )
      s_module.start_page  = Nfc_rd_data_fetch_next();         // Start page (8 bits)

      i=0;

      if(( ZONE_FIRMWARE == id_zone ) || ( ZONE_FIRMWARE_COPY == id_zone ))      
      {
         // To force the initialization of the fragment 0 in the loop below
         s_module.frag[0].device_number = 0xFF;
         b_first_block = TRUE;

         do
         {
            device_number       = Nfc_rd_data_fetch_next();   // Device number
            MSB(u16_block_addr) = Nfc_rd_data_fetch_next();   // Address of the block (16 bits)
            LSB(u16_block_addr) = Nfc_rd_data_fetch_next();
             
            if( 1 == v1.nb_blocks )
            {
               // The last block to integrate : its number of pages is equal to "nb_pages_remaining"
               u16_nb_pages = nb_pages_remaining;
               // Compute the number of fragments whose the module data is composed of
               s_module.nb_frag = i+1;
            }
            else
            {
               u16_nb_pages = NF_NB_PAGE_PER_BLOCK;
               if( b_first_block )  
               {
                  // The fisrt block to integrate : its number of pages is reduced of the start page offset
                  u16_nb_pages -= s_module.start_page;
               }
               // Compute the number of pages remaining for the next blocks to integrate
               nb_pages_remaining -= u16_nb_pages;
            } 
                                                     
            if( (u16_block_addr == contiguous_block_addr)
               && (device_number == s_module.frag[i].device_number) )
            {
               // The block read is contiguous to the current fragment.
               // So, this block is integrated to this fragment.
               s_module.frag[i].nb_pages += u16_nb_pages;
               contiguous_block_addr++;
            }
            else
            {
               // The block read is not contiguous to the current fragment.
               // So, fill the new fragment and set the new contiguous block address
               if( !b_first_block )    { i++; }
               b_first_block = FALSE;
               s_module.frag[i].nb_pages      = u16_nb_pages;
               s_module.frag[i].device_number = device_number;
               s_module.frag[i].block_addr    = u16_block_addr;
               contiguous_block_addr          = u16_block_addr;
            }
         }
         while( --v1.nb_blocks != 0 );
      }
      else
      {
         s_module.nb_frag = v1.nb_blocks; 
         while(1)
         {
            s_module.frag[i].device_number   = Nfc_rd_data_fetch_next();   // Device number
            MSB(s_module.frag[i].block_addr) = Nfc_rd_data_fetch_next();   // Address of the block (16 bits)
            LSB(s_module.frag[i].block_addr) = Nfc_rd_data_fetch_next();

            s_module.frag[i].nb_pages  = Nfc_rd_data_fetch_next();    // Number of blocks in the fragment (8 bits)
            s_module.frag[i].nb_pages *= NF_NB_PAGE_PER_BLOCK;
         
            // Compute the number of pages for the first fragment
            if( 0 == i ) 
               { s_module.frag[0].nb_pages -= (U16) s_module.start_page; }

            if( i == s_module.nb_frag-1 )
            {
               s_module.frag[i].nb_pages = nb_pages_remaining; 
               break;   // End of computing
            }

            nb_pages_remaining -= s_module.frag[i].nb_pages;
            i++;
         }
      }
   }
   return PASS;
}
  
//! Get the number of sectors used to store the module
//! The size of the module must not exceed 64K
//! (sector = 512B)
//!
//! @param   none
//! @return  U8  Number of sectors
//!
U8 nfloader_get_module_sector_number( void )
{
   return( s_module.data_amount /512 );
}

#if 0  
//! Get the number of bytes used to store the module
//! The size of the module must not exceed 64K
//!
//!
//! @param   none
//! @return  U16  Number of bytes
//!
U16 nfloader_get_module_size( void )
{
   return( s_module.true_size );
}
#endif

//! Get the remaining number of Bytes in a module after a given offset.
//! The size of the module must not exceed 64K
//!
//! @param   U16  u16_offset
//! @return  U16  Number of remaining bytes
//!
#if (CODE_BANKING == ENABLE) && (BANK_DECIPHER == ENABLE)
U16 nfloader_get_remaining_size( U16 u16_offset )
{
   return( (U16)s_module.data_amount - u16_offset);
}
#endif
//! Get the number of sectors used to store the module data from a given logical address
//! The size of the module must not exceed 64K
//! (sector = 512B)
//!
//! @param   U16 log_addr : logical address on the module data section
//! @return  U8  Number of sectors
//!
#if (CODE_BANKING == ENABLE)
U8 nfloader_get_sector_number( U16 log_addr )
{
   log_addr = Align_down(log_addr, 512);   
   log_addr = s_module.data_amount - log_addr;
   return( log_addr /512 );
}

⌨️ 快捷键说明

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