mcf5441x, instruction cache enable issue

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

mcf5441x, instruction cache enable issue

606 Views
angelo_d
Senior Contributor I

Dear all,

i am still in the process to have a new custom board with mcf54415 booting u-boot from sbf and spi - nor.

Actually, SBF works, some code is loaded to internal SRAM and then full u-boot is loaded in SRAM (DDR2) after proper DDR2 initialization.

Btw, when u-boot sets CONFIG_SYS_CACHE_ACR6 and finally CONFIG_SYS_CACHE_ICACR (so enable instruction cache from DDR2,) the system seems to hang.

Some info on the issue:

  • My u-boot board config.h i more or less the same of M54418TWR.h except some parts i don't need.
  • I am using an assembly square wave to see where the code stops
/******************************************************************************/

/* square 54415 */
#define PAR_BE          0xEC094049
#define PAR_FBCTL     0xEC094048
#define PODR_A          0xEC094000
#define PDDR_A          0xEC09400C

.globl __square
__square:
     move.l     #0xFC04002f, %a1
     move.b     #37, (%a1)

     move.l     #PAR_BE, %a0
     move.b     #0x00, (%a0)
     move.l     #PAR_FBCTL, %a0
     move.b     #0x00, (%a0)          /* PA0 to 7 set as gpio */
     move.l     #PDDR_A, %a0
     move.b     #0xff, (%a0)
     move.l     #PODR_A, %a0
__sq1:     move.b     #0xff, (%a0)
     nop
     nop
     nop
     nop
     nop
     move.b     #0x00, (%a0)
     nop
     nop
     nop
     nop
     nop
     bra     __sq1

  • I see that code is properly read from SPI NOR, properly copied to DDR2, and properly executed from DDR2 on initial steps.
    board_init_f_alloc_reserve()   passed, ok
    board_init_f_init_reserve() passed ok
    cpu_init_f() --> icache_enable()  cpu seems to hang here, or in anyway, i can't see dbg square wave anymore.

The involved code is

From board.h

/* Cache Configuration */
#define CONFIG_SYS_CACHELINE_SIZE     16
#define ICACHE_STATUS               (CONFIG_SYS_INIT_RAM_ADDR + \
                          CONFIG_SYS_INIT_RAM_SIZE - 8)
#define DCACHE_STATUS               (CONFIG_SYS_INIT_RAM_ADDR + \
                          CONFIG_SYS_INIT_RAM_SIZE - 4)
#define CONFIG_SYS_ICACHE_INV          (CF_CACR_BCINVA + CF_CACR_ICINVA)
#define CONFIG_SYS_DCACHE_INV          (CF_CACR_DCINVA)
#define CONFIG_SYS_CACHE_ACR2          (CONFIG_SYS_SDRAM_BASE | \
                          CF_ADDRMASK(CONFIG_SYS_SDRAM_SIZE) | \
                          CF_ACR_EN | CF_ACR_SM_ALL)
#define CONFIG_SYS_CACHE_ICACR          (CF_CACR_BEC | CF_CACR_IEC | \
                          CF_CACR_ICINVA | CF_CACR_EUSP)
#define CONFIG_SYS_CACHE_DCACR          ((CONFIG_SYS_CACHE_ICACR | \
                          CF_CACR_DEC | CF_CACR_DDCM_P | \
                          CF_CACR_DCINVA) & ~CF_CACR_ICINVA)

From cache.c

void icache_invalid(void)
{
     u32 temp;

     temp = CONFIG_SYS_ICACHE_INV;
     if (*cf_icache_status)
          temp |= CONFIG_SYS_CACHE_ICACR;

     __asm__ __volatile__("movec %0, %%cacr"::"r"(temp));
}


void icache_enable(void)
{
     icache_invalid();

     *cf_icache_status = 1;

#if defined(CONFIG_CF_V4)
     __asm__ __volatile__("movec %0, %%acr2"::"r"(CONFIG_SYS_CACHE_ACR2));
     __asm__ __volatile__("movec %0, %%acr3"::"r"(CONFIG_SYS_CACHE_ACR3));
#elif defined(CONFIG_CF_V4e)
     __asm__ __volatile__("movec %0, %%acr6"::"r"(CONFIG_SYS_CACHE_ACR6));
     __asm__ __volatile__("movec %0, %%acr7"::"r"(CONFIG_SYS_CACHE_ACR7));
#else
     __asm__ __volatile__("movec %0, %%acr0"::"r"(CONFIG_SYS_CACHE_ACR0));
     __asm__ __volatile__("movec %0, %%acr1"::"r"(CONFIG_SYS_CACHE_ACR1));
#endif

     __asm__ __volatile__("movec %0, %%cacr"::"r"(CONFIG_SYS_CACHE_ICACR));
     
     __square();  <<-- never reeached
}


  • I already found an issue, the CONFIG_CF_V4e is never entered since in cache.h it is misteriously defined as CONFIG_CF_V4E (upper E). Fixing this allows to set ACR6 but nothing changes, still code "seems" to stop
    in line 51 above.

If any hint, welcome,

thanks

angelo

0 Kudos
2 Replies

394 Views
angelo_d
Senior Contributor I

Hi Tom,

still many thanks.

I solved this too, and i am now at u-boot prompt :smileyhappy:

My issue was related to DDR2, as you pointed out, but maybe on a special case, so i found out an interesting thing:

1) DDR2 cannot work from specification below 125Mhz. So, if as i did, some one wants to test SBF boot at a very low system clock,

and DDR2 clock results < 125Mhz, DDR2 will probably not work reliably. This because of the internal "delayed locked loop" circuit that is designed to work often at not less than 125Mhz (but for this you need to check the specific producer datasheet).

2) I found also a bug in u-boot that i'll fix, on cache.c, seems instruction cache was never enabled since ACR2 was not set (found 2 issues, a typo CONFIG_CF_V4e (lower 'e') in place of a more proper CONFIG_CF_V4E, and some ifdef mismatchs that was never setting ACR2 for this cpu.

Below my current SBF header before u-boot code, i set 240 Mhz cpu, 480 vco, and a 33 divider for spi boot clock.

Screenshot_20170604_233021.png

In this way i can have a reasonable > 125Mhz ddr2 clock.

thanks again

Regards,

angelo

0 Kudos

394 Views
TomE
Specialist II

First I'll list "the usual problems" with enabling the cache on these CPUs.

1 - First you have to invalidate the cache before enabling - you seem to have a function doing that.

2 - Then you have to make sure you don't have the I/O page mapped, but that's a Data Cache problem.

3 - Then DMA is always difficult, but again, a Data Cache problem.

Now I'll get on to "the usual problem".

Before enabling Data or Instruction caches, these CPUs usually fetch instructions and data one word at a time from the memory. The only time the CPU preforms a "burst read" (or a "burst write") is when the Cache is involved. Then an instruction fetch gets implemented as a four-word burst read from memory.

That's the point where you find that the Memory Controller hasn't been set up properly for your memory chips for this sort of cycle.

One way to investigate this would be to leave the instruction cache disabled (or run some test code from any on-chip SRAM) and run a small memory read/write test to the SDRAM with the Data Cache disabled.. Then enable the Data Cache and read back the pattern that the first test wrote. If there's a problem burst-reading from the SDRAM then that should show it while allowing the CPU to keep running and telling you about it. Make sure the stack is in SRAM though.

Tom

0 Kudos