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

📄 flashpic.c

📁 完整的Bell实验室的嵌入式文件系统TFS
💻 C
字号:
/* flashpic.c:   This file contains the flash-support code that is relocated to   RAM prior to execution.  This file supports all bus widths, dependent   on the definition of WIDTH8, WIDTH16, or WIDTH32 on the command line.   Refer to flash.h for definition of the width-dependent macros.*/#include "cpu.h"#include "flashdev.h"#include "flash.h"#include "config.h"#include "stddefs.h"#if INCLUDE_FLASHstruct uart405 {    union {        vuchar  data;       /* DATA_REG */        vuchar  dllsb;      /* DL_LSB (when DLAB is set in linectl reg) */    } b0;    union {        vuchar  inte;       /* INT_ENABLE */        vuchar  dlmsb;      /* DL_MSB when DLAB is set in linectl reg) */    } b1;    vuchar  fifoctl;        /* FIFO_CONTROL */    vuchar  linectl;        /* LINE_CONTROL */    vuchar  modemctl;       /* MODEM_CONTROL */    vuchar  linestat;       /* LINE_STATUS */    vuchar  modemstat;      /* MODEM_STATUS */    vuchar  scratch;        /* SCRATCH */};#define UARTA   ((struct uart405 *)0xef600300)#define THRE    0x20    /* Transmit Holding Register Empty */#define FLASH_ROT(x) (((x>>1)&0x7FFFFF)|((x&0x1)<<22)) /* Flasherase():   This "broke" version of flash driver does not support a per-sector   flash erase; so, we copy the monitor sectors to RAM, then erase the   entire device, then re-write the monitor to flash.*/intFlasherase(struct flashinfo *fdev,int snum){    volatile int i, j;    int bytecnt;    uchar *src, *dest;    ulong   foo;    src = (uchar *)0xfff80000;    dest = (uchar *)0x00200000;    while(src != 0)        *dest++ = *src++;        UARTA->b0.data = 'a';    while(!(UARTA->linestat & THRE));    *(uchar *)0xff800000 = 0xF0;    *(uchar *)(0xff800000 | FLASH_ROT((unsigned)0xAAA)) = 0xAA;    *(uchar *)(0xff800000 | FLASH_ROT((unsigned)0x555)) = 0x55;    *(uchar *)(0xff800000 | FLASH_ROT((unsigned)0xAAA)) = 0x80;    *(uchar *)(0xff800000 | FLASH_ROT((unsigned)0xAAA)) = 0xAA;    *(uchar *)(0xff800000 | FLASH_ROT((unsigned)0x555)) = 0x55;    *(uchar *)(0xff800000 | FLASH_ROT((unsigned)0xAAA)) = 0x10;    UARTA->b0.data = 'b';    while(!(UARTA->linestat & THRE));    /* Wait for device erase to complete or timeout.. */    for(j=10000000;j>0;j--) {        if (*(uchar *)fdev->base & 0x80)            break;    }    if (j == 0) {        UARTA->b0.data = 'c';        while(!(UARTA->linestat & THRE));    }    else {        UARTA->b0.data = 'C';        while(!(UARTA->linestat & THRE));    }    bytecnt = 0x80000;    src = (uchar *)0x00200000;    dest = (uchar *)0xfff80000;    for (i=0;i<bytecnt;i+=fdev->width) {        /* Flash write command */        foo = (ulong)dest & 0x3ff800;        *(uchar *)((ulong)fdev->base | foo) = 0xf0;        *(uchar *)((ulong)fdev->base | (foo | 0x555)) = 0xaa;        *(uchar *)((ulong)fdev->base | (foo | 0x4002aa)) = 0x55;        *(uchar *)((ulong)fdev->base | (foo | 0x555)) = 0xa0;        Fwrite(dest,src);        /* Wait for write to complete or timeout. */        for(j=10000000;j>0;j--) {            if (Is_Equal(dest,src)) {                if (Is_Equal(dest,src))                    break;            }        }        if ((i % 1000) == 0) {            if (j == 0) {                UARTA->b0.data = '.';                while(!(UARTA->linestat & THRE));            }             else {                UARTA->b0.data = '!';                while(!(UARTA->linestat & THRE));            }        }        dest++; src++;                }    return(0);}/* EndFlasherase():   Function place holder to determine the "end" of the   sectorerase() function.*/voidEndFlasherase(){}/* Flashwrite():   Return 0 if successful, else -1.   Note: this assumes that source & destination properly aligned   based on the width of the flash bank.*/intFlashwrite(struct flashinfo *fdev,ftype *dest,ftype *src,long bytecnt){    int i, ret;    ulong   foo;    /* Each pass through this loop writes 'fdev->width' bytes... */    ret = 0;    for (i=0;i<bytecnt;i+=fdev->width) {        /* Flash write command */        foo = (ulong)dest & 0x3ff800;        *(uchar *)((ulong)fdev->base | foo) = 0xf0;        *(uchar *)((ulong)fdev->base | (foo | 0x555)) = 0xaa;        *(uchar *)((ulong)fdev->base | (foo | 0x4002aa)) = 0x55;        *(uchar *)((ulong)fdev->base | (foo | 0x555)) = 0xa0;        Fwrite(dest,src);        /* Wait for write to complete or timeout. */        while(1) {            if (Is_Equal(dest,src)) {                if (Is_Equal(dest,src))                    break;            }        }        dest++; src++;    }    *(uchar *)fdev->base = 0xF0;    return(ret);}/* EndFlashwrite():    Function place holder to determine the "end" of the    Flashwrite() function.*/voidEndFlashwrite(){}/* Ewrite():   Erase all sectors that are part of the address space to be written,   then write the data to that address space.  This is basically a   concatenation of flasherase and flashwrite done in one step.  This is   necessary primarily for re-writing the bootcode; because after the boot   code is erased, there is nowhere to return so the re-write must be done   while executing out of ram also.*/intFlashewrite(struct flashinfo *fdev,ftype *dest,ftype *src,int bytecnt){    int i;    ulong   foo;    void    (*reset)();    ftype   *src1, *dest1;    src1 = src;    dest1 = dest;    /* Erase the entire device... */    *(uchar *)fdev->base = 0xf0;    *(uchar *)((ulong)fdev->base | FLASH_ROT(0xaaa)) = 0xaa;    *(uchar *)((ulong)fdev->base | FLASH_ROT(0x555)) = 0x55;    *(uchar *)((ulong)fdev->base | FLASH_ROT(0xaaa)) = 0x80;    *(uchar *)((ulong)fdev->base | FLASH_ROT(0xaaa)) = 0xaa;    *(uchar *)((ulong)fdev->base | FLASH_ROT(0x555)) = 0x55;    *(uchar *)((ulong)fdev->base | FLASH_ROT(0xAAA)) = 0x10;    while(1) {        if (*(uchar *)fdev->base & 0x80)            break;    }    /* Read/reset command: */    *(uchar *)fdev->base = 0xf0;    for(i=0;i<bytecnt;i+=fdev->width) {        /* Flash write command */        foo = (ulong)dest & 0x3ff800;        *(uchar *)((ulong)fdev->base | foo) = 0xf0;        *(uchar *)((ulong)fdev->base | (foo | 0x555)) = 0xaa;        *(uchar *)((ulong)fdev->base | (foo | 0x4002aa)) = 0x55;        *(uchar *)((ulong)fdev->base | (foo | 0x555)) = 0xa0;        Fwrite(dest,src);        /* Wait for write to complete or timeout. */        while(1) {            if (Is_Equal(dest,src)) {                if (Is_Equal(dest,src))                    break;            }        }        dest++; src++;    }    /* Issue the read/reset command sequence: */    *(uchar *)fdev->base = 0xF0;    /* Wait till flash is readable, or timeout: */    for(i=0;i<FLASH_TIMEOUT;i++) {        if (Is_Equal(dest1,src1))            break;    }    /* Now that the re-programming of flash is complete, reset: */    reset = RESETFUNC();    reset();    return(0);  /* won't get here */}/* EndFlashewrite():    Function place holder to determine the "end" of the    FlashEraseAndWrite() function.*/voidEndFlashewrite(){}/* Flashtype():   Use the AUTOSELECT command sequence to determine the type of device.   Note: there is one additional step that I found necessary to keep   SGS29040 device happy... For some reason after issuing the read/reset   command and returning (to code that actually executes out of the FLASH   device) I was consistently getting an illegal opcode exception at   the return location in the flash.  It appears that the SGS part needs   a bit of time after the read/reset to be able to fetch an instruction.   Reading a value in the flash (stored in val) prior to issuing the   command sequence, then waiting for that read to be the same after    issuing the read/reset, assures the algorithm of not returning unless   the flash device is readable.  Note that I found this ONLY to be necessary   for the signature read command of SGS flash.*/intFlashtype(struct flashinfo *fdev){    ushort  man, dev;    /* Issue the autoselect command sequence: */    *(uchar *)fdev->base = 0xF0;    *(uchar *)((ulong)fdev->base | FLASH_ROT(0xAAA)) = 0xAA;    *(uchar *)((ulong)fdev->base | FLASH_ROT(0x555)) = 0x55;    *(uchar *)((ulong)fdev->base | FLASH_ROT(0xAAA)) = 0x90;        man = (ushort)*(uchar *)fdev->base;    dev = (ushort)*(uchar *)((ulong)fdev->base | FLASH_ROT(0x2));    man &= 0xff;    dev &= 0xff;    man <<= 8;    dev |= man;    fdev->id = (ushort)dev;    /* Issue the read/reset command sequence: */    *(uchar *)fdev->base = 0xF0;    return((int)(fdev->id));}/* EndFlashtype():    Function place holder to determine the "end" of the    Flashtype() function.*/voidEndFlashtype(){}#endif

⌨️ 快捷键说明

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