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.

Compiler/SW-EK-TM4C1294XL: How to set system clock frequency to 120 MHZ and How calculation execution time of instructions In TM4C1294xl

Part Number: SW-EK-TM4C1294XL
Other Parts Discussed in Thread: EK-TM4C1294XL, TM4C1294NCPDT

Tool/software: TI C/C++ Compiler

Hi all,

I woarking on watchdog timer which requires calculation of execution time of each instruction can any help me with this.

Iam also want to how set set clock frequency and what is the defualt clock frequency and how to set it to max 120 MhZ

  • Since you are using a TI LaunchPad, the best way to learn how to setup the system clock frequency is to look at example code that comes with TivaWare. If you install TivaWare 2.1.4.178 to the default location then the example programs for your board are in:

    C:\ti\TivaWare_C_Series-2.1.4.178\examples\boards\ek-tm4c1294xl

    Most of these examples will set the system clock frequency to 120 MHz. The following file:

    C:\ti\TivaWare_C_Series-2.1.4.178\examples\boards\ek-tm4c1294xl\project0\project0.c

    contains one such example:

        //
        // Run from the PLL at 120 MHz.
        //
        ui32SysClock = SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ |
                                           SYSCTL_OSC_MAIN |
                                           SYSCTL_USE_PLL |
                                           SYSCTL_CFG_VCO_480), 120000000);

  • *** LIKE ***

    One wonders, "Why & How" - those "guiding/influencing" (yet not instructing) such new users have "Failed SO Badly" to convey the vital (required) direction - you've nicely supplied!

  • cb1_mobile said:

    *** LIKE ***

    One wonders, "Why & How" - those "guiding/influencing" (yet not instructing) such new users have "Failed SO Badly" to convey the vital (required) direction - you've nicely supplied!

    Thank you.

    When I first started with TI MCUs and TM4C in particular, I was overwhelmed by the sheer amount of information that is available. There are the web pages pertaining to the MCUs; the web pages pertaining to the LaunchPads; more User Guides than you can shake a stick at; Application Notes; the Wiki; the Forums; the Datasheets...

    So the question isn't whether the information you need is available; rather it is how to find that information!

    What I've learned to do, in this order, is:

    (1) Look for a TivaWare code example; the examples are well-documented with comments for almost every line of code

    (2) In fact, all of TivaWare is well documented. If you're programming a peripheral, find the driverlib file pertaining to it. The source code contains very good documentation.

    (3) When working with a LaunchPad, its User Guide and schematic are helpful.

    (4) The MCU datasheet "Functional Description" and register documentation.

    (5) When all else fails, ask in the forums!

    Items 1 and 2 require being familiar with how code is organized within the TivaWare directory. It can seem overwhelming because there are so many directories and files, but I find that most of the time I'm looking in driverlib and examples.

    It helps if you can do fast text searching. I use UltraEdit as my editor; it has a "Find In Files" feature that I use all day long. So for example if I am looking at a TivaWare example and come across a call like SysCtlClockFreqSet() as shown above, I can immediately highlight "SysCtlClockFreqSet" and do a "Find In Files" under C:\ti\TivaWare_C_Series-2.1.4.178\driverlib to find the function itself. If a function is not found in driverlib then I go up a directory and search in C:\ti\TivaWare_C_Series-2.1.4.178. If you are working in CCS then there is a "Go To Definition" feature. I don't do editing in CCS though, only building and debugging, so I can't help much there. The nice thing about text search, rather than "go to definition," is that text search can show you where the function is used in addition to showing you where it is defined. So you can learn from additional examples.

    Hope this helps.

  • TI thinks this resolved, really!

    Yet poster asked another question not yet answered relative to the dog timer and where to find the instruction times.
  • On any decent idea, you can right click a word and find it's definition and implementation, making life much easier.
  • Yours is an excellent "reference" - yet the clear "Failure" by poster's "guide/advisor" is to be well noted!
    Employing this forum as a "dumping ground" - lessens its value - and should be resisted...
  • Danny F said:
    On any decent idea, you can right click a word and find it's definition and implementation, making life much easier.

    I'm not so sure about your wording "decent idea" - yet your advice is accurate & helpful.

    Is it not "highly unlikely" that any New User would,  "Have such awareness?"      This IS my point - the user has arrived "Unguided & Unsupported" - that's a crime...

    Good as your (and poster 12_squared's) advice is - it will (very) shortly  "Rotate away into forum oblivion" - rarely (if ever) to be seen again...

  • You are correct. I answered relative to the system clock (because I know the answer to that) and was hoping someone else would jump in and answer about the watchdog. However in the meantime I looked into example code and datasheet on the watchdog. The OP asked about "calculation of execution time of each instruction." However I think the OP is really asking what load value to use with the watchdog to get a desired watchdog timeout. There is an example here:

    C:\ti\TivaWare_C_Series-2.1.4.178\examples\boards\ek-tm4c1294xl\watchdog\watchdog.c

    Like the other example I mentioned, the system clock frequency is set once again with:

        g_ui32SysClock = MAP_SysCtlClockFreqSet((SYSCTL_XTAL_25MHZ |
                                                 SYSCTL_OSC_MAIN |
                                                 SYSCTL_USE_PLL |
                                                 SYSCTL_CFG_VCO_480), 120000000);
    

    At a system clock of 120 MHz, the watchdog counts down each 1/120,000,000 of a second. Hence if you want, say, a 1 second timeout, the load value is 120,000,000. If you want a 0.5 second timeout, that would be 60,000,000. And so on.

    The example sets the period to 1 second:

        //
        // Set the period of the watchdog timer to 1 second.
        //
        ROM_WatchdogReloadSet(WATCHDOG0_BASE, g_ui32SysClock);
    

    Note the parameter g_ui32SysClock is the same value saved in the call to SysCtlClockFreqSet(), which is 120,000,000.

  • pras p said:
    I woarking on watchdog timer which requires calculation of execution time of each instruction can any help me with this.

    Why would you need to calculate the execution time of each instruction to determine the watchdog? That seems a backwards way of approaching things?

    Robert

  • The right way to find that load value requires counting the number of instructions to be executed up to the point of function/s exit and totaling instruction times. Then set dog reload value with the smallest time value the function/s can fully execute before exit without feeding the dog again to keep it from expiring. A loop function of course keeps kicking the dog with the smallest possible reload value.

    Merely setting the load value to 1 second may cause very bad things to occur if or when switching large voltages. That of course assumes something has gone wrong prior to 1 second dog expiring. That case bits and pieces of plastic lie strewn around a chard FR4 PCB surface and a very bad smell permeates the room.
  • BP101 said:
    The right way to find that load value requires counting the number of instructions to be executed up to the point of function/s exit and totaling instruction times. Then set dog reload value with the smallest time value the function/s can fully execute before exit without feeding the dog again to keep it from expiring

    No. Especially in control loops involving PIDs etc..., you determine how often the loop must be serviced in order to perform correctly. Determining how long it takes is a matter of loading not of correct operation. Indeed if you want a more secure check then you also very the loop isn't executing too often. Haven't seen many people do that though.

    Sometimes, if dealing with long operations you might use sub period monitoring and check for step completion rather than overall loop. The principal is still the same however. Setting the watchdog time to the execution time appears bass ackwards

    Robert

  • The thing I would be concerned about is false alarms / nuisance trips.

    I have instrumentation built in to my firmware, including code that uses a timer peripheral to measure to 2 uS accuracy the "scan time" of the program, meaning the time it takes to complete one revolution through the main loop. The software is polled superloop and all "tasks" are written as state machines that perform a short non-blocking operation and return to the main loop.

    The measured scan time can vary wildly depending on what software is doing at the moment. However it is up to several milliseconds, no more. The instrumentation makes it possible to display the average and maximum scan times encountered, so we know what that maximum expected value is.

    If I were setting up my watchdog, I would feed the dog once per main loop. I would do so only if the software's "sanity checks" pass. And I would set the dog timeout interval to, say, twice the maximum scan time. This way, I would have reasonable confidence of avoiding false alarms, while catching any really ugly problems within only a few milliseconds of things going awry.

    Of course, everything requires: testing, testing, testing!
  • twelve12pm said:
    The thing I would be concerned about is false alarms / nuisance trips.

    Pretty much by definition they would not be false. They indicate a real problem with the system. If your system cannot respond in the time allotted that indicates a problem that must be addressed.

    twelve12pm said:
    If I were setting up my watchdog, I would feed the dog once per main loop.

    If?

    You are measuring the wrong thing. It's not your superloop time that matters. It's the time for your control structure to run. One of the problems that superloops have is that they obfuscate the control structure.

    So if you have something simple like the following

    • A 1 ms control loop on current (perhaps a limit or a PID).
    • A user input running at 50mS which gathers setpoints (say throttle and direction) which are fed to the output.

    Then you have two critical controls that must run at speed in order for your control to be successful. The 1mS loop would be particularly critical so you might watchdog it at 11mS (any longer would be a failure). The user input loop should run every 50mS but maybe you can allow a little more sloppiness there and watchdog it at 75mS. In either case exceeding the associated time is a problem and the superloop time is irrelevant.

    Note also that in both of these cases running too fast can also be considered a problem but it's not usually watched for.

    twelve12pm said:
    , twice the maximum scan time

    PLC background perchance?

    Robert

  • See also my screed here (e2e.ti.com/.../2447636) on how to properly set up a watchdog.

    Robert

  • Robert Adsett said:

    twelve12pm
    , twice the maximum scan time

    PLC background perchance?

    Robert

    Yes.

    Robert Adsett said:

    See also my screed here (e2e.ti.com/.../2447636) on how to properly set up a watchdog. 

    Robert

    Thank you for your post at the link above. I appreciate your posting it and I will certainly put some considerable thought into that.

    I have a different approach for dealing with the unexpected.

    I do not feed the watchdog in an interrupt because main context could get stuck in an endless loop somewhere, while interrupts may continue to work. Hence I do the feeding in the superloop, and only if all "tasks" (interrupts and main context based state machines) report they are OK (similar to your software watchdogs), and all "sanity checks" pass.

  • Robert Adsett said:
    No. Especially in control loops involving PIDs etc..., you determine how often the loop must be serviced in order to perform correctly

    No is definitive yet totaling instruction times is a proper method to determine how long the dog timer should remain primed within the realm of a certain software loop, interrupts or not. Your basically saying the same thing but in a different narrative as serviced is simply kicking, petting, feeding the dog at the beginning of repeating loop execution. 

    Robert Adsett said:
    Indeed if you want a more secure check then you also very the loop isn't executing too often

    The primary idea is to monitor if the software (does not) complete proper flow within the watchdogs expiration 1st timeout, anything beyond that is simply a bonus to the hardware especially if the 2nd timeout executes MCU POR. I disable that 2nd timeout reset feature as it tends to cover up software design flaws, precise bus faults or the stack blowing up etc.. 

    Robert Adsett said:
    Setting the watchdog time to the execution time appears bass ackwards

    Total instruction execution times within the function/s that would be perceived failure or possible destructor of hardware controlled within watchdogs expiration time. Will review your dog link above yet the method I describe works quite well during PWM inverter commutation cycles with several GPTM, ADC interrupts occurring within the same loop. 

  • BP101 said:

    Robert Adsett
    Indeed if you want a more secure check then you also very the loop isn't executing too often

    The primary idea is to monitor if the software (does not) complete proper flow within the watchdogs expiration 1st timeout, anything beyond that is simply a bonus to the hardware especially if the 2nd timeout executes MCU POR. I disable that 2nd timeout reset feature as it tends to cover up software design flaws, precise bus faults or the stack blowing up etc.. 

    I agree with placing the system in a "safe state" using the absolute minimum of instructions. Once a serious malfunction occurs -- whether it's the CPU stopping, memory becoming corrupt due to hardware / software /  solar flares etc, or some larger problem in the system -- the instructions in your software may or may not actually execute. So you need a layered approach to deal with these issues across software, hardware, and the overall system; the watchdog is only one line of defense.

  • twelve12pm said:
    Of course, everything requires: testing, testing, testing!

    Three mentions of  "testing" - where is, "Thoughtful, focused & carefully planned - DESIGN?"

    Testing - provided it is (both) proper & sufficiently extensive - (may) uncover program and/or design weakness.     Yet - too often "testing" is, "Last/late to be considered" - and then - "After the fact!"

    Provision should be made - early & "up front" - for key/critical board measurements - for robust, "Instrument attachment points" (or accommodation of "Bed of Nails") test platforms.

    But for poster Robert - all watchdog references here - focused upon "Code Segment Execution" - taking "Too long."     Cannot the reverse (segment executing too FAST) also prove true?    And what then?

    In the Analog world - "Window Voltage Comparators" assure that the signal is w/in (both) "Low & High" bounds.     Should not (some) checks be implemented to, "Catch key/critical Code Segments - which execute too quickly?     (signaling "premature exit" - either for "fair" or  (especially) "unwanted/distressed" reasons?)    

    This check - along w/Robert's suggested, "monitoring of function's execution frequency" - can enhance code's performance.     And neither is likely to result from (just) "testing."

  • cb1_mobile said:

    twelve12pm
    Of course, everything requires: testing, testing, testing!

    Three mentions of  "testing" - where is, "Thoughtful, focused & carefully planned - DESIGN?"

    That's the DESIGNER'S JOB!!!!!

    You wouldn't want me to ruin someone's job security, would you? :-p

  • twelve12pm said:
    ruin someone's job security

    The "guilty party" may have - "accomplished that fact" - all on their own.

    It proves "rare" to "Test In" Quality.      In depth, methodical, "thought & planning" - during the Design Process (which itself should flow into "test") prove the best drivers towards  "success."

  • twelve12pm said:
    Robert Adsett
    twelve12pm
    , twice the maximum scan time

    Robert

    That explains both your use of 'scan time' and your choice of watchdog. The former is a concept the should be applied to more embedded systems, the latter should not.

    High end PLC use a better watchdog from what little I've seen of them. They allow multiple processes so a scan time watchdog cannot work. These processes are usually run on a regular schedule. One might run every 10mS and another every 55mS. The watchdog(s) then check that each one completes its allotted work within it's scheduled time. That's more akin to what I suggest.

    twelve12pm said:
    I do not feed the watchdog in an interrupt because main context could get stuck in an endless loop somewhere, while interrupts may continue to work.

    There's a reason I used the word process rather than interrupt.

    However note that your complaint here equally applies to a superloop. The loop may continue blissfully along without executing critical processes in a timely manner. Conversely the superloop may execute slowly at some time but still meet its deadlines for critical processes easily. The time it takes to execute the superloop is not obviously correlated to meeting process execution requirements.

    twelve12pm said:
    Hence I do the feeding in the superloop, and only if all "tasks" (interrupts and main context based state machines) report they are OK (similar to your software watchdogs), and all "sanity checks" pass.

    If those checks include timeliness of the processes in the tasks then it devolves into the same as I've suggested, perhaps with less structure and more complexity. If it does not then I think you are missing an important check.

    Robert

  • twelve12pm said:
    cb1_mobile
    twelve12pm
    Of course, everything requires: testing, testing, testing!

    You wouldn't want me to ruin someone's job security, would you? :-p

    I do want the designer to do their job and that includes setting bounds on the execution time for critical processes.

    Robert

  • cb1_mobile said:
    But for poster Robert - all watchdog references here - focused upon "Code Segment Execution" - taking "Too long."     Cannot the reverse (segment executing too FAST) also prove true?    And what then?

    I don't check for that often enough myself.

    Certainly a PID will fail if it strays far off a metronome like repeatability.

    Robert

  • BP101 said:
    Robert Adsett
    No. Especially in control loops involving PIDs etc..., you determine how often the loop must be serviced in order to perform correctly

    Nope, NADA, Anti-yes.

    That's far enough different from what I said to not even be wrong.

    BP101 said:
    Robert Adsett
    Setting the watchdog time to the execution time appears bass ackwards

    Phenomenological setting up of the watchdog time, especially when done in conjunction with disabling the watchdog (and only using it as a timer) is asking for problems. If you do not have requirements for the time you cannot say you are meeting them.

    Robert

  • twelve12pm said:
    So you need a layered approach to deal with these issues across software, hardware, and the overall system; the watchdog is only one line of defense.

    And the last one at that. If you reach the state where the watchdog is firing then you can no longer be sure of anything. That's the purpose of the reset, to get to a clean state (if possible) as quickly as possible in the surest fashion possible. It is not part of the normal error detection process, it is not part of the normal error recovery, you should never depend upon it, it is a last ditch, desperate attempt to salvage the system.

    Robert

  • Robert Adsett said:
    If you do not have requirements for the time - you cannot say you are meeting them.

    Bravo - and as noted - "Bounds" - both high & low - offer the greatest SAFETY!    

    As to your response to "one" here:  "Nope, NADA, Anti-Yes" ...  might you share how you (really) feel?     (no personality contest lands here - yet...)

  • cb1_mobile said:
    might you share how you (really) feel?  

    Well..., you know, the cold reserve of the tundra restricts emotional expression.

    Robert

  • Such HAS been noted!
  • Robert Adsett said:
    That's far enough different from what I said to not even be wrong.

    Robert I think you are confusing the watchdogs required load count function with it being some kind of SW watchdog. That is in the thread link provided above you state there being a SW watchdog, what are you thinking?

    The required reload function (kicking, petting, feeding) of watchdog peripheral is not a last ditch effort, rater a front line defense for both SW and HW faulting. The TM4C1294 datasheet does list all instructions but FAILS to indicate any timing relative to clock ticks. Past computer systems I maintained had a seamless watchdog located on main processor board, some how kept other system processor boards from ever faulting in (S100) bus architecture. Either that or the watchdog never fired, that's how good those business systems were and very expensive at that.    

    The likely hood of executing code to fast would seem to suggest program stack failure or an instruction pointer failure occurred outside of the watchdogs peripheral reload count time window. That would still trigger the watchdog 1st timeout flag if the control function loop no longer is being monitored by it failing to reload the watchdog interval count.

    I am curious if or how a 2nd watchdog could be made to watch 1st watchdog in a double dog team or if anything at all can be gained by doing that.

  • BP101 said:
    Robert Adsett
    That's far enough different from what I said to not even be wrong.

    Nope

    BP101 said:
    That is in the thread link provided above you state there being a SW watchdog, what are you thinking?

    If you were to read it carefully you would see it all depends upon the hardware watchdog. It is, in actuality, an elaboration on the HW watchdog and the HW watchdogs proper functioning is critical.

    BP101 said:
    The required reload function (kicking, petting, feeding) of watchdog peripheral is not a last ditch effort, rater a front line defense for both SW and HW faulting.

    That approach leads to perdition and many fruitless hours of debugging items which have little to nothing to do with the actual required performance.

    BP101 said:
    The TM4C1294 datasheet does list all instructions but FAILS to indicate any timing relative to clock ticks. 

    That makes sense, clock tick timing is a software issue.

    BP101 said:
    Past computer systems I maintained had a seamless watchdog located on main processor board, some how kept other system processor boards from ever faulting in (S100) bus architecture. Either that or the watchdog never fired,

    In a properly built mature system, the watchdog should (almost) never fire. If the watchdog fires that's by definition a serious problem.

    BP101 said:
    The likely hood of executing code to fast would seem to suggest program stack failure or an instruction pointer failure occurred outside of the watchdogs peripheral reload count time window

    These are your only suggestions?

    BP101 said:
    I am curious if or how a 2nd watchdog could be made to watch 1st watchdog in a double dog team or if anything at all can be gained by doing that.

    You can implement a separate independent watchdog. Such might be done to catch problems with oscillator failures etc... I've not done so, but I can imagine there are systems that would need multiple watchdogs.

    Robert

  • Robert Adsett said:
    BP101 The TM4C1294 datasheet does list all instructions but FAILS to indicate any timing relative to clock ticks

    Robert Adsett said:
    That makes sense, clock tick timing is a software issue.

    It was a complaint as other processors often list each instruction duration relative to a number of system clocks. The only way to know what instructions of a function are executing is via debug disassembly view, link source to window. Seem to recall seeing Thumb instruction times somewhere in the past. Perhaps it was a Wiki page as they are not in the ARM Cortex Ref Manual, only a few instructions indicate a number of cycle times.
    Robert Adsett said:
    You can implement a separate independent watchdog. Such might be done to catch problems with oscillator failures etc... I've not done so, but I can imagine there are systems that would need multiple watchdogs.
    I currently have both dogs expiration handler in the same function, tests peripheral IRQ status to know which dog expired. One dog is now doing all the work to monitor several functions but two dogs might be better than just one, at least it would seem so. The odd part is somehow the default setting to reset MCU on second timeout was asserting SWRST on bus faults yet the count was not being reloaded via SW function when that occurred.
    There seems to be a SYSCTRL built in dog (heart beat) that checks the APB/AHB/CPU and recall reading text in the SYSCRTL section relative to watchdog peripheral default behavior, when it is enabled. The same Watchdog (reset MCU) was also randomly causing issues with ICDI gaining DAP control. That DAP behavior stopped after disabling reset MCU on 2nd timeout. So it seems the watchdog may be system control preemptive as well, without reloading a count interval.
    Seemingly the dog expiration handler function is continuously cycled pre-empted by the watchdog peripheral when ever the timer expires but does not trigger 1st or 2nd timeouts. The smart watchdog seems to know that after the reload count is transferred by the application the expiration IRQ flags are thus valid in NVIC. That would suggest the count down timer auto reloads a system default count on reaching zero if the dog is not being fed by SW, perhaps when the BUS has control. Other wise the HW dog would be dead, no heart beat.
  • I checked the Watchdog initialization code to confirm this. It loads the default reload value but never asserts a timeout flag after that unless reload count is being updated in a loop. That is to say the dogs counter is being updated inside the application loop via WatchdogReloadSet().

    BTW: Just discovered Tivaware SysCtlClockGet() function often used in older firmware to reset the watchdog reload value is only valid for TM4C123 and not supported with TM4C1294.
  • BP101 said:
    BTW: Just discovered Tivaware SysCtlClockGet() function often (past) used  to reset the watchdog reload value is only valid for TM4C123 and not supported with TM4C1294.

    Your "discovery" has,  "Long been known!"      The "complementary function" to "SysCtlClockGet()" ... "SysCtlClockSet()" - also exited w/the arrival of '129!        Thus you/other '129 users - get to deal w/a brand new function for System Clock frequency Setting!

    We are told that (any)  "Fountain of Youth" (still) awaits your (latest) discovery...   

  • Point is the compiler was silent when it should be flagging an error/s otherwise what is the point of having an MCU variant or Symbols that indicate the MCU to the linker. The asserts of SysCtlClockGet() should also have flagged CCS code analyzer warnings, yet it remained silent.

    Odd thing is the compiled code seemed to work or at least was not causing any apparent issues.
  • Some here continue in the belief that your "point" was,  "As Presented": the invalidity of  "SysCtlClockGet()"  -  "just discovered."     Your earlier "discovery post" - made no mention of compiler issues - and appeared to have "missed" the "enormity" of the System Clock change!

    If you are seriously interested - Amit dealt w/many such "System Clock issues" - brought on by the "Changed Functions" - demanded by the '129.      Search box - up top - awaits your "click barrage."

    BTW - you "do" ...  look younger.     Might your (other) discoveries have (better) panned out?

  • BP101 said:

    BTW: Just discovered Tivaware SysCtlClockGet() function often used in older firmware to reset the watchdog reload value is only valid for TM4C123 and not supported with TM4C1294.

    This is why I write functions like this:

    struct GlobalData {
    	uint32_t SysClockFreqHz; // Actual system clock frequency in Hz
    
    	bool HaveSysClockPllVco; // true if PllVco contains a valid value
    	                         // false if PLL VCO was not obtained, cannot be
    	                         // obtained, and/or PLL is not used
    
    	uint32_t SysClockPllVco; // Calculated value of PLL VCO before system
    	                         // divider is applied, as obtained from TivaWare
    	                         // SysCtlVCOGet()
    	
    	// Other global data here
    	.
    	.
    	.
    };
    
    
    struct GlobalData Global;
    
    
    static void SetUpSystemClock(void)
    {
    	#if defined (PART_TM4C129ENCPDT)
    		MAP_SysCtlMOSCConfigSet(SYSCTL_MOSC_HIGHFREQ);
    
    		Global.SysClockFreqHz = 
    			MAP_SysCtlClockFreqSet(
    				(
    				 SYSCTL_XTAL_25MHZ | 
    				 SYSCTL_OSC_MAIN   | 
    				 SYSCTL_USE_PLL    | 
    				 SYSCTL_CFG_VCO_480
    				), 
    				SYSTEM_CLOCK_FREQ_HZ
    			);
    		
    		Global.HaveSysClockPllVco = 
    			SysCtlVCOGet(SYSCTL_XTAL_25MHZ, &Global.SysClockPllVco);
    
    	#elif defined (PART_TM4C123GH6PM) || defined (PART_TM4C123AH6PM)
    		MAP_SysCtlClockSet(
    			SYSCTL_SYSDIV_2_5 | 
    			SYSCTL_USE_PLL    | 
    			SYSCTL_XTAL_16MHZ | 
    			SYSCTL_OSC_MAIN
    		);
    
    		Global.SysClockFreqHz = MAP_SysCtlClockGet();
    		
    		Global.HaveSysClockPllVco = false;
    		Global.SysClockPllVco = 0;
    
    	#else
    		#error "Not setting system clock!"
    
    	#endif
    
    	if (Global.SysClockFreqHz == 0) {
    		// Failed to set system clock!
    		... handle this error ...
    	}
    }
    

    This encapsulates the behavior but more importantly it codifies the "knowledge" that system clock is set differently on TM4C123 and TM4C129.

    I've written functions like this to handle all sorts of differences, including in how uDMA signals completion in the different chips, etc.

    It uses compile-time checks to select the appropriate code based on the PART_* define set at the project level.

    This code probably won't work for you as-is. You would need to customize it for your MCUs and boards. I posted it to illustrate the overall idea of building up a "library" of such functions so that you won't need to remember all these little details and clutter your program with lots of ifdef statements. Only the encapsulation functions need to be cluttered this way.

  • BP101 said:

    Point is the compiler was silent when it should be flagging an error/s otherwise what is the point of having an MCU variant or Symbols that indicate the MCU to the linker. The asserts of SysCtlClockGet() should also have flagged CCS code analyzer warnings, yet it remained silent.

    Odd thing is the compiled code seemed to work or at least was not causing any apparent issues.

    The compiler cannot and will not flag any kind of error. The compiler toolchain only knows how to translate the code you write in C to machine code. When you call a function, whether that is "allowed" for your MCU / board or not, the compiler has no way to know and does not care. It generates the code to call that function.

    The only way you *could* get a compiler error is if you custom-built the TivaWare library for each chip, excluding functions that are not allowed for that chip. Then, when code attempts to make that call, the compiler and/or linker will be unable to locate that function and will therefore flag an error.

    I've found that the TivaWare driverlib functions are commented very well. When you make a call to any TivaWare function, it is very important to first look up its definition and read the description! I am not sure if it's true 100% of the time but so far whenever I've needed to call a function that is only good for some TM4C parts and not others, it says so in the function documentation. Most of the functions are short and most assign one or more peripheral control registers. So you need to look in the datasheet and make sure that the registers exist and that the particular bits in the registers are implemented. If so, then the function will work.

  • May I ... ***   LIKE   ***    Both posts - excellent.

    Especially your wording:  "true if PllVco contains a valid value  -  false if PLL VCO was not obtained, cannot be obtained, and/or PLL is not used.      Most excellent - (detailed & reads - like a legal brief)

    The vendor change imposed (much) extra awareness & in your case extra effort - upon its user base.      Your method "is" one means of compensating for such change - yet may be thrown into (some) disarray - by (further) vendor changes - downstream.

    It would be of interest to know - in general - how you (similarly) managed the (rather extreme) code changes demanded by the (extended) I2C module.     (the "back to back" (inverted) Ready Check has been acknowledged to fail - under some conditions!       A "real fix" has long "seemed in order.")  

    Good job - much appreciated - and excellent content & presentation...   (crack staff/I believe)

  • cb1_mobile said:

    May I ... ***   LIKE   ***    Both posts - excellent.

    Thank you.

    cb1_mobile said:

    Especially your wording:  "true if PllVco contains a valid value  -  false if PLL VCO was not obtained, cannot be obtained, and/or PLL is not used.      Most excellent - (detailed & reads - like a legal brief)

    If it were a legal brief it would read more like this: "False if PLL VCO not available for any reason including but not limited to failure and/or inability to use and/or obtain PLL VCO and/or lack of necessity to do the same, whether due to technical or legal reasons, licensing, tort, negligence, acts of God, and/or any other legal theory now known or later developed."

    cb1_mobile said:

    The vendor change imposed (much) extra awareness & in your case extra effort - upon its user base.      Your method "is" one means of compensating for such change - yet may be thrown into (some) disarray - by (further) vendor changes - downstream.

    That is why the ifdef logic only tests for the several parts we are using and if the part is otherwise, a compiler error is generated and compilation stops. In the future, if newer TM4C series parts add anything new that must be handled, we will need to implement an additional case for that. However, once implemented, the knowledge is codified once again and we need not remember it any longer.

    cb1_mobile said:

    It would be of interest to know - in general - how you (similarly) managed the (rather extreme) code changes demanded by the (extended) I2C module.     (the "back to back" (inverted) Ready Check has been acknowledged to fail - under some conditions!       A "real fix" has long "seemed in order.")  

    In short: we didn't. We have not used I2C with TM4C. In the past we ran into problems on boards we built with I2C hardware, mostly (I think) stemming from errata relating to the I2C peripherals of the MCUs in use (which were not TI MCUs). The software support for that seemed to be some sort of dark magic and there were still circumstances under which the I2C bus would get "stuck." It was an exercise in hair-pulling to say the least. I think we ended up remaking those boards with SPI parts instead.

  • twelve12pm said:
    That is why the ifdef logic only tests for the several parts we are using

    And - it is "Not Unknown" for design and/or process variations - to impact those (very) "parts you are using!"      The "ifdef" proves helpless - in your rescue - under those conditions...       (such has recently occurred @ another MCU vendor - my firm discovered - thought you'd "benefit" from such awareness.)       Not ALL defenses prove,  "ALWAYS and Forever" Successful!

  • twelve12pm said:

    Point is the compiler was silent when it should be flagging an error/s otherwise what is the point of having an MCU variant or Symbols that indicate the MCU to the linker. The asserts of SysCtlClockGet() should also have flagged CCS code analyzer warnings, yet it remained silent.

    Odd thing is the compiled code seemed to work or at least was not causing any apparent issues.

    The compiler cannot and will not flag any kind of error.

    [/quote]

    It can and, IMO, should. It's a matter of the libraries being done properly. Arguably even the need to check is the matter of a bad library decision but that a question for another day.

    One simple, if a trifle ugly, approach is along the following lines

    #ifdef SUPPORTED_PROCESSOR
       #define function(a,b) (function)((a),(b))
    #else
       #define function(a,b) __FUNCTION_function_not_supported()
    #endif

    I might be able to come up with something cleaner with effort. I might not, the pre-processor is bit of a crude tool.

    A second approach would be to redefine the original function in terms of the replacement via the macro.

    Alternatively PC-LINT (you are linting aren't you?) provide mechanisms to deprecate functions.

    However it's done, TI should have done it.

    Robert

  • Robert Adsett said:

    twelve12pm
    BP101

    Point is the compiler was silent when it should be flagging an error/s otherwise what is the point of having an MCU variant or Symbols that indicate the MCU to the linker. The asserts of SysCtlClockGet() should also have flagged CCS code analyzer warnings, yet it remained silent.

    Odd thing is the compiled code seemed to work or at least was not causing any apparent issues.

    The compiler cannot and will not flag any kind of error.

    It can and, IMO, should. It's a matter of the libraries being done properly. Arguably even the need to check is the matter of a bad library decision but that a question for another day.

    One simple, if a trifle ugly, approach is along the following lines

    #ifdef SUPPORTED_PROCESSOR
       #define function(a,b) (function)((a),(b))
    #else
       #define function(a,b) __FUNCTION_function_not_supported()
    #endif

    I might be able to come up with something cleaner with effort. I might not, the pre-processor is bit of a crude tool.

    A second approach would be to redefine the original function in terms of the replacement via the macro.

    Alternatively PC-LINT (you are linting aren't you?) provide mechanisms to deprecate functions.

    However it's done, TI should have done it.

    Robert

    That's library design. As I said, the compiler cannot and will not flag things like this -- unless your library is designed such that an actual compiler-recognized error results.
    The header file could have placed ifdef guards around the TM4C123-only functions so that when compiled for TM4C129 a compiler warning would be emitted to the effect that such function is declared implicitly. It would still compile though, so if you ignore compiler warnings, that won't help much.
    The alternative is to build a separate copy of the library for each MCU variant. Then you would install hundreds of megabytes of such libraries onto your computer. Not a terribly big deal in this day and age but then inevitably a certain percentage of people will mistakenly link against the wrong library variant.
    You could place ASSERT statements in said function which will have the effect of locking your code up in a while(1) loop or go to FaultISR() or something -- if compiled with DEBUG.
    There are lots of things you can do. But none of them make it unnecessary to understand the hardware on which you're writing software.
  • twelve12pm said:
    But none of them make it unnecessary to understand the hardware on which you're writing software.

    I cannot recall (anyone) here - arguing for,  "Minimizing HW grasp."       Somehow that final sentence appears to "break" - from your otherwise - well organized response.

  • twelve12pm said:
    That's library design.

    Yes, you have to make your design capable as well but the compiler can detect such things if the library is properly designed.

    The compiler can also detect other things like parameter mismatches etc... However, if the library is designed to use a single type for almost everything (say uint32_t) then you lose a lot of that capability. That doesn't mean the compiler is incapable of detecting an issue, it means the library has stunted the compiler's capabilities.

    twelve12pm said:
    The alternative is to build a separate copy of the library for each MCU variant.

    You could but I don't think the variants here demand that, or even favour it particularly. there are certainly system that do that though.

    twelve12pm said:
    You could place ASSERT statements in said function which will have the effect of locking your code up in a while(1) loop or go to FaultISR() or something -- if compiled with DEBUG.

    You could but that loses the advantage of compile time (or earlier) detection. The earlier you can detect an issue generally the easier it is to find and fix.

    More useful in early detection would be a TDD setup that had mocks of the library the detected that mismatches between processors. I don't think we are close enough to having a common TDD setup for that though.

    twelve12pm said:
    But none of them make it unnecessary to understand the hardware on which you're writing software.

    Nope, but there are certain errors that the compiler can help with finding if the libraries are built to take advantage of the standard compiler usages, and in some cases not actively work against the compiler.

    Robert

  • Actually the CCS code analyzer will/should flag a (warning) if the function being called includes an ASSERT test for specific MCU class type.  Likewise the compiler should throw and (error) for the same ASSERT test during compile or linking. If the function is known as are others to be class specific there is often an ASSERT test of MCU class type.

    Notice such test exists below the header area but failed to warn/error even in CCS7.3 with Code Analysis use workspace settings & run as you type set. That is what the ASSERT below is meant to do and failed to flag warning for the project included Symbol (CLASS_IS_TM4C129) being a mismatch.

    uint32_t SysCtlClockGet(void) {

    uint32_t ui32RCC, ui32RCC2, ui32PLL, ui32Clk, ui32Max;

    uint32_t ui32PLL1;

    //// This function is only valid on TM4C123 devices.

    ASSERT(CLASS_IS_TM4C123);

       

  • The ASSERT(CLASS_IS_TM4C123); Symbol missing/mismatch is also not checked with Code Analyzer set to run during compile. So the Tivaware library ASSERT testing of device class is not working and is very misleading to anyone that believes they are safe from monsters luring in dark corners.

  • BTW CCS build debug also did not fault or flag the ASSERT(CLASS_IS_TM4C123). Perhaps the compile silently stripped off the ASSERT.
  • This appears to be the code analyzer of the underlying Eclipse platform. Is that correct? Or is this something specific to CCS?
  • twelve12pm said:
    I've found that the TivaWare driverlib functions are commented very well. When you make a call to any TivaWare function, it is very important to first look up its definition and read the description! I am not sure if it's true 100% of the time but so far whenever I've needed to call a function that is only good for some TM4C parts and not others, it says so in the function documentation

    Good for developing a new project yet not so good when migrating existing projects from one MCU class to another. What about all the TM4C1294 example projects that TI never migrated from TM4C123 MCU and simply placed them in a folder with TM4C129xx name?

    That is why compiler cross checking for Symbols in calls made to Tivaware libraries makes good use of ASSERTS to identify MCU CLASS under the header.

    Perhaps one reason for no warning/errors during compile is the project defined library paths are sourcing compiled driver object, not the actual Tivaware drivers in the folders. Amit mentions some time ago CCS debug requires the Tivaware project source driver library must be compiled, I think for fault tracking of library source code. 

    This thread from the point of SysCtlClockGet() should be put into another post so we can look into why the Tivaware function ASSERTS are failing to warn CCS users.

  • BP101 said:

    twelve12pm
    I've found that the TivaWare driverlib functions are commented very well. When you make a call to any TivaWare function, it is very important to first look up its definition and read the description! I am not sure if it's true 100% of the time but so far whenever I've needed to call a function that is only good for some TM4C parts and not others, it says so in the function documentation

    Good for developing a new project yet not so good when migrating existing projects from one MCU class to another.

    Don't get me started about the "joys" of porting from one MCU to another!

    I will say, since we are writing one code base for TM4C129 and TM4C123, yes, there are differences causing us to run into some "gotchas!" along the way, but the process is MUCH easier using the TivaWare APIs than it would be if we had to stuff registers the old fashioned way. In other projects, when moving from one MCU to another, I would often end up having to re-code major portions from scratch because that was actually faster than having the datasheets for both MCUs open, identifying what each bit stuffed into each register meant on one device and trying to translate that to the other device. The whole idea of code reuse is to actually reuse your code! The TivaWare APIs have eased that pain significantly.

    If it truly is possible to run a Code Analyzer in CCS to identify that we are calling APIs we shouldn't because they don't match up with our MCU, that would be great! But something makes me doubt that it can actually work because the TivaWare ASSERTs and MCU CLASS defines are resolved at runtime, not by the compiler.

    BP101 said:

    Perhaps one reason for no warning/errors during compile is the project defined library paths are sourcing compiled driver object, not the actual Tivaware drivers in the folders. Amit mentions some time ago CCS debug requires the Tivaware project source driver library must be compiled, I think for fault tracking of library source code. 

    If, while single-stepping through your code, you wish to single-step into TivaWare code, then yes, you need to compile TivaWare with your project, to make the debug information available to the debugger. Otherwise you can only single-step into ASM code without seeing what code translated to that.

    Perhaps there are other benefits to compiling TivaWare?

    BP101 said:

    This thread from the point of SysCtlClockGet() should be put into another post so we can look into why the Tivaware function ASSERTS are failing to warn CCS users.

    Agreed. This has definitely gone off the original topic.