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.

Unable to set correct SPI clock rate using DSP/BIOS in c6747

Hi there,

I am trying to increase the CPU clock of my c6747 custom board from 300Mhz to 450Mhz, while keeping the clock rate of the remaining peripherals before the change, such as SPI remaining at 1Mhz.

All these settings are done upon power up, i.e. not dynamically.

Fyi the 1Mhz SPI setting is working fine at SYSCLK1 300Mhz and the crystal's frequency is 15Mhz.

However, after
1) adjusting the PLL multiplier from 20 to 30 to produce a SYSCLK1 of 450Mhz and
2) changing the .tcf file under System>GlobalSettings>DSP Speed In MHz (CLKOUT) to 450Mhz,
the Spi's output clock changes from 1Mhz to 1.5Mhz

I suspect that the DSP/BIOS is not correctly informed of the change in DSP clock rate, causing the SPI to output a wrong clock rate. This is observed from the 1.5 times increase in SYSCLK1 corresponding to the undesired 1.5 times increase in SPI clockrate.

Fyi im using DSP/BIOS 5.41.04.18, Code gen tool 6.1.13, CCS 3.3.

Welcome any comments or solution.

  • Hi Choo,

    I think the SPI output clock depends on the SYSCLK2 (See TRM: Table 6-2, Page 104 and 27.2.1, Page 1171). Also, from DSP/BIOS UG, Page 141 the DSP Speed (CLKOUT) affects the on device timers only. I am not sure if the CLKOUT will change the SPI output clock values.

    Are you setting the SYSCLK2?

    Hope this helps.

    Vikram

  • Hi Vikram,

    Thank you for your reply.

    Yes i understand that SPI depends on SYSCLK2, while DSP depends on SYSCLK1. I was previously trying to keep the explanation short.

    For c6747, the ratio of SYSCLK1 : SYSCLK2 : SYSCLK4 has to be fixed to the ratio 1:2:4. (TRM page 118)

    As such, SYSCLK2 cannot be adjusted independent of SYSCLK1.

    The alternative way to set SPI output clock frequency is to configure the prescale register of the SPI.

    However, to initialize the SPI clock rate in DSP/BIOS, the only field provided is outputClkFreq in the Spi_Params struct. (located in PSP driver: ti\pspiom\spi\spi.h)

    I know one quick work around to is to manually set the SPI's prescale register value but that kind of defeats the purpose of using the DSP/BIOS to initialize the SPI.

    What i really want to know is: Why is the DSP/BIOS unable to recognize the new DSP clock speed and adjust the SPI clock rate accordingly?

    Am i missing something?

  • I think you will need to recompile the BIOSPSP library after you update the hard-coded clock frrequency definition here:
    H:\ti\pspdrivers_01_30_01\packages\ti\pspiom\cslr\soc_C6747.h
    #define CSL_SYSCLK_1_FREQ                   (300000000)

  • Hi Norman,

    Thank you for your reply.

    My current implementation do not make use of the CSL to do the PLL settings.

    Instead, the PLL MUL value is written straight to its address, as shown below.

    void initPll(void)
    {
        int i = 0;
    
        // Configure DSP at 300MHz, EMIFs at 133MHz
    //    unsigned int DIV45_EN = 1;
    //    unsigned int CLKMODE = 0;
    	unsigned int CLKMODE = 1;		// Changed to Oscillator input
        unsigned int PLLM = 29;//19;//24;
        unsigned int POSTDIV = 0;//1;
        //unsigned int PLLDIV2 = 1;
        //unsigned int PLLDIV4 = 3;
    	unsigned int PLLDIV3 = 0x1F;	// Changed slower from 0x02 to slow down EMIFA.
        unsigned int PLLDIV5 = 5;
        unsigned int PLLDIV7 = 7;
    
    	// Moved step 2c and 2d to step 0
       	// Set PLLEN=0 and PLLRST=0, Reset the PLL
        PLL0_PLLCTL &=  0xFFFFFFFE; 	// PLL BYPASS MODE
       
      	// Wait for 4 cycles to allow PLLEN mux switches properly to bypass clock
       	for(i=0; i<PLLEN_MUX_SWITCH; i++);	// Make PLLEN_MUX_SWITCH as bootpacket
    
      	// Select the Clock Mode bit 8 as External Clock or On Chip Oscilator
    	PLL0_PLLCTL &= 0xFFFFFEFF;  
        PLL0_PLLCTL |= (CLKMODE<<8);  // Make CLKSRC as BootPacket to pass the value
    
       	// Set PLLENSRC '0',bit 5, PLL Enable(PLLEN) selection is controlled through MMR
        PLL0_PLLCTL &=  0xFFFFFFDF; 
       
       	// PLLCTL.EXTCLKSRC bit 9 should be left at 0 for Primus
        PLL0_PLLCTL &=  0xFFFFFDFF;
    
       	// Clear PLLRST bit to 0 -Reset the PLL
       	PLL0_PLLCTL &= 0xFFFFFFF7; 	
      
       	// Disable the PLL output
       	PLL0_PLLCTL |= 0x10; 		
       
       	// PLL initialization sequence
       
       	// Power up the PLL- PWRDN bit set to 0 to bring the PLL out of power down bit
    	PLL0_PLLCTL &= 0xFFFFFFFD;
       
       	// Enable the PLL from Disable Mode PLLDIS bit to 0 - This is step is not required for Primus
       	PLL0_PLLCTL &= 0xFFFFFFEF;
       
       	// PLL stabilisation time- take out this step , not required here when PLL in bypassmode
    	// for(i=0; i<PLL_STABILIZATION_TIME; i++);	//Make PLL_STABILIZATION_TIME as bootpacket
       
       	// Program the required multiplier value in PLLM
    	PLL0_PLLM    = PLLM;	// Make PLLMULTIPLEIR as bootpacket
    
       	// If desired to scale all the SYSCLK frequencies of a given PLLC, program the POSTDIV ratio
       	PLL0_POSTDIV = 0x8000 | POSTDIV;		// Make POSTDIV as bootpacket
    
       	// If Necessary program the PLLDIVx
       	// Check for the GOSTAT bit in PLLSTAT to clear to 0 to indicate that no GO operation is currently in progress
       	while((PLL0_PLLSTAT & 0x1)==1){}
    
       	// Program the RATIO field in PLLDIVx with the desired divide factors. In addition, make sure in this step you leave the PLLDIVx.DxEN bits set so clocks are still enabled (default).
        //PLL0_PLLDIV2 = 0x8000 | PLLDIV2; // Make PLLDIV2 as bootpacket, do it for other PLLDIVx to if required
        //PLL0_PLLDIV4 = 0x8000 | PLLDIV4; // Make PLLDIV4 as bootpacket, do it for other PLLDIVx to if required
        PLL0_PLLDIV3 = 0x8000 | PLLDIV3; // Make PLLDIV3 as bootpacket, do it for other PLLDIVx to if required
        PLL0_PLLDIV5 = 0x8000 | PLLDIV5; // Make PLLDIV5 as bootpacket, do it for other PLLDIVx to if required
        PLL0_PLLDIV7 = 0x8000 | PLLDIV7; // Make PLLDIV7 as bootpacket, do it for other PLLDIVx to if required
    
    	// observer output clk = 9.3Mhz / 3 = 3.1Mhz
    	PLL0_OCSEL = 0x19;//0x014;// obsclk divider select sysclk3 9.3Mhz 
    	PLL0_OSCDIV1 = 0x8002; // enable post divider AND set post divider divide by 3 
    
        // Set the GOSET bit in PLLCMD to 1 to initiate a new divider transition.
    	PLL0_PLLCMD |= 0x1;
    
    	// Wait for the GOSTAT bit in PLLSTAT to clear to 0 (completion of phase alignment).
        while((PLL0_PLLSTAT & 0x1)==1); 
       
     
       	// Wait for PLL to reset properly. See PLL spec for PLL reset time - This step is not required here -step11
      	// for(i=0; i<PLL_RESET_TIME_CNT; i++);	// 128 MXI Cycles. Make PLL_RESET_TIME_CNT as boot packet
          
       	// Set the PLLRST bit in PLLCTL to 1 to bring the PLL out of reset
    	PLL0_PLLCTL |= 0x8;
       
       	// Wait for PLL to lock. See PLL spec for PLL lock time
       	for(i=0; i<PLL_LOCK_TIME_CNT; i++);	// Make PLL_LOCK_TIME_CNT as boot Packet
       
       	// Set the PLLEN bit in PLLCTL to 1 to remove the PLL from bypass mode
      	PLL0_PLLCTL |=  0x1;
    
       	KICK0R = 0x83e70b13;  	// Kick0 register + data (unlock)
      	KICK1R = 0x95a4f1e0;  	// Kick1 register + data (unlock)
       	CFGCHIP3 |= 0x4;       	// Enable 4.5 divider PLL
       	CFGCHIP3 |= 0x1;       	// Select 4.5 divider for EMIFB clock source only (not EMIFA)
    }

    I am able to verify the change in SYSCLK1 is done correctly by the measuring the 1.5 times change in the SPI clock rate output.

    However, this is not the desired behavior as i have:

    1) set the clock rate through Spi_Params.

        spiParams.outputClkFreq     = 1000000;

    2) made changes to the .tcf file under System>GlobalSettings>DSP Speed In MHz (CLKOUT) to 450Mhz.

    While experimenting with different spiParams.outputClkFreq values,  all of them turn out to be 1.5 times when measured with an oscilloscope.

    Somehow, ithe DSP/BIOS seems to be setting the SPI clock prescale register with the wrong reference DSP clock rate.

  • Not quite sure I understand. It sounds like you have successfully changed the clock speed at a HW level and at the DSPBIOS(TCF) level. I don't think BIOSPSP uses those. The SPI driver of BIOSPSP does use the CSL_SYSCLK_1_FREQ definition. So setting spiParams.outputClkFreq = 1000000 will result in the SPI driver code setting the prescale using the CSL_SYSCLK_1_FREQ value.

  • Norman Wong said:

    Not quite sure I understand. It sounds like you have successfully changed the clock speed at a HW level and at the DSPBIOS(TCF) level. I don't think BIOSPSP uses those. The SPI driver of BIOSPSP does use the CSL_SYSCLK_1_FREQ definition. So setting spiParams.outputClkFreq = 1000000 will result in the SPI driver code setting the prescale using the CSL_SYSCLK_1_FREQ value.

    Norman,

    Your latest reply answers the first part of my question.

    The next part is to correct the SPI clock rate.

    I have checked my copy of soc_c6747.h and it does not contain the definition CSL_SYSCLK_1_FREQ .

    After simply adding it in, the SPI output still remains wrong at 1.5Mhz.

    From your first reply, you mentioned that there is a need to recompile the BIOSPSP library.

    May i know how to do so?

    Thanks for the help so far.

  • This is what I see in my installion of BIOSPSP (admittedly it is old):

    pspdrivers_01_30_01\packages\ti\pspiom\cslr\soc_C6747.h

    ...
    #define CSL_SYSCLK_1_FREQ                   (300000000)
    ...
    #define CSL_SPI_0_MODULE_FREQ               (CSL_SYSCLK_2_FREQ)
    #define CSL_SPI_1_MODULE_FREQ               (CSL_SYSCLK_2_FREQ)
    ...

    The SPI library project is here:

    pspdrivers_01_30_01\packages\ti\pspiom\spi\build\C6747\ccs3\spi.pjt

  • Thanks Norman,

    My question has been answered and problem solved.

    Cheers.