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.

C6657 LocalReset through PCIe

We are trying to PCIe boot our custom board based on C6657 without IBL. One feature we need is to reset the DSP through PCIe.

We based our code using MCSDK_2_01_01_04/tools/boot_loader/examples/pcie/linux_host_loader/pciedemo.c. As there is no example code for C6657, but only for C6670 and C6678, we created our own function mimicing C6670 code.

In this code, we disable the PSC for core 0 and 1. The real reset seems to be carried out by updating the DSP_BOOT_ADDR of bootcfg then send IPCG to the appropriate core, then, enable the PSC.

I have the following questions

1. Is the triggering the IPCG not enough for reset? Why do we have to disable PSC first?

2. I've tried to send this command to DSP, but it does not seem to trigger a reset for DSP already running code. Is there anything I miss?

3. I did a simple test using the following code, running in dsp, but after running through it, no reset is triggered.

    /* kick unlock */
    *((volatile unsigned int *)KICK0)=0x83e70b13;
    *((volatile unsigned int *)KICK1)=0x95a4f1e0;

/* dsp_boot_addr */
    *((volatile unsigned int *)0x02620040)=(unsigned int)_c_int00;

/* ipcg register */
    *((volatile unsigned int *)0x02620240)=1;
    bootloaderflag=0x1234abcd;

thanks

