aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Doxygenfile6
-rw-r--r--changelog.txt (renamed from docs/changelog.txt)8
-rw-r--r--drivers/multiple/Win32/gdisp_lld_Win32.c4
-rw-r--r--drivers/multiple/Win32/gdisp_lld_config.h2
-rw-r--r--src/gfx_compilers.h1
-rw-r--r--src/gmisc/gmisc.h2
-rw-r--r--src/gos/gos_x_heap.c112
-rw-r--r--src/gos/gos_x_threads.c7
-rw-r--r--src/gos/gos_x_threads.h2
-rw-r--r--src/gos/gos_x_threads_cortexm01.h57
-rw-r--r--src/gos/gos_x_threads_cortexm347.h33
-rw-r--r--src/gos/gos_x_threads_cortexm47fp.h37
-rw-r--r--src/gtimer/gtimer.c2
-rw-r--r--src/gwin/gwin.c14
-rw-r--r--src/gwin/gwin.h34
15 files changed, 198 insertions, 123 deletions
diff --git a/Doxygenfile b/Doxygenfile
index 86ce081c..49d65ca2 100644
--- a/Doxygenfile
+++ b/Doxygenfile
@@ -38,13 +38,13 @@ PROJECT_NAME =
# could be handy for archiving the generated documentation or if some version
# control system is used.
-PROJECT_NUMBER = 2.6
+PROJECT_NUMBER = 2.7
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a
# quick idea about the purpose of the project. Keep the description short.
-PROJECT_BRIEF = "version 2.6"
+PROJECT_BRIEF = "version 2.7"
# With the PROJECT_LOGO tag one can specify an logo or icon that is included in
# the documentation. The maximum height of the logo should not exceed 55 pixels
@@ -1494,7 +1494,7 @@ MATHJAX_CODEFILE =
# The default value is: YES.
# This tag requires that the tag GENERATE_HTML is set to YES.
-SEARCHENGINE = NO
+SEARCHENGINE = YES
# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
# implemented using a web server instead of a web client using Javascript. There
diff --git a/docs/changelog.txt b/changelog.txt
index 7334298b..fd553138 100644
--- a/docs/changelog.txt
+++ b/changelog.txt
@@ -2,8 +2,10 @@
*** Releases ***
*****************************************************************************
+*** Changes after 2.7 ***
-*** Changes after 2.6 ***
+
+*** Release 2.7 ***
FEATURE: Added EXC7200 driver
FEATURE: Added STM32F439i-EVAL board files
FIX: Fixed crash when passing NULL to gwinSetStyle()
@@ -13,7 +15,7 @@ FEATURE: Added ILI9225 driver
FEATURE: Added ST7735 driver
FEATURE: Added Linux event input driver
FIX: Fixed an issue with color formats in Linux-Framebuffer board files
-FIX: Fixing and improving arc rendering functions
+FIX: Fixed and improving arc rendering functions
FIX: Preventing possible crash when no valid GWIN default font has been set
FIX: Updating Windows binaries of the font encoder to improve compatibility
FIX: Fixed progressbar bounds checking and decrementing
@@ -29,6 +31,8 @@ FEATURE: Added the ability to display the detected compiler
FIX: Fixed an illegal instruction in the Cortex M0 task switcher
FEATURE: Added RAW32 task switching functions which work with ARMCC (the compiler used by Keil) for Cortex M0,M1,M3,M4 and M7
FEATURE: Added gdispGDrawThickArc()
+FIX: Fixed a memory merging issue with the RAW32 memory allocator
+FIX: Update RAW32 libc threads support for more recent versions of the MinGW compiler
*** Release 2.6 ***
diff --git a/drivers/multiple/Win32/gdisp_lld_Win32.c b/drivers/multiple/Win32/gdisp_lld_Win32.c
index 9f0bb397..7bb6d137 100644
--- a/drivers/multiple/Win32/gdisp_lld_Win32.c
+++ b/drivers/multiple/Win32/gdisp_lld_Win32.c
@@ -451,8 +451,8 @@ typedef struct winPriv {
#endif
} winPriv;
-void gfxEmulatorSetParentWindow(HWND hwnd) {
- hWndParent = hwnd;
+void gfxEmulatorSetParentWindow(void *hwnd) {
+ hWndParent = (HWND)hwnd;
}
#if GFX_USE_GINPUT && GINPUT_NEED_MOUSE
diff --git a/drivers/multiple/Win32/gdisp_lld_config.h b/drivers/multiple/Win32/gdisp_lld_config.h
index 91891290..53f8bff7 100644
--- a/drivers/multiple/Win32/gdisp_lld_config.h
+++ b/drivers/multiple/Win32/gdisp_lld_config.h
@@ -51,7 +51,7 @@
// Passing a NULL will reset window creation to creating top level windows.
// Note: In order to affect any static displays it must be called BEFORE gfxInit().
// Note: Creating a window under a parent causes the Mouse to be disabled by default (rather than enabled as for a top window)
-void gfxEmulatorSetParentWindow(HWND hwnd);
+void gfxEmulatorSetParentWindow(void *hwnd);
#if GINPUT_NEED_MOUSE
// This function allows you to inject mouse events into the ugfx mouse driver
diff --git a/src/gfx_compilers.h b/src/gfx_compilers.h
index 2449c05e..46d6c8b1 100644
--- a/src/gfx_compilers.h
+++ b/src/gfx_compilers.h
@@ -625,6 +625,7 @@
#pragma diag_remark 767 // Turn off warning: conversion from pointer to smaller integer
#pragma diag_remark 188 // Turn off warning: enumerated type mixed with another type
#pragma diag_remark 68 // Turn off warning: integer conversion resulted in a change of sign
+ #pragma diag_remark 111 // Turn off warning: statement is unreachable
#ifndef GFXINLINE // Get the Keil definition for inline
#define GFXINLINE __inline
#endif
diff --git a/src/gmisc/gmisc.h b/src/gmisc/gmisc.h
index f805345c..21178774 100644
--- a/src/gmisc/gmisc.h
+++ b/src/gmisc/gmisc.h
@@ -473,7 +473,7 @@ extern "C" {
* @note This function works both with convex and concave polygons
*
* @param[in] pntarray The array of points that form the polygon
- * @param[in] cnt The number of points in the point array @pntarray
+ * @param[in] cnt The number of points in the point array @p pntarray
* @param[in] p The point to test
*
* @return @p TRUE if the point @p p is inside or on the edge of the polygon @p pntarray, @p FALSE otherwise.
diff --git a/src/gos/gos_x_heap.c b/src/gos/gos_x_heap.c
index 7e79d1c6..813d0199 100644
--- a/src/gos/gos_x_heap.c
+++ b/src/gos/gos_x_heap.c
@@ -34,7 +34,6 @@
// Slot structure - user memory follows
typedef struct memslot {
- struct memslot *next; // The next memslot
size_t sz; // Includes the size of this memslot.
} memslot;
@@ -48,13 +47,10 @@
#define Ptr2Slot(p) ((memslot *)(p) - 1)
#define Slot2Ptr(pslot) ((pslot)+1)
- static memslot * firstSlot;
- static memslot * lastSlot;
static memslot * freeSlots;
static char heap[GFX_OS_HEAP_SIZE];
void _gosHeapInit(void) {
- lastSlot = 0;
gfxAddHeapBlock(heap, GFX_OS_HEAP_SIZE);
}
@@ -62,18 +58,12 @@
if (sz < sizeof(memslot)+sizeof(freeslot))
return;
- if (lastSlot)
- lastSlot->next = (memslot *)ptr;
- else
- firstSlot = lastSlot = freeSlots = (memslot *)ptr;
-
- lastSlot->next = 0;
- lastSlot->sz = sz;
- NextFree(lastSlot) = 0;
+ ((memslot *)ptr)->sz = sz;
+ gfxFree(Slot2Ptr((memslot *)ptr));
}
void *gfxAlloc(size_t sz) {
- register memslot *prev, *p, *new;
+ register memslot *prev, *p, *pnew;
if (!sz) return 0;
sz = GetSlotSize(sz);
@@ -81,23 +71,22 @@
// Loop till we have a block big enough
if (p->sz < sz)
continue;
+
// Can we save some memory by splitting this block?
if (p->sz >= sz + sizeof(memslot)+sizeof(freeslot)) {
- new = (memslot *)((char *)p + sz);
- new->next = p->next;
- p->next = new;
- new->sz = p->sz - sz;
+ pnew = (memslot *)((char *)p + sz);
+ pnew->sz = p->sz - sz;
p->sz = sz;
- if (lastSlot == p)
- lastSlot = new;
- NextFree(new) = NextFree(p);
- NextFree(p) = new;
+ NextFree(pnew) = NextFree(p);
+ NextFree(p) = pnew;
}
+
// Remove it from the free list
if (prev)
NextFree(prev) = NextFree(p);
else
freeSlots = NextFree(p);
+
// Return the result found
return Slot2Ptr(p);
}
@@ -106,7 +95,7 @@
}
void *gfxRealloc(void *ptr, size_t oldsz, size_t sz) {
- register memslot *prev, *p, *new;
+ register memslot *prev, *p, *pfree;
(void) oldsz;
if (!ptr)
@@ -120,19 +109,14 @@
sz = GetSlotSize(sz);
// If the next slot is free (and contiguous) merge it into this one
- if ((char *)p + p->sz == (char *)p->next) {
- for (prev = 0, new = freeSlots; new != 0; prev = new, new = NextFree(new)) {
- if (new == p->next) {
- p->next = new->next;
- p->sz += new->sz;
- if (prev)
- NextFree(prev) = NextFree(new);
- else
- freeSlots = NextFree(new);
- if (lastSlot == new)
- lastSlot = p;
- break;
- }
+ for (prev = 0, pfree = freeSlots; pfree != 0; prev = pfree, pfree = NextFree(pfree)) {
+ if (pfree == (memslot *)((char *)p + p->sz)) {
+ p->sz += pfree->sz;
+ if (prev)
+ NextFree(prev) = NextFree(pfree);
+ else
+ freeSlots = NextFree(pfree);
+ break;
}
}
@@ -140,50 +124,54 @@
if (sz < p->sz) {
// Can we save some memory by splitting this block?
if (p->sz >= sz + sizeof(memslot)+sizeof(freeslot)) {
- new = (memslot *)((char *)p + sz);
- new->next = p->next;
- p->next = new;
- new->sz = p->sz - sz;
+ pfree = (memslot *)((char *)p + sz);
+ pfree->sz = p->sz - sz;
p->sz = sz;
- if (lastSlot == p)
- lastSlot = new;
- NextFree(new) = freeSlots;
- freeSlots = new;
+ NextFree(pfree) = freeSlots;
+ freeSlots = pfree;
}
return Slot2Ptr(p);
}
// We need to do this the hard way
- new = gfxAlloc(sz);
- if (new)
+ pfree = gfxAlloc(sz);
+ if (pfree)
return 0;
- memcpy(new, ptr, p->sz - sizeof(memslot));
+ memcpy(pfree, ptr, p->sz - sizeof(memslot));
gfxFree(ptr);
- return new;
+ return pfree;
}
void gfxFree(void *ptr) {
- register memslot *prev, *p, *new;
+ register memslot *prev, *p, *pfree;
if (!ptr)
return;
p = Ptr2Slot(ptr);
- // If the next slot is free (and contiguous) merge it into this one
- if ((char *)p + p->sz == (char *)p->next) {
- for (prev = 0, new = freeSlots; new != 0; prev = new, new = NextFree(new)) {
- if (new == p->next) {
- p->next = new->next;
- p->sz += new->sz;
- if (prev)
- NextFree(prev) = NextFree(new);
- else
- freeSlots = NextFree(new);
- if (lastSlot == new)
- lastSlot = p;
- break;
- }
+ // Find a free slot that is contiguous precceding and merge it into us
+ for (prev = 0, pfree = freeSlots; pfree != 0; prev = pfree, pfree = NextFree(pfree)) {
+ if (p == (memslot *)((char *)pfree + pfree->sz)) {
+ pfree->sz += p->sz;
+ if (prev)
+ NextFree(prev) = NextFree(pfree);
+ else
+ freeSlots = NextFree(pfree);
+ p = pfree;
+ break;
+ }
+ }
+
+ // Find a free slot that is contiguous after and merge it into this one
+ for (prev = 0, pfree = freeSlots; pfree != 0; prev = pfree, pfree = NextFree(pfree)) {
+ if (pfree == (memslot *)((char *)p + p->sz)) {
+ p->sz += pfree->sz;
+ if (prev)
+ NextFree(prev) = NextFree(pfree);
+ else
+ freeSlots = NextFree(pfree);
+ break;
}
}
diff --git a/src/gos/gos_x_threads.c b/src/gos/gos_x_threads.c
index 7afd224a..b696ee77 100644
--- a/src/gos/gos_x_threads.c
+++ b/src/gos/gos_x_threads.c
@@ -122,6 +122,7 @@ void gfxSleepMilliseconds(delaytime_t ms) {
case TIME_INFINITE:
while(1)
gfxYield();
+ return;
}
// Convert our delay to ticks
@@ -143,6 +144,7 @@ void gfxSleepMicroseconds(delaytime_t ms) {
case TIME_INFINITE:
while(1)
gfxYield();
+ return;
}
// Convert our delay to ticks
@@ -212,12 +214,12 @@ static thread mainthread; // The main thread context
* If they don't exist compile them to be the standard setjmp() function.
* Similarly for longjmp().
*/
- #if (!defined(setjmp) && !defined(_setjmp)) || GFX_COMPILER == GFX_COMPILER_KEIL
+ #if (!defined(setjmp) && !defined(_setjmp)) || GFX_COMPILER == GFX_COMPILER_KEIL || GFX_COMPILER == GFX_COMPILER_MINGW32 || GFX_COMPILER == GFX_COMPILER_MINGW64
#define CXT_SAVE setjmp
#else
#define CXT_SAVE _setjmp
#endif
- #if (!defined(longjmp) && !defined(_longjmp)) || GFX_COMPILER == GFX_COMPILER_KEIL
+ #if (!defined(longjmp) && !defined(_longjmp)) || GFX_COMPILER == GFX_COMPILER_KEIL || GFX_COMPILER == GFX_COMPILER_MINGW32 || GFX_COMPILER == GFX_COMPILER_MINGW64
#define CXT_RESTORE longjmp
#else
#define CXT_RESTORE _longjmp
@@ -346,6 +348,7 @@ static thread mainthread; // The main thread context
uint32_t i;
// Copy the stack frame
+ s = 0;
#if AUTO_DETECT_STACKFRAME
if (STACK_DIR_UP) { // Stack grows up
nf = (char *)(t) + sizeof(thread) + sizeof(jmp_buf) + STACK_BASE;
diff --git a/src/gos/gos_x_threads.h b/src/gos/gos_x_threads.h
index ee7a9cd0..585585c5 100644
--- a/src/gos/gos_x_threads.h
+++ b/src/gos/gos_x_threads.h
@@ -90,7 +90,7 @@ extern "C" {
threadreturn_t gfxThreadWait(gfxThreadHandle thread);
gfxThreadHandle gfxThreadMe(void);
- /** The following is not part of the public ugfx API has some operating systems
+ /** The following is not part of the public ugfx API as some operating systems
* simply do not provide this capability.
* For RAW32 we need it anyway so we might as well declare it here.
*/
diff --git a/src/gos/gos_x_threads_cortexm01.h b/src/gos/gos_x_threads_cortexm01.h
index 8a44bd35..15a90b2a 100644
--- a/src/gos/gos_x_threads_cortexm01.h
+++ b/src/gos/gos_x_threads_cortexm01.h
@@ -27,8 +27,10 @@
"mov r6, r10 \n\t"
"mov r7, r11 \n\t"
"push {r4, r5, r6, r7} \n\t"
- "str sp, %[oldtcxt] \n\t"
- "ldr sp, %[newtcxt] \n\t"
+ "mov r4, sp \n\t"
+ "str r4, %[oldtcxt] \n\t"
+ "ldr r4, %[newtcxt] \n\t"
+ "mov sp, r4 \n\t"
"pop {r4, r5, r6, r7} \n\t"
"mov r8, r4 \n\t"
"mov r9, r5 \n\t"
@@ -41,15 +43,17 @@
}
static __attribute__((pcs("aapcs"),naked)) void _gfxStartThread(thread *oldt, thread *newt) {
- newt->cxt = (char *)newt + newt->size;
+ newt->cxt = (void *)(((unsigned)newt + newt->size) & ~7);
__asm__ volatile ( "push {r4, r5, r6, r7, lr} \n\t"
"mov r4, r8 \n\t"
"mov r5, r9 \n\t"
"mov r6, r10 \n\t"
"mov r7, r11 \n\t"
"push {r4, r5, r6, r7} \n\t"
- "str sp, %[oldtcxt] \n\t"
- "ldr sp, %[newtcxt] \n\t"
+ "mov r4, sp \n\t"
+ "str r4, %[oldtcxt] \n\t"
+ "ldr r4, %[newtcxt] \n\t"
+ "mov sp, r4 \n\t"
: [newtcxt] "=m" (newt->cxt)
: [oldtcxt] "m" (oldt->cxt)
: "memory");
@@ -59,8 +63,12 @@
}
#elif GFX_COMPILER == GFX_COMPILER_KEIL || GFX_COMPILER == GFX_COMPILER_ARMCC
+ #define GFX_THREADS_DONE
+ #define _gfxThreadsInit()
static __asm void _gfxTaskSwitch(thread *oldt, thread *newt) {
+ PRESERVE8
+
// Save the old context
push {r4, r5, r6, r7, lr}
mov r4, r8
@@ -68,10 +76,12 @@
mov r6, r10
mov r7, r11
push {r4, r5, r6, r7}
- str sp, [r0,#__cpp(offsetof(thread,cxt))] // oldt->cxt
+ mov r4, sp
+ str r4, [r0,#__cpp(offsetof(thread,cxt))] // oldt->cxt
// Load the new context
- ldr sp, [r1,#__cpp(offsetof(thread,cxt))] // newt->cxt
+ ldr r4, [r1,#__cpp(offsetof(thread,cxt))] // newt->cxt
+ mov sp, r4
pop {r4, r5, r6, r7}
mov r8, r4
mov r9, r5
@@ -81,11 +91,14 @@
}
static __asm void _gfxStartThread(thread *oldt, thread *newt) {
+ PRESERVE8
+
// Calculate where to generate the new context
- // newt->cxt = (char *)newt + newt->size;
- ldr r2,[r1,#__cpp(offsetof(thread,size))]
- add r2,r2,r1
- str r2,[r1,#__cpp(offsetof(thread,cxt))]
+ // newt->cxt = (void *)(((unsigned)newt + newt->size) & ~7);
+ ldr r2,[r1,#__cpp(offsetof(thread,size))]
+ add r2,r2,r1
+ and r2, r2, #0xFFFFFFF8
+ str r2,[r1,#__cpp(offsetof(thread,cxt))]
// Save the old context
push {r4, r5, r6, r7, lr}
@@ -94,20 +107,24 @@
mov r6, r10
mov r7, r11
push {r4, r5, r6, r7}
- str sp, [r0,#__cpp(offsetof(thread,cxt))] // oldt->cxt
+ mov r4, sp
+ str r4, [r0,#__cpp(offsetof(thread,cxt))] // oldt->cxt
// Load the new (imcomplete) context
- ldr sp, [r1,#__cpp(offsetof(thread,cxt))] // newt->cxt
+ ldr r4, [r1,#__cpp(offsetof(thread,cxt))] // newt->cxt
+ mov sp, r4
// Run the users function - we save some code because gfxThreadExit() never returns
// gfxThreadExit(_gfxCurrentThread->fn(_gfxCurrentThread->param));
- LDR r2,__cpp(&_gfxCurrentThread)
- LDR r2,[r2,#0]
- LDR r0,[r2,#__cpp(offsetof(thread,param))]
- LDR r1,[r2,#__cpp(offsetof(thread,fn))]
- BLX r1
- MOV r4,r0
- BL gfxThreadExit
+ ldr r2,=__cpp(&_gfxCurrentThread)
+ ldr r2,[r2,#0]
+ ldr r0,[r2,#__cpp(offsetof(thread,param))]
+ ldr r1,[r2,#__cpp(offsetof(thread,fn))]
+ blx r1
+ mov r4,r0
+ bl __cpp(gfxThreadExit)
+
+ ALIGN
}
#else
diff --git a/src/gos/gos_x_threads_cortexm347.h b/src/gos/gos_x_threads_cortexm347.h
index 03c13052..40d30138 100644
--- a/src/gos/gos_x_threads_cortexm347.h
+++ b/src/gos/gos_x_threads_cortexm347.h
@@ -32,7 +32,7 @@
}
static __attribute__((pcs("aapcs"),naked)) void _gfxStartThread(thread *oldt, thread *newt) {
- newt->cxt = (char *)newt + newt->size;
+ newt->cxt = (void *)(((unsigned)newt + newt->size) & ~7);
__asm__ volatile ( "push {r4, r5, r6, r7, r8, r9, r10, r11, lr} \n\t"
"str sp, %[oldtcxt] \n\t"
"ldr sp, %[newtcxt] \n\t"
@@ -45,8 +45,12 @@
}
#elif GFX_COMPILER == GFX_COMPILER_KEIL || GFX_COMPILER == GFX_COMPILER_ARMCC
+ #define GFX_THREADS_DONE
+ #define _gfxThreadsInit()
static __asm void _gfxTaskSwitch(thread *oldt, thread *newt) {
+ PRESERVE8
+
// Save the old context
push {r4, r5, r6, r7, r8, r9, r10, r11, lr}
str sp, [r0,#__cpp(offsetof(thread,cxt))] // oldt->cxt
@@ -57,11 +61,14 @@
}
static __asm void _gfxStartThread(thread *oldt, thread *newt) {
+ PRESERVE8
+
// Calculate where to generate the new context
- // newt->cxt = (char *)newt + newt->size;
- ldr r2,[r1,#__cpp(offsetof(thread,size))]
- add r2,r2,r1
- str r2,[r1,#__cpp(offsetof(thread,cxt))]
+ // newt->cxt = (void *)(((unsigned)newt + newt->size) & ~7);
+ ldr r2,[r1,#__cpp(offsetof(thread,size))]
+ add r2,r2,r1
+ and r2, r2, #0xFFFFFFF8
+ str r2,[r1,#__cpp(offsetof(thread,cxt))]
// Save the old context
push {r4, r5, r6, r7, r8, r9, r10, r11, lr}
@@ -72,13 +79,15 @@
// Run the users function - we save some code because gfxThreadExit() never returns
// gfxThreadExit(_gfxCurrentThread->fn(_gfxCurrentThread->param));
- LDR r2,__cpp(&_gfxCurrentThread)
- LDR r2,[r2,#0]
- LDR r0,[r2,#__cpp(offsetof(thread,param))]
- LDR r1,[r2,#__cpp(offsetof(thread,fn))]
- BLX r1
- MOV r4,r0
- BL gfxThreadExit
+ ldr r2,=__cpp(&_gfxCurrentThread)
+ ldr r2,[r2,#0]
+ ldr r0,[r2,#__cpp(offsetof(thread,param))]
+ ldr r1,[r2,#__cpp(offsetof(thread,fn))]
+ blx r1
+ mov r4,r0
+ bl __cpp(gfxThreadExit)
+
+ ALIGN
}
#else
diff --git a/src/gos/gos_x_threads_cortexm47fp.h b/src/gos/gos_x_threads_cortexm47fp.h
index 9767ac9a..f5eeff80 100644
--- a/src/gos/gos_x_threads_cortexm47fp.h
+++ b/src/gos/gos_x_threads_cortexm47fp.h
@@ -12,10 +12,6 @@
* The context is saved at the current stack location and a pointer is maintained in the thread structure.
*/
-#if !CORTEX_USE_FPU
- #warning "GOS Threads: You have specified GFX_CPU=GFX_CPU_CORTX_M?_FP with hardware floating point support but CORTEX_USE_FPU is FALSE. Try using GFX_CPU_GFX_CPU_CORTEX_M? instead"
-#endif
-
#if GFX_COMPILER == GFX_COMPILER_GCC || GFX_COMPILER == GFX_COMPILER_CYGWIN || GFX_COMPILER == GFX_COMPILER_MINGW32 || GFX_COMPILER == GFX_COMPILER_MINGW64
#define GFX_THREADS_DONE
#define _gfxThreadsInit()
@@ -33,7 +29,7 @@
}
static __attribute__((pcs("aapcs-vfp"),naked)) void _gfxStartThread(thread *oldt, thread *newt) {
- newt->cxt = (char *)newt + newt->size;
+ newt->cxt = (void *)(((unsigned)newt + newt->size) & ~7);
__asm__ volatile ( "push {r4, r5, r6, r7, r8, r9, r10, r11, lr} \n\t"
"vpush {s16-s31} \n\t"
"str sp, %[oldtcxt] \n\t"
@@ -47,8 +43,12 @@
}
#elif GFX_COMPILER == GFX_COMPILER_KEIL || GFX_COMPILER == GFX_COMPILER_ARMCC
+ #define GFX_THREADS_DONE
+ #define _gfxThreadsInit()
static __asm void _gfxTaskSwitch(thread *oldt, thread *newt) {
+ PRESERVE8
+
// Save the old context
push {r4, r5, r6, r7, r8, r9, r10, r11, lr}
vpush {s16-s31}
@@ -61,11 +61,14 @@
}
static __asm void _gfxStartThread(thread *oldt, thread *newt) {
+ PRESERVE8
+
// Calculate where to generate the new context
- // newt->cxt = (char *)newt + newt->size;
- ldr r2,[r1,#__cpp(offsetof(thread,size))]
- add r2,r2,r1
- str r2,[r1,#__cpp(offsetof(thread,cxt))]
+ // newt->cxt = (void *)(((unsigned)newt + newt->size) & ~7);
+ ldr r2,[r1,#__cpp(offsetof(thread,size))]
+ add r2,r2,r1
+ and r2, r2, #0xFFFFFFF8
+ str r2,[r1,#__cpp(offsetof(thread,cxt))]
// Save the old context
push {r4, r5, r6, r7, r8, r9, r10, r11, lr}
@@ -77,13 +80,15 @@
// Run the users function - we save some code because gfxThreadExit() never returns
// gfxThreadExit(_gfxCurrentThread->fn(_gfxCurrentThread->param));
- LDR r2,__cpp(&_gfxCurrentThread)
- LDR r2,[r2,#0]
- LDR r0,[r2,#__cpp(offsetof(thread,param))]
- LDR r1,[r2,#__cpp(offsetof(thread,fn))]
- BLX r1
- MOV r4,r0
- BL gfxThreadExit
+ ldr r2,=__cpp(&_gfxCurrentThread)
+ ldr r2,[r2,#0]
+ ldr r0,[r2,#__cpp(offsetof(thread,param))]
+ ldr r1,[r2,#__cpp(offsetof(thread,fn))]
+ blx r1
+ mov r4,r0
+ bl __cpp(gfxThreadExit)
+
+ ALIGN
}
#else
diff --git a/src/gtimer/gtimer.c b/src/gtimer/gtimer.c
index eda88d5a..22ec9ed2 100644
--- a/src/gtimer/gtimer.c
+++ b/src/gtimer/gtimer.c
@@ -109,7 +109,7 @@ static DECLARE_THREAD_FUNCTION(GTimerThreadHandler, arg) {
lastTime = tm;
gfxMutexExit(&mutex);
}
-// THREAD_RETURN(0);
+ THREAD_RETURN(0);
}
void _gtimerInit(void)
diff --git a/src/gwin/gwin.c b/src/gwin/gwin.c
index 586636ec..c5082ea0 100644
--- a/src/gwin/gwin.c
+++ b/src/gwin/gwin.c
@@ -281,6 +281,14 @@ void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coor
}
#endif
+#if GDISP_NEED_DUALCIRCLE
+ void gwinFillDualCircle(GHandle gh, coord_t x, coord_t y, coord_t radius1, coord_t radius2) {
+ if (!_gwinDrawStart(gh)) return;
+ gdispGFillDualCircle(gh->display, gh->x+x, gh->y+y, radius1, gh->bgcolor, radius2, gh->color);
+ _gwinDrawEnd(gh);
+ }
+#endif
+
#if GDISP_NEED_ELLIPSE
void gwinDrawEllipse(GHandle gh, coord_t x, coord_t y, coord_t a, coord_t b) {
if (!_gwinDrawStart(gh)) return;
@@ -307,6 +315,12 @@ void gwinBlitArea(GHandle gh, coord_t x, coord_t y, coord_t cx, coord_t cy, coor
gdispGFillArc(gh->display, gh->x+x, gh->y+y, radius, startangle, endangle, gh->color);
_gwinDrawEnd(gh);
}
+
+ void gwinDrawThickArc(GHandle gh, coord_t x, coord_t y, coord_t startradius, coord_t endradius, coord_t startangle, coord_t endangle) {
+ if (!_gwinDrawStart(gh)) return;
+ gdispGDrawThickArc(gh->display, gh->x+x, gh->y+y, startradius, endradius, startangle, endangle, gh->color);
+ _gwinDrawEnd(gh);
+ }
#endif
#if GDISP_NEED_ARCSECTORS
diff --git a/src/gwin/gwin.h b/src/gwin/gwin.h
index 5912046b..c3d18c31 100644
--- a/src/gwin/gwin.h
+++ b/src/gwin/gwin.h
@@ -718,6 +718,24 @@ extern "C" {
void gwinFillCircle(GHandle gh, coord_t x, coord_t y, coord_t radius);
#endif
+ #if GDISP_NEED_DUALCIRCLE || defined(__DOXYGEN__)
+ /**
+ * @brief Draw two filled circles with the same centre in the window.
+ * @note Uses the current foreground color to draw the inner circle
+ * @note Uses the current background color to draw the outer circle
+ * @note May leave GDISP clipping to this window's dimensions
+ * @pre GDISP_NEED_DUALCIRCLE must be TRUE in your gfxconf.h
+ *
+ * @param[in] gh The window handle
+ * @param[in] x,y The center of the circle
+ * @param[in] radius1 The radius of the larger circle
+ * @param[in] radius2 The radius of the smaller circle
+ *
+ * @api
+ */
+ void gwinFillDualCircle(GHandle gh, coord_t x, coord_t y, coord_t radius1, coord_t radius2);
+ #endif
+
#if GDISP_NEED_ELLIPSE || defined(__DOXYGEN__)
/**
* @brief Draw an ellipse.
@@ -776,6 +794,22 @@ extern "C" {
* @api
*/
void gwinFillArc(GHandle gh, coord_t x, coord_t y, coord_t radius, coord_t startangle, coord_t endangle);
+
+ /*
+ * @brief Draw a thick arc in the window.
+ * @note Uses the current foreground color to draw the thick arc
+ * @note May leave GDISP clipping to this window's dimensions
+ *
+ * @param[in] gh The window handle
+ * @param[in] x,y The center point
+ * @param[in] startradius The inner radius of the thick arc
+ * @param[in] endradius The outer radius of the thick arc
+ * @param[in] startangle The start angle (0 to 360)
+ * @param[in] endangle The end angle (0 to 360)
+ *
+ * @api
+ */
+ void gwinDrawThickArc(GHandle gh, coord_t x, coord_t y, coord_t startradius, coord_t endradius, coord_t startangle, coord_t endangle);
#endif
#if GDISP_NEED_ARCSECTORS || defined(__DOXYGEN__)