-4

I am using Keil u4, TivaC TM4C123GH6PM. It's embedded system related, based on ARM Microcontrollers.

The problem I am facing is whenever I try to use a function from math.h Library things go crazy. I don't get any error messages, but the TivaC board freezes what should I do?

enter image description here

  • Not all embedded microprocessors are able to handle floating point numbers. That could lead to extremely slow code that seems to halt the system, the call just not doing anything, the call just "freezing" or the CPU to throw a hardware exception. You need to read the documentation for your compiler, run-time environment and hardware to figure this one out. – Some programmer dude Jun 08 '21 at 15:02
  • 1
    I think ti only has the stellaris series and cortex-m4s. this is a cortex-m4f so should support but also understand the float support is limited (might be single not double that kind of thing). also you have to enable the coprocessor before you try to use the floating point coprocessor(s). try a simple math operation before pulling in a full blown library. add a couple of numbers see if it faults. – old_timer Jun 08 '21 at 15:05
  • 1
    do you have the appropriate fault handlers in place? and are they being triggered by this? – old_timer Jun 08 '21 at 15:05
  • 1
    Be sure that you ARE including math.h. And also be sure you're compiling with all warnings turned on, and no warnings are reported. Because one surprising thing is that without a header definition for `cos(0)` it will pass the `0` as an integer. Only with the definition for `double cos(double x);` will it convert the 0 into a double `0.0` value before calling `cos`. – Zan Lynx Jun 08 '21 at 15:19
  • Check your compiler settings. Not all functionality for a MCU is enabled by default. Its common for a choice between software or hardware enabled floating point. – ChrisBD Jun 08 '21 at 15:20
  • Hard_Fault Handler is triggered at B. what does it mean ? – Mohamed Khaled Jun 08 '21 at 15:38
  • Believe me u dont need the code, there's the functions definitions, and the ports initializations. If u can't help just pass. dont act smart about it. – Mohamed Khaled Jun 08 '21 at 15:51
  • 1
    Post code, not _pictures of code_. – Clifford Jun 08 '21 at 16:55
  • 1
    In the projects "Target Options" there is an option to enable/disable the floating point hardware - what have you set that to? Try the opposite. `B .` is a _"branch to program counter"_ instruction - i.e. an infinite loop. What you really want to know is what caused the hardfault. The [fault reports](https://www.keil.com/support/man/docs/uv4/uv4_cp_m347_faults.htm) dialog may help, or the [call stack trace](https://www.keil.com/support/man/docs/uv4/uv4_db_dbg_callstack.htm). – Clifford Jun 08 '21 at 17:10
  • In any case you should edit your question to show the debugger information. Otherwise it is incomplete and we are debugging by comment which will be rather slow. We need to see what you are seeing. – Clifford Jun 08 '21 at 17:13
  • @old_timer the TM4C123GH6PM has a single precision FPU. In Keil ARM MDK you can disable the FPU and it will use software floating point. It should not in itself cause an exception. That would happen if you enabled hardware floating point and didn't have one, but the Keil environment is "device aware" and the FPU enable/disable is not available in the target settings dialog if the part does not have one. Moreover you cannot select double-precision if the hardware does not support it (unless you set the compiler switches directly of course). – Clifford Jun 08 '21 at 17:20
  • 1
    Don't get "smart" about criticising those trying to help you. Providing the code as text allows others to copy and paste your code and test it for themselves to attempt to reproduce the issue. Here I suggest you strip it down to just `int main(){ double distance = cos(0) ; while(1) ; }` - if you don't end up in the hard-fault handler then clearly the issue is in the surrounding code and not related to the math library at all, and if it still crashes, you have removed doubt and minimised the code to something that others can reproduce without LCD/LED hardware dependencies. – Clifford Jun 08 '21 at 17:27
  • and my point was to be even simpler than cos, a single operation (well maybe load operate store depends). Likewise something easy to disassemble and example and see what is being generated. Are there no ways to use keil that allow you to just use the toolchain? (and your own bootstrap and linker script and as a result if you didnt know to enable the coprocessor then the thing wont work). – old_timer Jun 08 '21 at 18:38
  • a dozen lines of asm would cover the whole topic (and say telnet into openocd to see what happened). – old_timer Jun 08 '21 at 18:39
  • @Clifford can u write ur comment about Floating point as Answer, so I can mark it as solved. Thanks for ur help – Mohamed Khaled Jun 08 '21 at 19:01
  • @MohamedKhaled I posted several comments, I am not certain which you mean, or in what manner it constituted an answer. Most of what I said were investigative comments, not answers. If you meant the part about disabling or enabling the FPU, it should work either way. If it fails with one option or the other, you have simply avoided the problem, not fixed it. Best you post your own answer or add a comment to say how you fixed it. That may indicate what the actual problem was. – Clifford Jun 08 '21 at 19:32
  • @Clifford We shouldn't advise beginners to use `int main()` in bare metal embedded systems. They don't return from main() so using `int` might cause needless stacking from the reset ISR and return instructions getting needlessly generated. Every compiler I know supports the implementation-defined form `void main (void)`. (For gcc you'll need to set `-ffreestanding`.) – Lundin Jun 09 '21 at 06:50
  • @Lundin Possibly. Mostly harmless. I code embedded in C++, (not with GCC - like this question) where void main is not valid, so habit. Also, to advocate void main, would get a lot more comment from those claiming it was wrong. Effective debugging technique is the take-home here. – Clifford Jun 09 '21 at 06:58
  • @Clifford C++17 6.6.1. "It is implementation-defined whether a program in a freestanding environment is required to define a main function. [ Note: In a freestanding environment, start-up and termination is implementation-defined;" Details here: https://stackoverflow.com/a/31263079/584518 but the answer hasn't been updated in a long time. You might be correct that you aren't allowed to name it `main` in C++ if it doesn't return int. – Lundin Jun 09 '21 at 07:04
  • Even that Keil documentation uses `int main()` in its ["hello world" example](https://www.keil.com/support/man/docs/armclang_intro/armclang_intro_dwe1472208421505.htm) and in the ARM ABI, function returns are in R0, I doubt there is any overhead imposed by it. – Clifford Jun 09 '21 at 09:28

1 Answers1

1

If your code doesn't run after the execution of distance = cos(0), some exception is being generated. That exception number can give some idea that what is wrong with the execution of cos(0) function. Try attaching the target with a debugger and look carefully at the values of the processor registers. You should also find out that what exception handler is being executed. All of this will surely help in narrowing down your problem.

Usama
  • 11
  • 3
  • I tried the debugger, i found the Hard_Fault_Handler, triggered at B value i think. I don't know that is, but the program freezed at it. – Mohamed Khaled Jun 08 '21 at 15:52
  • I found that, my Stack is set to 512, I need to set it to 2048. can u help me with that? – Mohamed Khaled Jun 08 '21 at 15:57
  • Maybe [this](https://community.arm.com/developer/ip-products/system/f/embedded-forum/3257/debugging-a-cortex-m0-hard-fault) can help you. – Usama Jun 08 '21 at 16:17
  • @MohamedKhaled. That is not a "B value" that is an assembler branch instruction. The default handlers are of the form `B .` i.e. branch to self. It will wait indefinitely (normally until a watchdog reset if you have enabled the watchdog). w.r.t. stack size, There will be a start-up assembly file in your project (with a .s extension). Open that in uVision and select the "configuration Wizard tab. There you can set the stack and heap sizes. – Clifford Jun 08 '21 at 16:51
  • @MohamedKhaled Add `--info=summarystack --info=stack` to the linker options to get stack requirement reporting in the map file. Then check the stack requirement for `main()` and any thread or interrupt entry points. – Clifford Jun 08 '21 at 16:59
  • @Usama Note that if specific exception handling has not been enabled, everything ends up in the hard-fault handler. The [exception registers](https://www.keil.com/support/man/docs/uv4/uv4_cp_m347_faults.htm) will indicate the exception type however. – Clifford Jun 08 '21 at 17:32