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.

TMS320F28020: SCI Clock Confusion

Part Number: TMS320F28020
Other Parts Discussed in Thread: C2000WARE

Hi All,

I'm back with more questions about setting up the SCI BAUD rate.

In the last episode, I was getting irrational BAUD rates due to the fact that I had the SYSCLK running at 50MHz, but thought it was 40MHz.  Correcting that error helped straighten things out, but there still seems to be a kink.

With SYSCLK running at 40MHz (confirmed, reconfirmed, and double checked after that), the BRR value still won't reconcile with the BAUD rate measured at the output.

Here's the path I followed:  (SCI code borrowed from Driverlib example code, "Example_F2802xSci_FFDLB.c" on TIREX)

Set SYSCLK to 40MHz:

Using a TMS320F28020 (spec'd at 40MHz) in my target (prototype assembly).

Setting the PLL to multiply by 8 and divide by 2:

 

Fullscreen
1
2
3
4
//
// Setup the PLL for x8 /2 which will yield 40Mhz = 10Mhz * 8 / 2
//
PLL_setup(myPll, PLL_Multiplier_8, PLL_DivideSelect_ClkIn_by_2); // 10MHz x (8/2) = 40MHz
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

With a scope on XCLKOUT, and setting the prescaler to divide by 1 (to match SYSCLK's 40MHz):

Fullscreen
1
2
3
4
//
// Setup the clock out prescaler to check SYSCLK frequency at XCLKOUT
//
CLK_setClkOutPreScaler(myClk, CLK_ClkOutPreScaler_SysClkOut_by_1); // Div by 1 = SYSCLKOUT
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Here's the scope image:

So far, so good...

Set LSPCLK to 40MHz using common code function:

Here's where things get weird.

Using the following function, shouldn't LSPCLK run at 40MHz:

Fullscreen
1
2
3
4
//
// Setup the LOSPCP to produce 40MHz LSPCLK
//
CLK_setLowSpdPreScaler(myClk, CLK_LowSpdPreScaler_SysClkOut_by_1);
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

BUT, when applying a value to BRR, the measure BAUD rate doesn't match what the calculation says it should be.  You may want more detail about how I arrived at that, but for now let's focus on the above function.

The value that should be applied to LOSPCP as a result of the above function is zero:

Fullscreen
1
2
3
4
5
6
7
8
9
10
11
12
13
//! \brief Enumeration to define the low speed clock prescaler, which sets the clock frequency
//!
typedef enum
{
CLK_LowSpdPreScaler_SysClkOut_by_1=(0 << 0), //!< Denotes Low Speed Clock = SYSCLKOUT/1
CLK_LowSpdPreScaler_SysClkOut_by_2=(1 << 0), //!< Denotes Low Speed Clock = SYSCLKOUT/2
CLK_LowSpdPreScaler_SysClkOut_by_4=(2 << 0), //!< Denotes Low Speed Clock = SYSCLKOUT/4
CLK_LowSpdPreScaler_SysClkOut_by_6=(3 << 0), //!< Denotes Low Speed Clock = SYSCLKOUT/6
CLK_LowSpdPreScaler_SysClkOut_by_8=(4 << 0), //!< Denotes Low Speed Clock = SYSCLKOUT/8
CLK_LowSpdPreScaler_SysClkOut_by_10=(5 << 0), //!< Denotes Low Speed Clock = SYSCLKOUT/10
CLK_LowSpdPreScaler_SysClkOut_by_12=(6 << 0), //!< Denotes Low Speed Clock = SYSCLKOUT/12
CLK_LowSpdPreScaler_SysClkOut_by_14=(7 << 0) //!< Denotes Low Speed Clock = SYSCLKOUT/14
} CLK_LowSpdPreScaler_e;
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

However, it is instead 0x0002:

By locating the source code for that function, which is found in the TI install directory at this path:

C:\ti\C2000Ware_4_01_00_00\device_support\f2802x\common\source\clk.c

Fullscreen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//
// CLK_setLowSpdPreScaler -
//
void
CLK_setLowSpdPreScaler(CLK_Handle clkHandle,
const CLK_LowSpdPreScaler_e preScaler)
{
CLK_Obj *clk = (CLK_Obj *)clkHandle;
ENABLE_PROTECTED_REGISTER_WRITE_MODE;
//
// set the bits
//
clk->LOSPCP |= preScaler;
DISABLE_PROTECTED_REGISTER_WRITE_MODE;
return;
}
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

The function is OR'ing the prescaler value coming in as the second parameter of the function.  Since the default reset value is 0x0002, it would follow that this function could never set LOSPCP to zero or any other value that doesn't include having bit 1 high.  Shouldn't the 'or-equals' statement:

Fullscreen
1
2
3
4
//
// set the bits
//
clk->LOSPCP |= preScaler;
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

be changed to 'equals':

Fullscreen
1
2
3
4
//
// set the bits
//
clk->LOSPCP = preScaler;
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

or at least 'and-equals':

Fullscreen
1
2
3
4
//
// set the bits
//
clk->LOSPCP &= preScaler;
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Question #1:

Is this function correct as it stands, and I am misunderstanding what's going on?

Moving on...

If I change the line of code that calls the function from this:

Fullscreen
1
2
3
4
//
// Setup the LOSPCP to produce 40MHz LSPCLK
//
CLK_setLowSpdPreScaler(myClk, CLK_LowSpdPreScaler_SysClkOut_by_1);
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

to this:

Fullscreen
1
2
3
4
5
6
//
// Setup the LOSPCP to produce 40MHz LSPCLK
//
EALLOW;
myClk->LOSPCP = CLK_LowSpdPreScaler_SysClkOut_by_1;
EDIS;
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

then LOSPCP does achieve the value zero, which should setup LSPCLK to be running at 40MHz.

With this configuration, the calculation for BRR works correctly.

Please help me understand.

Thanks,
robin