This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Writes to Cortex-A15 CSSELR register don't take effect when single stepping in CCS 6.1.3

Other Parts Discussed in Thread: 66AK2H14, AM5728

Due to failures when running different SYS/BIOS examples on a Cortex-A15 in a 66AK2H14, due to data in the cache from a previously run apparently getting flushed to RAM, was single stepping the code in bios_6_45_01_29\packages\gnu\targets\arm\rtsv7A\boot.asm which should be invalidating the Cortex-A15 caches. That code writes to the CSSELR register to select a cache, and then reads the CCSIDR register to determine the cache size to invalidate.

When stepping initially thought there was a bug in that the SYS/BIOS boot.asm source file wasn't selecting the cache correctly. On further investigation, when single stepping code writes to the CSSELR register don't seem to take effect. The following bare-metal program was created using the GNU v4.9.3 compiler to illustrate the issue:

/*
 * main.c
 */

#include <stdint.h>

/*
 * Write the level and type you want to Cache Size Selection Register(CSSELR)
 * to get size details from Current Cache Size ID Register(CCSIDR)
 */
static void set_csselr(uint32_t level, uint32_t type)
{
    const uint32_t csselr = level << 1 | type;
    /* Write to Cache Size Selection Register(CSSELR) */
    asm volatile ("mcr p15, 2, %0, c0, c0, 0" : : "r" (csselr));
    asm volatile ("isb");
}

static uint32_t get_csselr(void)
{
    uint32_t csselr;
    /* Read current CP15 Cache Size Selection Register(CSSELR) */
    asm volatile ("mrc p15, 2, %0, c0, c0, 0" : "=r" (csselr));
    return csselr;
}

static uint32_t get_ccsidr(void)
{
    uint32_t ccsidr;
    /* Read current CP15 Cache Size ID Register */
    asm volatile ("mrc p15, 1, %0, c0, c0, 0" : "=r" (ccsidr));
    return ccsidr;
}

static uint32_t get_clidr(void)
{
    uint32_t clidr;
    /* Read current CP15 Cache Level ID Register */
    asm volatile ("mrc p15,1,%0,c0,c0,1" : "=r" (clidr));
    return clidr;
}

struct
{
    uint32_t clidr;
    uint32_t initial_csselr;
    uint32_t l1d_csselr;
    uint32_t l1d_ccsidr;
    uint32_t l1i_csselr;
    uint32_t l1i_ccsidr;
    uint32_t l2_csselr;
    uint32_t l2_ccsidr;
} cp15_results;

int main(void) {

    cp15_results.clidr = get_clidr ();
    cp15_results.initial_csselr = get_csselr ();

    set_csselr (0, 0); /* L1 data cache */
    cp15_results.l1d_csselr = get_csselr ();
    cp15_results.l1d_ccsidr = get_ccsidr ();

    set_csselr (0, 1); /* L1 instruction cache */
    cp15_results.l1i_csselr = get_csselr ();
    cp15_results.l1i_ccsidr = get_ccsidr ();

    set_csselr (1, 0); /* L2 unified cache */
    cp15_results.l2_csselr = get_csselr ();
    cp15_results.l2_ccsidr = get_ccsidr ();
	
	return 0;
}

The program selects different caches by writing to the CSSELR register, and then reading the CCSIDR register for the selected cache. The CSSELR register is also read back  The results are stored in a global structure to be checked in the debugger (so that don't need semihost support).

The following screen shot shows the correct results after the program was set to free-run at main, and then suspended once _exit has been entered:

The expressions view shows that:

- l1d_ccsidr has the expected value for the 32 Kbyte L1 data cache (as decoded from the ARMv7-A Architecture Reference Manual)

- l1i_ccsidr has the expected value for the 32 Kbyte L1 instruction cache

- l2_ccsidr has the expected value for the 4 Mbyte L2 cache

- l1d_csselr, l1i_csselr and l2_csselr show the expected read-back values for the CSSELR register.

The following screen shot shows incorrect results after using Step-Over to step through the main function:

The expressions view shows that:

- l1d_csselr and l2_csselr have the incorrect value of 1 (the L1 instruction cache), meaning the writes to the CSSELR register to select the L1 data and L2 caches failed to change the CSSELR register.

- l1d_ccsidr and l2_ccsidr have the size of what is the L1 instruction cache, due to the writes to the CSSELR register not taking effect.

The setup is:

- CCS 6.1.3.00033, with TI Emulators 6.0.228.0

- A 66AK2H14 Rev 2 device in a EVMK2H Rev 4 board

- Using the EVMK2H XDS200 USB onboard debug probe

- The EVMK2H boot mode set to "SLEEP W/ SLOW PLL & SLOW ARM PLL" to prevent uboot from running from flash, and the xtcievmk2x_arm.gel script used on the Cortex-A15 to initialize the device.

- The debug project properties for the Cortex-A15 set to the default of Disable interrupts when source stepping (selecting to not disable interrupts didn't produce the correct behavior when stepping)

The test project is attached 66AK2H14_A15_cache_ops.zip

  • This thread has been moved from CCS forum to Keystone device forum by CCS forum moderator. We will check and get back to you as soon as possible. Thank you for your patience.
  • Chester,

    I am able to reproduce the issue that you are reporting but haven`t been able to root cause it as yet. I will spend some time debugging this and let you know if I can come up with an explanation for this behavior.

    Regards,
    Rahul
  • Rahul Prabhu said:
    I am able to reproduce the issue that you are reporting but haven`t been able to root cause it as yet.

    Thank you for investigating this.

    I did run the same test program on a Cortex-A9 core in an OMAP4430 connected using a Blackhawk USB560-M with 20-pin JTAG cable. In the case of the Cortex-A9 writes to the CSSELR register did take effect when single stepping.

    However, given that the device and debug probe are different that doesn't really help to narrow down if the cause is the Cortex-A15 in the 66AK2H14 or the EVMK2H XDS200 USB onboard debug probe.

    [I don't have the correct adapters to try swapping the Blackhawk USB560-M and XDS200 USB onboard debug probes between the 66AK2H14 and OMAP4430 devices to see if the failure for writes to the CSSELR register to take effect when single stepping are due to the device and/or debug probe]

  • Chester Gillon said:
    However, given that the device and debug probe are different that doesn't really help to narrow down if the cause is the Cortex-A15 in the 66AK2H14 or the EVMK2H XDS200 USB onboard debug probe.

    I repeated the test with a AM5728 Rev 1.1 device which uses a Cortex-A15 r2p2 version. When used the AM5728 with the Blackhawk USB560-M with 20-pin JTAG cable the behavior was the same as with the 66AK2H14 and XDS200 USB onboard debug probe in that:

    a) Writes to the CSSELR didn't take effect when single stepping.

    b) Writes to the CSSELR did take effect when free running.

    i.e. the problem appears related to the Cortex-A15 rather than debug probe.