0

I got a weird problem last night. Here is a simple program that uses pin PA7 to drive a LED:

#include <stdint.h>
#include <stdbool.h>
#include "driverlib/sysctl.h"
#include "inc/tm4c123gh6pm.h"

void PortA_Init(void){ 
    volatile unsigned long delay;
    SYSCTL_RCGC2_R |= 0x00000001;     
    delay = SYSCTL_RCGC2_R;              
    GPIO_PORTA_LOCK_R = 0x4C4F434B;   // 2) unlock PortA
    GPIO_PORTA_CR_R = 0x80;           // allow changes to PA7       
    GPIO_PORTA_AMSEL_R = 0x00;        // 3) disable analog function
    GPIO_PORTA_PCTL_R = 0x00000000;   // 4) GPIO clear bit PCTL  
    GPIO_PORTA_DIR_R |= 0x80;         // 5) PA7 output   
    GPIO_PORTA_AFSEL_R = 0x00;        // 6) no alternate function  
    GPIO_PORTA_DEN_R |= 0x80;         // 7) enable digital pins PA7  
}

int main(void) {
    PortA_Init();
    while(1) {
        GPIO_PORTA_DATA_R |= 0x80;
        SysCtlDelay(500000);
        GPIO_PORTA_DATA_R &= ~0x80;
        SysCtlDelay(500000);
    }
    return 0;
}

When debugging in simulator (and real hardware), it is stuck in hardfault_handler section of startup.s. I Googled for a while and found out that I can check address 0xe000ed2s for additional bits:

hardware fault

From what I understand, 0x08 means that I have a NOCP error, according to this tutorial. However, I'm NOT using the FPU so I don't get where the error comes from:

enter image description here

I did some further tests and found something interesting. You can see that I'm using some header files under /driverlib. I also added the driverlib.lib file into the project, as shown in the pic below. However, this hardfault error is gone whenever I remove the #include "driverlib/sysctl.h line (as well as the SysCtlDelay() calls) from the source code. But I don't know why and how to fix. I still want to use this header file for further development.

Thanks in advance~~

  • 1
    Can you use breakpoints and single-stepping to determine which statement is causing the fault? Debugging code by staring at it doesn't usually work, in my opinion. – Elliot Alderson Feb 20 '22 at 16:56
  • @ElliotAlderson good point, I just did that and the first step puts me in the HardFault_Handler section. The first line of code it executes is actually the `B __main` assembly code in `startup.s` which I believe is the bootloader. Setting up breakpoint at first line in `main()` doesn't really help as the error is prior to that. I also tried to enable/disable the FPU in Option but to no avail. TBH I still think it has something to do with that `driverlib` include, just no proof. – Nicholas Humphrey Feb 20 '22 at 17:07
  • Just one thought, could it be a wrong version of driverlib.lib (which contains the implementation of all functions whenever I include a header file under folder `driverlib/`)? I don't know if that' possible but maybe? – Nicholas Humphrey Feb 20 '22 at 17:11
  • 1
    Are you sure it's not the watchdog that triggers? I can't see where you're initializing core stuff like the sysclk, watchdog, .... – Velvel Feb 20 '22 at 17:12
  • @Seir not sure about that, I never needed to initialize the core stuffs myself. I thought they are taken care of elsewhere? I'm probably too newbie to answer your question TBH. I usually just initialize some ports and bit bang them, this is the first program I'm trying to use the TI library (thus the `driverlib/` header included). – Nicholas Humphrey Feb 20 '22 at 17:14
  • 1
    @Seir I just read the part about watchdogs, not sure but looks like it has to be initialized before being used. I don't intend to use them so I never initialize them, does it sound good? Anyway I never used them in my other projects before, hmmm... – Nicholas Humphrey Feb 20 '22 at 17:17
  • 1
    Do a binary compare between the code that works vs what doesn’t. Hardware_fault suggests that you are accessing a peripheral that is not enabled and/or does not have its clock enabled. You can examine the stack to find the address where the fault occurred. That should give a hint as to what is wrong. – Kartman Feb 20 '22 at 17:22
  • 1
    Nothing wrong using registers directly when you need to do some fancy stuff. But I'd recommend you use the `driverlib` for GPIO config and access. – Velvel Feb 20 '22 at 17:34
  • 1
    Also, when you're configuring peripheral clocks (here RCGC2 GPIOA) you need a delay of 3 system clocks before you can access GPIOA registers. I'm not sure your `delay = SYSCTL_RCGC2_R;` equals to at least 3 cycles. – Velvel Feb 20 '22 at 17:36
  • @Seir so far I have been using that for delays successfully, but that's a good point and I'll try to maybe add a few more cycles just to make sure. – Nicholas Humphrey Feb 20 '22 at 17:40
  • 1
    Using driverlib it's so much easier to spot bugs: ```SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);``` ```while (!SysCtlPeripheralReady(SYSCTL_PERIPH_GPIOA));``` – Velvel Feb 20 '22 at 17:46
  • @ElliotAlderson Hi, I switched to assembly mode in debugger and found out that the code tries to go into _fp_init and then triggers a hardfault. I can trace it went into __rt_lib_init (at 0x000002F8) first, and then __rt_lib_init_fp_1 (0x000002FA), and then _fp_init. Eventially it tries to run `VMSR FPSCR, r0` and went into the hardfault handler. This is really weird as you can see from the pics that I already disabled the FPU. – Nicholas Humphrey Feb 20 '22 at 17:55

