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.

TM4C123GE6PM: What is the correct way of waiting for a peripheral ready state?

Part Number: TM4C123GE6PM

I think I know the answer of the thread title's question, but let me explain why I'm asking it anyway.

I'm taking the Edx course Embedded Systems - Shape The World: Microcontroller Input/output. In one of the lectures there's a code fragment that's confusing me a lot. Here's the important part of that code:

#include "tm4c123ge6pm.h"

// Subroutine to initialize port F pins for input and output
// PF4 is input and PF2 is output
void PortF_Init(void) 
{ 
  volatile unsigned long delay;

  SYSCTL_RCGC2_R |= 0x00000020;     // 1) activate clock for Port F
  delay = SYSCTL_RCGC2_R;           // allow time for clock to start
  
  GPIO_PORTF_LOCK_R = 0x4C4F434B;   // 2) unlock GPIO Port F
  GPIO_PORTF_CR_R = 0x1F;           // allow changes to PF4-0
  
  // only PF0 needs to be unlocked, other bits can't be locked
  GPIO_PORTF_AMSEL_R = 0x00;        // 3) disable analog on PF
  GPIO_PORTF_PCTL_R = 0x00000000;   // 4) PCTL GPIO on PF4-0
  GPIO_PORTF_DIR_R = 0x0E;          // 5) PF4,PF0 in, PF3-1 out
  GPIO_PORTF_AFSEL_R = 0x00;        // 6) disable alt funct on PF7-0
  GPIO_PORTF_PUR_R = 0x11;          // enable pull-up on PF0 and PF4
  GPIO_PORTF_DEN_R = 0x1F;          // 7) enable digital I/O on PF4-0
}

What bothers me here is line #10. I know what is the purpose of that line of code. But why it was written that way? Is that some kind of idiomatic way of waiting in TI's microcontrollers code?

In ISSUE#2 of Diagnosing Common Development Problems and Tips & Info for TM4C Devices the same problem is solved with a much clearer code.

Please don't take my question as criticism to the authors of the code. I'm just really confused.

