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

📄 flashpic.c

📁 完整的Bell实验室的嵌入式文件系统TFS
💻 C
字号:
/* flashpic_strata.c: * This file contains the portion of the flash driver code that can be * relocated (pic =  position independent code) to RAM space so that it * is not executing out of the same flash device that it is operating on. * * This code is written for 2 Strata devices in 16-bit mode in parallel. * This forms one 32-bit wide flash bank. */#include "config.h"#if INCLUDE_FLASH#include "genlib.h"#include "stddefs.h"#include "flashdev.h"#include "flash.h"#include "cpu.h"#define USE_WRITE_BUFFER 1/* When this is used in an environment where it is NOT relocated,  * then it is safe to turn on trace and call printf for debugging. * This can be changed to a #define initialized to zero to save * space if printf is not going to be used. */int STRATA_TRACE;/* Flasherase(): * Based on the 'snum' value, erase the appropriate sector(s). * Write the "Erase Setup" and "Erase Confirm" commands... * Return 0 if success, else -1. */intFlasheraseStrata_8x32(struct flashinfo *fdev,int snum){    ftype           stat;    volatile ulong  add, *lp, *lp1;    volatile int    ret, sector, outofrange;    ret = 0;    outofrange = 1;    add = (ulong)(fdev->base);    if (STRATA_TRACE)        printf("erase(%d)\n",snum);    /* Start operation off by clearing the status register. */    Write_50_to_base();     /* Erase the request sector(s): */    for (sector=0;sector<fdev->sectorcnt;sector++) {        if ((snum == ALL_SECTORS) || (snum == sector)) {            /* Skip sector if it is protected.             */            if ((!FlashProtectWindow) &&                (fdev->sectors[sector].protected)) {                add += fdev->sectors[sector].size;                continue;            }            /* As long as we enter this block of code once, we know             * that the sector number requested was within the range             * of the specified bank.             */            outofrange = 0;            /* If the space within the sector is all FF, then it             * doesn't need to be erased, so don't...             */            lp = (ulong *)fdev->sectors[sector].begin;             lp1 = (ulong *)((char *)lp + fdev->sectors[sector].size);             while(lp < lp1) {                if (*lp++ != 0xffffffff) {      /* Erased? */                    Write_20_to_base();         /* setup */                    Write_d0_to_(add);          /* confirm */                    WAIT_FOR_WSMS_READY();      /* Wait for WSMS ready */                    stat = Read_0000();                    if (stat & ECLBS) {         /* Check for error */                        Write_50_to_base();     /* Clear status register */                        printf("Eerr 0x%lx\n",(ulong)stat);                        Write_ff_to_base();     /* Go to read-array mode */                        return(-1);                    }                    Write_ff_to_base();         /* Go to read-array mode */                    WAIT_FOR_FF(add);           /* Wait for read == 0xff */                    break;                }            }                        if (ret == -1)                break;        }        add += fdev->sectors[sector].size;    }    if (outofrange)        ret = -1;    return(ret);}/* EndFlasherase(): *  Function place holder to determine the "end" of the *  sectorerase() function. */voidEndFlasheraseStrata_8x32(){}/* Flashwrite(): * This device has a 32-byte write buffer.  The only gotcha for this is  * that the destination address into the flash must be on a 32-byte boundary, * so we an only use the buffer when the destination address has the lower 5 * bits clear.  To do this, we do however many "individual" writes are * necessary to get the destination address 32-byte aligned; then, if there * are at least 32 bytes left, we use the write-buffer mechanism for each * remaining block of 32 bytes. */intFlashwriteStrata_8x32(struct flashinfo *fdev,uchar *dest,uchar *src,                    long bytecnt){    ftype           stat;    volatile long   cnt, buf4[1];    volatile int    i, tot, ret, delta;    volatile uchar  *bp4;#if USE_WRITE_BUFFER    volatile uchar  *block, *bp64;    volatile long   buf64[16];#endif    /* Start operation off by clearing the status register. */    Write_50_to_base();     /* If the destination address is not properly aligned, then build a     * fake source buffer using bytes below dest.  Then call this function     * recursively to do that operation.     */    if (Not32BitAligned(dest)) {        uchar   *tmpdest;        delta = (long)dest & 3;        tmpdest = dest - delta;        bp4 = (uchar *)buf4;        for(i=0;delta>0;i++,delta--) {            *bp4++ = *(dest-delta);        }        for(;i<4;i++) {            *bp4++ = *src++;            bytecnt--;            dest++;        }        if (STRATA_TRACE)            printf("pre-align:  0x%lx = %08lx\n",(ulong)tmpdest,buf4[0]);        if (FlashwriteStrata_8x32(fdev,tmpdest,(uchar *)buf4,4) == -1)            return(-1);    }    /* This device supports a write-buffer mode.  The buffer is 32 bytes     * (16 words) and greatly speeds up the programming process.  This     * This function starts up with the word-at-a-time mode and uses it     * until the destination address is mod32.  Then for each successive     * 32-byte block, the write buffer is used. When there is less than 32     * bytes left, the algorithm falls back to the one-word-at-a-time mode     * to finish up.     */    ret = 0;    cnt = bytecnt & ~3;    for (tot=0;tot<cnt;tot+=4) {#if USE_WRITE_BUFFER        if (((ulong)dest & 0x3f) == 0)  /* Break out when 6 LSBs are zero */            break;#endif        bp4 = (uchar *)buf4;        *bp4++ = *src++;                /* Just in case src is not aligned... */        *bp4++ = *src++;                        *bp4++ = *src++;                        *bp4++ = *src++;                        if (STRATA_TRACE)            printf("fwrite1:    0x%lx = %08lx\n",(ulong)dest,buf4[0]);        Write_40_to_(dest);             /* Flash program setup command */        Fwrite(dest,buf4);              /* Write the value */        WAIT_FOR_WSMS_READY();          /* Wait for WSMS ready */        stat = Read_0000();        if (stat & PSLBS) {             /* Check for error */            Write_50_to_base();         /* Clear status register */            Write_ff_to_base();         /* Go to read-array mode */            printf("Werr1 0x%lx\n",(ulong)stat);            return(-1);        }        do {            Write_ff_to_base();             /* Go to read-array mode */        } WAIT_FOR_WRITE(dest,buf4);                dest += 4;     }#if USE_WRITE_BUFFER    /* If tot is less than cnt, then the upper loop reached a point where     * the destination address had the 5 LSBs low.  This means that we can     * use the write-buffer for all remaining 32-byte blocks...  Note that     * each 32-byte block is actually 64 because we have two devices in     * parallel.     */    if ((cnt-tot) >= 64) {        while((cnt-tot) >= 64) {                Write_ff_to_base();         /* Go to read-array mode */            bp64 = (uchar *)buf64;      /* Copy next buffer's worth of data */            for(i=0;i<64;i++)           /* into local buffer just in case */                *bp64++ = *src++;       /* the source is this flash device. */            bp64 = (uchar *)buf64;                do {                Write_e8_to_(dest);             } while (WBUF_NOT_AVAIL(dest));            block = dest;            Write_0f_to_(dest);             for(i=0;i<16;i++) {                bp4 = (uchar *)buf4;                *bp4++ = *bp64++;       /* Just in case src is not aligned... */                *bp4++ = *bp64++;                               *bp4++ = *bp64++;                               *bp4++ = *bp64++;                               if (STRATA_TRACE)                    printf("fwrite2:    0x%lx = %08lx\n",(ulong)dest,buf4[0]);                Fwrite(dest,buf4);      /* Write the value */                dest += 4;             }            Write_d0_to_(block);        /* Write-confirm command */            tot += 64;            Write_70_to_base();         /* Read Status Register */            WAIT_FOR_WSMS_READY();      /* Wait for idle state machine */        }        stat = Read_0000();             /* Check for error */        if (stat & PSLBS) {                 Write_50_to_base();         /* Clear status register */            Write_ff_to_base();         /* Go to read-array mode */            printf("Werr2 0x%lx\n",stat);            return(-1);        }        Write_ff_to_base();             /* Go to read-array mode */    }#endifonemore:    for (;tot<cnt;tot+=4) {        bp4 = (uchar *)buf4;        *bp4++ = *src++;                /* Just in case src is not aligned... */        *bp4++ = *src++;        *bp4++ = *src++;        *bp4++ = *src++;        if (STRATA_TRACE)            printf("fwrite3:    0x%lx = %08lx\n", (ulong)dest,buf4[0]);        Write_40_to_(dest);             /* Flash program setup command */        Fwrite(dest,buf4);              /* Write the value */        WAIT_FOR_WSMS_READY();          /* Wait for WSMS ready */        stat = Read_0000();        if (stat & PSLBS) {             /* Check for error */            Write_50_to_base();         /* Clear status register */            Write_ff_to_base();         /* Go to read-array mode */            printf("Werr3 0x%lx\n",stat);            return(-1);        }        do {            Write_ff_to_base();             /* Go to read-array mode */        } WAIT_FOR_WRITE(dest,buf4);                dest += 4;     }    /* If cnt != bytecnt then bytecnt is not mod4, so one more write must be     * be done.  To do this, we must combine the source data with data that     * is already in the flash above the intended final address...     */    if (cnt != bytecnt) {        bp4 = (uchar *)buf4;        for(delta=0;cnt != bytecnt;delta++,cnt++)            *bp4++ = *src++;        for(;delta != 4;delta++)            *bp4++ = *(dest+delta);        src = (uchar *)buf4;        if (STRATA_TRACE)            printf("post-align: 0x%lx = %08lx\n",(ulong)dest,buf4[0]);        tot = cnt-1;        goto onemore;    }    return(ret);}/* EndFlashwrite(): * Function place holder to determine the "end" of the * Flashwrite() function. */voidEndFlashwriteStrata_8x32(){}/* 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. */intFlashewriteStrata_8x32(struct flashinfo *fdev,ftype *dest,ftype *src,                    int bytecnt){    int i;    ulong   add, stat;    void    (*reset)();    add = (ulong)(fdev->base);    /* For each sector, if it overlaps any of the destination space */    /* then erase that sector. */    for (i=0;i<fdev->sectorcnt;i++) {        if ((((uchar *)dest) > (fdev->sectors[i].end)) ||            (((uchar *)dest+bytecnt-1) < (fdev->sectors[i].begin))) {            add += fdev->sectors[i].size;            continue;        }        /* Sector erase sequence: */        Write_20_to_base();         /* setup */        Write_d0_to_(add);          /* confirm */        WAIT_FOR_WSMS_READY();      /* Wait for WSMS ready */        stat = Read_0000();        if (stat & ECLBS) {         /* Check for error */            Write_50_to_base();     /* Clear status register */            printf("Eerr 0x%lx\n",(ulong)stat);            Write_ff_to_base();     /* Go to read-array mode */            return(-1);        }        Write_ff_to_base();         /* Go to read-array mode */        WAIT_FOR_FF(add);           /* Wait for read == 0xff */        add += fdev->sectors[i].size;    }    for(i=0;i<bytecnt;i+=fdev->width) {        Write_40_to_(dest);             /* Flash program setup command */        Fwrite(dest,src);               /* Write the value */        WAIT_FOR_WSMS_READY();          /* Wait for WSMS ready */        stat = Read_0000();        if (stat & PSLBS) {             /* Check for error */            Write_50_to_base();         /* Clear status register */            Write_ff_to_base();         /* Go to read-array mode */            printf("Werr1 0x%lx\n",(ulong)stat);            return(-1);        }        do {            Write_ff_to_base();             /* Go to read-array mode */        } WAIT_FOR_WRITE(dest,src);             dest++; src++;     }    /* 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. */voidEndFlashewriteStrata_8x32(){}/* Flashtype(): * Use the ReadConfiguration command (90H) to read manufacturer code (0000) * and device id code (0001). */intFlashtypeStrata_8x32(struct flashinfo *fdev){    ulong   man, dev;    /* Start operation off by clearing the status register. */    Write_50_to_base();     /* Issue the read array command: */    Write_ff_to_base();    /* Issue the read configuration command: */    Write_90_to_base();    man = Read_0000();  /* manufacturer ID */    if (man == MANUFACTURER_INTEL) {        dev = Read_0001();  /* device ID */        if (STRATA_TRACE)            printf("Strata man-id/dev-id: 0x%lx 0x%lx\n",man,dev);    }    else {        dev = 0xDEADBEEF;    }    if (fdev)        fdev->id = dev;    /* Issue the read array command: */    Write_ff_to_base();    return((int)dev);}/* EndFlashtype(): * Function place holder to determine the "end" of the * Flashtype() function. */voidEndFlashtypeStrata_8x32(){}#endif

⌨️ 快捷键说明

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