Jump to content

Zedboard Standalone with uGfx


dewees

Recommended Posts

I am currently trying to add uGfx to a standalone (bare metal) Zedboard project. Zedboard uses the Xilinx Zynq-7000 processor, and I have a framebuffer display plugged into it with a touchscreen controller. 

I am trying to add the touchscreen support, but my application seems to be failing once I get to the gtimerStart() function inside _gmouseInitDriver(), found in source here

Basically this timer seems to infinitely loop and never appropriately exits. I'm hoping to get help and clarification on how to hookup a touchscreen driver without an OS, as I haven't encountered too many examples or documentation that helps. 

I will be happy to provide more details if needed. Thanks in advance for any help. 

Link to comment
Share on other sites

Hello @dewees and welcome to the µGFX community!

When running bare-metal you're using the RAW32 port. That port allows running µGFX without modifications on any 32-Bit platform. That port relies on the use of setjmp() and longjmp() functions of the c library to implement a very small and primitive cooperative (non-preemptive) scheduler. Unfortunately many c libraries that come with embedded compilers are known to contain bugs in the implementation of these two functions. It appears that they simply don't get tested because they are a lot less common than stuff like memcpy() and similar. However, they are still the best way for us to implement a generic, platform independent scheduler that is very small and simple but provides everything required to implement a full blown GUI without any draw-backs. Even some larger players like ARMCC have that/these bug(s) in them but they simply don't seem to care to fix them. If you give the forum search a quick try you'll see that this is a very common problem reported here.
To workaround that problem we provide custom schedulers for certain processors. That is why the GFX_CPU macro exists (doc). For example, the entire ARM Cortex-M series family is completely supported. Unfortunately there's currently no custom scheduler that would be compatible with the Xilinx Zynq-7000 processor. However, it is fairly easy to create one. After all only the context switching functions need to be implemented which is just a matter of putting the current processor context (registers) onto the stack and getting it back from there again. You can have a look at the implementations of the Cortex-M context switching code at /src/gos/gos_x_threads_*.h. Basically you'd have to write the same code for your processor (which appears to be an ARM Cortex-A compatible one and therefore quite straight forward). Note that the Cortex-M implementations contain code for different compilers so you can simply divide the code you see by two to get an idea of what needs to be done. You can divide it by two again once you realize that we implement the context switching functions for both the Cortex-M cores that come with and without an FPU.

But before you do that, you might want to check whether that is actually the problem (it's very very likely that that is the problem provided that you correctly implemented the two functions to retrieve the systick and to convert milliseconds to systicks). You can simply run the GOS threads demo that you can find under /demos/modules/gos/threads to see whether the context switching is working. If not, you'll either have to change your toolchain to one that provides proper non-bugged versions of setjmp() and longjmp() or you have to implement the custom context switching.
We are very happy to help with the latter if you have any questions.

Please don't hesitate to ask if you have any further questions. We're really happy to help wherever we can!

Link to comment
Share on other sites

Joel, 

Thank you very much for your response. I appreciate the quick reply. 

I ran the demo in demos/modules/gos/threads and if I comment out the gtimerStart() call inside _gmouseInitDriver(), the demo works. However, when I put that function call back in, it doesn't because it doesn't get past gfxInit() in the main. 

I am also going to try the demo in demos/modules/gtimer as well to see if that helps. In the meantime, any thoughts? 

Link to comment
Share on other sites

Wait... does this mean that the /demos/modules/gos/threads demo is working correctly (the threads are running in parallel) if GTIMER is not used?
I see that that demo only creates two threads. If those are working, can you please add a third (and maybe fourth) thread and test again?

If the scheduling really is working then I can't think of much else other than a too small GTIMER stack (configuration file!) or a blocking thread (note that RAW32 is a non-preemtive system, you have to use gfxSleepMilliseconds() (or gfxYield()) in your own threads to give other threads a change to run.

Running the test as described above as well as running the /demos/modules/gtimer demo as you suggested should help tracking the issue down.

Link to comment
Share on other sites

A little trick that may help...

The Cortex A processors are part of the Cortex range. If you find the closest M processor to the A series (i suspect the m7 or m4) you may be able to use the existing cpu specific scheduler just by changing your compiler flags to compile for that platform and set the GFX_CPU macro appropriately. 

From memory the threads demo contains no reference to gtimer at all so something doesn't sound right here.

Link to comment
Share on other sites

4 minutes ago, inmarket said:

From memory the threads demo contains no reference to gtimer at all so something doesn't sound right here.

I assume that he kept his config and didn't use the one that is part of the demo (which you really should, @dewees) which might have the GTIMER module enabled which in turn would initialize it upon gfxIni().

Link to comment
Share on other sites

Okay, the gtimer demo (yes, @Joel Bodenmann you're right, I used my config instead of the demo one) didn't work, as suspected. 

In that case, I will do the three things previously suggested. I will create more threads in the first demo, I will use the configs provided in each of the demos, and I will look into a close, compatible CPU-specific scheduler. 

I should also mention that the infinite loop that is occurring on gtimerStart() is only after I have implemented my touchscreen driver. If I remove my driver, it goes back to working with the gtimerStart() function still implemented. 

Link to comment
Share on other sites

3 minutes ago, inmarket said:

The reason it is likely working without your touch driver is that is where it actually uses gtimer. It is on the first use of gtimer that it probably falls over and this is likely because of a crash in the schedular. 

You're right about this. 

 

@Joel Bodenmann I added 2 more threads to that demo and it is still working no problem. I looked at my gfxconf.h and the lines under GTIMER were commented out: 

//#define GTIMER_THREAD_PRIORITY HIGH_PRIORITY

//#define GTIMER_THREAD_WORKAREA_SIZE 2048

 

I have added those to my config, cleaned and built, and unfortunately that did not fix the problem. It appears my scheduler is working fine; the problem really seems to be within gtimerStart().

Link to comment
Share on other sites

I stepped through and noticed that one of the times that cleanUpDeadThreads() is called (here), it is trying to free a thread that is stack allocated. I added a check in my free function to check if the pointer is within the heap or not; this hasn't actually fixed the problem I'm experiencing yet though. I will keep stepping through to figure out why. 

Link to comment
Share on other sites

Update and workaround: The thread in cleanUpDeadThreads() was not stack allocated; the pointer was being modified on the stack. I have removed the static declaration from the thread and threadQ type variables (in gos_x_threads.c) and this has made the problem go away. I'm not certain what causes this bug in Xilinx's cross compiler. 

@Joel Bodenmann and @inmarket thanks for helping me narrow it down. I appreciate your quick responses

Link to comment
Share on other sites

Can you please include a diff or patch on this forum thread for future reference. We will then look at if it is something we should push back to the repository. Also can you please tell us what the compiler is being detected as. There is a macro something like GFX_COMPILER_SHOW that causes the detected compiler to be displayed as a warning during compilation.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...