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.

Setting Clock Frequency on TM4C129

Other Parts Discussed in Thread: TM4C1294NCPDT

Hi, I'm having an issue with setting the sysclk speed on the tm4c129 on the Launchpad to its full 120 MHz rate.

I have experience with the NXP LPC1700 and 4300 series and with the STM32F4, but Tiva is new to me. I've read the relevant section of the datasheet and think I'm interpreting it correctly, but as soon as I switch the system clock over to the PLL output, the processor becomes unresponsive.

I know that there's probably a library routine to do this, but I'm a hobbyist and enjoy programming microcontrollers at the bare metal register level.

Here's my code; can someone tell me where I'm going wrong? Thanks. BTW, the board has a 25 MHz crystal connected to MOSC.

#define MINT 64
#define MFRAC 0
#define N 4
#define Q 0
#define PDIV 3

#define FBCHT 0x6
#define EBCHT 0x6
#define FBCE 0
#define EBCE 0
#define FWS 0x5
#define EWS 0x5

/*
* HardwareInit()
*
* Initializes the processor's clocks and PLL and returns the value of the reset status.
*
*/
uint32_t
HardwareInit(void)

{

uint32_t reset_cause;

reset_cause = SYSCTL->RESC; // read clock control and status register to get cause of reset bits
SYSCTL->RESC = 0; // clear reset flags


/*
* Perform oscillator/PLL setup for 120 MHz SYSCLK speed
*/

SYSCTL->MOSCCTL |= 1 << 4;       // high speed crystal connected to MOSC (>= 10 MHz)
SYSCTL->MOSCCTL &= ~(1 << 2); // enable external oscillator
SYSCTL->MOSCCTL &= ~(1 << 3); // power up the main oscillator
while(!(SYSCTL->RIS & (1 << 8)))
        ;        // wait for oscillator ready

SYSCTL->RSCLKCFG &= ~(0b11111111 << 20);         // clear oscillator and PLL source field
SYSCTL->RSCLKCFG |= (0x3 << 20);                            // set MOSC as oscillator source
SYSCTL->RSCLKCFG |= (0x3 << 24);                            // set MOSC as PLL input source

SYSCTL->PLLFREQ0 = (MFRAC << 10) | MINT;           // set PLL M integer and fractional values
SYSCTL->PLLFREQ1 = (Q << 8) | N;                               // set PLL N and Q
SYSCTL->PLLFREQ0 |= 1 << 23;                                     // power up the PLL

SYSCTL->MEMTIM0 = (EBCHT << 22) | (EBCE << 21) | (EWS << 16) | (FBCHT << 6) | (FBCE << 5) | FWS;      // set memory timing parameters

while(!(SYSCTL->PLLSTAT & 1))
            ;                        // wait for PLL to lock

SYSCTL->RSCLKCFG |= (1 << 31) | (1 << 30) | (1 << 28) | PDIV;         // set PLL system clock divisor, lock the system clock to the PLL, and force a memory timing register update


/*
* Enable user fault, bus fault, and mm faults
*/
setshcsr(0x70000);

return(reset_cause);

}

  • Hello Jerry

    To make sure we safeguard against incorrect programming the API SysCtlClockFreqSet is provided as part of the TivaWare API. The examples for the using the same are available in TivaWare examples for TM4C129x devices.

    You can go through the API, if you still wish to use DRM style (I strongly recommended not using DRM recently and got a slam dunk on the forum). Again: Avoid DRM, use TivaWare (which is better than what other vendors provide for driver library), sharpen your skills with the device before going "true" bare metal.

    Regards
    Amit
  • Amit,

    Thanks for the comments.

    As I mentioned in my original post, I don't want to use TivaWare or any other API. I want to program the chip at the bare metal register level. I have experience programming dozens of microcontrollers at the register level going back to the 1980s, so I'm not a newbie at this.

    If anyone has any suggestions as to what my code is not doing right, please let me know. I'm sure that it's just something very subtle that I don't have quite right.

    Thanks.

  • Hi Jerry,

    Actually the solution is quite simple: code it in TivaWare and then copy the generated code to your DRM pile.  This way you don't have to ask Amit (or this community) to waste their time serving your personal preferences.

    Regards,

    Dave

  • Might "personal preferences" rise (bit) high w/poster & friend?  

    Fortunately - the world does (not) always honor such hopes/desires - especially so when a clearly superior alternative (API) is placed squarely at their doorstep!

  • Hello Jerry,

    Did you try step debug of the sequence, to see where it hangs? Also I would like to mention that there is a new errata (not yet published) which may cause the sequence to be changed (which the SysCtlClockFreqSet will accommodate without user evaluation of custom steps)

    Regards
    Amit
  • Okay, I found and fixed the problem and the answer is making me see red and I'm very angry...

    It turns out the only problem with my code was the following line:

    SYSCTL->MEMTIM0 = (EBCHT << 22) | (EBCE << 21) | (EWS << 16) | (FBCHT << 6) | (FBCE << 5) | FWS; // set memory timing parameters

    It turns out to make the clock/PLL setting code work one must set bits 4 and 20 in the MEMTIM0 register. These bits are listed as RESERVED bits in the TM4C1294NCPDT data sheet! WTF!!! Why would these bits be listed as reserved in the data sheet if they have to be set in order for the chip to work properly? It's not mentioned in the errata either.

    This puzzled me so much that I decided to download TivaWare and see what it does. TivaWare has a function that returns the value to write to the SYSCTL->MEMTIM0 register that's appropriate for a given clock speed. It uses a lookup table to return a value, and entries in this table look like this:

    { 40000000, (SYSCTL_MEMTIM0_FBCHT_1_5 | (1 << SYSCTL_MEMTIM0_FWS_S) |
    SYSCTL_MEMTIM0_EBCHT_1_5 | (1 << SYSCTL_MEMTIM0_EWS_S) |
    SYSCTL_MEMTIM0_MB1) },

    The last item is the smoking gun: SYSCTL_MEMTIM0_MB1. This is defined in hw_sysctl.h as follows:

    #define SYSCTL_MEMTIM0_MB1 0x00100010 // Must be one

    Guess what! This has RESERVED bits 4 and 20 set! Again, WTF! Why doesn't the data sheet or the errata say something about this?

    Now I know why everyone on this forum is saying "just use TivaWare" -- it's because it knows how to deal with important details that are not listed in the datasheets.

    I've just wasted hours tracking this down, and man am I pissed!
  • Hello Jerry

    That is correct. Certain bits are reserved and "Software should not rely on the value of a reserved bit. To provide compatibility with future products, the value of a reserved bit should be preserved across a read-modify-write operation." This is the statement on the reserved bits in the data sheet.

    Regards
    Amit
  • May I (really) note my happiness for your expanded method - and success.

    What you endured should not have happened - yet (as you know) ARM MCUs are complex - and the "Sherpa Guides" (API & proponents) have made that climb many times - & extended their hand.   Register-Only trails are badly marked (if at all) and loitered w/ "dead/dying bodies."

    From a general logic (and business standpoint) far more vendor time & effort is invested in insuring that the API is correct & functional. (especially so w/those most commonly used functions)   Now a 1K+ manual - that many (most) only skim - and w/hundreds of pages of "mind-numbing" register bit notations - surely takes far longer (if ever) to fully correct.  (I past worked @ a similar "giant" semi-firm - I wrote portions of those manuals...)

    Now - as small, tech biz owner - I cannot allow the pitfalls & inefficiency which Register-Only usage invites - even welcomes. The race is to the swift - to those who can get their product to work - and then to market - EARLY (while the profits are still HIGH) - and "Now you know" the rest of the API story!

    The greatest vendor attention is directed towards the API - and by rejecting it - you "Toss that security blanket to the curb!"

    Is that fair?   Is that right?   Really - who cares - it IS reality - and we must (all) deal with it...

  • It's been decades since I've worked with a CPU or MCU where doing a RMW access to a register with reserved bits would crash the processor. I should have been wary of this even though I haven't seen it for such a long time. I wish TI would have used a few more transistors to ensure this didn't happen with their products.

    I'm sorry if my earlier posts came across as overly bitching. I was perhaps a little overly hot and perturbed and should have throttled the tone of my posts a little.

    I'm still not a fan of vendor APIs, though. In my career, I've spent perhaps as much time debugging vendor libraries as I have writing my own. It got to the point where I decided not to bother with vendor libs and write all of my own code from scratch. I still feel this is the best approach for my current needs and will continue to eschew these libraries. YMMV.
  • Again - I'm sure that all here are glad that you've solved your noted issue.

    And of course you're free to employ (any) means (even writing your own code from scratch) to meet your goals & comfort level.   You acknowledge that, "Life Guards" AND the API provide similar service - yet you've chosen to (dive) into (often) unmarked (shallow) waters - where the outcome may not always prove pleasant!    

    Those responding/guiding - once more - have made their time, effort & expertise available to you - seeking only your success.   That fact should be notable - as should their (very) considered choice (after weighing many variables) to (most always) employ the API.   Bon chance mon ami...