Weichun

 /* ============================================================================
2231  *  @func   c6657LocalReset
2232  *
2233  *  @desc   Perform DSP cores and periphrals reset
2234  *
2235  *  @modif  None.
2236  *  ============================================================================
2237  */
2238 void c6657LocalReset(gauss_device_t *gss_dev,uint32_t bootEntryAddr)
2239 {
2240         uint32_t i;
2241
2242         /* Local reset of all cores */
2243         coreLocalReset(gss_dev, PD13, LPSC_C0_TIM0, LOC_RST_ASSERT);
2244         //coreLocalReset(PD14, LPSC_C1_TIM1, LOC_RST_ASSERT);
2245         //coreLocalReset(PD15, LPSC_C2_TIM2, LOC_RST_ASSERT);
2246         //coreLocalReset(PD16, LPSC_C3_TIM3, LOC_RST_ASSERT);
2247
2248         /* Disable all other modules */
2249         setPscState(PD0, LPSC_TCP3E, PSC_SWRSTDISABLE);
2250         setPscState(PD0, LPSC_VCP2A, PSC_SWRSTDISABLE);
2251         setPscState(PD1, LPSC_DEBUG, PSC_SWRSTDISABLE);
2252         setPscState(PD1, LPSC_TETB, PSC_SWRSTDISABLE);
2253         setPscState(PD2, LPSC_SA, PSC_SWRSTDISABLE);
2254         setPscState(PD2, LPSC_SGMII, PSC_SWRSTDISABLE);
2255         setPscState(PD2, LPSC_PA, PSC_SWRSTDISABLE);
2256         //setPscState(PD3, LPSC_PCIE, PSC_SWRSTDISABLE);
2257         setPscState(PD4, LPSC_SRIO, PSC_SWRSTDISABLE);
2258         setPscState(PD5, LPSC_HYPER, PSC_SWRSTDISABLE);
2259         //setPscState(PD6, LPSC_RESERV, PSC_SWRSTDISABLE);
2260         setPscState(PD7, LPSC_MSMCRAM, PSC_SWRSTDISABLE);
2261         setPscState(PD8, LPSC_RACA_RACB, PSC_SWRSTDISABLE);
2262         setPscState(PD8, LPSC_TAC, PSC_SWRSTDISABLE);
2263         setPscState(PD9, LPSC_FFTCA_FFTCB, PSC_SWRSTDISABLE);
2264         setPscState(PD10, LPSC_AIF2, PSC_SWRSTDISABLE);
2265         setPscState(PD11, LPSC_TCP3DA, PSC_SWRSTDISABLE);
2266         setPscState(PD12, LPSC_VCP2B, PSC_SWRSTDISABLE);
2267         setPscState(PD12, LPSC_VCP2C, PSC_SWRSTDISABLE);
2268         setPscState(PD12, LPSC_VCP2D, PSC_SWRSTDISABLE);
2269         setPscState(PD17, LPSC_TCP3dB, PSC_SWRSTDISABLE);
2270
2271         for (i = 0; i < 1; i++) {
2272                 //pushData(localResetCode, i, &bootEntryAddr);
2273                 if (setBootAddrIpcgr(gss_dev,i, bootEntryAddr) == 0) {
2274                         printk("Core %d is not ready !!! \n", i);
2275                 }
2276         }
2277
#if 0
2278         /* Enable all other modules */
2279         setPscState(PD0, LPSC_TCP3E, PSC_ENABLE);
2280         setPscState(PD0, LPSC_VCP2A, PSC_ENABLE);
2281         setPscState(PD1, LPSC_DEBUG, PSC_ENABLE);
2282         setPscState(PD1, LPSC_TETB, PSC_ENABLE);
2283         setPscState(PD2, LPSC_PA, PSC_ENABLE);
2284         setPscState(PD2, LPSC_SGMII, PSC_ENABLE);
2285         setPscState(PD2, LPSC_SA, PSC_ENABLE);
2286         //setPscState(PD3, LPSC_PCIE, PSC_ENABLE);
2287         setPscState(PD4, LPSC_SRIO, PSC_ENABLE);
2288         setPscState(PD5, LPSC_HYPER, PSC_ENABLE);
2289         //setPscState(PD6, LPSC_RESERV, PSC_ENABLE);
2290         setPscState(PD7, LPSC_MSMCRAM, PSC_ENABLE);
2291         setPscState(PD8, LPSC_RACA_RACB, PSC_ENABLE);
2292         setPscState(PD8, LPSC_TAC, PSC_ENABLE);
2293         setPscState(PD9, LPSC_FFTCA_FFTCB, PSC_ENABLE);
2294         setPscState(PD10, LPSC_AIF2, PSC_ENABLE);
2295         setPscState(PD11, LPSC_TCP3DA, PSC_ENABLE);
2296         setPscState(PD12, LPSC_VCP2B, PSC_ENABLE);
2297         setPscState(PD12, LPSC_VCP2C, PSC_ENABLE);
2298         setPscState(PD12, LPSC_VCP2D, PSC_ENABLE);
2299         setPscState(PD17, LPSC_TCP3dB, PSC_ENABLE);
2300
2301         /* Local out of reset of all cores */
2302         coreLocalReset(gss_dev,PD13, LPSC_C0_TIM0, LOC_RST_DEASSERT);
2303         //coreLocalReset(PD14, LPSC_C1_TIM1, LOC_RST_DEASSERT);
2304         //coreLocalReset(PD15, LPSC_C2_TIM2, LOC_RST_DEASSERT);
2305         //coreLocalReset(PD16, LPSC_C3_TIM3, LOC_RST_DEASSERT);
2306
2307
2308 }

  • Weichun,

    I think there is some misunderstanding between the CPU local reset and IPCG.

    IPCG is just being used to generate interrupt to certain CorePac. It does not do local reset to that CorePac.

    The PSC module controls the reset of CorePac and other modules in the device. Please take a look at section "2.2.3 Local Reset" in the PSC user guide.

    The reset consists of two stages: assert the reset and de-assert the reset. The CPU will immediately executes program instructions after reset is de-asserted. Execution of code previously in L2 begins execution.

    That is why you will see two PSC operations for the CorePac at the beginning (assert) and end (de-assert) of the code.

    To do reset to the DSP, you need to call the whole function as what demonstrates in "pciedemo.c":

    #if LOCAL_RESET
    mdelay(10000);
    dspLocalReset(); //maybe c6657LocalReset() in your case
    #endif

  • Hi, Steven, thank you very much for your help.

    I have several additional questions regarding PCIe reset:

    1. PSC document sprugv4b.pdf section 2.2.3 says that the local reset is intended to be used by watchdog timer to reset the C66x core in teh event of an error. But after we put the dsp in reset state by setting MDCTL[Y].LRSTZ, the dsp is in reset state, how can it execute the next instruction to clear MDCTL[Y].LRSTZ? Does it mean that this procedure can only be carried out through external device such as PCIe? Can jtag control the register and trigger the reset?

    2. When dsp core is out of reset, where does it jump to? I can not find it in the document, but from the attached pciedemo.c under mcsdk_2_01_01_04\tools\boot_loader\examples\pcie\linux_host_loader, it seems to start from bootcfg address BOOT_ADDR at 0x02620040. Is this correct?

    3. In the PSC document, it always says "Execution of code previously in L2 begins execution". Is this a limitation? Can I put the code in DDR or put the BOOT_ADDR to be 0x20b00000 so that it jumps to BOOTROM?

    4. in the sample program pciedemo.c, IPCGR is generated to all the cores, including core 0. As you pointed out in previous post, this is not needed. What is the purpose then?

    5. We have multiple programs to run before we start our boot strap code to download our dsp application, such as manufacuturing test, diag, POST. They are independent and could run selectively. We therefore are trying to re-enter BOOTROM so that we can arbitrarily download any program without worrying about inter-program booting and allocate memory map between those programs. I tried to do the following at end of each POST, bootstrap 1) clear memory used by BOOTROM (between (0x008FFFFF-0xD23f) and 0x008FFFFF) 2) jump to BOOTROM 0x20b00000 3) download new code, 4) write entry addr to BOOT_MAGIC 0x008FFFFC 5) send MSI interrupt to core 0

    5.1) should this work?

    5.2) after finishing the previous steps, it seems that the bootcode never jump to the new entry.

    5.3) is there anything else I miss? Are there other information about booting recorded somewhere else?

    thanks

    Weichun

  • Weichun,

    1. Watchdog is using hardware path to reset the CPU, so the CPU could be reset by its own Watchdog.

     Programming the LPSC registers to do the local reset is software path. The CPU needs the help from the external master which could assert and de-assert the reset for the local CPU.

    JTAG could toggle the register as well. But you have to use one CPU view to do the toggling of the other CPU register.

    2. Yes. DSP_BOOT_ADDRn specifies the boot address for CorePac_n. And it is 0x20b00000 by default, which is the starting point of ROM Boot Loader (RBL). Please see the Bootloader user guide for details.

    3. Out of reset, the Program Counter of CPU will jump to the address specified in DSP_BOOT_ADDR register. You may already observe this behavior if issue the reset correctly.

    4. I think the IPC interrupt is used to wake up the secondary cores as specified in the bootloader user guide section 2.2 “During the boot process, the bootloader executes an IDLE command on the secondary CorePacs and keeps the secondary CorePacs waiting for an interrupt.  After the application code to be loaded in these secondary CorePacs are loaded and the BOOT_MAGIC_ADDRESS in individual corePacs are populated, the application code in the corePac0 can trigger the IPC interrupt to wake up the secondary cores and branch up to the address specified in the BOOT_MAGIC_ADDRESS.”

    5. You do not need to clear the boot ROM. Once you go back to base of boot rom and run it, the RBL should initialize. Can you verify where the program counter is stuck at the end?

  • Thanks a lot, Steven. I am adding my observations abased on your 5 items. Could you please help me to understand them better?

    1. Thanks for the clarification of the reset.

    2. The default DSP_BOOT_ADDRn is 0x20b00001, which is the starting point of RBL. Is there any alignment requirement for these addresses? When I tried to write a value (_c_int00) into this DSP_BOOT_ADDR0, such as 0x0084efe0 after kick_unlock, the value will move to 0x0084ec01. I searched all the documents and also on E2E forum on C66, but could not find anything about alignment or value allowable for these address.

    Another questions is, after reset, would is be the hardware directly changing PC to the value in DSP_BOOT_ADDRn, or through RBL?

    3. I could use the algorithm based on pciedemo.c to reset and could see that after I ASSERT the bit, the jtag on the dsp core reports that dsp is in reset mode and after I DEASSERT the bit, the dsp comes one more be out of reset and can be connected by jtag. Just the PC is in a location around 0x1151259c, not an defined memory location if I DSP_BOOT_ADDRn is 0x20b00000.

    4. I think we should only start core 0 and core 0 will send IPCG to other cores to start the core on address pointed by BOOT_MAGIC. But in the pciedemo.c, the code is that we put all the cores to reset, load the code, and set DSP_BOOT_ADDRn for all the cores, and unreset the all the cores. BOOT_MAGIC is at 0x008FFFFC while DSP_BOOT_ADDRn is at 0x026200040+4*n. Are they internally linked by hardware?

    5. I have a simple code running in dsp core 0 as below. After init DDR3, I just jump to bootrom entry and somehow I landed in some random place, every time different. Is there source code for RBL available so that it is easier for me to trace through the RBL?

    thanks

    WEichun

    void main(void) {
        int i;
        unsigned int     core0_MSI0_IRQ_STATUS_RAW=-1;
        unsigned int    pcie_int_bits;
        void            (*jumpbacktobootloader)();
        void            (*appentry)();


        bootloaderflag=0x900d900d;
        /* clear BOOT MAGIC */
        *((volatile unsigned int *) 0x008ffffc)=0;

        platform_write_configure(2);//platform_write_configure (PLATFORM_WRITE_ALL);
        /*disable L2 and L1D*/
        *((volatile unsigned int *)0x01840000) = 0;
        *((volatile unsigned int *)0x01840040) = 0;

        *((volatile unsigned int *)0x01840020) = 0;

        /* disable edma interrupts */
        *((volatile unsigned int *)0x02741050) = 0;

        //clearIER(0);

        /* clear msi interrupt */
        core0_MSI0_IRQ_STATUS_RAW=*((volatile unsigned int *) 0x21800100);

        /* check MSI0_IRQ_STATUS */
        pcie_int_bits=*((volatile unsigned int *) 0x21800104);
        if ((core0_MSI0_IRQ_STATUS_RAW) != 0){
            *((volatile unsigned int *) 0x21800104)=pcie_int_bits;//MSI0_IRQ_STATUS
            //*((volatile uint32_t *) 0x21800100)=0; //MSI0_IRQ_STATUS_RAW
            *((volatile unsigned int *) 0x21800050)=4; //IRQ_EOI for
        }
        /* clear boot rom area */
        for (i=(0x008FFFFF-0xD23f);i<0x008FFFFF;i+=4){
            *((volatile unsigned int *)i)=0;
        }

        //test_core_clock();
        for (i=0;i<total_test;i++){
            dsp_init_main(1,0);//EVM DDR init code for DDR3
        }



    #if 1

        bootloaderflag=0x1234abcd;
        /* jump back to rom bootloader */
        jumpbacktobootloader = (void (*)())0x20b00000;
        jumpbacktobootloader();
        while (1){
            asm(" nop ");
        }
    }

  • 2. DSP_BOOT_ADDRn will hold the 22 MSBs (bits31-10) of the CorePac boot address. bits9-0 are reserved in this register. The reset value is 22 MSBs of 0x20b00000.

    We will add this piece of info in the next release of C66x data manuals. And CorePac will jump to the address specified in DSP_BOOT_ADDRn register automatically after out of reset. It is not software controlled (hardware controlled, not by RBL).

    3. Do you halt the CorePac right after the reset de-assert? I am wondering if the boot ROM already run to some other places when you check the PC values. 

    Theoretically the CPU will jump to the address in DSP_BOOT_ADDRn register after out of reset.

    4. I think you are probably right that the application code in Core0 could send IPC and wake up the other Cores, as mentioned in bootloader user guide sectino 2.2.

    The PCIe local reset demo might do some things unnecessary. In your own application code, you could try any sequence which is working for you.

    5. I am not sure if we have RBL source code available somewhere. You probably could search the previous threads first. If no answer, you could start another thread specifically for this question. The other TIers or community members could help there.