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

📄 blkmem.c

📁 单片机学习资料 适合初学者进行开发学习
💻 C
📖 第 1 页 / 共 5 页
字号:
/* *	FLASH programming routine for the 29LVX00 device family. */static void flash_amd8_write(struct arena_t * a, unsigned long pos, unsigned long length, char * buffer){  volatile unsigned char *address;  unsigned long flags, fbase = a->address;  unsigned char *wbuf, status;  int i;  #if 0  printk("%s(%d): flash_amd8_write(a=%x,pos=%x,length=%d,buf=%x)\n",	__FILE__, __LINE__, (int) a, (int) pos, (int) length, (int) buffer);#endif  down(&spare_lock);#if defined(CONFIG_WATCHDOG)  watchdog_disable();#endif  address = (unsigned volatile char *) (fbase + pos);  wbuf = (unsigned char *) buffer;  for (; (length > 0); length--, address++, wbuf++) {      if (*address != *wbuf) {      save_flags(flags); cli();      *((volatile unsigned char *) (fbase | 0xaaa)) = 0xaa;      *((volatile unsigned char *) (fbase | 0x555)) = 0x55;      *((volatile unsigned char *) (fbase | 0xaaa)) = 0xa0;      *address = *wbuf;      for (i = 0; (i < FTIMEOUT); i++) {	status = *address;	if (status == *wbuf) {	  /* Program complete */	  break;	}      }      if (*address != *wbuf) {          printk("%s(%d): FLASH write failed i=%d, address %p -> %x(%x)\n",		__FILE__, __LINE__, i, address, *wbuf, *address);          *((unsigned volatile char *) fbase) = 0xf0; /* Reset */      }      restore_flags(flags);    }  }#if defined(CONFIG_WATCHDOG)  watchdog_enable();#endif  up(&spare_lock);}/* *	Program a complete FLASH image. This runs from DRAM, so no *	need to worry about writing to what we are running from... */static void flash_amd8_writeall(struct arena_t * a, struct blkmem_program_t * prog){  unsigned long		base, offset, erased;  unsigned long		ptr, min, max;  unsigned char		*w, status;  int			failures;  int			i, j, l;#if defined(CONFIG_WATCHDOG)  watchdog_disable();#endif  #if 0  printk("FLASH: programming");#endif  failures = 0;  erased = 0;  cli();    for (i = 0; (i < prog->blocks); i++) {#if 0    printk("%s(%d): block=%d address=%x pos=%x length=%x range=%x-%x\n",      __FILE__, __LINE__, i, (int) a->address, (int) prog->block[i].pos,      (int) prog->block[i].length, (int) (prog->block[i].pos + a->address),      (int) (prog->block[i].pos + prog->block[i].length - 1 + a->address));#endif    /*     *	Erase FLASH sectors for this program block...     */    for (l = prog->block[i].pos / a->blksize;	l <= ((prog->block[i].pos+prog->block[i].length-1) / a->blksize);	l++) {      if (erased & (0x1 << l))	continue;      ptr = l * a->blksize;      offset = ptr % a->unitsize;      base = ptr - offset;	      base += a->address;      ptr += a->address;      j = 0;flash_redo:#if 0      printk("%s(%d): ERASE BLOCK sector=%d base=%x offset=%x ptr=%x\n",	  __FILE__, __LINE__, l, (int) base, (int) offset, (int) ptr);#endif      /* Erase this sector */      *((volatile unsigned char *) (base | 0xaaa)) = 0xaa;      *((volatile unsigned char *) (base | 0x555)) = 0x55;      *((volatile unsigned char *) (base | 0xaaa)) = 0x80;      *((volatile unsigned char *) (base | 0xaaa)) = 0xaa;      *((volatile unsigned char *) (base | 0x555)) = 0x55;      *((volatile unsigned char *) ptr) = 0x30;      for (;;) {	status = *((volatile unsigned char *) ptr);	if (status & 0x80) {	  /* Erase complete */	  break;	}	if (status & 0x20) {	  printk("FLASH: (%d) erase failed\n", __LINE__);	  /* Reset FLASH unit */	  *((volatile unsigned char *) base) = 0xf0;	  failures++;	  /* Continue (with unerased sector) */	  break;	}      }      /*       * Some flash have a set of small segments at the top or bottom.       * These need to be erased individually, even better, different       * devices uses different segment sizes :-(       * This code currently only handles bottom booters...       */      if ((ptr & FLASHMASK) < 64*1024) {	ptr += flash_bootsegs[j++];        if ((ptr - base) < a->length)	  goto flash_redo;      }      erased |= (0x1 << l);    }    /*     *	Program FLASH with the block data...     */    min = prog->block[i].pos+a->address;    max = prog->block[i].pos+prog->block[i].length+a->address;    w = (unsigned char *) prog->block[i].data;    /* Progress indicators... */    printk(".");#ifdef CONFIG_LEDMAN	if (i & 1) {		ledman_cmd(LEDMAN_CMD_OFF, LEDMAN_NVRAM_1);		ledman_cmd(LEDMAN_CMD_ON,  LEDMAN_NVRAM_2);	} else {		ledman_cmd(LEDMAN_CMD_ON,  LEDMAN_NVRAM_1);		ledman_cmd(LEDMAN_CMD_OFF, LEDMAN_NVRAM_2);	}#endif#if 0    printk("%s(%d): PROGRAM BLOCK min=%x max=%x\n", __FILE__, __LINE__,      (int) min, (int) max);#endif    for (ptr = min; (ptr < max); ptr++, w++) {            offset = (ptr - a->address) % a->unitsize;      base = ptr - offset;#if 0      printk("%s(%d): PROGRAM base=%x offset=%x ptr=%x value=%x\n",	  __FILE__, __LINE__, (int) base, (int) offset, (int) ptr, (int) *w);#endif      *((volatile unsigned char *) (base | 0xaaa)) = 0xaa;      *((volatile unsigned char *) (base | 0x555)) = 0x55;      *((volatile unsigned char *) (base | 0xaaa)) = 0xa0;      *((volatile unsigned char *) ptr) = *w;      for (j = 0; (j < FTIMEOUT); j++) {	status = *((volatile unsigned char *) ptr);	if (status == *w) {	  /* Program complete */	  break;	}      }      status = *((volatile unsigned char *) ptr);      if (status != *w) {	printk("FLASH: (%d) write failed, addr=%x val=%x status=%x cnt=%d\n",		__LINE__, (int) ptr, *w, status, j);	/* Reset FLASH unit */	*((volatile unsigned char *) ptr) = 0xf0;	failures++;      }    }  }#ifdef CONFIG_LEDMAN  ledman_cmd(LEDMAN_CMD_RESET, LEDMAN_NVRAM_1);  ledman_cmd(LEDMAN_CMD_RESET, LEDMAN_NVRAM_2);#endif  if (failures > 0) {    printk("FLASH: %d failures programming FLASH!\n", failures);    return;  }#if 0  printk("\nFLASH: programming successful!\n");#endif  if (prog->reset) {    printk("FLASH: rebooting...\n\n");    HARD_RESET_NOW();  }}/****************************************************************************//*                            AMD 16bit FLASH                               *//****************************************************************************/#else/* *	FLASH erase routine for the AMD 29LVxxx family devices. */static void flash_amd16_erase(struct arena_t *a, unsigned long pos){  unsigned volatile short *address;  unsigned long fbase = a->address;  unsigned long flags;  unsigned short status;  int i;  #if 0  printk("%s(%d): flash_amd16_erase(a=%x,pos=%x)\n", __FILE__, __LINE__,    (int) a, (int) pos);#endif  if (pos >= a->length)    return;  address = (unsigned volatile short *) (fbase + pos);  /* Mutex all access to FLASH memory */  down(&spare_lock);  save_flags(flags); cli();#if defined(CONFIG_WATCHDOG)  watchdog_disable();#endif  /* Erase this sector */  *((volatile unsigned short *) (fbase | (0x555 << 1))) = 0xaaaa;  *((volatile unsigned short *) (fbase | (0x2aa << 1))) = 0x5555;  *((volatile unsigned short *) (fbase | (0x555 << 1))) = 0x8080;  *((volatile unsigned short *) (fbase | (0x555 << 1))) = 0xaaaa;  *((volatile unsigned short *) (fbase | (0x2aa << 1))) = 0x5555;  *address = 0x3030;  for (i = 0; (i < FTIMEOUT); i++) {    status = *address;    if ((status & 0x0080) || (status & 0x0020))      break;  }  if (*address != 0xffff) {     printk("%s(%d): FLASH erase failed, address %p iteration=%d status=%x\n",		__FILE__, __LINE__, address, i, status);     *((unsigned volatile short *) fbase) = 0xf0f0; /* Reset */  }#if defined(CONFIG_WATCHDOG)  watchdog_enable();#endif  restore_flags(flags);  up(&spare_lock);}/* *	FLASH programming routine for the 29LVxxx device family. */static void flash_amd16_write(struct arena_t * a, unsigned long pos, unsigned long length, char * buffer){  volatile unsigned short *address;  unsigned long flags, fbase = a->address;  unsigned short *wbuf, status;  int i;  #if 0  printk("%s(%d): flash_amd16_write(a=%x,pos=%x,length=%d,buf=%x)\n",	__FILE__, __LINE__, (int) a, (int) pos, (int) length, (int) buffer);#endif  down(&spare_lock);#if defined(CONFIG_WATCHDOG)  watchdog_disable();#endif  address = (unsigned volatile short *) (fbase + pos);  wbuf = (unsigned short *) buffer;  length += 1;   /* Fix it so that an odd number of bytes gets written correctly */  for (length >>= 1; (length > 0); length--, address++, wbuf++) {      if (*address != *wbuf) {      save_flags(flags); cli();      *((volatile unsigned short *) (fbase | (0x555 << 1))) = 0xaaaa;      *((volatile unsigned short *) (fbase | (0x2aa << 1))) = 0x5555;      *((volatile unsigned short *) (fbase | (0x555 << 1))) = 0xa0a0;      *address = *wbuf;      for (i = 0; (i < FTIMEOUT); i++) {	status = *address;	if (status == *wbuf) {	  /* Program complete */	  break;	}      }      if (*address != *wbuf) {          printk("%s(%d): FLASH write failed i=%d, address %p -> %x(%x)\n",		__FILE__, __LINE__, i, address, *wbuf, *address);          *((unsigned volatile short *) fbase) = 0xf0f0; /* Reset */      }      restore_flags(flags);    }  }#if defined(CONFIG_WATCHDOG)  watchdog_enable();#endif  up(&spare_lock);}/* *	Program a complete FLASH image. This runs from DRAM, so no *	need to worry about writing to what we are running from... */static void flash_amd16_writeall(struct arena_t * a, struct blkmem_program_t * prog){  unsigned long		base, offset, erased;  unsigned long		ptr, min, max;  unsigned short	*w, status;  int			failures;  int			i, j, l;#if defined(CONFIG_WATCHDOG)  watchdog_disable();#endif  #if 0  printk("FLASH: programming");#endif  failures = 0;  erased = 0;  cli();    for (i = 0; (i < prog->blocks); i++) {#if 0    printk("%s(%d): block=%d address=%x pos=%x length=%x range=%x-%x\n",      __FILE__, __LINE__, i, (int) a->address, (int) prog->block[i].pos,      (int) prog->block[i].length, (int) (prog->block[i].pos + a->address),      (int) (prog->block[i].pos + prog->block[i].length - 1 + a->address));#endif    /*     *	Erase FLASH sectors for this program block...     */    for (l = prog->block[i].pos / a->blksize;	l <= ((prog->block[i].pos+prog->block[i].length-1) / a->blksize);	l++) {      if (erased & (0x1 << l))	continue;      ptr = l * a->blksize;      offset = ptr % a->unitsize;      base = ptr - offset;	      base += a->address;      ptr += a->address;      j = 0;flash_redo:#if 0      printk("%s(%d): ERASE BLOCK sector=%d base=%x offset=%x ptr=%x\n",	  __FILE__, __LINE__, l, (int) base, (int) offset, (int) ptr);#endif      /* Erase this sector */      /* FIX: check which byte lane the value needs to be on */      *((volatile unsigned short *) (base | (0x555 << 1))) = 0xaaaa;      *((volatile unsigned short *) (base | (0x2aa << 1))) = 0x5555;      *((volatile unsigned short *) (base | (0x555 << 1))) = 0x8080;      *((volatile unsigned short *) (base | (0x555 << 1))) = 0xaaaa;      *((volatile unsigned short *) (base | (0x2aa << 1))) = 0x5555;      *((volatile unsigned short *) ptr) = 0x3030;      for (;;) {	status = *((volatile unsigned short *) ptr);	if (status & 0x0080) {	  /* Erase complete */	  break;	}	if (status & 0x0020) {	  printk("FLASH: (%d) erase failed\n", __LINE__);	  /* Reset FLASH unit */	  *((volatile unsigned short *) base) = 0xf0f0;	  failures++;	  /* Continue (with unerased sector) */	  break;	}      }      /*       * Some flash have a set of small segments at the top or bottom.       * These need to be erased individually, even better, different       * devices uses different segment sizes :-(       * This code currently only handles bottom booters...       */      if ((ptr & FLASHMASK) < 64*1024) {	ptr += flash_bootsegs[j++];        if ((ptr - base) < a->length)	  goto flash_redo;      }      erased |= (0x1 << l);    }    /*     *	Program FLASH with the block data...     */    min = prog->block[i].pos+a->address;    max = prog->block[i].pos+prog->block[i].length+a->address;    w = (unsigned short *) prog->block[i].data;    /* Progress indicators... */

⌨️ 快捷键说明

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