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

📄 flash_i128.c

📁 Intrisyc 公司的PXA255-bootloader,源码易懂
💻 C
字号:
//////////////////////////////////////////////////////////////////////////////////// Copyright(c) 2001 Intrinsyc Software Inc. All rights reserved.//// Module name:////      flash_i128.c//// Description:////      Driver for Intel StrataFlash chips.//// Author:////      Mike Kirkland//// Created:////      October 2001//////////////////////////////////////////////////////////////////////////////////#include <flash_i128.h>#include <string.h>#include <c_main.h>#include <platform.h>#include <messages.h>#include <debug.h>////////////////////////////////////////////////////////////////////////////////// status_flash// PURPOSE: Checks the flash status for error.// PARAMS   (IN) volatile u16 *flash_addr - flash address to check for errors.// RETURNS: 1 on error, 0 otherwise.////////////////////////////////////////////////////////////////////////////////static intstatus_flash(volatile u32 *flash_addr){   u32 flash_status = 0;   int error = 0;   if(!wait_flash(flash_addr))   {      return 1;   }   //make sure status is up to date   {      volatile u32 foo;      foo = DEREF(flash_addr);      foo = DEREF(flash_addr);      foo = DEREF(flash_addr);   }   DEREF(flash_addr) = STATUS_READ;   flash_status = DEREF(flash_addr);   if(flash_status & STATUS_PGM_ERR)   {      error_print(FLASH_PROGRAMMING_ERROR);      error = 1;   }   if(flash_status & STATUS_PROTECT)   {      error_print(FLASH_PROTECTED_ERROR);      error = 1;   }   if(flash_status & STATUS_VOLTAGE_ERR)   {      error_print(FLASH_PROGRAMMING_ERROR);      error = 1;   }   if(flash_status & STATUS_ERASE_ERR)   {      error_print(FLASH_ERASE_ERROR);      error = 1;   }   if(error)   {      itc_printf("flash_status: 0x%x\r\n", flash_status);   }   return error;}////////////////////////////////////////////////////////////////////////////////// init_flash// PURPOSE: This is the initialization function for the flash driver. Here is//          where things such as buswidth should be set and so on.// PARAMS:  None.// RETURNS: Nothing.////////////////////////////////////////////////////////////////////////////////voidinit_flash(void){  //This chip needs no initialization.} // end of init_flash////////////////////////////////////////////////////////////////////////////////// block_erase_flash// PURPOSE: To erase an entire block of flash.// PARAMS:  (IN) u32 uBlockAddr - This is the starting address of the block that//                                 we wish to erase.// RETURNS  1 for success, 0 for failure.////////////////////////////////////////////////////////////////////////////////intblock_erase_flash(u32 *addr){   volatile u32 *flash = addr;   int error = 0;   if(!wait_flash((u32 *)flash))   {      return 0;   }   DEREF(flash) = CAST(STATUS_CLEAR);   if(!wait_flash(flash))   {      return 0;   }   DEREF(flash) = CAST(CMD_CLEAR_LOCK);   DEREF(flash) = CAST(CMD_CONFIRM);   if(!wait_flash(flash))   {      return 0;   }   DEREF(flash) = CAST(ERASE_SETUP);   DEREF(flash) = CAST(ERASE_CONFIRM);   if(!wait_flash(flash))   {      return 0;   }   error = status_flash(flash);   if(error)   {      DEBUG_0("bad erase: 0x%x\r\n", (u32)flash);   }   DEREF(flash) = CAST(READ_ARRAY);   return !error;} // end of block_erase_flash////////////////////////////////////////////////////////////////////////////////// block_write_flash_sector// PURPOSE: Writes one sector of flash// PARAMS:  (IN) u32 *dest - address to write to.//          (IN) u32 *src  - data to write. Should have one full block.// RETURNS: 1 for success, 0 for failure.////////////////////////////////////////////////////////////////////////////////intblock_write_flash_sector(u32 *dest,                         u32 *src){   unsigned long i = 0;   volatile u8 *flash = (u8 *)dest;   u8 *data = (u8 *)src;   int error = 0;   int pollmax = POLLMAX;   if(!block_erase_flash((u32 *)flash))      return 0;   while(i < MAIN_BLOCK_SIZE)   {      int cnt = WR_BUFF_SIZE / sizeof(u16);      if(!wait_flash((u32 *)flash))      {	 return 0;      }      do      {         DEREF(flash) = CAST(CMD_WR_BUFF);      } while( pollmax-- && (DEREF(flash) & CAST(STATUS_BUSY)) !=		             CAST(STATUS_BUSY));      if(!pollmax)      {         error_print(FLASH_DEAD_ERROR);         return 0;      }      if(status.flash_chip == i128x2)      {	 DEREF(flash) = CAST((WR_BUFF_SIZE / sizeof(u16) - 1) |		             ((WR_BUFF_SIZE / sizeof(u16) - 1) <<			      (FLASH_BUS_WIDTH * 4)));      }      else if(status.flash_chip == i128)      {	 DEREF(flash) = CAST(WR_BUFF_SIZE / FLASH_BUS_WIDTH - 1);      }      while( cnt-- )      {         DEREF((flash + i)) = DEREF(data);         i += FLASH_BUS_WIDTH;	 data += FLASH_BUS_WIDTH;      }      DEREF((flash + i-FLASH_BUS_WIDTH)) = CAST(CMD_CONFIRM);      if(!wait_flash((u32 *)flash))      {	 return 0;      }      error = status_flash((u32 *)(flash + i-FLASH_BUS_WIDTH));      if(error)      {         itc_printf("bad addr: %x\r\n", (u32)(flash + i));         break;      }   }   DEREF(dest) = CAST(READ_ARRAY);   return error;}////////////////////////////////////////////////////////////////////////////////// block_write_flash// PURPOSE: To write one, or more, blocks of flash// PARAMS:  (IN) u32 dest   - This is the starting address in flash to write//                            the data to.//          (IN) u32 source - This is the source address to read the data//                            from.//          (IN) u32 size   - This is the amount of data in bytes to write.//          (IN) int perm   - Permissions. Certian blocks may be "off limits" to//                            certian functions. For the moment, only the boot//                            block is protected. To write to the boot block,//                            parameter must be "FLASH_BOOT".// RETURNS: 1 for success, 0 for failure.////////////////////////////////////////////////////////////////////////////////intblock_write_flash(u32 *dest,                  u32 *source,                  int size,                  int perm){   int error = 0;   if(perm != FLASH_BOOT)   {      if((u32)dest < MAIN_BLOCK_SIZE)      {         error_print(FLASH_FLASHLOADER_ERROR);         return -1;      }   }   if((u32)dest > FLASH_MAX){      DEBUG_0("Error: destination address (0x%x) is out of range.\r\n", (u32)dest);      return 0;   }   itc_printf("0x");   do   {      itc_printf("%x", (u32)dest);      error = block_write_flash_sector((u32 *)dest, (u32 *)source);      if(error)         break;      dest += MAIN_BLOCK_SIZE / sizeof(dest);      source += MAIN_BLOCK_SIZE / sizeof(source);      itc_printf("\b\b\b\b\b\b\b\b");   } while((size -= MAIN_BLOCK_SIZE) > 0);   itc_printf("%x\r\n", (u32)dest);   return (error ? 0 : 1);} // end of block_write_flash////////////////////////////////////////////////////////////////////////////////// block_read_flash// PURPOSE://   There are many cases where this would not be neccessary to implement, but//   there are a few cases where this might become neccessary.  If so it is here//   otherwise use of it is optional.  (should just be a memcpy then).// IN://   u32 uDestAddr - This is the starting location to write the data from//     flash.////   u32 uSrcAddr - This is the starting location of flash to read from.////   u32 uSize - This is the size of data (in bytes) to read.// SIDE EFFECTS://   This will cause an area of memory starting at uDestAddr to be written with//   uSize bytes of data from uSrcAddr.////////////////////////////////////////////////////////////////////////////////intblock_read_flash(u32 uDestAddr,                 u32 uSrcAddr,                 u32 uSize){  //memcpy(uDestAddr, uSrcAddr, uSize);  return 1;} // end of block_read_flash////////////////////////////////////////////////////////////////////////////////// FUNCTION: get_device_info_flash// PURPOSE://   We need to get information about the flash, like manufacturer type, and//   size of flash and so on.// IN://   u32 uBlockAddr - This is the Address of the flash device.// OUT://   u32 *pManufacturerID - This is the Manufacturer ID.  NOTE that on//     16 and 8 bit flash interfaces that there will have to be some special//     mangling done.////   u32 *pDeviceID - This is the Device ID.  NOTE that on 16 and 8 bit//     flash interfaces that there will have to be some special mangling done.////   u32 *pBlockSize - This is set to the Block Size of the Flash.////   u32 *pDeviceSize - This is the actual size of flash.// SIDE EFFECTS://   None.// SPECIAL NOTES://   On systems with a 16 or 8 bit buswidth, there is going to have to be some//   special handling with the pManufacturerID and pDeviceID fields as those //   would normally be 32-bit fields.////////////////////////////////////////////////////////////////////////////////intget_device_info_flash(u32 uBlockAddr,		     u32 *pManufacturerID,		     u32 *pDeviceID,		     u32 *pBlockSize,		     u32 *pDeviceSize){  return 0;} // end of get_device_info_flash////////////////////////////////////////////////////////////////////////////////// FUNCTION: wait_flash// PURPOSE://   To wait till the flash chip is done executing the last command (most//   likely either a write or clear.)// IN://   u32 uBlockAddr - This is the Address of flash that we will be waiting//     for// SPECIAL NOTES://   After writing certain commands to the Flash, a period of time must elapse//   for the actual flash chip to finish the command internally.  Because of//   this we must wait for it to finish.  That should be done here.////////////////////////////////////////////////////////////////////////////////int wait_flash(volatile u32 *flash){   int pollmax = POLLMAX;   u32 flash_status;   do   {      DEREF(flash) = CAST(STATUS_READ);      flash_status = DEREF(flash);   } while(--pollmax && (flash_status & CAST(STATUS_BUSY)) !=	                 CAST(STATUS_BUSY));   if(pollmax)   {      return 1;   }   else   {      error_print(FLASH_DEAD_ERROR);      return 0;   }} // end of wait_flash

⌨️ 快捷键说明

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