ThreadX GUIX用于其它RTOS的接口文件gx_system_rtos_bind.c,默认还提供了uCOS-II和III的移植代码
下面的代码里面uCOS-II和uCOS-III都提供了:
/**************************************************************************/
/* */
/* Copyright (c) Microsoft Corporation. All rights reserved. */
/* */
/* This software is licensed under the Microsoft Software License */
/* Terms for Microsoft Azure RTOS. Full text of the license can be*/
/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */
/* and in the root directory of this software. */
/* */
/**************************************************************************/
/**************************************************************************/
/**************************************************************************/
/** */
/** GUIX Component */
/** */
/** System Management (System) */
/** */
/**************************************************************************/
//#define GX_SOURCE_CODE
/* Include necessary system files.*/
#include "gx_api.h"
#include "gx_system.h"
#include "gx_system_rtos_bind.h"
/**************************************************************************/
/* */
/*FUNCTION RELEASE */
/* */
/* _gx_system_rtos_bind PORTABLE C */
/* 6.0 */
/*AUTHOR */
/* */
/* Kenneth Maxwell, Microsoft Corporation */
/* */
/*DESCRIPTION */
/* */
/* This file contains a small set of shell functions used to bind GUIX */
/* to a generic RTOS. GUIX is by default configured to run with the */
/* ThreadX RTOS, but you can port to another RTOS by defining the */
/* pre-processor directive GX_DISABLE_THREADX_BINDING and completing */
/* the implementation of the functions found in this file. */
/* Refer to the GUIX User Guide for more information. */
/* */
/*INPUT */
/* */
/* Refer to GUIX User Guide */
/* */
/*OUTPUT */
/* */
/* Refer to GUIX User Guide */
/* */
/*CALLS */
/* */
/* Refer to GUIX User Guide */
/* */
/*CALLED BY */
/* */
/* GUIX system serives */
/* */
/*RELEASE HISTORY */
/* */
/* DATE NAME DESCRIPTION */
/* */
/*05-19-2020 Kenneth Maxwell Initial Version 6.0 */
/* */
/**************************************************************************/
#ifndef GX_THREADX_BINDING
/* This is an example of a generic RTOS binding. We have #ifdefed this code out
of the GUIX library build, so that the user attempting to port to a new RTOS
will intentionally observe a series of linker errors. These functions need to
be implemented in a way that works correctly with the target RTOS.
*/
#if defined(GUIX_BINDING_UCOS_III)
#include "os.h"
#ifndef OS_CFG_TICK_RATE_HZ
#define OS_CFG_TICK_RATE_HZ 100
#endif
#define GX_TIMER_TASK_PRIORITY (GX_SYSTEM_THREAD_PRIORITY + 1)
#define GX_TIMER_TASK_STACK_SIZE 512
void guix_timer_task_entry(void *);
/* a few global status variables */
GX_BOOL guix_timer_event_pending;
/* define stack space for GUIX task */
CPU_STK guix_task_stack;
/* define stack space for timer task */
CPU_STK guix_timer_task_stack;
/* define semaphore for lock/unlock macros */
OS_MUTEX guix_system_lock_mutex;
OS_ERR uc_error;
OS_TCB guix_tcb;
OS_TCB guix_timer_tcb;
/* a custom event structure, to hold event and linked list */
typedef struct guix_linked_event_struct
{
GX_EVENT event_data; /* the GUIX event structure */
struct guix_linked_event_struct *next; /* add link member */
} GUIX_LINKED_EVENT;
/* a custom fifo event queue structure */
typedef struct guix_event_queue_struct
{
GUIX_LINKED_EVENT *first; /* first (oldest) event in fifo */
GUIX_LINKED_EVENT *last; /* last (newest) event in fifo*/
GUIX_LINKED_EVENT *free; /* linked list of free events */
GUIX_LINKED_EVENT *free_end; /* end of the free list */
OS_SEM count_sem; /* number of queued events */
OS_MUTEX lock; /* lock to protect queue update */
} GUIX_EVENT_QUEUE;
/* an array of GX_EVENTs used to implement fifo queue */
GUIX_LINKED_EVENT guix_event_array;
GUIX_EVENT_QUEUEguix_event_queue;
/* rtos initialize: perform any setup that needs to be done before the GUIX task runs here */
VOID gx_generic_rtos_initialize(VOID)
{
int Loop;
GUIX_LINKED_EVENT *current;
guix_timer_event_pending = GX_FALSE;
OSMutexCreate(&guix_system_lock_mutex, "gx_system_lock", &uc_error);
/* initialize a custom fifo queue structure */
guix_event_queue.first = GX_NULL;
guix_event_queue.last = GX_NULL;
guix_event_queue.free = guix_event_array;
current = guix_event_queue.free;
/* link all the structures together */
for (Loop = 0; Loop < GX_MAX_QUEUE_EVENTS - 1; Loop++)
{
current -> next = (current + 1);
current = current -> next;
}
current -> next = GX_NULL; /* terminate the list */
guix_event_queue.free_end = current;
/* create mutex for lock access to this queue */
OSMutexCreate(&guix_event_queue.lock, "gx_queue_lock", &uc_error);
/* create counting semaphore to track queue entries */
OSSemCreate(&guix_event_queue.count_sem, "gx_queue_count", 0, &uc_error);
}
VOID (*gx_system_thread_entry)(ULONG);
// A small shell function to convert the void * arg expected by uC/OS to
// a ULONG parameter expected by GUIX thread entry
void gx_system_thread_entry_shell(void *parg)
{
gx_system_thread_entry((ULONG) parg);
}
/* thread_start: start the GUIX thread running. */
UINT gx_generic_thread_start(VOID(*guix_thread_entry)(ULONG))
{
/* save the GUIX system thread entry function pointer */
gx_system_thread_entry = guix_thread_entry;
/* create the main GUIX task */
OSTaskCreate(&guix_tcb, "guix_task",
gx_system_thread_entry_shell,
GX_NULL,
GX_SYSTEM_THREAD_PRIORITY,
&guix_task_stack,
GX_THREAD_STACK_SIZE - 1,
GX_THREAD_STACK_SIZE,
0, 0, GX_NULL, OS_OPT_TASK_NONE, &uc_error);
/* create a simple task to generate timer events into GUIX */
OSTaskCreate(&guix_timer_tcb, "guix_timer_task",
guix_timer_task_entry,
GX_NULL,
GX_TIMER_TASK_PRIORITY,
&guix_timer_task_stack,
GX_TIMER_TASK_STACK_SIZE -1,
GX_TIMER_TASK_STACK_SIZE,
0, 0, GX_NULL, OS_OPT_TASK_NONE, &uc_error);
/* suspend the timer task until needed */
OSTaskSuspend(&guix_timer_tcb, &uc_error);
return GX_SUCCESS;
}
/* event_post: push an event into the fifo event queue */
UINT gx_generic_event_post(GX_EVENT *event_ptr)
{
GUIX_LINKED_EVENT *linked_event;
/* lock down the guix event queue */
OSMutexPend(&guix_event_queue.lock, 0, OS_OPT_PEND_BLOCKING, NULL, &uc_error);
/* grab a free event slot */
if (!guix_event_queue.free)
{
/* there are no free events, return failure */
OSMutexPost(&guix_event_queue.lock, OS_OPT_POST_NONE, &uc_error);
return GX_FAILURE;
}
linked_event = guix_event_queue.free;
guix_event_queue.free = guix_event_queue.free->next;
if (!guix_event_queue.free)
{
guix_event_queue.free_end = GX_NULL;
}
/* copy the event data into this slot */
linked_event -> event_data = *event_ptr;
linked_event -> next = GX_NULL;
/* insert this event into fifo queue */
if (guix_event_queue.last)
{
guix_event_queue.last -> next = linked_event;
}
else
{
guix_event_queue.first = linked_event;
}
guix_event_queue.last = linked_event;
/* Unlock the guix queue */
OSMutexPost(&guix_event_queue.lock, OS_OPT_POST_NONE, &uc_error);
/* increment event count */
OSSemPost(&guix_event_queue.count_sem, OS_OPT_POST_ALL, &uc_error);
return GX_SUCCESS;
}
/* event_fold: update existing matching event, otherwise post new event */
UINT gx_generic_event_fold(GX_EVENT *event_ptr)
{
GUIX_LINKED_EVENT *pTest;
/* Lock down the guix queue */
OSMutexPend(&guix_event_queue.lock, 0, OS_OPT_PEND_BLOCKING, NULL, &uc_error);
// see if the same event is already in the queue:
pTest = guix_event_queue.first;
while (pTest)
{
if (pTest -> event_data.gx_event_type == event_ptr -> gx_event_type)
{
/* found matching event, update it and return */
pTest -> event_data.gx_event_payload.gx_event_ulongdata = event_ptr -> gx_event_payload.gx_event_ulongdata;
OSMutexPost(&guix_event_queue.lock, OS_OPT_POST_NONE, &uc_error);
return GX_SUCCESS;
}
pTest = pTest -> next;
}
/* did not find a match, push new event */
OSMutexPost(&guix_event_queue.lock, OS_OPT_POST_NONE, &uc_error);
gx_generic_event_post(event_ptr);
return GX_SUCCESS;
}
/* event_pop: pop oldest event from fifo queue, block if wait and no events exist */
UINT gx_generic_event_pop(GX_EVENT *put_event, GX_BOOL wait)
{
if (!wait)
{
if (guix_event_queue.first == GX_NULL)
{
/* the queue is empty, just return */
return GX_FAILURE;
}
}
/* wait for an event to arrive in queue */
OSSemPend(&guix_event_queue.count_sem, 0, OS_OPT_PEND_BLOCKING, NULL, &uc_error);
/* lock down the queue */
OSMutexPend(&guix_event_queue.lock, 0, OS_OPT_PEND_BLOCKING, NULL, &uc_error);
/* copy the event into destination */
*put_event = guix_event_queue.first -> event_data;
/* link this event holder back into free list */
if (guix_event_queue.free_end)
{
guix_event_queue.free_end -> next = guix_event_queue.first;
}
else
{
guix_event_queue.free = guix_event_queue.first;
}
guix_event_queue.free_end = guix_event_queue.first;
guix_event_queue.first = guix_event_queue.first -> next;
guix_event_queue.free_end -> next = GX_NULL;
if (!guix_event_queue.first)
{
guix_event_queue.last = GX_NULL;
}
/* check for popping out a timer event */
if (put_event -> gx_event_type == GX_EVENT_TIMER)
{
guix_timer_event_pending = GX_FALSE;
}
/* unlock the queue */
OSMutexPost(&guix_event_queue.lock, OS_OPT_POST_NONE, &uc_error);
return GX_SUCCESS;
}
/* event_purge: delete events targetted to particular widget */
VOID gx_generic_event_purge(GX_WIDGET *target)
{
GX_BOOL Purge;
GUIX_LINKED_EVENT *pTest;
/* Lock down the guix queue */
OSMutexPend(&guix_event_queue.lock, 0, OS_OPT_PEND_BLOCKING, NULL, &uc_error);
// look for events targetted to widget or widget children:
pTest = guix_event_queue.first;
while (pTest)
{
Purge = GX_FALSE;
if (pTest ->event_data.gx_event_target)
{
if (pTest -> event_data.gx_event_target == target)
{
Purge = GX_TRUE;
}
else
{
gx_widget_child_detect(target, pTest->event_data.gx_event_target, &Purge);
}
if (Purge)
{
pTest ->event_data.gx_event_target = GX_NULL;
pTest->event_data.gx_event_type = 0;
}
}
pTest = pTest -> next;
}
OSMutexPost(&guix_event_queue.lock, OS_OPT_POST_NONE, &uc_error);
}
/* start the RTOS timer */
VOID gx_generic_timer_start(VOID)
{
OSTaskResume(&guix_timer_tcb, &uc_error);
}
/* stop the RTOS timer */
VOID gx_generic_timer_stop(VOID)
{
OSTaskSuspend(&guix_timer_tcb, &uc_error);
}
/* lock the system protection mutex */
VOID gx_generic_system_mutex_lock(VOID)
{
OSMutexPend(&guix_system_lock_mutex, 0, OS_OPT_PEND_BLOCKING, NULL, &uc_error);
}
/* unlock system protection mutex */
VOID gx_generic_system_mutex_unlock(VOID)
{
OSMutexPost(&guix_system_lock_mutex, OS_OPT_POST_NONE, &uc_error);
}
/* return number of low-level system timer ticks. Used for pen speed caculations */
ULONGgx_generic_system_time_get(VOID)
{
return((ULONG)OSTimeGet(&uc_error));
}
/* thread_identify: return current thread identifier, cast as VOID * */
VOID*gx_generic_thread_identify(VOID)
{
return((VOID *)OSTCBCurPtr);
}
/* a simple task to drive the GUIX timer mechanism */
void guix_timer_task_entry(void *unused)
{
int TickCount = OS_CFG_TICK_RATE_HZ / GX_TICKS_SECOND;
if (TickCount <= 0)
{
TickCount = 1;
}
while (1)
{
OSTimeDly(TickCount, OS_OPT_TIME_DLY, &uc_error);
/* prevent sending timer events faster than they can be processed */
if (!guix_timer_event_pending)
{
guix_timer_event_pending = GX_TRUE;
_gx_system_timer_expiration(0);
}
}
}
VOID gx_generic_time_delay(int ticks)
{
OSTimeDly(ticks, OS_OPT_TIME_DLY, &uc_error);
}
#endif/* Binding for UCOS-III enabled */
#if defined(GUIX_BINDING_UCOS_II)
#include "ucos_ii.h"
#define TIMER_TASK_PRIORITY (GX_SYSTEM_THREAD_PRIORITY + 1)
#define TIMER_TASK_STACK_SIZE 512
void guix_timer_task_entry(void *);
/* a few global status variables */
GX_BOOL guix_timer_event_pending;
INT8U guix_uc_err = 0;
/* define stack space for GUIX task */
OS_STK guix_task_stack;
OS_STK guix_task_stack;
/* define stack space for timer task */
OS_STK guix_timer_task_stack;
/* define semaphore for lock/unlock macros */
OS_EVENT *guix_system_lock_semaphore;
/* a custom event structure, to hold event and linked list */
typedef struct guix_linked_event_struct
{
GX_EVENT event_data; /* the GUIX event structure */
struct guix_linked_event_struct *next; /* add link member */
} GUIX_LINKED_EVENT;
/* a custom fifo event queue structure */
typedef struct guix_event_queue_struct
{
GUIX_LINKED_EVENT *first; /* first (oldest) event in fifo */
GUIX_LINKED_EVENT *last; /* last (newest) event in fifo*/
GUIX_LINKED_EVENT *free; /* linked list of free events */
GUIX_LINKED_EVENT *free_end; /* end of the free list */
OS_EVENT *count_sem; /* number of queued events */
OS_EVENT *lock_sem; /* lock to protect queue update */
} GUIX_EVENT_QUEUE;
/* an array of GX_EVENTs used to implement fifo queue */
GUIX_LINKED_EVENT guix_event_array;
GUIX_EVENT_QUEUEguix_event_queue;
/* rtos initialize: perform any setup that needs to be done before the GUIX task runs here */
VOID gx_generic_rtos_initialize(VOID)
{
int Loop;
GUIX_LINKED_EVENT *current;
guix_timer_event_pending = GX_FALSE;
guix_system_lock_semaphore = OSSemCreate(1);
/* initialize a custom fifo queue structure */
guix_event_queue.first = GX_NULL;
guix_event_queue.last = GX_NULL;
guix_event_queue.free = guix_event_array;
current = guix_event_queue.free;
/* link all the structures together */
for (Loop = 0; Loop < GX_MAX_QUEUE_EVENTS - 1; Loop++)
{
current -> next = (current + 1);
current = current -> next;
}
current -> next = GX_NULL; /* terminate the list */
guix_event_queue.free_end = current;
/* create mutex for lock access to this queue */
guix_event_queue.lock_sem = OSSemCreate(1);
/* create counting semaphore to track queue entries */
guix_event_queue.count_sem = OSSemCreate(0);
}
/* A variable to store GUIX thread entry function pointer */
VOID (*gx_thread_entry)(ULONG);
/* a simple shell function to convert the UCOS (void *)
parameter to the GUIX ULONG param type. */
void guix_thread_entry_shell(void *ptr)
{
gx_thread_entry((ULONG) ptr);
}
/* thread_start: start the GUIX thread running. */
UINT gx_generic_thread_start(VOID(*guix_thread_entry)(ULONG))
{
/* save pointer to GUIX thread entry function */
gx_thread_entry = guix_thread_entry;
/* create the main GUIX task */
OSTaskCreate(guix_thread_entry_shell, (void *)0,
&guix_task_stack, GX_SYSTEM_THREAD_PRIORITY);
/* create a simple task to generate timer events into GUIX */
OSTaskCreate(guix_timer_task_entry, (void *)0,
&guix_timer_task_stack, TIMER_TASK_PRIORITY);
/* suspend the timer task until needed */
OSTaskSuspend(TIMER_TASK_PRIORITY);
return GX_SUCCESS;
}
/* event_post: push an event into the fifo event queue */
UINT gx_generic_event_post(GX_EVENT *event_ptr)
{
GUIX_LINKED_EVENT *linked_event;
/* lock down the guix event queue */
OSSemPend(guix_event_queue.lock_sem, 0, &guix_uc_err);
/* grab a free event slot */
if (!guix_event_queue.free)
{
/* there are no free events, return failure */
OSSemPost(guix_event_queue.lock_sem);
return GX_FAILURE;
}
linked_event = guix_event_queue.free;
guix_event_queue.free = guix_event_queue.free->next;
if (!guix_event_queue.free)
{
guix_event_queue.free_end = GX_NULL;
}
/* copy the event data into this slot */
linked_event -> event_data = *event_ptr;
linked_event -> next = GX_NULL;
/* insert this event into fifo queue */
if (guix_event_queue.last)
{
guix_event_queue.last -> next = linked_event;
}
else
{
guix_event_queue.first = linked_event;
}
guix_event_queue.last = linked_event;
/* Unlock the guix queue */
OSSemPost(guix_event_queue.lock_sem);
/* increment event count */
OSSemPost(guix_event_queue.count_sem);
return GX_SUCCESS;
}
/* event_fold: update existing matching event, otherwise post new event */
UINT gx_generic_event_fold(GX_EVENT *event_ptr)
{
GUIX_LINKED_EVENT *pTest;
/* Lock down the guix queue */
OSSemPend(guix_event_queue.lock_sem, 0, &guix_uc_err);
// see if the same event is already in the queue:
pTest = guix_event_queue.first;
while (pTest)
{
if (pTest -> event_data.gx_event_type == event_ptr -> gx_event_type)
{
/* found matching event, update it and return */
pTest -> event_data.gx_event_payload.gx_event_ulongdata = event_ptr -> gx_event_payload.gx_event_ulongdata;
OSSemPost(guix_event_queue.lock_sem);
return GX_SUCCESS;
}
pTest = pTest -> next;
}
/* did not find a match, push new event */
OSSemPost(guix_event_queue.lock_sem);
gx_generic_event_post(event_ptr);
return GX_SUCCESS;
}
/* event_pop: pop oldest event from fifo queue, block if wait and no events exist */
UINT gx_generic_event_pop(GX_EVENT *put_event, GX_BOOL wait)
{
if (!wait)
{
if (guix_event_queue.first == GX_NULL)
{
/* the queue is empty, just return */
OSSemPost(guix_event_queue.lock_sem);
return GX_FAILURE;
}
}
/* wait for an event to arrive in queue */
OSSemPend(guix_event_queue.count_sem, 0, &guix_uc_err);
/* lock down the queue */
OSSemPend(guix_event_queue.lock_sem, 0, &guix_uc_err);
/* copy the event into destination */
*put_event = guix_event_queue.first -> event_data;
/* link this event holder back into free list */
if (guix_event_queue.free_end)
{
guix_event_queue.free_end -> next = guix_event_queue.first;
}
else
{
guix_event_queue.free = guix_event_queue.first;
}
guix_event_queue.free_end = guix_event_queue.first;
guix_event_queue.first = guix_event_queue.first -> next;
guix_event_queue.free_end -> next = GX_NULL;
if (!guix_event_queue.first)
{
guix_event_queue.last = GX_NULL;
}
/* check for popping out a timer event */
if (put_event -> gx_event_type == GX_EVENT_TIMER)
{
guix_timer_event_pending = GX_FALSE;
}
/* unlock the queue */
OSSemPost(guix_event_queue.lock_sem);
return GX_SUCCESS;
}
/* event_purge: delete events targetted to particular widget */
VOID gx_generic_event_purge(GX_WIDGET *target)
{
GX_BOOL Purge;
GUIX_LINKED_EVENT *pTest;
/* Lock down the guix queue */
OSSemPend(guix_event_queue.lock_sem, 0, &guix_uc_err);
// look for events targetted to widget or widget children:
pTest = guix_event_queue.first;
while (pTest)
{
Purge = GX_FALSE;
if (pTest ->event_data.gx_event_target)
{
if (pTest -> event_data.gx_event_target == target)
{
Purge = GX_TRUE;
}
else
{
gx_widget_child_detect(target, pTest->event_data.gx_event_target, &Purge);
}
if (Purge)
{
pTest ->event_data.gx_event_target = GX_NULL;
pTest->event_data.gx_event_type = 0;
}
}
pTest = pTest -> next;
}
OSSemPost(guix_event_queue.lock_sem);
}
/* start the RTOS timer */
VOID gx_generic_timer_start(VOID)
{
OSTaskResume(TIMER_TASK_PRIORITY);
}
/* stop the RTOS timer */
VOID gx_generic_timer_stop(VOID)
{
OSTaskSuspend(TIMER_TASK_PRIORITY);
}
/* lock the system protection mutex */
VOID gx_generic_system_mutex_lock(VOID)
{
OSSemPend(guix_system_lock_semaphore, 0, &guix_uc_err);
}
/* unlock system protection mutex */
VOID gx_generic_system_mutex_unlock(VOID)
{
OSSemPost(guix_system_lock_semaphore);
}
/* return number of low-level system timer ticks. Used for pen speed caculations */
ULONGgx_generic_system_time_get(VOID)
{
return((ULONG)OSTimeGet());
}
/* thread_identify: return current thread identifier, cast as VOID * */
VOID*gx_generic_thread_identify(VOID)
{
return((VOID *)OSTCBCur);
}
/* a simple task to drive the GUIX timer mechanism */
VOID guix_timer_task_entry(VOID *unused)
{
int TickCount = OS_TICKS_PER_SEC / GX_TICKS_SECOND;
if (TickCount <= 0)
{
TickCount = 1;
}
while (1)
{
OSTimeDly(TickCount);
/* prevent sending timer events faster than they can be processed */
if (!guix_timer_event_pending)
{
guix_timer_event_pending = GX_TRUE;
_gx_system_timer_expiration(0);
}
}
}
VOID gx_generic_time_delay(int ticks)
{
OSTimeDly(ticks);
}
#endif /* Binding for UCOS-II enabled */
#endif/* if !ThreadX */
有计划有模板吗? hqgboy 发表于 2020-9-15 10:44
有计划有模板吗?
这个可以有,其它RTOS下都整个模板。 硬汉大哥,这就是典型的OS接口抽象层,有了这个,可以随便换OS,是吧? morning_enr6U 发表于 2020-9-15 11:56
硬汉大哥,这就是典型的OS接口抽象层,有了这个,可以随便换OS,是吧?
对,是这个接口文件。 eric2013 发表于 2020-9-16 09:44
对,是这个接口文件。
如果更换了 freertos,例程中 gx_system_initialize,gx_widget_show,gx_system_start 这些函数怎么办?
哪里有初始化模板
页:
[1]