Jump to content

nathanwiebe

Members
  • Posts

    9
  • Joined

  • Last visited

Everything posted by nathanwiebe

  1. Thanks for taking the time to look into this! Just to be sure, can you also attach a copy of the gdisp_lld_Win32.c file you are using to test? I have implemented the fixes in my copy of that file, but I have also implemented some other mods such as scaling/stretching/minimize/maximize on the win32 canvas, as well as window styles), and it would help to be able to do a before and after comparison.
  2. I think for the sake of time I will have to respond in pseudocode: //create a display and clear it to all white disp = createDisplay(800, 480) clearDisplay(disp, WHITE) //create a pixmap and fill it with an image pm = createPixmap(800, 600) img = loadImage("puppy.png") //an 800x480 (full-screen) image drawImage(pm, img) //blit the entire pixmap on the display - works correctly blit(disp, pm, 0, 0, 800, 480, 0, 0) //at this point, the display contains the entire image //blit a partial pixmap on the display with source coord (0,0) - works correctly blit(disp, pm, 0, 0, 200, 200, 0, 0) //at this point, the display still contains the entire image, and we re-drew the top left 200x200 pixels //blit a region from the middle of the pixmap to the display (source coord != (0,0)) - PROBLEM!! blit(disp, pm, 200, 200, 200, 200, 200, 200) //If all was working correctly, at this point, the display still would contain the entire image, //and we would have now also re-drew the middle 200x200 pixels. But... //Due to bug #2 above: when the stock code is run with rotation = 0, the line of code labelled //PROBLEM will cause a cras hbecause the buffer is erroneously freed (see bug #2 description above). //when the fix for the free bug (#2) is applied, there still is a drawing bug. //Due to bug #1 above, the code labelled PROBLEM will now draw the wrong region of the image onto the display //because the source pointer computation does not take into account the supplied source horizontal offset. **For both cases, the fixes are above.
  3. Line 545 of gdisp_lld_STM32LTDC.c currently reads: srcstart = LTDC_PIXELBYTES * ((gU32)g->p.x2 * g->p.y1 * + g->p.x1) + (gU32)g->p.ptr; Given that the operator "* +" clearly compiles but is nonsense, the correct line of code should be: srcstart = LTDC_PIXELBYTES * ((gU32)g->p.x2 * g->p.y1 + g->p.x1) + (gU32)g->p.ptr; I think this is a plain and simple typo, but it has been there since uGFX 2.7 or earlier. This means the srcstart (the starting address of the blit source) is not being calculated correctly. I believe the reason this slipped passed the radar in v2.7 is that, for some unknown reason, this same calculation was repeated (without the typo) in line 578, where DMA2D->FGMAR was set to the source address. So in 2.7, the only time the erroneous value was used was in cache flushing and invalidation. In the latest (2.9 release and guthub) version, the erroneously-calculated srcstart is being used directly to set FGMAR (as it should), but due to the typo, the resulting blit regions are copying essentially from random areas as their source. As for reproduction steps, any blit from a pixmap to the display will calculate incorrectly except for, I suppose, blits with a source of (0,0) and a few other lucky combinations. I just thought I would report this to be helpful.
  4. The gdisp_lld_blit_area() function is broken in a few ways, both to do with blits whose source X coordinate is non-zero: 1. The following line is intended to compute the source array for the blit operation, but doesn't take into account the source offset. buffer += g->p.x2*g->p.y1; It should be changed to something like: buffer += g->p.x2 * g->p.y1 + g->p.x1; 2. Near the bottom of the function, the following code is intended to detect if a rotation has been done (thereby changing the buffer variable from the pixmap base buffer to a freshly allocated, rotated buffer: buffer = g->p.ptr; buffer += g->p.x2 * g->p.y1 + g->p.x1; //STUFF if (orientation needs to change): buffer = rotateimg(g, buffer); //STUFF if (buffer != (gPixel *)g->p.ptr) free(buffer); The problem is that after setting buffer to the pixmap base array at the top of the function, it is tweaked by horizontal and vertical offsets to a new value representing the top left of the source image, but is still located in the original pixmap buffer. This means that if your source x or y offsets are non-zero and rotation is not required, it will erroneously decide that is has rotated the image and needs to free the array, causing a crash (free an invalid memory pointer). It should be fixed to something more like: buffer = g->p.ptr; buffer += g->p.x2 * g->p.y1 + g->p.x1; bufferBase = buffer; //STUFF if (orientation needs to change) buffer = rotateimg(g, buffer); //STUFF if (bufferBase != buffer) free(buffer);
  5. Sounds great! I may be looking in the wrong place, but the only changelog I can find only includes changes up until v2.7. is there a newer changelog by chance with a basic overview of v2.8 changes?
  6. I am using what I think is the stock 2.7.0 release, rather than follow the repo, so likely I am using an old FreeRTOS port. In any case, it is a subtle bug, but not too hard to search for. Searching for the text portENTER_CRITCAL and taskENTER_CRITICAL will find all critical sections in the FreeRTOS/uGFX interface code, and it should be checked that there is no FreeRTOS API usage (even non-blocking calls such as a binary semaphore push/give - see the note on the FreeRTOS critical section documentation) within the critical sections. In the version I have (stock 2.7.0 I think), gos_freertos.c:139 contains a semaphore give inside a critical section in the gfxSemSignal() function.
  7. Good news! The bug has been fixed. Unfortunately I am able to offer less clarity on the exact solution that I had hoped. As I mentioned, my specific display glitch started 26:49 after boot, continued for 67 seconds, and repeated every 71 minutes. I believe the root cause to have been related to something thrashing and eating up too much SDRAM bandwidth. I hoped to narrow down precisely which lines of code this was, however this did not happen before the bug was solved another way. FreeRTOS on CortexM parts forbids making any OS API call from within a critical section. Probably 99.99% of the time you'll be lucky and get away with it, but sometimes it'll hang the OS or do some other unpredictable thing. I had an occasional boot issue (unrelated to the LCD) that I narrowed down to a race condition caused by a syscall from within a critical section, and decided to go through all critical sections in the whole codebase to make sure there were no syscalls from within them. Lo and behold, I found 10. Most were in my code, but one was in an ATMEL WiFi driver, and one was in uGFX's FreeRTOS port for the GFX layer (which I should probably report as a bug). Anyways, after fixing these... poof... no display glitch. So the solution is far less satisfying that finding a specific line of code that was actually chewing up the SDRAM bandwidth, but it is an important lesson nonetheless. And it uncovered a bug in uGFX, so I guess we all win.
  8. A huge thanks for all the helpful suggestions. I will look into all of these things, although I have to apologize for being slow to look into this because of other project demands. For now, here is a quick update on my investigation: As I mentioned, it takes 27 minutes to get the glitch to happen, and it only lasts 67 seconds, so gathering info is extremely inefficient. I have stepped through various parts of the code during the glitch and nothing sticks out. I can see some flickers as I single-step, but haven't correlated it to a particular area of code or RTOS thread priority level. When the glitch starts, I can lock up my highest priority thread and the glitch stops, suggesting that something may be competing with the SDRAM for bandwidth during this time. I don't, however, have any application code that fits this pattern of memory usage. My next step (as time allows), is to remove the individual components of the application and driver code one by one to find the culprit, but that will take some time. I should mention that the reason I am thinking that this is a single 'culprit' chunk of code rather than a general problem like overall SDRAM bandwidth is because the display looks beautiful 98% of the time with the full application running (the application code is all written in lua, and the lua heap is located in SDRAM). As for possibilities such as caching and/or FPU interactions, my use of floating point numbers is consistent throughout the code, and my glitch lasts exactly 67 seconds out of every 71 minutes, so I don't see that as a good fit. I have also essentially ruled out corruption of the contents of my SDRAM because the remainder of the SDRAM is the lua heap, and that would hard fault the whole system real quick if the odd byte were being corrupted. I also appreciate the suggestion that the LTDC or DMA2D clocks may be in some state of synchronization during the glitches (67 seconds out of 71 minutes, exactly 1/64th of the time), causing my effective available SDRAM bandwidth to decrease. However, as I mentioned, I can halt the lua engine (halting virtually all SDRAM access) during the glitch and it continues for the same exact amount of time. I have also read out the SFR register bank of the LTDC during that time to make sure nothing is accidentally getting changed, and it all looks good. I guess I could do the same with the GPIO (IO directions, speed config, and alternate function selections)... Either way, thanks for all the suggestions!
  9. I was wondering if anyone has any hints on how I can troubleshoot a problem I am having. I am a paid customer with a commercial license and my first design using uGFX is almost production-ready, but there is a glitch in the software that is holding me up. I am using an STM32F777 processor with a 800x480 LCD with the frame buffer located in external SDRAM. I have a second frame buffer that I actually draw to, and I use the hardware blit/region copy functionality of the STM32's DMA2D to draw updates to the live frame buffer. As far as uGFX is concerned, my code is very closely based on the STM32F746 discovery board demo. The glitch seems to last a very deterministic amount of time: ~67 seconds out of every ~71 minutes. Note that this is pretty much exactly 1/64th of the time, and that 71 minutes is 2^32 microseconds, although this might be a coincidence (I am grasping at straws to get some kind of a handle on what might be causing this issue). The best I can describe the glitch is that the display seems to draw a fraction of the horizontal lines, and then shift to a random horizontal offset and draw another bunch of lines, and then repeat. The result is an image comprised of horizontal bars that are the correct image except at random horizontal offsets, and the random offsets seem to change each scan - i.e. a weird flickery side-scrolling pattern. Image quality is perfect the rest of the time. It happens on all 5 prototype units, and has been consistent all through development, and I feel like I am no closer to discovering the cause of the glitch. Because all drawing happens in lua (a scripting language that wraps the uGFX library), I can easily lock up the lua thread to halt all drawing operations, effectively preventing all uGFX API calls during the glitch. Doing so seems to maybe have some effect on the pattern, but the glitch continues until the 67 seconds are done. I am over-the-top happy with how well uGFX is working overall, but I would love if someone more familiar with the STM32F7 LTDC port could brainstorm with me on what might be causing this. Please let me know if there is any additional information that I can post that would help get to the bottom of this.
×
×
  • Create New...