[U-Boot] [RFC] command/cache: Add flush_cache command

Jim Chargin
2013-04-03T14:02:15Z

I apologize for being so late with this question.

York Sun <yorksun <at> freescale.com> writes:

>
> When we need the copied code/data in the main memory, we can flush the
> cache now. It uses the existing function flush_cache. Syntax is
>
> flush_cache <addr> <size>
>
> The addr and size are given in hexadecimal. Like memory command, there is
> no sanity check for the parameters.
>

Are there symptoms for a specific system failure you can provide?

My problem is that when a stand alone application, which is copied from NOR
flash to DDR, is started with the "go" command, it sometimes experiences a
program check (illegal instruction) after a block of 32 zero bytes "appears" in
memory.

I'm using a U-Boot for a custom Freescale P1022-based board, currently based on
the old 2010.12 U-Boot as patched by Freescale in their
SDK_V1_0_20110429_ltib.iso. Unfortunately, upgrading to a more recent version of
U-Boot is not possible at this time, no more recent version is available from
Freescale and I don't have the resources to verify all their patches apply
correctly to a release directly from DENX.

I've used Codewarrior to observe the block of zeros in memory once the program
check has happened, and I've verified that before the stand alone application
begins execution, there are no zeros. Figuring it is likely that I have an error
in my stand alone application code that corrupts the stack or writes based on an
un-initialized pointer, I've tried using the CW watchpoint to catch where the
zeros are written, but enabling the watchpoint seems to avoid the problem.

Based on later discussion on this thread, I've tried adding "flush_dcache();
invalidate_icache();" to cmd_boot.c:do_go(), just before control is passed to
the stand alone app. Based on my ad hoc testing with this change, I don't get
the program check exception.

I believe this result helps make the case that caching behavior is at the root
of my problem, but since I was not able to isolate the actual cause of that
problem, I can't be sure I've really got the solution.

(By the way, I would not leave the "flush_dcache(); invalidate_icache();" in
do_go(), I merely found that for demonstrating a possible solution, this change
easier than switching to a stand alone app that starts with bootm, or similar)

Any help or comments are very welcome.

Thanks,
Jim

> Signed-off-by: York Sun <yorksun <at> freescale.com>
> ---
> common/cmd_cache.c | 30 ++++++++++++++++++++++++++++++
> 1 file changed, 30 insertions(+)
>
> diff --git a/common/cmd_cache.c b/common/cmd_cache.c
> index 5512f92..93b7337 100644
> --- a/common/cmd_cache.c
> +++ b/common/cmd_cache.c
> @@ -94,6 +94,29 @@ int do_dcache(cmd_tbl_t *cmdtp, int flag, int argc, char *
const argv[])
> return 0;
> }
>
> +void __weak flush_cache(ulong addr, ulong size)
> +{
> + puts("No arch specific flush_cache available!\n");
> + /* please define arch specific flush_cache */
> +}
> +
> +int do_flush_cache(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
> +{
> + ulong addr, size;
> +
> + switch (argc) {
> + case 3:
> + addr = simple_strtoul(argv[1], NULL, 16);
> + size = simple_strtoul(argv[2], NULL, 16);
> + flush_cache(addr, size);
> + break;
> + default:
> + return cmd_usage(cmdtp);
> + }
> + return 0;
> +
> +}
> +
> static int parse_argv(const char *s)
> {
> if (strcmp(s, "flush") == 0)
> @@ -120,3 +143,10 @@ U_BOOT_CMD(
> "[on, off, flush]\n"
> " - enable, disable, or flush data (writethrough) cache"
> );
> +
> +U_BOOT_CMD(
> + flush_cache, 3, 0, do_flush_cache,
> + "flush cache for a range",
> + "<addr> <size>\n"
> + " - flush cache for specificed range"
> +);