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

📄 flashprg.c

📁 lpc3250 example program
💻 C
字号:
/***********************************************************************/
/*  This file is part of the ARM Toolchain package                     */
/*  Copyright KEIL ELEKTRONIK GmbH 2003 - 2006                         */
/***********************************************************************/
/*                                                                     */
/*  FlashDev.C:  Flash Programming Functions adapted                   */
/*               for NAND Flash programmed with Philips LPC318x        */
/***********************************************************************/

#include "..\FlashOS.H"                 // FlashOS Structures
#include "FlashHW.h"                    // Low level NAND flash declarations
#include "NAND_Error.h"                 // Error definitions

#define STACK_SIZE   64                 // Stack Size

// Enumerated type names definitions
enum PAGE_TYPE {SMALL_PAGE = 0, LARGE_PAGE};
enum BOOL_TYPE {     FALSE = 0,       TRUE};

// Constants values for Small and Large Page
const unsigned int BLOCK_SIZE[2]      = {16384, 131072};  // Block size
const unsigned int BLOCK_SIZE_SHIFT[2]= {   14,     17};  // Block size in bit shifts
const unsigned int PAGE_SIZE[2]       = {  528,   2112};  // Size of complete page
const unsigned int PAGE_USR_SIZE[2]   = {  512,   2048};  // Size of page user data

// Global variables used throughout this module
unsigned long base_adr;                 // Base Address
unsigned long nand_block_offset;        // Offset of valid block
unsigned char ICR;                      // Interface Configuration Data
unsigned char SZ_INFO = 0x1F ;          // Size info for bootloader (1-st level from ROM) (copy 31 pages)
unsigned char bus_width;                // Bus width
unsigned char adr_cycles;               // Address word count
unsigned char page_type;                // Page type (small or large)
unsigned int  block_size;               // Block size
unsigned int  block_size_shift;         // Block size in bit shifts
unsigned int  page_size;                // Size of Complete Page
unsigned int  page_usr_size;            // Size of User Page Data
unsigned char data_buf[2112];           // Data buffer

// Module's local functions prototypes
static int WriteBootInfo (void);
static int TryInit       (unsigned char bus_wdth, unsigned char adr_cyc, unsigned char page_typ, unsigned long clk);
static int FindBlock     (unsigned long adr, unsigned int restart);


/************************* Flash Algorithm Functions ***************************/

/*- Init (...) -----------------------------------------------------------------
 *
 *  Initialize Flash Programming Functions
 *    Parameter:      adr:  Device Base Address
 *                    clk:  Clock Frequency (Hz)
 *                    fnc:  Function Code (1 - Erase, 2 - Program, 3 - Verify)
 *    Return Value:   0 - OK,  1 - Failed
 */
           
