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

📄 drv.c

📁 MMI层OBJ不能完全编译
💻 C
📖 第 1 页 / 共 5 页
字号:
    if (*dev.addr & 0x80) {
        ffsdrv_amd_erase_end();
        tlw(led_off(LED_ERASE_SUSPEND));
        return;
    }

    // NOTEME: As there is no way to be absolutely certain that erase
    // doesn't finish between last poll and the following erase suspend
    // command, we assume that the erase suspend is safe even though the
    // erase IS actually already finished.

    cpsr = int_disable();
    dev.state = DEV_ERASE_SUSPEND;
    *dev.addr = 0xB0;

    // Wait for erase suspend to finish
    while ((*dev.addr & 0x80) == 0)     /* Enabling the interrupt should be after this while, */
                                        /* because DQ7==1 on entering to erase suspend mode */
        ;

    int_enable(cpsr);
}

void ffsdrv_amd_erase_resume(void)
{
    uint32 cpsr;

    ttw(str(TTrDrvErase, "er" NL));

    // NOTEME: See note in erase_suspend()... We assume that the erase
    // resume is safe even though the erase IS actually already finished.
    cpsr = int_disable();
    dev.state = DEV_ERASE;
    *dev.addr = 0x30;
    int_enable(cpsr);

    tlw(led_off(LED_ERASE_SUSPEND));
}

#endif

/******************************************************************************
 * SST Dual/Multi Bank Driver Functions
 ******************************************************************************/

// SST flashes use almost same command set as AMD flashes. Only the command
// addresses (4 more bits) and erase command data (0x50 instead of 0x30) are
// different. SST flashes have no erase suspend/resume commands because they
// are so fast at erasing!

void ffsdrv_sst_write_end(void);
void ffsdrv_sst_erase_end(void);

void ffsdrv_sst_write(void *dst, const void *src, uint16 size)
{
    uint8 *mydst = dst;
    const uint8 *mysrc = src;

    if (size > 0)
    {
        if ((unsigned int) mydst & 1) {
            ffsdrv_write_byte(mydst++, *mysrc++);
            size--;
        }
        while (size >= 2) {
            ffsdrv_amd_write_halfword((uint16 *) mydst,
                                      mysrc[0] | (mysrc[1] << 8));
            size -= 2;
            mysrc += 2;
            mydst += 2;
        }
        if (size == 1)
            ffsdrv_write_byte(mydst++, *mysrc++);
    }
}

// Note that SST flashes have smaller sectors than other flash families.
// Fortunately they support erasure of several of these sectors in a logical
// unit called a "block".
void ffsdrv_sst_erase(uint8 block)
{
    uint16 *addr = (uint16 *) block2addr(block);
    ffsdrv.erase_sector(addr);
}

void ffsdrv_sst_erase_sector(void *dst)
{
    volatile char *flash = dev.base;
    uint32 cpsr;

    tlw(led_on(LED_ERASE));
    ttw(ttr(TTrDrvErase, "e(%d)" NL, dst));

    dev.addr = dst;

    cpsr = int_disable();
    dev.state = DEV_ERASE;
    flash[0xAAAA] = 0xAA; // unlock cycle 1
    flash[0x5555] = 0x55; // unlock cycle 2
    flash[0xAAAA] = 0x80;
    flash[0xAAAA] = 0xAA; // unlock cycle 1
    flash[0x5555] = 0x55; // unlock cycle 2
    *dev.addr = 0x50; // SST erase block command
    int_enable(cpsr);

    ffsdrv_sst_erase_end();
}

void ffsdrv_sst_erase_end(void)
{
    // Wait for erase end
    while ((*dev.addr & 0x80) == 0)
        ;

    dev.state = DEV_READ;

    tlw(led_off(LED_ERASE));
}

// Erase suspend/resume commands do not exist for SST flashes, so we just
// poll for the end of the erase operation...

void ffsdrv_sst_erase_suspend(void)
{
    ttw(str(TTrDrvErase, "es" NL));

    ffsdrv_sst_erase_end();
}


/******************************************************************************
 * Intel Single Bank Driver Functions
 ******************************************************************************/
#ifdef INTEL_FLASH
#if (TARGET == 1)

// Forward declaration of functions in file intelsbdrv.c
int  ffsdrv_ram_intel_sb_init(void);
void ffsdrv_ram_intel_sb_write_halfword(volatile uint16 *addr, uint16 value);
void ffsdrv_ram_intel_sb_erase(uint8 block);
void ffsdrv_ram_intel_sb_erase_sector(void *dst);
void ffsdrv_ram_intel_erase(uint8 block);
void ffsdrv_ram_intel_erase_sector(void *dst);

#else // (TARGET == 0)

// On PC these functions are empty
void ffsdrv_ram_intel_sb_write_halfword(volatile uint16 *addr, uint16 value) {}
void ffsdrv_ram_intel_sb_erase(uint8 block) {}
void ffsdrv_ram_intel_sb_erase_sector(void *dst) {}
void ffsdrv_ram_intel_erase(uint8 block) {}
void ffsdrv_ram_intel_erase_sector(void *dst);

