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 + -
显示快捷键?