int Init (unsigned long adr, unsigned long clk, unsigned long fnc) {
  int i;
  unsigned char byte, temp;
  static unsigned char first_run_f = TRUE;

  base_adr = adr;

  if (first_run_f == TRUE) {
    first_run_f = FALSE;

    // Autodetect address cycles and page type
    if (TryInit(16, 4, SMALL_PAGE, clk)) {
      if (TryInit(16, 4, LARGE_PAGE, clk)) {
        if (TryInit(16, 5, LARGE_PAGE, clk)) {
          if (TryInit( 8, 4, SMALL_PAGE, clk)) {
            if (TryInit( 8, 4, LARGE_PAGE, clk)) {
              if (TryInit( 8, 5, LARGE_PAGE, clk)) {
                return (1);             // Fail 
              }
            }
          } else {
            if (TryInit( 8, 3, SMALL_PAGE, clk))
              TryInit( 8, 4, SMALL_PAGE, clk);
          }
        }
      }
    } else {
      if (TryInit(16, 3, SMALL_PAGE, clk))
        TryInit(16, 4, SMALL_PAGE, clk);
    }

    // Remember block size information
    block_size       = BLOCK_SIZE[page_type];
   
    // Remember block size information in bit shifts
    block_size_shift = BLOCK_SIZE_SHIFT[page_type];

    // Remember page size information
    page_size        = PAGE_SIZE[page_type];

    // Remember user page size information
    page_usr_size    = PAGE_USR_SIZE[page_type];

    // Check if Interface Configuration Data (ICR) are valid and setup interface accordingly
    for (i=0; i<16; i=i+4) {
      byte = data_buf[i];

      // Check if ICR valid
      if (((byte & 0x0F) ^ (byte >> 4)) == 0x0F) {

        ICR = byte;
        if (ICR & 0x01) bus_width = 16;
        else            bus_width =  8;
  
        if (ICR & 0x04) {
          page_type = LARGE_PAGE;
          if (ICR & 0x02) adr_cycles = 5;
          else            adr_cycles = 4;
        } else {
          page_type = SMALL_PAGE;
          if (ICR & 0x02) adr_cycles = 4;
          else            adr_cycles = 3;
        }
        if (TryInit(bus_width, adr_cycles, page_type, clk) == 0) {
          // Restart block searching from beginning
          FindBlock(0, 1);

          return (0);
        }
      }
    }

    // If no ICRs were valid erase first block detect bus width 
    // and setup new ICRs and write them to page 0 of bank 0
    EraseBlock_HW(0);

    // Check if 8-bit bus width not already autodetected
    if (bus_width != 8) {
      if (InitFlashController_HW(16, adr_cycles, page_type, clk) == NAND_OK) {
        for (i=0; i<page_size; i++) data_buf[i]=0xFF;
        data_buf[0] = 0x55;
        data_buf[1] = 0xAA;
        ProgramPage_HW (0, 2, data_buf);
        ReadPage_HW    (0, 2, data_buf);
        if ((data_buf[0] != 0x55) || (data_buf[1] != 0xAA)) {
          // 8-bit bus width detected
          InitFlashController_HW(8, adr_cycles, page_type, clk);
        } else {
          // 16-bit bus width detected, it is already used
        }
      }
    }

    // Setup Interface Configuration Data
    temp = 0;
    if (bus_width == 16) temp = 1;
    if (page_type == SMALL_PAGE && adr_cycles == 4) 
      temp |= 0x02;
      
    if (page_type == LARGE_PAGE) {
      temp |= 0x04;
      if (adr_cycles == 5) temp |= 0x02;
    }           
    
    // Generate ICR
    ICR = (temp | temp << 4) ^ 0xF0;

    // Clear data buffer
    for (i=0; i<page_size; i++) data_buf[i]=0xFF;

    // Setup ICRs to data buffer to be written to page 0 of bank 0
    for (i=0; i<16; i=i+4) data_buf[i] = ICR;

    // Write ICRs to flash to page 0 of bank 0
    ProgramPage_HW (0, 16, data_buf);
  }

  // Restart block searching from beginning
  FindBlock(0, 1);

  return (0);
}


/*
 *  De-Initialize Flash Programming Functions
 *    Parameter:      fnc:  Function Code (1 - Erase, 2 - Program, 3 - Verify)
 *    Return Value:   0 - OK,  1 - Failed
 */

int UnInit (unsigned long fnc) {
  return (0);
}


/*- BlankCheck (...) -----------------------------------------------------------
 *
 *  Blank Check Checks if Memory is Blank
 *    Parameter:      adr:  Block Start Address
 *                    sz:   Block Size (in bytes)
 *                    pat:  Block Pattern
 *    Return Value:   0 - OK,  1 - Failed
 */

int BlankCheck (unsigned long adr, unsigned long sz, unsigned char pat) {

  return (1);                           // Always Force Erase
}


/*- EraseSector (...) ----------------------------------------------------------
 *
 *  Erase Sector in Flash Memory
 *    Parameter:      adr:  Sector Address
 *    Return Value:   0 - OK,  1 - Failed
 */

int EraseSector (unsigned long adr) {

  if (adr == 0) {                       // Erasing block for 2-nd level bootloader
    EraseBlock_HW(0);
    if (WriteBootInfo () == 0) return (0);
  } else {                              // Erasing block for program
    FindBlock(adr, 0);
    if (EraseBlock_HW(nand_block_offset) == NAND_OK) return (0);
  }

  return (1);
}


/*- ProgramPage (...) ----------------------------------------------------------
 *
 *  Program Page in Flash Memory
 *    Parameter:      adr:  Page Start Address
 *                    sz:   Page Size
 *                    buf:  Page Data
 *    Return Value:   0 - OK,  1 - Failed
 */

int ProgramPage (unsigned long adr, unsigned long sz, unsigned char *buf) {
  unsigned long adr_dest;
  int stat;

  if (adr < block_size) {               // Programming 2-nd level bootloader data
    adr_dest = adr + page_usr_size;     // skip page 0 of block 0
  } else {                              // Programming program data
    FindBlock(adr, 0);
    adr_dest  = nand_block_offset + (adr & (block_size-1));
  }

  if (ProgramPage_HW(adr_dest, sz, buf) != NAND_OK) return (1);
  stat = ReadPage_HW(adr_dest, sz, data_buf);
  if (stat != NAND_OK) {
    if (stat == NAND_ECC_ERROR) {
      MarkBlockBad_HW(adr_dest);
    }
    return (1);
  }

  return (0);
}