#endif // (TARGET == 1)


/******************************************************************************
 * Intel Dual/Multi Bank Driver Functions
 ******************************************************************************/

void ffsdrv_intel_write_end(void);
void ffsdrv_intel_erase_end(void);

void ffsdrv_intel_init(void)
{
	volatile uint16	*flash = (volatile uint16*)dev.base;
	flash[0] = INTEL_READ_ARRAY;//reset intel flash status
	
}
// ffsdrv_intel_write_halfword and ffsdrv_intel_write_end is not used
// because of the bug in the intel flash device. Instead is the functions
// ffsdrv_ram_intel_sb_write_halfword and ffsdrv_ram_intel_erase used.
void ffsdrv_intel_write_halfword(volatile uint16 *addr, uint16 value)
{
    uint32 cpsr;

    tlw(led_on(LED_WRITE));
    ttw(ttr(TTrDrvWrite, "wh(%x,%x)" NL, addr, value));

    dev.addr = addr;
	
#if (FLASH_WRITE_CHECK == 1)
    if (~*addr & value) {
        ttw(ttr(TTrFatal, "wh(%x,%x->%x) fatal" NL, addr, *addr, value));
        return;
    }
#endif
    cpsr = int_disable();
    dev.state = DEV_WRITE;

#if (INTEL_UNLOCK_SLOW == 1)
    *addr = 0x60; // Intel Config setup
    *addr = 0xD0; // Intel Unlock block
    *addr = 0x50; // Intel Clear Status Register
#endif

    *addr = 0x40; // Intel program byte/word
    *addr = value;

    int_enable(cpsr);

    ffsdrv_intel_write_end();
}

// IMPORTANT: This function presupposes that the size not is above the flash
// write buffer size and the src is half word aligned.
void ffsdrv_intel_write_buffer_mode(volatile uint16 *addr, volatile uint16 *src,
                                    uint16 words2write)
{
    uint32 cpsr;
    uint16 i, status;

    ttw(ttr(TTrDrvWrite, "wbuf(%x, %x, %x)" NL, addr, src, words2write));

#if (FLASH_WRITE_CHECK == 1)
    // Make sure we don't try to flip a '0' to '1'.
    for (i = 0; i < words2write; i++) {
        if (~(int) addr[i] & (int) src[i]) {
            ttw(ttr(TTrFatal, "wbuf(%x,%x->%x) fatal" NL, addr, addr[i], src[i]));
            return;
        }
    }
#endif

    cpsr = int_disable(); // FIXME can we disable interrupt for all this time?
    dev.addr = addr;
    dev.state = DEV_WRITE;

    *dev.addr = INTEL_CLR_STATUS;
    *dev.addr = INTEL_LOCK_SETUP;
    *dev.addr = INTEL_UNLOCK_BLK;

    // Wait for buffer ready
    do {
        *dev.addr = INTEL_BUFFER_PRG;
        status = *dev.addr;
    } while (!(status & INTEL_STATE_MACHINE_DONE));

    // Write the word count - 1
    *dev.addr = words2write - 1;

    // Fill the write buffer
    while (words2write > 0) {
        *addr = *src;
        words2write--;
        addr++;
        src++;
    }

    // Start the write buffer process
    *dev.addr = INTEL_BUFFER_PRG_CONFIRM;
    *dev.addr = INTEL_READ_STATUS;

    int_enable(cpsr);
    ffsdrv_intel_write_end();
    // NOTEME Verify the write?
}

void ffsdrv_intel_write_end(void)
{
    uint32 cpsr;
    uint16 status;

    // We can be interrupted and reentered thus the state can have been changed.
    while (1) {
        if (dev.state == DEV_WRITE) {
            // write completed?
            if ((*dev.addr & INTEL_STATE_MACHINE_DONE) > 0)
                break; // write completed
            continue;
        }
        else if (dev.state == DEV_WRITE_SUSPEND)
            continue; // Wait until the write is resumed
        else if (dev.state == DEV_READ)
            break; // write completed in write_suspend() or a re-entered
                   // write_end()

        ttw(ttr(TTrFatal, "FATAL: invalid dev.state %d" NL, dev.state));
        return;
    }

    // The flash state and dev.state must be in sync thus the stat changes
    // must be protected from being interrupted
    cpsr = int_disable();

#if (FLASH_STATUS_CHECK == 1)
    *dev.addr = INTEL_READ_STATUS;
    status = *dev.addr;
    if (status != INTEL_STATE_MACHINE_DONE)
        ttw(ttr(TTrFatal, "FATAL write error 0x%x" NL, status));
#endif

    dev.state = DEV_READ;
    *dev.addr = INTEL_READ_ARRAY;
    int_enable(cpsr);

    tlw(led_off(LED_WRITE));
}