1 Answers1

1

I think you've configured the wrong MCU type.

enter image description here

The TM4C123GXL Tiva launchpad has a TM4C123GH6PM MCU.
The driverlib expects a TM4C1231C3PM, but it's actually a TM4C123GH6PM.

That's probably the reason the driverlib causes a NOCP fault, because some core registers have to be setup differently.

Velvel
  • 3,591
  • 3
  • 12
  • 30
  • Thanks @Seir, I noticed that issue long ago, but somehow my previous programs compiled and ran fine using either SFR file. BTW I also tested the error program using TM4C123GH6PM but it shows the same error. – Nicholas Humphrey Feb 20 '22 at 18:00
  • 1
    I'm not talking about the SRF file. It was just the means that I found out your MCU configuration is faulty. Never be content with 'somehow it ran fine in the past'. – Velvel Feb 20 '22 at 18:05
  • 1
    I use _Code Composer Studio_ myself, so I can't help you where exactly you need to configure your MCU within Keil. But seriously, you have to configure the correct MCU, otherwise there be dragons. – Velvel Feb 20 '22 at 18:06
  • 1
    Thanks @Seir I agree with you. BTW l seems to find (part of) the issue: Looks like the driverlib files are not compatible with the specific hardware. I downloaded a different copy from TI and comment out the `SysctlDelay()` lines and now it at least blinks the LED. However, adding `SysCtlDelay()` back still triggers the hardfault. So I think maybe the library uses FPU and I need to initialize it first. I'll read the document for the driver library to figure out, thanks again for the help~~ – Nicholas Humphrey Feb 20 '22 at 18:19
  • 1
    I rarely ever used the FPU on this MCU. The driverib and `SysCtlDelay` work perfectly without having to init the FPU. – Velvel Feb 20 '22 at 18:22
  • Hmmm, that's weird then. The debugger indeed jumps into _fp_init if I uncomment the `SysCtlDelay()` lines. I already set FPU as "Not Used". I'll check further. – Nicholas Humphrey Feb 20 '22 at 18:50
  • OK after many hours of head banging and tweaks I managed to remove the error by compiling with MicroLib. I'm still confused by the error as for my previous projects I never did that. Maybe that's required if I do not initialize FPU but still wants to use driverlib? I do not think so... – Nicholas Humphrey Feb 21 '22 at 00:23