I have several programs using PWM module of TM4C123GH6PM (Tiva LaunchPad). These programs were written using Keil v4.72a. They seemed to work fine.
Recently, I opened these projects in Keil v5.12 and they all stop working.
Here is the listing of the simplest program that sets up the PWM1 to generate 1 kHz 50% output at PF3:
1 #include "TM4C123GH6PM.h"
2
3 int main(void)
4 {
5 /* Enable Peripheral Clocks */
6 SYSCTL->RCGCPWM |= 2; /* enable clock to PWM1 */
7 SYSCTL->RCGCGPIO |= 0x20; /* enable clock to PORTF */
8 SYSCTL->RCC &= ~0x00100000; /* no pre-divide for PWM clock */
9
10 /* Enable port PF3 for PWM1 M1PWM7 */
11 GPIOF->AFSEL = 8; /* PF3 uses alternate function */
12 GPIOF->PCTL &= ~0x0000F000; /* make PF3 PWM output pin */
13 GPIOF->PCTL |= 0x00005000;
14 GPIOF->DEN |= 8; /* pin digital */
15
16 PWM1->_3_CTL = 0; /* stop counter */
17 PWM1->_3_GENB = 0x0000008C; /* M1PWM7 output set when reload, */
18 /* clear when match PWMCMPA */
19 PWM1->_3_LOAD = 16000; /* set load value for 1kHz (16MHz/16000) */
20 PWM1->_3_CMPA = 8000; /* set duty cycle to 50% */
21 PWM1->_3_CTL = 1; /* start timer */
22 PWM1->ENABLE = 0x80; /* start PWM1 ch7 */
23
24 for(;;) { }
25 }
26
27 //void SystemInit(void)
28 //{
29 // SCB->CPACR |= 0x00f00000;
30 //}
31
Line 27-30 were commented out because in Keil v5 there is a SystemInit() function in system_TM4C123c that was supplied by the device support package. The other code in the SystemInit() function is to configure the system clock from 16 MHz to 49.84 MHz. I will attach the code at the end of the post.
When I ran this program, there was no output and the program is stuck in the HardFault_Handler. FAULTSTAT was 0x00000400, HFAULTSTAT was 0x40000000, MMADDR was 0xE000EDF8, and FAULTADDR was 0xE000EDF8.
If I put a breakpoint after line 16, I always got the hard fault. If I put a breakpoint at line 16, no fault would occur. I could run the program by hitting continue without any problem from the breakpoint at line 16.
If I added a small delay before line 16 such as:
for(i = 0; i < 6; i++) ;
The program would run fine. If I reduced the loop count to 5, it would take the hard fault.
If I skipped the clock configuration in SystemInit(), the program ran fine without fault.
Here is the code for SystemInit():
void SystemInit (void)
{
#if(CLOCK_SETUP)
uint32_t i;
#endif
/* FPU settings ------------------------------------------------------------*/
#if (__FPU_USED == 1)
SCB->CPACR |= ((3UL << 10*2) | /* set CP10 Full Access */
(3UL << 11*2) ); /* set CP11 Full Access */
#endif
#if(CLOCK_SETUP)
SYSCTL->RCC2 = 0x07802810; /* set default value */
SYSCTL->RCC = 0x078E3AD1; /* set default value */
SYSCTL->RCC = (RCC_Val | (1UL<<11) | (1UL<<13)) & ~(1UL<<22); /* set value with BYPASS, PWRDN set, USESYSDIV reset */
SYSCTL->RCC2 = (RCC2_Val | (1UL<<11) | (1UL<<13)); /* set value with BYPASS, PWRDN set */
for (i = 0; i < 1000; i++); /* wait a while */
SYSCTL->RCC = (RCC_Val | (1UL<<11)) & ~(1UL<<22); /* set value with BYPASS, USESYSDIV reset */
SYSCTL->RCC2 = (RCC2_Val | (1UL<<11)); /* set value with BYPASS */
for (i = 0; i < 1000; i++); /* wait a while */
SYSCTL->RCC = (RCC_Val | (1<<11)); /* set value with BYPASS */
if ( (((RCC_Val & (1UL<<13)) == 0) && ((RCC2_Val & (1UL<<31)) == 0)) ||
(((RCC2_Val & (1UL<<13)) == 0) && ((RCC2_Val & (1UL<<31)) != 0)) ) {
while ((SYSCTL->RIS & (1UL<<6)) != (1UL<<6)); /* wait until PLL is locked */
}
SYSCTL->RCC = (RCC_Val); /* set value */
SYSCTL->RCC2 = (RCC2_Val); /* set value */
for (i = 0; i < 10000; i++); /* wait a while */
#endif
}
The value of RCC_Val is 0x01DE0542 and RCC2_Val is 0x01800000.