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.

TM4C123GH6PM: Code goes into exit.c

Part Number: TM4C123GH6PM
Other Parts Discussed in Thread: EK-TM4C123GXL

EDIT by moderator (Questions were in Title):
Q1:When I run the code below,it always goes into exit.c (void abort(void))   , if I add a while(1)  in the end ,it won't goes into exit.c  Q2:I made this project to test ButtonPoll() below,I copied it from http://www.ti.com/lit/zip/tidcb5

/**
 * main.c
 */

#include <stdint.h>
#include <stdbool.h>
#include "inc/hw_types.h"
#include "inc/hw_memmap.h"
#include "inc/hw_gpio.h"
#include "driverlib/fpu.h"
#include "driverlib/gpio.h"
#include "driverlib/sysctl.h"
#include "driverlib/rom.h"
#include "driverlib/pin_map.h"
#include "driverlib/interrupt.h"
#include "driverlib/gpio.h"

uint8_t ButtonsPoll(uint8_t *, uint8_t *);

static uint8_t g_ui8ButtonStates = GPIO_PIN_0|GPIO_PIN_4;   //两个按键状态,初始化为高,按下

uint8_t *pui8Delta = 0;
uint8_t *pui8RawState = 0;
uint8_t ui8Buttons = 0;

int main(void)
{
    SysCtlClockSet(SYSCTL_SYSDIV_5|SYSCTL_USE_PLL|SYSCTL_XTAL_16MHZ|SYSCTL_OSC_MAIN);
    SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);
    HWREG(GPIO_PORTF_BASE + GPIO_O_LOCK) = GPIO_LOCK_KEY;
    HWREG(GPIO_PORTF_BASE + GPIO_O_CR) |= 0x01;
    HWREG(GPIO_PORTF_BASE + GPIO_O_LOCK) = 0;
    GPIOPinTypeGPIOOutput(GPIO_PORTF_BASE, (GPIO_PIN_1 + GPIO_PIN_2 + GPIO_PIN_3));
    GPIOPinTypeGPIOInput(GPIO_PORTF_BASE, (GPIO_PIN_0 + GPIO_PIN_4));

    GPIODirModeSet( GPIO_PORTF_BASE,  GPIO_PIN_0|GPIO_PIN_4, GPIO_DIR_MODE_IN);
    GPIOPadConfigSet(GPIO_PORTF_BASE, GPIO_PIN_0|GPIO_PIN_4,
                            GPIO_STRENGTH_2MA, GPIO_PIN_TYPE_STD_WPU);

    g_ui8ButtonStates = GPIOPinRead( GPIO_PORTF_BASE, GPIO_PIN_0|GPIO_PIN_4);

//    while(1)
//    {
//        SysCtlDelay(SysCtlClockGet()/3000);
//        ui8Buttons = ButtonsPoll(pui8Delta, pui8RawState);
//    }

}

uint8_t ButtonsPoll(uint8_t *pui8Delta, uint8_t *pui8RawState)
{
    uint32_t ui32Delta;
    uint32_t ui32Data;
    static uint8_t ui8SwitchClockA = 0;
    static uint8_t ui8SwitchClockB = 0;

    //
    // Read the raw state of the push buttons.  Save the raw state
    // (inverting the bit sense) if the caller supplied storage for the
    // raw value.
    //
    ui32Data = (GPIOPinRead(GPIO_PORTF_BASE, GPIO_PIN_0|GPIO_PIN_4));
    if(pui8RawState)           //指针非空
    {
        *pui8RawState = (uint8_t)~ui32Data;//现在的状态取反得到原来的状态
    }

    //
    // Determine the switches that are at a different state than the debounced(抖动)
    // state.
    //
    ui32Delta = ui32Data ^ g_ui8ButtonStates;

    //
    // Increment the clocks by one.
    //
    ui8SwitchClockA ^= ui8SwitchClockB;
    ui8SwitchClockB = ~ui8SwitchClockB;

    //
    // Reset the clocks corresponding to switches that have not changed state.
    //
    ui8SwitchClockA &= ui32Delta;
    ui8SwitchClockB &= ui32Delta;

    //
    // Get the new debounced switch state.
    //
    g_ui8ButtonStates &= ui8SwitchClockA | ui8SwitchClockB;
    g_ui8ButtonStates |= (~(ui8SwitchClockA | ui8SwitchClockB)) & ui32Data;

    //
    // Determine the switches that just changed debounced state.
    //
    ui32Delta ^= (ui8SwitchClockA | ui8SwitchClockB);

    //
    // Store the bit mask for the buttons that have changed for return to
    // caller.
    //
    if(pui8Delta)
    {
        *pui8Delta = (uint8_t)ui32Delta;
    }

    //
    // Return the debounced buttons states to the caller.  Invert the bit
    // sense so that a '1' indicates the button is pressed, which is a
    // sensible way to interpret the return value.
    //
    return(~g_ui8ButtonStates);
}

  • Hello Liguo,

    If you don't have a while(1) at the end, then there is no more code to execute so the MCU no longer needs to do anything and exits as you see. If you want the code to continue running, the while(1) is required. This is standard for every MCU.

    For question 2, it got cut off because you tried to put it in the title. Please explain your question in a post.

  • Hi,Ralph,I copied this function uint8_t ButtonsPoll(uint8_t *pui8Delta, uint8_t *pui8RawState)  from somewhere,just as you see above,Its comments explains

    that it can help judge the state of SW1 and SW2 ,But I really feel puzzled  about how this function works to achieve its aim. My english is not very well,so I cannot  understand its comments and logics;

    as to Q1, my code always gets tripped in exit.c (more specific : abort function), I think it is not normal,so I want to work out why ,after all ,if Code run correctly,it won't goes into exit.c and abort. I can prevent it from aborting by adding  a while(1) ,But it is not a good way.

    thanks for your help.

    Best Regards

  • Hello Liguo,

    Using a while(1) is supposed to be done, NOT using a while(1) is what is not good. If there is no while(1) and the code runs correctly, then it will always end in exit.c. Without a while(1), there is no more code to process, so it aborts because the program is finished. There is nothing left to do.

    Try this to see what I mean.

    Load the hello project from TivaWare for your LaunchPad and run it as is out of the box.

    Then comment out the while(1) loop that has no purpose but to flash an LED.

    See what function your code ends up with when you comment out the while(1).

    As for your second question, I would recommend you read through the Buttons Driver section in our EK-TM4C123GXL User Guide. You can find this guide in the docs folder in TivaWare. It is titled SW-EK-TM4C123GXL-UG-2.1.4.178.pdf.

  • Greetings Ralph,

    Yours is a very good justification & explanation for the 'necessity' of the 'while loop.'

    That said - the 'poster's desire to learn'  is to be applauded - in my (not too humble) opinion.

    The particular code w/in that  Buttons Driver Section - while good - is  FAR MORE  'Indirect & Complex' than (really) needed.    And  that is the likely cause of  this poster's (and others') resistance to and/or confusion.

    Reading Switches attached to MCU pins demands 'real-world' recognition of  'Switch Bounce'  which does not always arrive - in (even) a 1K+ page, MCU Manual.  

    Classically the MCU must be ordered to 'Wait' - and to 'Only Read the Switch' after the 'bounce-period' has expired.  

    (if read too soon - it is likely that an (illegal) bounce event is noted - if read too late - the switch may have (already) been released!)   That's a (very) nice Catch-22 - is it not?

    My firm attempts to  resolve this dilemma  by:

    • Choosing switches with predictable (and repeatable) bounce periods
    • Periodically monitoring these switches - to insure the bounce-period remains as predicted
    • Causing the initial switch closure (usually to ground) to generate a, 'Switch Prepare to Read Interrupt'
    • Then inserting an appropriate time-delay - just beyond the maximum Switch-Bounce Time
    • And Only THEN - executing the Switch Read Command   (detail follows below - this space reserved for the 'Methodical Approach Sequence')

    I'm away from the office - but (likely) recall (most) of the details of the above procedure.   A reasonably 'decent' mechanical switch may 'bounce' (contacts 'chatter' - or 'make/break' repeatedly) - perhaps for up to 30 - 50mS.   And a 'human key-press' is unlikely to release in 'under 150mS.   Thus there exists a (near) 100mS interval - in which the key (or switch) has ceased bouncing - and is (still) prior to the key's being released!     This then is the 'ideal time-window' in which to read that 'switch or key.'    It is also useful to employ an R-C filter - to lessen the bounce-period.    Yet still - it is suggested to 'Avoid the switch read' until AFTER - any/all potential key bounce has ceased!

    Note that this method works well when reading (even) multiple switches - although in that case - 'multiple interrupts'  (and following delays) must be employed.

    Sometimes the 'simpler method' proves of high value...   Especially when the procedure is fully/properly detailed - which (just may be) - the case here...

  •  Hi,cb1_mobile,Thank you for your help again, your knowledge is very rich, I hope to learn more from you in future.

  • HI,Ralph,thanks for your patient help,I will Follow your advice and try it out.

  • Thank you as well, Mr. Wang.    It is joyful to assist those 'highly motivated to Learn' - as you (so clearly) are.    You remind me of the majority of my firm's staff - young, striving, and seeking endless challenge.     (and dare it be said - welcoming (skilled) management!)

    Now kindly comply w/Ralph's guidance - he is 'exactly right!'      I assure you - in time - you 'will fully understand' - the key/crucial value of the 'while loop.'

    If you can 'Acquire an Oscilloscope' - you can experiment with a variety of different mechanical switches - and observe the 'Contact Chatter' described earlier.   A friend or nearby school or (even) an 'experimenter's club' - may have such an instrument - if you do not.    Viewing the different signals - and noting their critical, timed relationship - will greatly aid your learning.

    I'd say that Ralph's post has 'earned' your kind Verify - doing that will free Ralph to aid (many) others...