[ECOS] Flash infrastructure rework
Fri Aug 20 14:44:00 GMT 2004
>>>>> "Andrew" == Andrew Lunn <firstname.lastname@example.org> writes:
>> I believe it is very important we sort out the interrupt issue.
Andrew> You are braver than i am. I decided this was too thorny an
Andrew> issue to tackle and just documented the problem. It is
Andrew> only a problem when the application or RedBoot is running
Andrew> from ROM. Currently interrupt disabling is left to the
Andrew> application programmer do use if needed.
I believe it is a much bigger problem than that. Any scenario
involving ROM RedBoot and a RAM application can be affected. The
application may make a virtual vector call into RedBoot, e.g. a
printf(). Or exceptions or incoming gdb events may drop you into gdb
stubs inside RedBoot. Or concurrent read and write operations in a
flash-based file system - although I am not sure how jffs2 handles
that at the moment. The application may also be manipulating the flash
directly in various ways.
Unless you know exactly what is going on in the application,
interrupts should be disabled before performing a low-level flash op.
Otherwise you end up with code that only works most of the time. I
believe by default this should be handled by eCos, not left to the
>> Disabling interrupts at a high level while erasing or writing
>> multiple blocks will affect real-time responsiveness, and
>> should be unnecessary. Instead that sort of thing should be
>> handled by the device drivers at a finer grain, to the extent
>> permitted by the hardware.
Andrew> Agreed. As a general approach, what i would like to do is
Andrew> get a generic CFI driver working which has all these bells
Andrew> and whistles and uses the new driver API. Since many flash
Andrew> devices nowadays are CFI compatible, i think it makes
Andrew> sense to do this rather than look at the AMD generic
Andrew> driver, the Intel Generic Driver, the SST generic driver
I am not sure we can drop the existing AMD driver, there are an awful
lot of board ports which use it. However any work done sorting out the
interrupt/cache issues in one driver should carry across fairly easily
to other drivers.
Also, the AMD driver may have size advantages because you don't need
the code that does the hardware querying. And it may be easier to
specify which bootblocks should be used for fis and fconfig if you
know exactly which chip(s) may be used, rather than figuring it out at
>> If we are going to move interrupt handling down into the
>> drivers then we'll also have to move any cache manipulation
>> there. The alternative would be e.g. a potential context switch
>> while the caches are disabled, and then the system is messed
Andrew> Why is it messed up? The current macros don't just disable
Andrew> it, they flush and invalidate it first. So a context
Andrew> switch is safe. The higher priority threads which gets to
Andrew> run will run slower since it does not have any caching,
Andrew> but thats how it currently works anyway. The only read
Andrew> danger is if something else unconditional re-enables the
Andrew> cache and then we are dead when the flash driver gets
Andrew> control again.
Running with caches disabled can easily cost you an order of magnitude
in performance. Suppose your application has a highish priority
thread, regularly woken up by an interrupt, which consumes about 50%
of the available cpu time for its processing. In a lower-priority
thread you do a write to a jffs2 logfile. The flash write starts, the
cache is disabled, an interrupt happens and wakes up the higher
priority thread, it tries to do its processing but will do so much
more slowly than before and can no longer keep up with the incoming
interrupts, and the lower-priority thread doing the flash write never
wakes up again to re-enable the cache. The system is messed up.
The only safe way to handle the cache is to disable interrupts,
manipulate the cache as required, do the appropriate things to the
hardware, restore the cache, and re-enable interrupts. Allowing
interrupts or context switches while the cache is disabled is unsafe.
>> cyg_flash_get_block_info() and cyg_flash_get_limits(): I think
>> we should just get rid of these completely. Full information on
>> the flash is available by other calls, and higher-level code
>> such as RedBoot should be made to use these.
Andrew> I thought about that and changing redoot to use the other
Andrew> calls is something that is needed when making redboot use
Andrew> bootblocks. Removing these calls just makes it harder for
Andrew> people porting there own applications to the new api.
I don't think that is a big deal, the functions would remain in the
legacy API. Since we are introducing a new API we should make it as
clean as possible.
>> cyg_flash_code_overlaps(): I am not sure this can be cleanly
>> defined. For example, consider a platform with one flash chip
>> that uses bottom boot blocks. If we want to make efficient use
>> of this chip then we want to place the fis and fconfig data in
>> these boot blocks. Hence the first boot block will contain some
>> startup code followed by a jump to later in the flash, then
>> we'll have the fis and fconfig blocks, and then the rest of the
>> code. How would cyg_flash_code_overlaps() work with that
Andrew> The HAL needs to be able to implement it. That is the only
Andrew> thing that knows what goes where. I didn't really like
Andrew> this function to start with, but redboot uses it quite a
Andrew> lot for user input sanity checking. We could remove it and
Andrew> hope the user knows what (s)he is doing.
HAL checks may not suffice if the application makes virtual vector
calls. RedBoot could get much the same functionality by detecting
CYG_HAL_STARTUP_ROM and looking for an overlap with its own fis entry,
without needing a dubious flash_code_overlaps() function. That won't
work 100% on all platforms, e.g. there may be startup types other than
ROM which also have RedBoot resident in flash, but it will work on
>> cyg_flash_lock() and cyg_flash_unlock(): possibly this
>> functionality should be provided by a more generic
>> cyg_flash_ioctl() function. That would also give us a way of
>> supporting device-specific flash operations in future. Usually
>> I don't like general-purpose ioctl() routines because they
>> cannot easily be garbage collected by the linker, but in this
>> case it may be worthwhile.
Andrew> The generally semantic of ioctl is that you have to open
Andrew> the device first, ie the unix file model. The flash API is
Andrew> not file based so i don't really think ioctl fits. Im also
Andrew> not sure what extensions could be added except for NAND
Andrew> devices where you need to add access to the OOB area. Gary
Andrew> is working on this at the moment i think. It would be
Andrew> interesting to know how he decided to do it.
I was thinking of a function cyg_flash_ioctl(const cyg_flashaddr_t, ...),
rather than something involving file descriptors. Of course if you use
open/read/write on a flash block device then ioctl() would be readily
mapped onto cyg_flash_ioctl().
Another possible extension that springs to mind is entering/leaving
power saving mode.
Bart Veer eCos Configuration Architect
http://www.ecoscentric.com/ The eCos and RedBoot experts
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss
More information about the Ecos-discuss