This is the mail archive of the ecos-patches@sourceware.org mailing list for the eCos project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug 1001561] Internal flash driver for Freescale TWR-K60N512 board


Please do not reply to this email. Use the web interface provided at:
http://bugs.ecos.sourceware.org/show_bug.cgi?id=1001561

--- Comment #48 from Jonathan Larmour <jifl@ecoscentric.com> 2012-09-26 15:41:56 BST ---
Hi Ilija,

Thanks for that. Unfortunately I've just noticed another issue (sorry!), but
it's an important one to be resolved. There are calls to HAL_DCACHE_DISABLE().
But if the dcache is in writeback mode, you need to flush any dirty cache lines
to memory, so a call to HAL_DCACHE_SYNC() is needed.

And, as you'll probably have seen elsewhere in eCos, because of the risk of an
interrupt coming in and creating more dirty cache lines after the sync but
before the disable, you also need to disable interrupts around it. And you also
need to allow for the cache already having been disabled (otherwise you may
flush lines to memory which aren't actually valid for what's running).

So in other words, you should have something like this:

static void __attribute__((__long_call__))
cache_off( cyg_uint32 *cachestate ) {
    cyg_uint32 intstate, dcachestate, icachestate;

    HAL_DISABLE_INTERRUPTS(intstate); 
    HAL_DCACHE_IS_ENABLED(dcachestate);
    HAL_ICACHE_IS_ENABLED(icachestate);
    *cachestate = (dcachestate?1:0) | (icachestate?2:0);
    if (dcachestate) {
        HAL_DCACHE_SYNC();
        HAL_DCACHE_DISABLE();
    }
    if (icachestate) {
        HAL_ICACHE_DISABLE();
    }
    HAL_RESTORE_INTERRUPTS(intstate);
#ifdef CYGNUM_DEVS_KINETIS_FLASH_LOGIC_ERROR_BUG
    disable_flash_optimisation();
#endif
}

You might also need a HAL_DCACHE_INVALIDATE_ALL() after the sync, before the
disable, depending on whether the kinetis cache will still look at cache lines
marked as valid in the cache, even when disabled (it may seem like it shouldn't
but some cache architectures do do that!). Ditto for the icache.

Given the separate cache_on/cache_off functions, you need the extra argument to
pass around the cache state instead.

To restore, for the Kinetis you probably don't need to disable interrupts I
think because IIRC it doesn't do anything which would be a problem on
interruption, so:

static void __attribute__((__long_call__))
cache_on( cyg_uint32 *cachestate ) {
#ifdef CYGNUM_DEVS_KINETIS_FLASH_LOGIC_ERROR_BUG
    enable_flash_optimisation();
#endif
    if (*cachestate & 1)
        HAL_DCACHE_ENABLE();
    if (*cachestate & 2)
        HAL_ICACHE_ENABLE();
}

Hopefully at least I've given enough code that this is an easy change for you
to try out (since I don't have hardware :-)).

Jifl

-- 
Configure bugmail: http://bugs.ecos.sourceware.org/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are on the CC list for the bug.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]