flash_am29xxxxx.inl

来自「eCos操作系统源码」· INL 代码 · 共 589 行 · 第 1/2 页

INL
589
字号
    return ((((unsigned long)&_stext >= (unsigned long)start) &&             ((unsigned long)&_stext < (unsigned long)end)) ||            (((unsigned long)&_etext >= (unsigned long)start) &&             ((unsigned long)&_etext < (unsigned long)end)));}//----------------------------------------------------------------------------// Erase Blockintflash_erase_block(void* block, unsigned int size){    volatile flash_data_t* ROM, *BANK;    volatile flash_data_t* b_p = (flash_data_t*) block;    volatile flash_data_t *b_v;    volatile flash_data_t *f_s0, *f_s1, *f_s2;    int timeout = CYGNUM_FLASH_TIMEOUT_QUERY;    int len = 0;    int res = FLASH_ERR_OK;    flash_data_t state;    cyg_bool bootblock = false;    cyg_uint32 *bootblocks = (cyg_uint32 *)0;    CYG_ADDRWORD bank_offset;    ROM = (volatile flash_data_t*)((unsigned long)block & flash_dev_info->base_mask);    BANK = find_bank(ROM, block, &bank_offset);    f_s0 = FLASH_P2V(BANK);    f_s1 = FLASH_P2V(BANK + FLASH_Setup_Addr1);    f_s2 = FLASH_P2V(BANK + FLASH_Setup_Addr2);    // Assume not "boot" sector, full size    bootblock = false;    len = flash_dev_info->block_size;    // Is this in a "boot" sector?    if (flash_dev_info->bootblock) {        bootblocks = (cyg_uint32 *)&flash_dev_info->bootblocks[0];        while (*bootblocks != _LAST_BOOTBLOCK) {            if (*bootblocks++ == ((unsigned long)block - (unsigned long)ROM)) {                len = *bootblocks++;  // Size of first sub-block                bootblock = true;                break;            } else {                int ls = flash_dev_info->block_size;                // Skip over segment                while ((ls -= *bootblocks++) > 0) ;            }        }    }    while (size > 0) {#ifndef CYGHWR_FLASH_AM29XXXXX_NO_WRITE_PROTECT        // First check whether the block is protected        *f_s1 = FLASH_Setup_Code1;        *f_s2 = FLASH_Setup_Code2;        *f_s1 = FLASH_WP_State;        state = *FLASH_P2V(b_p+FLASH_WP_Addr);        *f_s0 = FLASH_Reset;        if (FLASH_unlocked != state)            return FLASH_ERR_PROTECT;#endif        b_v = FLASH_P2V(b_p);            // Send erase block command - six step sequence        *f_s1 = FLASH_Setup_Code1;        *f_s2 = FLASH_Setup_Code2;        *f_s1 = FLASH_Setup_Erase;        *f_s1 = FLASH_Setup_Code1;        *f_s2 = FLASH_Setup_Code2;        *b_v = FLASH_Block_Erase;        // Now poll for the completion of the sector erase timer (50us)        timeout = CYGNUM_FLASH_TIMEOUT_ERASE_TIMER;              // how many retries?        while (true) {            state = *b_v;            if ((state & FLASH_Sector_Erase_Timer)				== FLASH_Sector_Erase_Timer) break;            if (--timeout == 0) {                res = FLASH_ERR_DRV_TIMEOUT;                break;            }        }        // Then wait for erase completion.        if (FLASH_ERR_OK == res) {            timeout = CYGNUM_FLASH_TIMEOUT_ERASE_COMPLETE;            while (true) {                state = *b_v;                if (FLASH_BlankValue == state) {                    break;                }                // Don't check for FLASH_Err here since it will fail                // with devices in parallel because these may finish                // at different times.                if (--timeout == 0) {                    res = FLASH_ERR_DRV_TIMEOUT;                    break;                }            }        }        if (FLASH_ERR_OK != res)            *FLASH_P2V(ROM) = FLASH_Reset;        size -= len;  // This much has been erased        // Verify erase operation        while (len > 0) {            b_v = FLASH_P2V(b_p++);            if (*b_v != FLASH_BlankValue) {                // Only update return value if erase operation was OK                if (FLASH_ERR_OK == res) res = FLASH_ERR_DRV_VERIFY;                return res;            }            len -= sizeof(*b_p);        }        if (bootblock) {            len = *bootblocks++;        }    }    return res;}//----------------------------------------------------------------------------// Program Bufferintflash_program_buf(void* addr, void* data, int len){    volatile flash_data_t* ROM;    volatile flash_data_t* BANK;    volatile flash_data_t* SECT=NULL;    volatile flash_data_t* data_ptr = (volatile flash_data_t*) data;    volatile flash_data_t* addr_p = (flash_data_t*) addr;    volatile flash_data_t* addr_v = FLASH_P2V(addr_p);    volatile flash_data_t *f_s1, *f_s2;    CYG_ADDRWORD bank_offset;    int timeout;    int res = FLASH_ERR_OK;    const CYG_ADDRWORD mask  =        flash_dev_info->bufsiz * sizeof (flash_data_t) - 1;    unsigned long rem_sect_size;    // check the address is suitably aligned    if ((unsigned long)addr & (CYGNUM_FLASH_INTERLEAVE * CYGNUM_FLASH_WIDTH / 8 - 1))        return FLASH_ERR_INVALID;    // Base address of device(s) being programmed.    ROM = (volatile flash_data_t*)((unsigned long)addr_p & flash_dev_info->base_mask);    BANK = find_bank(ROM, addr, &bank_offset);    f_s1 = FLASH_P2V(BANK + FLASH_Setup_Addr1);    f_s2 = FLASH_P2V(BANK + FLASH_Setup_Addr2);    rem_sect_size = 0;    len /= sizeof (flash_data_t);    while (len > 0) {        flash_data_t state;        unsigned int nwords;        addr_v = FLASH_P2V(addr_p);        if (flash_dev_info->bufsiz > 1) {            // Assume buffer size is power of two            unsigned int i;                        if (rem_sect_size == 0) {                SECT = find_sector(addr_v, &rem_sect_size);                rem_sect_size /= sizeof (flash_data_t);            }            // Compute word count to write                            nwords = flash_dev_info->bufsiz                - (((CYG_ADDRWORD) addr_v & mask) / sizeof (flash_data_t));            if (nwords > len)                nwords = len;            // Initiate buffered write            *f_s1 = FLASH_Setup_Code1;            *f_s2 = FLASH_Setup_Code2;            *SECT = FLASH_Load_Buffer;            *SECT = FLASHWORD(nwords - 1);  // All devices need to see this            // Load data into write buffer, flush buffer            for(i = 0; i < nwords; i++)                *addr_v++ = *data_ptr++;            --addr_v; --data_ptr;            *SECT = FLASH_Flush_Buffer;            rem_sect_size -= nwords;        } else {            // Program data [byte] - 4 step sequence            *f_s1 = FLASH_Setup_Code1;            *f_s2 = FLASH_Setup_Code2;            *f_s1 = FLASH_Program;            *addr_v = *data_ptr;                        nwords = 1;        }        addr_p += nwords;        timeout = CYGNUM_FLASH_TIMEOUT_PROGRAM;        while (true) {            state = *addr_v;            if (*data_ptr == state) {                break;            }            // Can't check for FLASH_Err since it'll fail in parallel            // configurations.            if (--timeout == 0) {                res = FLASH_ERR_DRV_TIMEOUT;                break;            }        }        if (FLASH_ERR_OK != res)            *FLASH_P2V(ROM) = FLASH_Reset;        if (*addr_v != *data_ptr++) {            // Only update return value if erase operation was OK            if (FLASH_ERR_OK == res) res = FLASH_ERR_DRV_VERIFY;            break;        }        len -= nwords;    }    // Ideally, we'd want to return not only the failure code, but also    // the address/device that reported the error.    return res;}static volatile flash_data_t *find_bank(volatile flash_data_t * base, void * addr, CYG_ADDRWORD * bo){    volatile flash_data_t * res = base;    if (flash_dev_info->banked) {        int b = 0;        *bo = (unsigned long)addr & ~(flash_dev_info->block_size-1);        *bo -= (unsigned long) base;        for(;;) {            if (*bo >= flash_dev_info->banks[b]) {                res = (volatile flash_data_t*) ((unsigned long)base + flash_dev_info->banks[b]);                break;            }            b++;        }    }        return res;}static flash_data_t *find_sector(volatile flash_data_t * addr, unsigned long *remain_size){    const CYG_ADDRESS mask = flash_dev_info->block_size - 1;    const CYG_ADDRESS a = (CYG_ADDRESS) addr;    const CYG_ADDRESS base = a & flash_dev_info->base_mask;    CYG_ADDRESS res = a & ~mask;        *remain_size = flash_dev_info->block_size - (a & mask);    if (flash_dev_info->bootblock) {        cyg_uint32 * bootblocks = flash_dev_info->bootblocks;        while (*bootblocks != _LAST_BOOTBLOCK) {            int ls = flash_dev_info->block_size;            if (*bootblocks++ == (res - base)) {                while (res + *bootblocks < a) {                    res += *bootblocks++;                }            } else {                // Skip over segment                while ((ls -= *bootblocks++) > 0) ;            }        }        if (*bootblocks != _LAST_BOOTBLOCK)               *remain_size = *bootblocks - (a - res);    }        return (flash_data_t *) res;}#endif // CYGONCE_DEVS_FLASH_AMD_AM29XXXXX_INL

⌨️ 快捷键说明

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