Sorry - this is long! I'm sure I'll get some TL;DRs. :/
I'm not at all new to the world of Cortex M3/4; I have encountered plenty of hard fault errors in the past and, without exception, they have been due to stack overflow on FreeRTOS. However, in this case, I'm really struggling to track down a hard fault on a system that has someone else's old code that I have slightly modified.
I have a system with an LCD and touch screen. We have new hardware, which is almost identical to the old hardware other than it changing from an LPC1788 to a drop-in equivalent LPC4088 and the touch screen being I2C rather than SPI.
I'm using Keil uvision (which is new to me) with an NXP4088 which is an M4 core and Keil RL-ARM RTOS (also new to me) which is using C/C++ hybrid, the C++ also not something I have much experience with. On top of this, there is Segger emWin (which I've never used) closed source code where it always seems to be crashing. It will render a few screens, read the touch screen buttons etc and then fall over. Sometimes it falls over immediately though.
I have followed this:
http://www.keil.com/appnotes/files/apnt209.pdf
I have attached a picture of the debugger/IDE when it crashes below (click to enlarge).
When it crashes, the highlighted green task in the OS is, without exception, ApplicationTask (which I have not modified).
If I am reading the info correctly the Keil uvision debugger tells me that the stack being used was the MSP stack which is at address 0x20003238. There's a memory dump below:
If I understand correctly, this means that R0, 2, 3 and 12 are 0, the program counter is at 0 as are LR and PSR. However, this goes against what's in the Call Stack + Locals window in the first picture. If I right click on the 0x00005A50 underneath ApplicationTask:4 and choose caller code, it itells me it is
BL.W GUI_ALLOC_UnlockH
Which is in the emWin binary blob I think.
However, if I look at 0x20001B60 (which is the PSP stack value) as below:
That seems to tally up much better with what the Call Stack + Local Window tells me. It also seems to tell me that it's crashing in emWin and extensive Googling shows that Segger always completely wash their hands of any possibility their closed source code could be at fault. To be fair, it's unlikely as it's been working OK until I modified the code to use an I2C touch screen interface rather than SPI. However, where it's crashing (or seems to be) is nothing to do with the code I have modified.
Also, this window below:
Gives the BFAR address as 0xF00B4DDA and the memory manager fault address as 0xF00B4DDA. I don't know whether I should be interpreting this as to being the issue.
I have found a few other posts around the web, including one staggeringly similar one to this here on Stack Overflow (but all have no solution associated with them) where people have the same issue.
So, my questions are:
Am I reading this data correctly and understanding the Keil document I linked to? I really feel I must be missing something with this MSP/PSP issue.
Am I using the caller code function with uvision correctly? The bit where I right click on Call Stack + Locals' address below ApplicationTask:4 and it always seems to take me to some Segger code I can't examine and surely isn't what's at fault.
Should I really be reading the issue as a bus fault address with it trying to read from or write to 0xF00B4DDA which is reserved space?
I tried implementing a piece of code such as this:
https://blog.frankvh.com/2011/12/07/cortex-m3-m4-hard-fault-handler/
But that just stops the whole system running properly and ends up in at BKPT instruction in some init code. On top of this, I am not convinced this kind of thing would tell me any more than uvision does, other than it showing me slightly faster and with zero effort. Am I right in this latter assumption?
Related
As soon as you hit "Play" what happens in the background of the software? The code is already compiled and ready at this point. So when I press "Play" the code gets executed. What other things occur along with this?
I have this question as an assignment and would really like to know. Thanks. :)
Actually everything is loaded by script. This graph explains the process. Also the links below can be useful for you to understand all the background process.
Execution Order of Event Functions
Overview: Script compilation
Asking what happens when you press Play is like asking Coke to reveal the drink recipe. This is what they sell. You got that as assignment, fact is you can say anything and your teacher would lie to tell you wrong, since he does not know either (except if he works for a company that bought the source code of the engine).
What you can say, is that the OpenGl/DirectX API is initialised, registration of all event to the OS like Input, application data and so on, then all the Engine functioning, registering of the needed classes in memory, init of the physics, parsing of the opening scene YAML file, creation of the content and placement in space, for each item, if a MonoBehaviour, registration of all callbacks, all the debug code related to profiler and stack tracing, crash reports and many more...
Those are the obvious ones and I cannot have any clue of what is going on without using a tool to decompose the code. Problem, it is against the EULA and then illegal.
From what experience I have programming whenever a program has a problem it crashes, whether it is from an unhanded exception or a piece of code that should have been checked for errors, but was not and threw one. What would cause a program to completely freeze a system to the point of requiring a restart.
Edit: Thanks for the answers. As for the language and OS this question was inspired by me playing Fallout and the game freezing twice in an hour causing me to have to restart the xbox, so I am guessing c++.
A million different things. The most common that come to mind are:
Spawning too many threads or processes, which drowns the OS scheduler.
Gobbling too much RAM, which puts the memory manager into page-fault hell.
In a Dotnet/Java type environment its quite difficult to seize a system up, because the Runtime keeps you code at a distance from the OS.
Closer to the metal say C or C++, Assembly etc you have to play fair with the rest of the system - If you dont have it already grab a copy of Petzold and observe/experiment yourself with the amount of 'boilerplate' code to get a single Window running...
Even closer, down at the driver level all sorts of things can happen...
There are number of reasons, being internal or external that leads to deadlocked application, more general case is when something is being asked for by a program but is not given that leads to infinite waiting, the practical example to this is, a program writes some text to a file, but when it is about to open a file for writing, same file is opened by any other application, so the requesting app will wait (freeze in some cases if not coded properly) until it gets exclusive control of the file.
And a critical freeze that leads to restarting the system is when the file which is asked for is something which very important for the OS. However, you may not need to restart the system in order to get it back to normal, unless the program which was frozen is written in a language that produces native binary, i.e. C/C++ to be precise. So if application is written in a language which works with the concept of managed code, like any .NET language, it will not need a system restart to get things back to normal.
page faults, trying to access inaccessible data or memory(acces violation), incompatible data types etc.
Good news, my c64 ist still running after lots of years spending time on my attic..
But what I always wanted to know is:
How can I automatically load & run a program from a floppy disk that is already inserted
when I switch on the c64?
Some auto-running command like load "*",8,1 would be adequate...
Regards
MoC
You write that a command that you type in, like LOAD"*",8,1 would be adequate. Can I assume, then, that the only problem with that particular command is that it only loads, but doesn't automatically run, the program? If so, you have a number of solutions:
If it's a machine language program, then you should type LOAD"<FILENAME>",8,1: and then (without pressing <RETURN>) press <SHIFT>+<RUN/STOP>.
If it's a BASIC program, type LOAD"<FILENAME>",8: and then (without pressing <RETURN>) press <SHIFT>+<RUN/STOP>.
It is possible to write a BASIC program such that it automatically runs when you load it with LOAD"<FILENAME>",8,1. To do so, first add the following line to the beginning of your program:
0 POKE770,131:POKE771,164
Then issue the following commands to save the program:
PRINT"{CLR}":POKE770,113:POKE771,168:POKE43,0;POKE44,3:POKE157,0:SAVE"<FILENAME>",8
This is not possible without some custom cartridge.
One way to fix this would be getting the Retro Replay cartridge and hacking your own code for it.
I doubt there is a way to do it; you would need a cartridge which handles this case and I don't think one like that exists.
A better and more suitable solution is EasyFlash actually. Retro Replay is commonly used with its own ROM. Since it is a very useful cartridge by default ROM, I would never flash another ROM to it. Also it is more expensive than EasyFlash if you don't have any of those cartridges.
At the moment, I have Prince Of Persia (!) ROM written to my EasyFlash and when I open my c64, it autoruns just like you asked for.
Not 100% relevant, but C128 can autoboot disks in C128 mode. For example Ultima V (which has musics on C128 but not on C64 or C128 in C64 mode) autoboots.
As for cartridges, I'd recommend 1541 Ultimate 2. It can also run games from module rom images (although Prince of Persia doesn't work for me for some reason, perhaps software issue?), but you also get rather good floppy emulator (which also makes it easier to transfer stuff to real disks), REU, tape interface (if you order it) etc.
If you are working with a ML program, there are several methods. If you aren't worried about ever returning to normal READY prompt without a RESET, you can have a small loader that loads into the stack ($0100-$01FF) The loader would just load the next section of code, then jump to it. It would start at $0102 and needs to be as small as possible. Many times, the next piece to load is only 2 characters, so the file name can be placed at $0100 & $0101. Then all you need to do is set LFS, SETNAM, LOAD, then JMP to it. Fill the rest of the stack area with $01. It is also rather safe to only save $0100-$010d so that the entire program will fit on a single disk block.
One issue with this, is that it clears out past stack entries (so, your program will need to reset the stack pointer back to the top.) If your program tries to do a normal RTS out of itself, random things can occur. If you want to exit the program, you'll need to jmp to the reset vector ($FFFC by default,) to do so.
Would it be possible to take the source code from a SNES emulator (or any other game system emulator for that matter) and a game ROM for the system, and somehow create a single self-contained executable that lets you play that particular ROM without needing either the individual rom or the emulator itself to play? Would it be difficult, assuming you've already got the rom and the emulator source code to work with?
It shouldn't be too difficult if you have the emulator source code. You can use a method that is often used to store images in c source files.
Basically, what you need to do is create a char * variable in a header file, and store the contents of the rom file in that variable. You may want to write a script to automate this for you.
Then, you will need to alter the source code so that instead of reading the rom in from a file, it uses the in memory version of the rom, stored in your variable and included from your header file.
It may require a little bit of work if you need to emulate file pointers and such, or you may be lucky and find that the rom loading function just loads the whole file in at once. In this case it would probably be as simple as replacing the file load function with a function to return your pointer.
However, be careful for licensing issues. If the emulator is licensed under the GPL, you may not be legally allowed to store a proprietary file in the executable, so it would be worth checking that, especially before you release / distribute it (if you plan to do so).
Yes, more than possible, been done many times. Google: static binary translation. Graham Toal has a good howto paper on the subject, should show up early in the hits. There may be some code out there I may have left some code out there.
Completely removing the rom may be a bit more work than you think, but not using an emulator, definitely possible. Actually, both requirements are possible and you may be surprised how many of the handheld console games or set top box games are translated and not emulated. Esp platforms like those from Nintendo where there isnt enough processing power to emulate in real time.
You need a good emulator as a reference and/or write your own emulator as a reference. Then you need to write a disassembler, then you have that disassembler generate C code (please dont try to translate directly to another target, I made that mistake once, C is portable and the compilers will take care of a lot of dead code elimination for you). So an instruction of a make believe instruction set might be:
add r0,r0,#2
And that may translate into:
//add r0,r0,#2
r0=r0+2;
do_zflag(r0);
do_nflag(r0);
It looks like the SNES is related to the 6502 which is what Asteroids used, which is the translation I have been working on off and on for a while now as a hobby. The emulator you are using is probably written and tuned for runtime performance and may be difficult at best to use as a reference and to check in lock step with the translated code. The 6502 is nice because compared to say the z80 there really are not that many instructions. As with any variable word length instruction set the disassembler is your first big hurdle. Do not think linearly, think execution order, think like an emulator, you cannot linearly translate instructions from zero to N or N down to zero. You have to follow all the possible execution paths, marking bytes in the rom as being the first byte of an instruction, and not the first byte of an instruction. Some bytes you can decode as data and if you choose mark those, otherwise assume all other bytes are data or fill. Figuring out what to do with this data to get rid of the rom is the problem with getting rid of the rom. Some code addresses data directly others use register indirect meaning at translation time you have no idea where that data is or how much of it there is. Once you have marked all the starting bytes for instructions then it is a trivial task to walk the rom from zero to N disassembling and or translating.
Good luck, enjoy, it is well worth the experience.
I'm new to VB6 but i'm currently in charge of maintaining a horror of editor like tool with plenty of forms, classes, modules and 3rd party tools all chunk together like the skin faces on that guy in the texas chainsaw massacre...
What i don't understand is why i get different results when i run the app in debugging mode, vs when i compiled it and run it on my devevelopment pc vs when i installed it on a different pc.
Yes i know i'm dumb, so please direct me to where i can find out more about this. I'm hoping to find out something like different linking, registry related etc connection that i'm simply not getting right now, i.e. something like wax on, wax off :P
The main pain in the neck is when i'm trying to debug some errors from my QA and i need to find a spare pc to test this on plus i can't directly debug because i don't know where the code is if i do it that manner.
Thanks.
i run the app in debugging mode vs when i compiled it and run it on my
devevelopment pc
When you compile you have the option of compiling to native code or pcode. The debugger runs using pcode only. Under rare circumstances when you compile to native code there will be a change in behavior. This particular is really rare. I used VB6 since it's release and I may get it once or twice a year. My application is a complex CAD/CAM creating shapes and running metal cutting machine and has two dozen DLLs. Not a typical situation. At home with my hobby software I never ran into this problem.
There are another class of errors that result from event sequencing problems. While VB6 isn't truly multi-tasking it has the ability to jump out of the current code block to process a event. If it re-enters the same block for the new event interesting things (to say the least) can result. I think this is the likely source of your problems as you software is an editor which is a highly interactive type of software.
In general the problem is fixed by reordering the effected areas. You find the effected area by inserting MsgBox or write to a text file to log where you are. I recommend logging to a text file as MsgBox tend to alter behavior that are timing or multi-tasking related.
Remember if a event fire while VB6 in the middle of a code block and there a DoEvents floating around then it will leave the code block process the event and return to the original code block. If it re-enters the same code block and you didn't mean for this to happen then you will have problems. And you will have different problems on different computers as the timing will be different for each.
The easiest way to deal with this type of issues is create some flag variables. In multi-tasking parlance they are known as semaphores or mutexes. WHen you enter a critical section of code, you set it true. When you leave the routine you set it to false. If it is already true when you enter that section of code you don't execute it.
when i installed it on a different pc.
These are usually the result of the wrong DLL installed. Most likely you have an older version while the target has a newer version. I would download the free Virtual PC and create a clean Window XP install to double check this.
If your problem is event timing this too can be different on different computers. This is found by logging (not MsgBox) suspect regions.
If you can display a screen shot or the text of your specific errors then I can help better.
The first thing to check would be the versions of all the dlls that your app depends on - including the service pack version of the VB6 dll.
Have you any more specific details about what's behaving differently?