r

  • Hi rrd,
    You should follow the recommendation in e2e.ti.com/.../374640. Your textbook example only reads from the register. The text example is assuming that after the read back of the register that was just written the peripheral is ready which may not be the case.
  • I just found an answer to my question in the Piazza Class of the Edx Course I'm taking.

    It says that is two alternatives for waiting for a peripheral ready state:

    1. Using delay=GPIO_RCGC_2; (delay declared as volatile) → Takes 6 system clocks to execute (in very special cases it could be executed in 3 system clocks). Enough delay*. If delay is NOT declared as volatile, takes only 4 system clocks to execute (in very special cases it could be executed in 2 system clocks!!! And we have troubles!)

    2. Using while((GPIO_RCGC_2&0x20)!=0x20); (Clock for PortF) → Takes from 8 to 11 system clocks to execute. Enough delay, but longer than the previous one.


    * There must be a delay of 3 system clocks after a module clock is enabled before any registers in that module are accessed.


    Well! Now I know why that ugly code was used, but I'd like to know the community members' opinion about the topic. Should I use alternative 1 or 2?
  • The highlighted line doesn't seem like a delay. It looks like you're assigning a variable called "delay" a value. Assigning a variable a value takes a few clock cycles I suppose.

    while(!SysCtlPeripheralReady()) polls a register continuously until the peripheral is ready. The TivaWare User Guide says " This function determines if a particular peripheral is ready to be accessed. The peripheral may be in a non-ready state if it is not enabled, is being held in reset, or is in the process of becoming ready after being enabled or taken out of reset."

    The source code is 

    bool
    SysCtlPeripheralReady(uint32_t ui32Peripheral)
    {
        //
        // Check the arguments.
        //
        ASSERT(_SysCtlPeripheralValid(ui32Peripheral));
    
        //
        // See if this peripheral is ready.
        //
        return(HWREGBITW(SYSCTL_PRBASE + ((ui32Peripheral & 0xff00) >> 8),
                         ui32Peripheral & 0xff));
    }
    
    #define HWREGBITW(x, b)                                                       \
            HWREG(((unsigned long)(x) & 0xF0000000) | 0x02000000 |                \
                  (((unsigned long)(x) & 0x000FFFFF) << 5) | ((b) << 2))

    Read the System Control register description in the datasheet to see what these address registers are doing. Take GPIO as an example, from the TM4C129XN datasheet "The PRGPIO register indicates whether the GPIO modules are ready to be accessed by software following a change in status of power, Run mode clocking, or reset"


    The SysCtlPeripheralReady() seems safer. Delay tricks may be removed by the compiler. If the compiler doesn't think a variable is being used, it could be removed as an optimization. You are better off checking the register that tells you things are ready.

  • Bravo for your "reminder" (to those often here) - and possible "introduction" (to this poster) - of the availability & usefulness of the API's Source Code. Unfortunately - poster's course continues its misguided, "Use and ONLY use of DRM" - which is devoid of any such code detailing.

    Note that the "time/effort/complexity" - demanded by DRM - has caused the (unnecessary) unlocking of, "PF1-PF4" - which were never, "locked." Such - "off in the weeds" efforts/false conclusions - may be seen as the result of the archaic, overly-demanding DRM - long since, "Kicked to the Curb" by the powerful, well documented and "long-proven" API.
  • Hey cb1_mobile. Are you saying the course I'm taking is not a good introduction to TI ARM microcontrollers programming? I'm just at the beginning of the course and I'm not so happy with it for a couple of reasons:

    1. They always #define symbolic constants for each register used in the code and I don't know why. The ARM compilers comes with an API with those definitions, am I right?

    2. They use Keil ARM-MDK instead of CCS.

    3. I feel like I'm taking the wrong path for learning TI TM4C programming.

    Could you point some alternative to me?
  • Hello rrd,

    I know a bit about the course you are taking so let me offer a few comments.

    Valvano's course(s) are very good on a conceptual level, and also if they delve into RTOS, they are great about teacing the basics of the primary RTOS concepts as well. However for real-world usage and applications, a lot of the finer details that are taught will end up being abstracted out into libraries when you entry industry jobs.

    You won't see direct register manipulation (DRM) calls in most software. Instead driver libraries like, for TM4C, TivaWare are used where we handle all the DRM aspects with our well tested libraries while you, as the customer, get to leverage a bank of API's that handle each individual peripheral as they need to be per device datasheet. It's not foolproof or 100% perfect, and occasionally you'll have to make your own functions for niche applications, but it covers 95%+ of all use cases.

    That said, I think there is a lot of value in understanding what goes on beneath the surface, so long as you also understand that what you see isn't necessarily going to be what you do in the end. I don't directly use a lot of what I learned in college MCU courses, but the fundamentals of how different peripherals work (timers, serial communications, interrupts, etc.) are invaluable overall. Just don't expect to be able to instantly code any MCU to do what you want without investing time to understand each family and their respective driver libraries first.

    CCS vs Keil (and even vs IAR) is it's own debate. Keil supports more MCU's over all as it is not exclusive to one vendor, whereas CCS is limited to TI processors/MCU's only. For overall broad learning, I'd be foolish to dismiss Keil as a good option even if I don't personally have experience with it due to using CCS. If you personally want to learn CCS more though, you may find this helpful: https://training.ti.com/getting-started-code-composer-studio-v7

    Ultimately, we don't have any sort of university-esque course for using TivaWare/CCS, but TivaWare provides a wide range of example programs to learn how to configure and leverage various peripherals, along with a lot of documentation. It won't be like having video lectures, but that would be a good way to learn how to really leverage the device.

  • Yuppies pay more for artisan firmware hand coded in assembly by the Amish.