/*- Verify (...) ---------------------------------------------------------------
 *
 *  Verify Flash Contents
 *    Parameter:      adr:  Start Address
 *                    sz:   Size (in bytes)
 *                    buf:  Data
 *    Return Value:   (adr+sz) - OK, Failed Address
 */

unsigned long Verify (unsigned long adr, unsigned long sz, unsigned char *buf) {
  unsigned long i, adr_dest, in_page_ofs;

  if (adr < block_size) {               // Verifying 2-nd level bootloader data
    adr_dest = adr + page_usr_size;     // skip page 0 of block 0
  } else {                              // Verifying program data
    FindBlock(adr, 0);
    adr_dest  = nand_block_offset + (adr & (block_size-1));
  }
  in_page_ofs = adr_dest & (page_usr_size-1);

  if (ReadPage_HW(adr_dest, page_usr_size, data_buf)) return (1);
  for (i=0; i<sz; i++)
    if (buf[i] != data_buf[i+in_page_ofs])
      break;

  return (adr+i);
}


/**************************** Auxiliary Functions ******************************/

/*- WriteBootInfo () -----------------------------------------------------------
 *
 *  Try initializing controller and reading Interface Configuration Data (ICR)
 *    Parameter:   
 *    Return Value:  0 - Ok, 1 - Fail
 */

static int WriteBootInfo (void) {
  int i;

  for (i=0;  i<page_size; i++) data_buf[i]=0xFF;   // Clear data buffer
  for (i=0;  i<16; i=i+4) data_buf[i] =  ICR;      // d0, d1, d2, d3  - Setup ICRs
  for (i=16; i<48; i=i+8) data_buf[i] =  SZ_INFO;  // d4, d6, d8, d10 - Setup Size info for bootloader
  for (i=20; i<48; i=i+8) data_buf[i] = ~SZ_INFO;  // d5, d7, d9, d11 - Setup inv Size info for bootloader
  data_buf[48] = 0xaa;                             // d12
  data_buf[49] = 0x00;
  data_buf[50] = 0x00;
  data_buf[51] = 0x00;

  ProgramPage_HW (0, 64, data_buf);

  return (0);
}


/*- TryInit (...) --------------------------------------------------------------
 *
 *  Try initializing controller and reading Interface Configuration Data (ICR)
 *    Parameter:     bus_wdth:  Bus Width (8, 16 bit)
 *                   adr_cyc:   Addressing Cycles (3, 4, 5)
 *                   page_typ:  Page Type (0 -Small Page, 1 - Large Page)
 *                   clk:       Clock Frequency (Hz)
 *    Return Value:  0 - Ok, 1 - Fail
 */

static int TryInit (unsigned char bus_wdth, unsigned char adr_cyc, unsigned char page_typ, unsigned long clk) {
  bus_width  = bus_wdth; 
  adr_cycles = adr_cyc; 
  page_type  = page_typ;

  if (InitFlashController_HW(bus_wdth, adr_cyc, page_typ, clk) != NAND_OK)
    return (1);
  if ((ReadPage_HW(0, 16, data_buf) != NAND_OK) && (ReadPage_HW(0, 16, data_buf) != NAND_ECC_ERROR))
    return (1);

  return (0);
}


/*- FindBlock (...) ------------------------------------------------------------
 *
 *  Find appropriate valid block for requested address
 *    Parameter:     adr:       Address Requested for Setting
 *                   restart:   0 - find operation, 1 - restart search from beginning
 *    Return Value:  0 - OK,  1 - Failed
 */

static int FindBlock (unsigned long adr, unsigned int restart) {
  static int last_src_index  = -1;
         int src_index;

  if (restart == 1) {                   // Just restart for block finding starting from beginning
    last_src_index = -1;
    nand_block_offset = 0;
    return (0);
  }

  adr      -= base_adr;                 // Address to relative
  src_index = adr >> block_size_shift;  // Get requested block index for source

  if (src_index == last_src_index)      // Same block as previously requested
    return (0);

  while (last_src_index < src_index) {  // Find appropriate valid block
    nand_block_offset += block_size;
    if (CheckBlock_HW(nand_block_offset) == NAND_OK) 
      last_src_index++;
  }

  return (0);
}


/*******************************************************************************/

⌨️ 快捷键说明

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