blkmem.c

来自「单片机学习资料 适合初学者进行开发学习」· C语言 代码 · 共 2,343 行 · 第 1/5 页

C
2,343
字号
#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();  }}#endif /* defined(CONFIG_INTELFLASH) *//****************************************************************************/#endif /* CONFIG_FLASH_SNAPGEAR *//****************************************************************************/#ifdef CONFIG_SHGLCOREstatic DECLARE_MUTEX(spare_lock);void read_spare(struct arena_t * a, unsigned long pos, unsigned long length, char * buffer){#ifdef DEBUG  printk("rsl\n");#endif    /* Mutex all access to FLASH */  down(&spare_lock);  #ifdef DEBUG  printk("rsld\n");#endif    /* Just copy the data into target buffer */  memcpy( buffer, (void*)(a->address+pos), length);  /* Release MUTEX */  up(&spare_lock);  #ifdef DEBUG  printk("rsud\n");#endif}void write_spare(struct arena_t * a, unsigned long pos, unsigned long length, char * buffer){  unsigned long start;  unsigned char c;  volatile unsigned char * address;  unsigned char result;  unsigned long fbase = a->address;  unsigned long flags;  #if 0  for(i = pos / a->blksize; i <= ((pos+length-1) / a->blksize); i++) {    if (test_bit(i, &a->auto_erase_bits)) {      /* erase sector start */      printk("Autoerase of sector %d\n", i);      erase_spare(a, i * a->blksize);      clear_bit(i, &a->auto_erase_bits);    }  }#endif#ifdef DEBUG  printk("wsl\n");#endif    down(&spare_lock);  #ifdef DEBUG  printk("wsld\n");#endif    start = jiffies;    address = (unsigned volatile char*)(fbase+pos);    while (length>0) {      c = *buffer++;        /*printk("Checking spare_flash program of byte %lx, at address %p, value %x (%c), current %x (%c)\n", pos, address, c, c, *address, *address);*/    if (*address != c) {        /*printk("Starting spare_flash program of byte %lx, at address %p\n", pos, address);*/                  if (c & ~*address) {        printk("Unable to write byte at %p (impossible bit transition in %x, actual %x)\n", address, c, *address);        /*continue;*/      }	save_flags(flags); cli();      *(unsigned volatile char *)(fbase | 0x5555)=0x0aa;      *(unsigned volatile char *)(fbase | 0x2aaa)=0x055;      *(unsigned volatile char *)(fbase | 0x5555)=0x0a0;            *address = c;                     for(;;) {        result = *address;        /*printk("Read value %x (%c)\n", result, result);*/        if ((result & 0x80) == (c & 0x80))          break;        if (result & 0x20) {          printk("timeout of FLASH write at address %p of value %x (actual %x)\n", address, c, *address);          *(unsigned volatile char *)(fbase)=0x0f0; /* Reset */          break;        }      }            restore_flags(flags);      /*printk("Completed spare_flash program of byte %lx, at address %p\n", pos, address);*/        #if 0      if (jiffies != start) {        /*printk("Spare_flash rescheduling in write\n");*/        current->state = TASK_INTERRUPTIBLE;        current->timeout = jiffies;        schedule();        current->timeout = 0;        /*schedule();*/        start = jiffies;      }#endif    }    address++;    length--;  }    up(&spare_lock);  #ifdef DEBUG  printk("wsud\n");#endif}void erase_spare(struct arena_t * a, unsigned long pos){  unsigned long fbase = a->address;  int delay;  unsigned volatile char * address;  unsigned long flags;    if (pos >= a->length)    return;    /* Mutex all access to FLASH memory */  #ifdef DEBUG  printk("esl\n");#endif    down(&spare_lock);#ifdef DEBUG  printk("esld\n");#endif  address = (unsigned volatile char*)(fbase + pos);  printk("Starting spare_flash erase of byte %lx, at address %p\n", pos, address);    save_flags(flags); cli();again:  delay = HZ/4+1;    /* Initiate erase of FLASH sector */    *(unsigned volatile char *)(fbase | 0x5555)=0x0aa;  *(unsigned volatile char *)(fbase | 0x2aaa)=0x055;  *(unsigned volatile char *)(fbase | 0x5555)=0x080;  *(unsigned volatile char *)(fbase | 0x5555)=0x0aa;  *(unsigned volatile char *)(fbase | 0x2aaa)=0x055;                         *address = 0x030;    /* Delay until erase is complete */       for (;;) {    unsigned char result;#ifdef original_spare_erase_delay    struct wait_queue *wait = NULL;#ifdef DEBUG    printk("Spare_flash erase delaying for %d ticks, status is %x\n", delay, (unsigned int)*address);#endif        current->timeout = jiffies + delay;#if 0        current->state = TASK_INTERRUPTIBLE;    schedule();    current->timeout = 0;#endif    interruptible_sleep_on(&wait);#endif    udelay(100000);        result = *address;    if (result & 0x80)       break;    if (result & 0x20) {       printk("timeout of Spare_flash erase of address %p\n", address);       *(unsigned volatile char *)(fbase)=0x0f0; /* Reset */       printk("Sleeping a second and retrying\n");       udelay(1000000);              goto again;    }  }    restore_flags(flags);#ifdef DEBUG  printk("Completed spare_flash erase of byte %lx, at address %p\n", pos, address);#endif    up(&spare_lock);#ifdef DEBUG  printk("esud\n");#endif}#define VSP(X) (*(volatile unsigned short *)(X))#define VSC(X) (*(volatile unsigned char *)(X))#define SCSR  VSP(0xfffc0c)#define SCSR_TDRE (1<<8)#define SCDR  VSP(0xfffC0e)#define print_char(x) ({			\	while (!(SCSR & SCSR_TDRE))		\		;				\	SCDR = (x);				\})#define print_hexdigit(x) ({			\	int digit = (x) & 0xf;			\	if (digit>9)				\		print_char('a'+digit-10);	\	else					\		print_char('0'+digit);		\						\})#define print_num(x) ({				\	unsigned long num = (x);		\	print_hexdigit(num >> 28);		\	print_hexdigit(num >> 24);		\	print_hexdigit(num >> 20);		\	print_hexdigit(num >> 16);		\	print_hexdigit(num >> 12);		\	print_hexdigit(num >> 8);		\	print_hexdigit(num >> 4);		\	print_hexdigit(num >> 0);		\})/* Note: sub_program_main must not reference _any_ data or code outside of itself,   or leave interrupts enabled, due to the fact that it is probably erasing   & reloading the kernel. */#define SET_SHORT(x,y) VSP((x)) = (y)/*#define SET_SHORT(x,y) ({})*/ /*print_char('>');print_num(x);*/ /*printk("%8.8lx <= %04x\n", (x), (y))*/#define SET_CHAR(x,y) VSC((x)) = (y)/*#define SET_CHAR(x,y) ({})*/ /*print_char('>');print_num(x);*/ /*printk("%8.8lx <= %02x\n", (x), (y))*/#define GET_SHORT(x) VSP((x))/*#define GET_SHORT(x) ({0;})*/ /*({print_char('<');print_num(x);0;})*/ /*(printk("%8.8lx => ....\n", (x)),0)*/#define GET_CHAR(x) VSC((x))/*#define GET_CHAR(x) ({0;})*/ /*({print_char('<');print_num(x);0;})*/ /*(printk("%8.8lx => ..\n", (x)),0)*/void sub_program_main(struct arena_t * a, struct blkmem_program_t * prog){  volatile int i,l;  unsigned long base, offset, ptr, min, max;  unsigned char * c;  unsigned int erased = 0;  int failures;  int retry;    cli();  retry = 0;again:  SET_ALARM_LED(1);    retry++;    if (retry>5) {  	goto give_up;  }    print_char('\r');    print_char('\n');    print_char('R');    print_char('0' + retry);  failures = 0;  erased = 0;  /*  for(i=prog->blocks-1;i>=0;i--) {*/  for(i=0;i<prog->blocks;i++) {    SET_COMM_STATUS_LED(!GET_COMM_STATUS_LED());    print_char('\r');    print_char('\n');    print_num(prog->block[i].pos+a->address);    print_char('-');    print_num(prog->block[i].pos+prog->block[i].length-1+a->address);    print_char('\r');    print_char('\n');    if(prog->block[i].length > 0xE0000)      break;    for(l=prog->block[i].pos / a->blksize; l <= ((prog->block[i].pos+prog->block[i].length-1) / a->blksize); l++) {      if (!test_bit(l, &erased)) {         	print_char('E'); 	print_char('0' + l / 10); 	print_char('0' + l % 10); 	print_char('\r'); 	print_char('\n'); 	 	if (l <  1) 	  break; 	/*if (l >= 8) 	  break;*/	ptr = l * a->blksize;	offset = ptr % a->unitsize;	base = ptr - offset;		base += a->address;	ptr += a->address;		print_char('b');	print_char('a');	print_char('s');	print_char('e');	print_char(' ');	print_num(base);	print_char('\r');	print_char('\n');	print_char('o');	print_char('f');	print_char('f');	print_char(' ');	print_num(offset);	print_char('\r');	print_char('\n');	print_char('p');	print_char('t');	print_char('r');	print_char(' ');	print_num(ptr);	print_char('\r');	print_char('\n');        set_bit(l, &erased);        if (ptr <  0x020000)          break;        /*if (ptr >= 0x100000)          break;*/                print_num(ptr);         	SET_COMM_ERROR_LED(1); 	        /* Erase even half of sector */        SET_SHORT( (base | (0x5555 << 1)), 0xaa00);        SET_SHORT( (base | (0x2aaa << 1)), 0x5500);        SET_SHORT( (base | (0x5555 << 1)), 0x8000);        SET_SHORT( (base | (0x5555 << 1)), 0xaa00);        SET_SHORT( (base | (0x2aaa << 1)), 0x5500);        SET_SHORT( ptr, 0x3000);#ifdef original_erase_logic        while (!(GET_SHORT(ptr) & 0x8000))          ;#else	for (;;) {		unsigned int status = GET_SHORT(ptr);		if (status & 0x8000) {			/* Erase complete */			break;		}		if (status & 0x2000) {			/* Check again */			status = GET_SHORT(ptr);			if (status & 0x8000) {				/* Erase complete */				break;			}						/* Erase failed */			print_char('F');						/* Reset FLASH unit */			SET_SHORT( base, 0xf000);						failures++;						/* Continue (with unerased sector) */			break;		}        }#endif        print_char(':');        /* Erase odd half of sector */        SET_SHORT( (base | (0x5555 << 1)), 0x00aa);        SET_SHORT( (base | (0x2aaa << 1)), 0x0055);        SET_SHORT( (base | (0x5555 << 1)), 0x0080);        SET_SHORT( (base | (0x5555 << 1)), 0x00aa);        SET_SHORT( (base | (0x2aaa << 1)), 0x0055);        SET_SHORT( ptr, 0x0030);#ifdef original_erase_logic        while (!(GET_SHORT(ptr) & 0x0080))          ;#else	for (;;) {		unsigned int status = GET_SHORT(ptr);		if (status & 0x0080) {			/* Erase complete */			break;		}		if (status & 0x0020) {					/* Check again */						status = GET_SHORT(ptr);			if (status & 0x0080) {				/* Erase complete */				break;			}			/* Erase failed */			print_char('F');						/* Reset FLASH unit */			SET_SHO

⌨️ 快捷键说明

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