void ffsdrv_intel_write_suspend(void)
{
    uint32 cpsr;
    uint16 poll;

    ttw(str(TTrDrvWrite, "wrs" NL));

    // The flash state and dev.state must be in sync thus the stat changes
    // must be protected from being interrupted
    cpsr = int_disable();
    dev.state = DEV_WRITE_SUSPEND;

    *dev.addr = INTEL_SUSPEND;
    *dev.addr = INTEL_READ_STATUS;

    while (((poll = *dev.addr) & INTEL_STATE_MACHINE_DONE) == 0)
        ;

    if ((poll & INTEL_PROGRAM_SUSPEND) == 0) {
        // Write has completed
        dev.state = DEV_READ;
    }
    // The write is fin韘hed or suspended, prepare to read data from the flash
    *dev.addr = INTEL_READ_ARRAY;
    int_enable(cpsr);
}

void ffsdrv_intel_write_resume(void)
{
    uint32 cpsr;

    ttw(str(TTrDrvWrite, "wrr" NL));

    // The flash state and dev.state must be in sync thus the stat changes
    // must be protected from being interrupted
    cpsr = int_disable();
    dev.state = DEV_WRITE;
    *dev.addr = INTEL_RESUME;
    // FFS always expect that the flash is in READ status mode while the
    // dev.state is DEV_WRITE
    *dev.addr = INTEL_READ_STATUS;
    int_enable(cpsr);
}

void ffsdrv_intel_erase(uint8 block) 
{
    uint16 *addr = (uint16 *) block2addr(block);
    ffsdrv.erase_sector(addr);
}

void ffsdrv_intel_erase_sector(void *dst)
{
    uint32 cpsr;

    ttw(ttr(TTrDrvErase, "e(0x%x)" NL, dst));
    tlw(led_on(LED_ERASE));

    dev.addr = (uint16 *)dst;

    cpsr = int_disable();
    dev.state = DEV_ERASE;

#if (INTEL_UNLOCK_SLOW == 1)
    *dev.addr = INTEL_CLR_STATUS; // Intel clear status register (not really necessary)
    *dev.addr = INTEL_LOCK_SETUP; // Intel Config setup
    *dev.addr = INTEL_UNLOCK_BLK; // Intel Unlock block
#endif

    *dev.addr = INTEL_BLOCK_ERASE_SETUP; // Intel erase setup
    *dev.addr = INTEL_ERASE_CONFIRM; // Intel erase confirm

     *dev.addr = INTEL_READ_STATUS;//fangcj added
    int_enable(cpsr);

    ffsdrv_intel_erase_end();
}

void ffsdrv_intel_erase_end(void)
{
    uint16 status;
#if (BOARD == 46)
    while ((*dev.addr & 0x80) == 0 && dev.state == DEV_ERASE)
    ;
#else
    while ((*dev.addr & 0x80) == 0 &&
           (dev.state == DEV_ERASE || dev.state == DEV_ERASE_SUSPEND))
        ;
#endif

#if (FLASH_STATUS_CHECK == 1)
   *dev.addr = INTEL_READ_STATUS;
    status = *dev.addr;
    if (status != INTEL_STATE_MACHINE_DONE)
        ttw(ttr(TTrFatal, "FATAL erase error 0x%x" NL, status));
#endif


    *dev.addr = INTEL_READ_ARRAY; // Intel read array
    dev.state = DEV_READ;
    tlw(led_off(LED_ERASE));
}

void ffsdrv_intel_erase_suspend(void)
{
    uint32 cpsr;
    uint16 poll;

    ttw(str(TTrDrvErase, "es" NL));
    tlw(led_on(LED_ERASE_SUSPEND));

    cpsr = int_disable();
    dev.state = DEV_ERASE_SUSPEND;
    *dev.addr = 0xB0; // Intel Erase Suspend
    *dev.addr = 0x70; // Intel Read Status Register
    while (((poll = *dev.addr) & 0x80) == 0)
        ;

    if ((poll & 0x40) == 0) {
        // Block erase has completed
        tlw(led_off(LED_ERASE_SUSPEND));
        dev.state = DEV_READ;
        tlw(led_off(LED_ERASE));
    }
    *dev.addr = 0xFF; // Intel read array
    int_enable(cpsr);
}

void ffsdrv_intel_erase_resume(void)
{
    uint32 cpsr;

    ttw(str(TTrDrvErase, "er" NL));

    cpsr = int_disable();
    dev.state = DEV_ERASE;
    *dev.addr = 0xD0; // Intel erase resume

// The following "extra" Read Status command is required because Intel has
// changed the specification of the W30 flash! (See "1.8 Volt Intel?
// Wireless Flash Memory with 3 Volt I/O 28F6408W30, 28F640W30, 28F320W30
// Specification Update")
    *dev.addr = 0x70; // Intel Read Status Register

    int_enable(cpsr);

    tlw(led_off(LED_ERASE_SUSPEND));
}

// NOTE this function has a little better performance than the
// generic_write() because it use less function pointers
void ffsdrv_intel_write(void *dst, const void *src, uint16 size)
{
    uint8 *mydst = dst;
    const uint8 *mysrc = src;

    if (size > 0)
    {
        if ((unsigned int) mydst & 1) {
            ffsdrv_write_byte(mydst++, *mysrc++);
            size--;
        }
        while (size >= 2) {

⌨️ 快捷键说明

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