📄 flash.c
字号:
#if !defined (BOOT_ROM) || !defined (NO_CONFIGINFO_FLASH) /* ** Can only read chip information when writing is permitted. */ flash_display_chip_info (i);#endif } /* ** Filing system information */ printf ("Flash start offset: 0x%08x\n", FLASH_START_OFFSET); printf ("Space for all FLASHFS partitions: 0x%08x\n", TOTAL_FLASH_SIZE - FLASH_START_OFFSET);#if defined (NUM_FIXED_FLASH_DEVICES) && (NUM_FIXED_FLASH_DEVICES > 0) printf ("Emergency flash size: 0x%08x\n", flash_total_size (NUM_FLASH_DEVICES - NUM_FIXED_FLASH_DEVICES) - FLASH_START_OFFSET);#elif defined (EMERGENCY_FLASHFS_SIZE) && (EMERGENCY_FLASHFS_SIZE > 0) printf ("Emergency flash size: 0x%08x\n", EMERGENCY_FLASHFS_SIZE);#endif}/*** A large amount of the following code is #ifdef'd out for BOOT ROMs which** don't require the ability to write to FLASH.*/#if !defined (BOOT_ROM) || !defined (NO_CONFIGINFO_FLASH)/*** Name: flash_display_chip_info**** Purpose: Display information about the specified chip.**** Arguments:** device 0 ... (NUM_FLASH_DEVICES - 1): chip to be identified.**** Result:** <Nothing>***/void flash_display_chip_info(U32 chip){ U32 protectMask; U32 id; U32 index = read_chip_id_info (chip, &id, &protectMask); assert (initialised); printf ("Chip %d ID is %x: (%s %s %ldk bytes), %slocked (%x)%s\n", chip, id, flashTypes [index].manufacturer, flashTypes [index].partname, flashTypes [index].size / 1024UL, (protectMask == 0) ? "un" : "" , protectMask, (flashTypes [index].size != flashDevices [chip].size) ? " MISCONFIGURED SIZE" : "" );}int flash_sector_bounds (U32 address, U32 *start, U32 *end){ int rc; assert (initialised); assert (NULL != start); assert (NULL != end); /* ** Must know the chip types to determine sector limits. */ if (!flashChipsChecked) { rc = flash_identify_chips (); } else if (flashChipsBad) { rc = EIO; } else { rc = ESUCCESS; } if (ESUCCESS == rc) { U32 device = FLASH_DEVICE(address); U32 offset = address - flashDevices [device].logicalBase; assert (device < NUM_FLASH_DEVICES); assert (actualFlashTypes [device].typeIndex != NUMBER_FLASH_TYPES); /* ** Look through chip definition to find where the sector falls. */ offset = flash_find_sector_size (actualFlashTypes [device].typeIndex, offset, start); *start += flashDevices [device].logicalBase; *end = *start + (offset - 1); } return rc;}/*** Name: flash_ready_for_update**** Purpose: Determine if the flash system can handle writes.**** If it can't this is either because the system wasn't compiled as such or** because there is no memory for a sector cache buffer**** Arguments:** <None>**** Result:** ESUCCESS Flash system can handle writes** <>ESUCCESS Other failure***/int flash_ready_for_update (void){ int rc; if (NULL == flashSectorCopy) { rc = ENOMEM; } else { rc = ESUCCESS; } return rc;}/* the address is a logical flash one, *not* a flash filing system address. */inline static BYTE flash_write_byte(BYTE data, U32 addr){ U32 device = FLASH_DEVICE(addr); U32 offset = addr - flashDevices [device].logicalBase; assert(device < NUM_FLASH_DEVICES); addr = offset * STRIDE; /* use macro, allows for StrongArm platform (or not) */ SELECT_FLASH_DEVICE (device); FLASH_WRITE_RAW(data, addr, device); return data;} /* the address is a logical flash one, *not* a flash filing system address. */inline static U16 flash_write_16(U16 data, U32 addr){ U32 device = FLASH_DEVICE(addr);#if 0 U32 offset = addr - flashDevices [device].logicalBase; assert(device < NUM_FLASH_DEVICES); addr = offset * STRIDE; /* use macro, allows for StrongArm platform (or not) */ SELECT_FLASH_DEVICE (device);#endif /* Since the 'base' is used to determine which flash device to communicate * with, it must be removed from the address when the address is passed * into FLASH_WRITE_RAW16. FLASH_WRITE_RAW16 uses the device to get the * real address of the flash part; this will already include the 'base' * in the case * of accessing any flash devices other that the first device. * The base addresses of the flash devices must be defined in * ascending order in the hardware file starting with FLASH0. */ if (device > 0) addr = addr - flashDevices [device].logicalBase; FLASH_WRITE_RAW16(data, addr, device); return data;} /*** Name: flash_write_data**** Purpose: Write data into flash device(s)**** This function is logically equivalent to 'fwrite'. It hides all the detail** involved in programming the FLASH devices from the calling function. No ** restrictions are placed on the calling function due to the architecture of** the FLASH devices (i.e. sector size) but the fastest operation will result** from calling this function in a rising address manner so that sector copies** and programs are minimised, the update code is designed to do this.** Due to the way a RAM sector copy is used, once all writes have been 'done'** the 'program_sector' function should be called to program the RAM sector into** FLASH if this has not already been done.**** Arguments:** ps Pointer to source data** d Desination address (FLASH address)** n Number of bytes to program**** Result:** rc ESUCCESS of OK, else errno***/int flash_write_data(BYTE *src, U32 dst, U32 num){ int rc = ESUCCESS; /* sanity check assert before we proceed */ assert((dst + num) <= TOTAL_FLASH_SIZE); TRACE4("%C: program src %6x dst %6x len %6d\n", (int)src, dst, num); /* if we don't know what type of chips we have yet, we should ... */ if (!flashChipsChecked) { /* check chips, keep result. */ if ((rc = check_flash_chips_writable()) != ESUCCESS) { /* if bad, return fault */ return rc; } } /* loop round programming bytes, sectors etc. until all done or ERROR */ while ((num != 0) && (rc == ESUCCESS)) { /* have we a current sector ? -1 is used as a 'NULL' as 0 is legit. */ if (currentSector == (U32) ~0) { /* at this point we have no sector so start a new one */ rc = overwrite_flash_bytes (&src, &dst, &num); if ((ESUCCESS == rc) && (num > 0)) { set_new_sector(dst); } } else { /* Is the address within the sector. */ if ((dst >= currentSector) && (dst < (currentSector + currentSectorSize))) { /* modify sector we have in ram. This might involve a sector write. */ rc = modify_sector(&src, &dst, &num); } else { /* address not in sector, write current sector, loop again for next */ rc = program_sector(); } /* we have a current sector */ } } /* programming loop */ /* result */ return rc; } /* flash_write_fs_data */static U32 read_chip_id_info16(U32 device, U32 *pid, U32 *protectMask){ BOOL notFound = TRUE; U32 j = 0; BITS id = 0; U32 base = flashDevices [device].logicalBase; /* WARNING: for this to work reliably (on certain ATMEL chips at least), it */ /* appears to be important to do the whole read id operation */ /* atomically, otherwise the device can be left in the */ /* identification mode until the power is cycled. */ BITS crit = atmos_startfiqcritical(); assert (initialised); assert (flashDevices[device].Is16);#ifndef SIMULATOR /* Enter product id mode */ flash_write_16(0xaaaa, base + (0x5555 << 1)); flash_write_16(0x5555, base + (0x2aaa << 1)); flash_write_16(0x9090, base + (0x5555 << 1)); timer_us_wait(10000); /* Spin for 10ms, don't want to be interrupted */#else /* !SIMULATOR */ simulator_flash_change_mode(device, id_mode);#endif /* !SIMULATOR */ /* manufacturer & device type, then lower and upper boot blocks locks. */ id = flash_read_16(base) << 8 | flash_read_16(base + 2); *pid = id; /* ** Try and match id against known devices */ while (notFound && (j < NUMBER_FLASH_TYPES)) { if ((id) == flashTypes [j].id) { notFound = FALSE; } else { j++; } } /* ** If not found set return code */ if (notFound) { id = UNKNOWN_CHIP_ID; j = NUMBER_FLASH_TYPES; } *protectMask = 0; #ifndef SIMULATOR /* ** Protection depends upon chip type. */ switch (id) { case AT29C1024_CHIP_ID: break; default: printf("Not found\n"); break; } /* Exit from product identification mode (return to normal operation) */ flash_write_16(0xaaaa, base + (0x5555 << 1)); flash_write_16(0x5555, base + (0x2aaa << 1)); flash_write_16(0xf0f0, base + (0x5555 << 1)); timer_us_wait(10000); /* Spin for 10ms, don't want to be interrupted */#else /* SIMULATOR */ simulator_flash_change_mode(device, read_mode);#endif /* !SIMULATOR */ atmos_endfiqcritical(crit); TRACE3("%C: device %d ID read: %04x protection: %0x %slocked\n", device, id, *protectMask, (*protectMask != 0) ? "" : "un"); return j;} /* read_chip_id_info16 */static U32 read_chip_id_info8(U32 device, U32 *pid, U32 *protectMask){ U32 width = 1; /* 1 = 8, 2 = 16 bits */ BOOL notFound = TRUE; U32 j = 0; BITS id = 0; U32 base = flashDevices [device].logicalBase; /* WARNING: for this to work reliably (on AT29C040A chips at least), it */ /* appears to be important to do the whole read id operation */ /* atomically, otherwise the device can be left in the */ /* identification mode until the power is cycled. */ BITS crit = atmos_startfiqcritical(); assert (initialised); do {#ifndef SIMULATOR /* Device unlock (ATMEL or AMD): note implication that devices > ~32k long */ flash_write_byte(0xaa, 0x5555 * width + base); flash_write_byte(0x55, 0x2aaa * width + base + width - 1); flash_write_byte(0x90, 0x5555 * width + base); timer_us_wait(10000); /* Spin for 10ms, don't want to be interrupted */#else /* !SIMULATOR */ simulator_flash_change_mode(device, id_mode);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -