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.

HardFault when configuring PWM following TM4C123GH6PM using KEIL

Other Parts Discussed in Thread: TM4C123GH6PM

Hi,

I am trying to control a EV3 Lego motor uning the TIVA Launchpad. I want to use the PWM functionality of the microcontroler. I am folllowng instructions from page 1230 from TM4C123GH6PM_April2013.

I have seen some discussion regarding the issue, but none of the solutions seem to work. Here is my code:

//====PWM.c file===
// PWM.c
// Runs on TM4C123
// A Software function to configure the M0PWM0 in PB6, to be used to control a single motor using L298 using
// implemented PWM in microcontroler
// Port B is also initialized in order to control other features in L298
// Wiring to L298
// PB6 is PWM signal to control motor velocity

// Motor A truth table
// PB6 PB1 PB0 Microcontroler pins
// ENA IN1 IN2 Description
// 0 N/A N/A Motor A is off
// 1 0 0 Motor A is stopped (brakes)
// 1 0 1 Motor A is on and turning backwards
// 1 1 0 Motor A is on and turning forwards
// 1 1 1 Motor A is stopped (brakes)

// Joan Sans
// 31 May 2016

#include "PWM.h"
#include "C:/Keil/Joan/JOAN_UTILS/tm4c123gh6pm.h"

void PortB_Init(void){ volatile unsigned long delay;
SYSCTL_RCGC2_R |= 0x00000002; // 1) activate clock for Port B: Already activated in PWM init
delay = 0x00000020; //SYSCTL_RCGC2_R;//When initializing port F we write a 0x20 but now it would be a0x02, so I set to 0x20. allow time for clock to start
GPIO_PORTB_LOCK_R = 0x4C4F434B; // 2) unlock GPIO Port B. To unlock all ports send 0x4C4F434B.

GPIO_PORTB_CR_R = 0x3F; // allow changes to PB5-0
GPIO_PORTB_AMSEL_R = 0x00; // 3) disable analog on PB
GPIO_PORTB_PCTL_R = 0x04000000; //PMC6 = 4 to configure M0PMW0
GPIO_PORTB_DIR_R = 0x3F; // 5) PB5 to PB0 out
GPIO_PORTB_AFSEL_R = 0x40; //Enable alternate functions for PB6. Dissable for the rest
GPIO_PORTB_PUR_R = 0x00; // disable pull-up on PB5-0
GPIO_PORTB_DEN_R = 0x3F; // 7) enable digital I/O on PB5-0
}

void PWM_Init(void){
// Initialization and Configuration

// The following example shows how to initialize PWM Generator 0 with a 25-kHz frequency, a 25%
// duty cycle on the MnPWM0 pin, and a 75% duty cycle on the MnPWM1 pin. This example assumes
// the system clock is 20 MHz.

// 1. Enable the PWM clock by writing a value of 0x0010.0000 to the RCGC0 register in the System
// Control module (see page 452). ATENTION: RCGCO is legacy. RCGCPWM should be used instead.
SYSCTL_RCGCPWM_R &= 0x00000001; //activate PWM0

// 2. Enable the clock to the appropriate GPIO module via the RCGC2 register in the System Control
// module (see page 460).
SYSCTL_RCGC2_R |= 0x00000002; //activate clock for Port B

// 3. In the GPIO module, enable the appropriate pins for their alternate function using the
// GPIOAFSEL register. To determine which GPIOs to configure, see Table 23-4 on page 1334.
GPIO_PORTB_AFSEL_R = 0x40; // Enable alternate functions for PB6. Dissable for the rest

// 4. Configure the PMCn fields in the GPIOPCTL register to assign the PWM signals to the appropriate
// pins (see page 682 and Table 23-5 on page 1341).
GPIO_PORTB_PCTL_R |= 0x04000000; //PMC6 = 4 to configure M0PMW0

// 5. Configure the Run-Mode Clock Configuration (RCC) register in the System Control module
// to use the PWM divide (USEPWMDIV) and set the divider (PWMDIV) to divide by 2 (000).
SYSCTL_RCC_R |=0x00100000; //RCC bit20=1(USEPWMDIV)
SYSCTL_RCC_R &=0xFFF1FFFF; //RCC bit17-19=000PWMDIV) to divide by 2 (000)

// 6. Configure the PWM generator for countdown mode with immediate updates to the parameters.
// ¦ Write the PWM0CTL register with a value of 0x0000.0000.
PWM0_0_CTL_R = 0x00000000; //

// ¦ Write the PWM0GENA register with a value of 0x0000.008C.
PWM0_0_GENA_R = 0x0000008C; //
// ¦ Write the PWM0GENB register with a value of 0x0000.080C.
PWM0_0_GENB_R = 0x0000080C;

// 7. Set the period. For a 25-KHz frequency, the period = 1/25,000, or 40 microseconds. The PWM
// clock source is 10 MHz; the system clock divided by 2. Thus there are 400 clock ticks per period.
// Use this value to set the PWM0LOAD register. In Count-Down mode, set the LOAD field in the
// PWM0LOAD register to the requested period minus one.
// ¦ Write the PWM0LOAD register with a value of 0x0000.018F.
// For 80 MHz, clock source is 40 MHz. Then there is 1600 clock ticks per period
PWM0_0_LOAD_R = 0x63F; //0x63F = 1599

// 8. Set the pulse width of the MnPWM0 pin for a 25% duty cycle.
// ¦ Write the PWM0CMPA register with a value of 0x0000.012B.
PWM0_0_CMPA_R = 0x4AF; //0x4AF = 1199

// 9. Set the pulse width of the MnPWM1 pin for a 75% duty cycle.
// ¦ Write the PWM0CMPB register with a value of 0x0000.0063.
PWM0_0_CMPB_R = 0x18F; //0x18F = 399

// 10. Start the timers in PWM generator 0.
// ¦ Write the PWM0CTL register with a value of 0x0000.0001.
PWM0_0_CTL_R = 0x00000001;

// 11. Enable PWM outputs.
// ¦ Write the PWMENABLE register with a value of 0x0000.0003.
// PWM0_ENABLE_R = 0x00000003;
};

I get trouble when line starting with  PWM0_0_GENA_R is executed.

Does anybody have an idea on what is going on?

Thanks in advance

Joan S.

  • Hello Joan,

    DRM to access the device registers may be creating the issue. I would suggest using TivaWare API.s

    Regards
    Amit
  • I agree with Amit - writing "magic" hex values to cryptically named registers is neither very readable nor very portable.

    But for the reason of your hardfault, I suggest to work "backwards". When the error occured, read the appropriate SCB registers in the debugger to determine the reason. Here is a good documentation : http://www.keil.com/appnotes/files/apnt209.pdf

    Then, you can start to instrument your code, to narrow down the cause.

  • Hello Joan,

    Can you check the NVIC_FAULTSTAT and NVIC_FAULTADDR location to see the cause of bus fault?

    Regards
    Amit
  • Hi f.m,

    I agree with your remark. I should have included the definitions file. Sorry for that. I will follow your advice and check the document.
    Thanks
  • Hi Amit,

    Thanks for your replies. I have been able to solve the issue with hardFault, but still PWM is not working...Tomorrow more.

    Regards

    Joan S-
  • Hello Joan,

    Do you still have the code in DRM or is it now in TivaWare for debug?

    Regards
    Amit
  • Hi Amit,
    Still in DRM. I know that I can switch to TivaWare but now I want to understand what is going on:
    The error was that AMSEL was not properly configured for the portB. With that the HardFault is solved but the PWM does not work.
    Then since PWM is in PB6 and the signals to comand L298 in PB0 and PB1 I was thinking that I was somehow overwriting configuration of PWM during portB configuration. Then I tried to use another port(PortF) to control direction in L298 and make indepedent the configuration of PWM(PB6) and GPIO, but with that I get again a HArdFaul. When PWM configuration is commented, then port F works fine...
    Now I am trying to see if I can find some example of configuring PWM using DRM...
    Thanks

  • Joan Sans said:
    Still in DRM. I know that I can switch to TivaWare but now I want to understand what is going on:

    The (claim) "want to understand (or learn)" is so often made - and so rarely proves out!

    What's learned? 

    Delay, repeated entries into Fault Handler, and (endless) turning of MCU manual pages to (maybe) discover "just the right "magic bits" w/in multiple, 32 bit registers!

    The API offers a safe, efficient path to REAL LEARNING.   Tried, true, tested vs. (always) an unpleasant adventure - untried, untested/unverified - and so often -failing!   Step right up folks - pain/suffering (surely) awaits.

    Small Tech Biz (surely) awaits those "moving in slow motion" due to the misguided use of an archaic method - when a vastly superior one - gleams in contrast!

    Nothing prevents users from studying the "complete" API Source Code - after the tried/true/tested (i.e. WORKING) code - runs successfully.  That builds understanding - speed - efficiency and investigatory skills - all sought by Tech Biz.   (and not AT ALL available via error-racked, painfully slow, DRM.  (Defeated, Reprehensible Method...)

  • Hello Joan,

    What is the value of the NVIC_FAULTADDR and NVIC_FAULTSTAT registers? The use of DRM will persistently cause more issues as your code develops.

    Regards
    Amit
  • Hi Amit,

    Issue happen when I try to write to DATA in port F, so something is not properly configured I assume...

    Anyway, you and cb1 are right... I should start with TivaWare and from there learn how it works at register level, otherwise is frustrating... So I will start with TivaWare asap.

    Only one question, I use Keil because it was used in the EdX course, but I have seen that TI has developed some other development environment. Which one do you recommend?

    Regards

    Joan S.
  • Joan Sans said:
    Anyway, you and cb1 are right... I should start with TivaWare and from there learn how it works at register level...

    In the immortal (and always sincere, words of Elvis),  "Thank you - thank you very much!"

    Your efforts and those of (previously) hapless helpers will be vastly eased, speeded & improved!  And such leads to "real" learning - not endless frustration!

    Most serious users prefer the more mature & "accepting nature" of Keil and/or IAR.  (any ARM MCU may be accommodated - not just ONE vendor!)

  • Hello Joan

    The use of IDE is not really mandated. Users are free to chose. I am more used to CCS and IAR than to keil.

    Regards
    Amit
  • Hi Amit,

    Finally I am trying to use TivaWare... but I have some trouble.

    Try 1 using CCSv6:
    I started with the Ti workshop about TivaLaunchPad. In the lesson 2 exercise, I follow all instructions, I compile and load the program to the LaunchPad and it works fine when I press the reset button, however the debugger seem to do not work and it is stopped in 0x0000026C (no symbols are defined for 0x0000026C ). --> No idea what is going on. Note that there is a danger symbol in front include <stdbool.h>, but unable to know why... Also I am using GNU compiler instead of ARM as shown in Tutorials (no idea why...)

    Try2 using keil:
    I loaded Hello example found in the examples folder of TivaWare. Then when I build the project I get following error: "Error: failed to execute 'C:\ti\TivaWare_C_Series-2.1.2.111\ARMCC\bin\ArmCC'. Do you know why?
    Realize that a red cross is in front of include <stdint.h>. I have downloaded the header and placed in same directory as <stdbool> and do not seem to react....

    Any idea??

    Thanks in advance

    Joan S.