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

📄 flash.c

📁 完整的Bell实验室的嵌入式文件系统TFS
💻 C
📖 第 1 页 / 共 2 页
字号:
/* flashcom.c: *  This file contains the portions of the flash code that are device *  independent.  Refer to the appropriate device sub-directory for the *  code that is specific to the flash device on the target. * *  General notice: *  This code is part of a boot-monitor package developed as a generic base *  platform for embedded system designs.  As such, it is likely to be *  distributed to various projects beyond the control of the original *  author.  Please notify the author of any enhancements made or bugs found *  so that all may benefit from the changes.  In addition, notification back *  to the author will allow the new user to pick up changes that may have *  been made by other users after this version of the code was distributed. * *  Note1: the majority of this code was edited with 4-space tabs. *  Note2: as more and more contributions are accepted, the term "author" *         is becoming a mis-representation of credit. * *  Original author:    Ed Sutter *  Email:              esutter@lucent.com *  Phone:              908-582-2351 */#include "config.h"#if INCLUDE_FLASH#include "cpu.h"#include "flashdev.h"#include "flash.h"#include "genlib.h"#include "ctype.h"#include "stddefs.h"#include "tfs.h"#include "cli.h"extern struct flashdesc FlashNamId[];int     FlashCurrentBank;int     sectortoaddr(int,int *,uchar **);#define SRANGE_ERROR    -1#define SRANGE_SINGLE   1#define SRANGE_RANGE    2#define SRANGE_ALL      3    /* FlashProtectWindow: *  Must be set to allow any flash operation to be done on space assumed *  to be software protected. */int FlashProtectWindow;/* FlashBank[]: *  This table contains all of the information that is needed to keep the *  flash code somewhat generic across multiple flash devices. */struct  flashinfo FlashBank[FLASHBANKS];#ifdef DISABLE_INTERRUPTS_DURING_FLASHOPS#define FLASH_INTSOFF()             intsoff()#define FLASH_INTSRESTORE(ival)     intsrestore(ival)#else#define FLASH_INTSOFF()             0#define FLASH_INTSRESTORE(ival)#endif/* showflashtype(): *  Find a match between the incoming id and an entry in the FlashNamId[] *  table.  The FlashNamId[] table is part of the device-specific code. */intshowflashtype(ulong id){    struct flashdesc *fdp;    fdp = FlashNamId;    while(fdp->desc) {        if (id == fdp->id) {            printf("Device = %s\n",fdp->desc);            return(0);        }        fdp++;    }    printf("Flash id 0x%lx not recognized\n",id);    return(-1);}/* flasherased(): * Return 1 if range of memory is all 0xff; else 0. * Scan through the range of memor specified by begin-end (inclusive) * looking for anything that is not 0xff.  Do this in three sections so * that the pointers can be 4-byte aligned for the bulk of the comparison * range... * The beginning steps through as a char pointer until aligned on a 4-byte * boundary.  Then do ulong * comparisons until the just before the end * where we once again use char pointers to align on the last few * non-aligned bytes (if any). */intflasherased(uchar *begin, uchar *end){    ulong *lp, *lp1;    /* Get pointers aligned so that we can do the bulk of the comparison     * with long pointers...     */    while(((long)begin & 3) && (begin != end)) {        if (*begin != 0xff) {            return(0);        }        begin++;    }    if (begin >= end)        return(1);    lp = (ulong *)begin;    lp1 = (ulong *)end;    (long)lp1 &= ~3;    while(lp < lp1) {        if (*lp != 0xffffffff) {            return(0);        }        lp++;    }    if (lp >= (ulong *)end)        return(1);        begin = (uchar *)lp;    do {        if (*begin++ != 0xff)            return(0);    } while(begin != end);    return(1);}/* showflashinfo(): * Dump information about specified flash device. */intshowflashinfo(struct flashinfo *fdev, char *range){    int i;    struct  sectorinfo *sp;    if (showflashtype(fdev->id) < 0)        return(-1);    printf("  Base addr   : 0x%08lx\n",(ulong)(fdev->base));    printf("  Sectors     : %d\n",fdev->sectorcnt);    printf("  Bank width  : %d\n",fdev->width);    printf("  Sector     Begin       End        Size     SWProt?  Erased?\n");    for(i=0;i<fdev->sectorcnt;i++) {        sp = &fdev->sectors[i];        if (inRange(range,sp->snum)) {            printf("    %2d    0x%08lx  0x%08lx  0x%06lx    %s       %s\n",                sp->snum, (ulong)(sp->begin), (ulong)(sp->end), sp->size,                sp->protected ? "yes" : " no",                flasherased(sp->begin,sp->end) ? "yes" : "no");        }    }    return(0);}/* flashopload(): *  Copy flash operation to ram space.   *  Note that this function assumes that cache is disabled at this point. *  This is important because we are copying text into bss space and if *  cache was on, there could be a coherency problem. */intflashopload(ulong *begin,ulong *end,ulong *copy,int size){    volatile ulong  *bp;    int ret;    /* Verify space availability: */    if (((int)end - (int)begin) >= size) {        printf("flashopload overflow ((0x%lx-0x%lx) > 0x%x)\n",            (ulong)end,(ulong)begin,size);        return(-1);    }    ret = 0;    /* Copy function() to RAM, then verify: */    bp = begin;    while(bp <= end) {        *copy = *bp;        if (*copy++ != *bp++) {            printf("flashopload failed\n");            ret = -1;            break;        }    }    return(ret);}/* flashtype(): *  Use the device-specific function pointer to call the routine *  relocated to RAM space. */intflashtype(fdev)struct flashinfo *fdev;{    return(fdev->fltype(fdev));}/* flasherase(): *  Use the device-specific function pointer to call the routine *  relocated to RAM space. *  Note that flasherase() is called with a sector number.  The sector *  number is relative to the entire system, not just the particular device. *  This means that if there is more than one flash device in the system that *  the actual sector number (relative to the device) may not be the same *  value.  This adjustment is made here so that the underlying code that is *  pumped into ram for execution does not have to be aware of this. */intflasherase(fdev,snum)struct  flashinfo *fdev;int snum;{    int size;    unsigned char *base, *end;    if (fdev->id == FLASHRAM) {        if (snum == ALL_SECTORS) {            size = fdev->end - fdev->base;            base = fdev->base;        }        else {            sectortoaddr(snum,&size,&base);        }        end = base+size;        while(base < end) {            *base = 0xff;            if (*base++ != 0xff)                return(-1);        }        return(0);    }    if ((snum != ALL_SECTORS) && (fdev->sectors[0].snum != 0)) {/*      printf("Adjusting snum from %d to",snum); */        snum -= fdev->sectors[0].snum;/*      printf(" %d.\n",snum); */    }    return(fdev->flerase(fdev,snum));}/* flashwrite(): *  Use the device-specific function pointer to call the routine *  relocated to RAM space. *  First make a few checks on the request, then write to flash if all *  checks succeed. */intflashwrite(struct flashinfo *fdev,uchar *dest,uchar *src,long bytecnt){    int j, lowsector, highsector;    register uchar  *dp, *sp, *edp;    if (fdev->id == FLASHRAM) {        uchar *sp, *dp, *end;        sp = src;        dp = dest;        end = dp+bytecnt;        while(dp < end) {            *dp = *sp;            if (*dp != *sp)                return(-1);            dp++; sp++;        }        return(0);    }    dp = dest;    sp = src;    edp = (dest + bytecnt) - 1;    /* If outside the devices space, return failed.. */    if ((edp < fdev->sectors[0].begin) ||        (dp > fdev->sectors[fdev->sectorcnt-1].end)) {        printf("flashwrite() failed: dest out of flash range\n");        return(-1);    }    /* Make sure the destination is not within a protected sector */    if (FlashProtectWindow == FLASH_PROTECT_WINDOW_CLOSED) {        /* First determine the sectors that overlap with the         * flash space to be written...         */        lowsector = highsector = -1;        for(j=0;j<fdev->sectorcnt;j++) {            if ((dp >= fdev->sectors[j].begin) &&                (dp <= fdev->sectors[j].end))                lowsector = j;        }        for(j=0;j<fdev->sectorcnt;j++) {            if ((edp >= fdev->sectors[j].begin) &&                (edp <= fdev->sectors[j].end))                highsector = j;        }        if ((lowsector == -1) || (highsector == -1)) {            printf("flashwrite() failed: can't find sector\n");            return(-1);        }        /* Now that the range of affected sectors is known,         * verify that those sectors are not protected...         */        for(j=lowsector;j<=highsector;j++) {            if (fdev->sectors[j].protected) {                printf("flashwrite() failed: sector protected\n");                return(-1);            }        }    }    /* Now make sure that there is no attempt to transition a bit     * in the affected range from 0 to 1...  A flash write can only     * bring bits low (erase brings them  high).     */    while(dp < edp) {        if ((*dp & *sp) != *sp) {            printf("flashwrite() failed: bit 0->1 rqst denied.\n");            return(-1);        }        dp++;         sp++;    }    return(fdev->flwrite(fdev,dest,src,bytecnt));}/* flashewrite(): *  Use the device-specific function pointer to call the routine *  relocated to RAM space. */intflashewrite(struct flashinfo *fdev,uchar *dest,uchar *src,long bytecnt){    int i;    /* Source and destination addresses must be long-aligned. */    if (((int)src & 3) || ((int)dest & 3))        return(-1);    /* If the protection window is closed, then verify that no protected     * sectors will be written over...     */    if (FlashProtectWindow == FLASH_PROTECT_WINDOW_CLOSED) {        for (i=0;i<fdev->sectorcnt;i++) {            if((((uchar *)dest) > (fdev->sectors[i].end)) ||                (((uchar *)dest+bytecnt) < (fdev->sectors[i].begin)))                continue;            else                if (fdev->sectors[i].protected)                    return(-1);        }    }    return(fdev->flewrite(fdev,dest,src,bytecnt));}/* addrtosector(): *  Incoming address is translated to sector number, size of sector *  and base of sector. *  Return 0 if successful; else -1. */intaddrtosector(uchar *addr,int *sector,int *size,uchar **base){    struct flashinfo *fbnk;    struct  sectorinfo *sinfo;    int     dev, sec, i;    sec = 0;    for(dev=0;dev<FLASHBANKS;dev++) {        fbnk = &FlashBank[dev];        for(i=0;i<fbnk->sectorcnt;i++,sec++) {            sinfo = &fbnk->sectors[i];            if ((addr >= sinfo->begin) && (addr <= sinfo->end)) {                if (sector) {                    *sector = sec;                }                if (base) {                    *base = sinfo->begin;                }                if (size) {                    *size = sinfo->size;                }                return(0);            }        }    }    printf("addrtosector(0x%lx) failed\n",(ulong)addr);    return(-1);}/* addrtobank(): *  From the incoming address, return a pointer to the flash bank that *  this address is within. */struct flashinfo *addrtobank(uchar *addr){    struct flashinfo *fbnk;    int     dev;    for(dev=0;dev<FLASHBANKS;dev++) {        fbnk = &FlashBank[dev];        if ((addr >= fbnk->base) && (addr <= fbnk->end))            return(fbnk);    }    printf("addrtobank(0x%lx) failed\n",(ulong)addr);    return(0);}int

⌨️ 快捷键说明

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