diff options
| author | qiuyiuestc <[email protected]> | 2010-05-29 14:19:56 +0000 |
|---|---|---|
| committer | qiuyiuestc <[email protected]> | 2010-05-29 14:19:56 +0000 |
| commit | 8b8dba661f5e29e1592cc9df92ef219099809330 (patch) | |
| tree | 31451ddff2d979d338cc0e9fc25b74bda5117632 | |
| parent | 1fb4d848370a33e176b2a3bf7fb532e7ed8e7823 (diff) | |
module developing
git-svn-id: https://rt-thread.googlecode.com/svn/trunk@742 bbd45198-f89e-11dd-88c7-29a3b14d5316
| -rw-r--r-- | components/SConscript | 5 | ||||
| -rw-r--r-- | components/hello/SConscript | 10 | ||||
| -rw-r--r-- | components/hello/hello.c | 22 | ||||
| -rw-r--r-- | components/module/examples/application/basicapp/SConscript | 27 | ||||
| -rw-r--r-- | components/module/examples/application/basicapp/basicapp.c | 26 | ||||
| -rw-r--r-- | components/module/examples/application/basicapp/module_entry.c | 21 | ||||
| -rw-r--r-- | components/module/interface/SConscript | 23 | ||||
| -rw-r--r-- | components/module/interface/include/interface_help.h | 124 | ||||
| -rw-r--r-- | components/module/interface/include/interface_kernel.h | 244 | ||||
| -rw-r--r-- | components/module/interface/include/interface_module.h | 1 | ||||
| -rw-r--r-- | components/module/interface/src/interface_filesys.c | 0 | ||||
| -rw-r--r-- | components/module/interface/src/interface_gui.c | 0 | ||||
| -rw-r--r-- | components/module/interface/src/interface_kernel.c | 195 | ||||
| -rw-r--r-- | components/module/interface/src/interface_net.c | 0 | ||||
| -rw-r--r-- | include/rtdef.h | 32 | ||||
| -rw-r--r-- | include/rtm.h | 2 | ||||
| -rw-r--r-- | src/idle.c | 2 | ||||
| -rw-r--r-- | src/module.c | 121 | ||||
| -rw-r--r-- | src/module.h | 9 | ||||
| -rw-r--r-- | src/rtm.c | 129 |
20 files changed, 788 insertions, 205 deletions
diff --git a/components/SConscript b/components/SConscript index 538e976a52..ae6f3271ab 100644 --- a/components/SConscript +++ b/components/SConscript @@ -27,8 +27,11 @@ if 'RT_USING_MODBUS' in dir(rtconfig) and rtconfig.RT_USING_MODBUS: if 'RT_USING_RTGUI' in dir(rtconfig) and rtconfig.RT_USING_RTGUI:
objs = objs + SConscript('rtgui/SConscript')
+if 'RT_USING_MODULE' in dir(rtconfig) and rtconfig.RT_USING_MODULE:
+ objs = objs + SConscript('module/interface/SConscript')
+
# build each modules
if rtconfig.CROSS_TOOL == 'gcc':
- SConscript('hello/SConscript')
+ SConscript('module/examples/application/basicapp/SConscript')
Return('objs')
diff --git a/components/hello/SConscript b/components/hello/SConscript deleted file mode 100644 index 215c4eb4cb..0000000000 --- a/components/hello/SConscript +++ /dev/null @@ -1,10 +0,0 @@ -Import('env') - -target = 'hello.mo' - -module_env = env.Clone(CPPDEFINE = 'RT_MODULE') -module_env.Replace(LINKFLAGS = ' -r -d -e rtm_main -nostdlib') - -src_local = Glob('*.c') - -module_env.Program(target, src_local) diff --git a/components/hello/hello.c b/components/hello/hello.c deleted file mode 100644 index 6b6402de1c..0000000000 --- a/components/hello/hello.c +++ /dev/null @@ -1,22 +0,0 @@ -#include <rtthread.h> - -static int a = 0; -int b = 1000000; - -void function(int count1, int count2) -{ - rt_kprintf("Hello RT-Thread %d %d\n", count1, count2); -} - -int rtm_main(void) -{ - int i; - for(i=0; i<1000; i++) - { - a++; - b--; - function(a, b); - } - - return 0; -} diff --git a/components/module/examples/application/basicapp/SConscript b/components/module/examples/application/basicapp/SConscript new file mode 100644 index 0000000000..e8f79a5fd9 --- /dev/null +++ b/components/module/examples/application/basicapp/SConscript @@ -0,0 +1,27 @@ +Import('env') +Import('projects') +Import('RTT_ROOT') +Import('rtconfig') + +# group definitions +group = {} +group['name'] = 'examples' +group['src'] = Glob('*.c') +group['CCFLAGS'] = '' +group['CPPPATH'] = [RTT_ROOT + '/components/module/interface'] +group['CPPDEFINES'] = '' + +target = 'hello.mo' + +# add group to project list +projects.append(group) + +env.Append(CCFLAGS = group['CCFLAGS']) +env.Append(CPPPATH = group['CPPPATH']) +env.Append(CPPDEFINES = group['CPPDEFINES']) +module_env = env.Clone(CPPDEFINE = 'RT_MODULE') +module_env.Replace(LINKFLAGS = ' -mcpu=arm920t -r -d -e rt_module_entry -nostdlib -s') + +src_local = Glob('*.c') + +module_env.Program(target, src_local) diff --git a/components/module/examples/application/basicapp/basicapp.c b/components/module/examples/application/basicapp/basicapp.c new file mode 100644 index 0000000000..90d39f1427 --- /dev/null +++ b/components/module/examples/application/basicapp/basicapp.c @@ -0,0 +1,26 @@ +#include <rtthread.h> +#include <interface_help.h> + +int a = 0; +int b = 1000000; +int c = 0; + +void function(int count1, int count2, int count3) +{ + rt_kprintf("Hello RT-Thread %d %d\n", count1, count2, count3); +} + +int rt_application_entry(void) +{ + int i; + for(i=0; i<1000; i++) + { + a++; + b--; + c++; + function(a, b, c); + } + + return 0; +} + diff --git a/components/module/examples/application/basicapp/module_entry.c b/components/module/examples/application/basicapp/module_entry.c new file mode 100644 index 0000000000..1b523da100 --- /dev/null +++ b/components/module/examples/application/basicapp/module_entry.c @@ -0,0 +1,21 @@ +#include <rtthread.h>
+#include <interface_help.h>
+
+extern int rt_application_entry();
+rt_shell_t ishell = RT_NULL;
+
+int rt_module_entry(const void* shell, void** object_info)
+{
+ /* init shell */
+ ishell = (rt_shell_t)shell;
+ struct rt_module_info *info = (struct rt_module_info*)rt_malloc(sizeof(struct rt_module_info));
+
+ info->module_refs = 0;
+ info->module_type = RT_Module_Class_APP;
+ info->module_guid = 0xdead;
+ info->exec_entry = (void *)rt_application_entry;
+ info->module_interface = RT_NULL;
+
+ *object_info = info;
+}
+
diff --git a/components/module/interface/SConscript b/components/module/interface/SConscript new file mode 100644 index 0000000000..a0956d9a18 --- /dev/null +++ b/components/module/interface/SConscript @@ -0,0 +1,23 @@ +Import('env') +Import('projects') +Import('RTT_ROOT') +Import('rtconfig') + +# group definitions +group = {} +group['name'] = 'module' +group['src'] = Glob('src/*.c') +group['CCFLAGS'] = '' +group['CPPPATH'] = [RTT_ROOT + '/components/module/interface/include'] +group['CPPDEFINES'] = '' + +# add group to project list +projects.append(group) + +env.Append(CCFLAGS = group['CCFLAGS']) +env.Append(CPPPATH = group['CPPPATH']) +env.Append(CPPDEFINES = group['CPPDEFINES']) + +objs = env.Object(group['src']) + +Return('objs') diff --git a/components/module/interface/include/interface_help.h b/components/module/interface/include/interface_help.h new file mode 100644 index 0000000000..88dc2b1630 --- /dev/null +++ b/components/module/interface/include/interface_help.h @@ -0,0 +1,124 @@ +#include <rtdef.h>
+#include <interface_kernel.h>
+
+extern rt_shell_t ishell;
+#define SHELL() ishell
+
+#define IKSERVICE() (SHELL()->i_kservice)
+#define ITHREAD() (SHELL()->i_thread)
+#define ISEM() (SHELL()->i_sem)
+#define IMUTEX() (SHELL()->i_mutex)
+#define IEVENT() (SHELL()->i_event)
+#define IMB() (SHELL()->i_mb)
+#define IMQ() (SHELL()->i_mq)
+#define IMP() (SHELL()->i_mp)
+#define IHEAP() (SHELL()->i_heap)
+#define IDEVICE() (SHELL()->i_device)
+#define ITIMER() (SHELL()->i_timer)
+
+/* kernel service */
+#define rt_kprintf IKSERVICE()->rt_kprintf
+
+/* thread */
+#define rt_thread_init ITHREAD()->rt_thread_init
+#define rt_thread_create ITHREAD()->rt_thread_create
+#define rt_thread_detach ITHREAD()->rt_thread_detach
+#define rt_thread_find ITHREAD()->rt_thread_find
+#define rt_thread_self ITHREAD()->rt_thread_self
+#define rt_thread_startup ITHREAD()->rt_thread_startup
+#define rt_thread_delete ITHREAD()->rt_thread_delete
+#define rt_thread_yield ITHREAD()->rt_thread_yield
+#define rt_thread_delay ITHREAD()->rt_thread_delay
+#define rt_thread_control ITHREAD()->rt_thread_control
+#define rt_thread_suspend ITHREAD()->rt_thread_suspend
+#define rt_thread_resume ITHREAD()->rt_thread_resume
+#define rt_thread_timeout ITHREAD()->rt_thread_timeout
+
+/* semaphore */
+#define rt_sem_init ISEM()->rt_sem_init
+#define rt_sem_detach ISEM()->rt_sem_detach
+#define rt_sem_create ISEM()->rt_sem_create
+#define rt_sem_delete ISEM()->rt_sem_delete
+#define rt_sem_take ISEM()->rt_sem_take
+#define rt_sem_trytake ISEM()->rt_sem_trytake
+#define rt_sem_release ISEM()->rt_sem_release
+#define rt_sem_control ISEM()->rt_sem_control
+
+/* mutex */
+#define rt_mutex_init IMUTEX()->rt_mutex_init
+#define rt_mutex_detach IMUTEX()->rt_mutex_detach
+#define rt_mutex_create IMUTEX()->rt_mutex_create
+#define rt_mutex_delete IMUTEX()->rt_mutex_delete
+#define rt_mutex_take IMUTEX()->rt_mutex_take
+#define rt_mutex_trytake IMUTEX()->rt_mutex_trytake
+#define rt_mutex_release IMUTEX()->rt_mutex_release
+#define rt_mutex_control IMUTEX()->rt_mutex_control
+
+/* event */
+#define rt_event_init IEVENT()->rt_event_init
+#define rt_event_detach IEVENT()->rt_event_detach
+#define rt_event_create IEVENT()->rt_event_create
+#define rt_event_delete IEVENT()->rt_event_delete
+#define rt_event_send IEVENT()->rt_event_send
+#define rt_event_recv IEVENT()->rt_event_recv
+#define rt_event_control IEVENT()->rt_event_control
+
+/* mailbox */
+#define rt_mb_init IMB()->rt_mb_init
+#define rt_mb_detach IMB()->rt_mb_detach
+#define rt_mb_create IMB()->rt_mb_create
+#define rt_mb_delete IMB()->rt_mb_delete
+#define rt_mb_send IMB()->rt_mb_send
+#define rt_mb_recv IMB()->rt_mb_recv
+#define rt_mb_control IMB()->rt_mb_control
+
+/* message queue interface */
+#define rt_mq_init IMQ()->rt_mq_init
+#define rt_mq_detach IMQ()->rt_mq_detach
+#define rt_mq_create IMQ()->rt_mq_create
+#define rt_mq_delete IMQ()->rt_mq_delete
+#define rt_mq_send IMQ()->rt_mq_send
+#define rt_mq_urgent IMQ()->rt_mq_urgent
+#define rt_mq_recv IMQ()->rt_mq_recv
+#define rt_mq_control IMQ()->rt_mq_control
+
+/* memory pool */
+#define rt_mp_init IMP()->rt_mp_init
+#define rt_mp_detach IMP()->rt_mp_detach
+#define rt_mp_create IMP()->rt_mp_create
+#define rt_mp_delete IMP()->rt_mp_delete
+#define rt_mp_alloc IMP()->rt_mp_alloc
+#define rt_mp_free IMP()->rt_mp_free
+
+/* heap memory */
+#define rt_malloc IHEAP()->rt_malloc
+#define rt_free IHEAP()->rt_free
+#define rt_realloc IHEAP()->rt_realloc
+#define rt_calloc IHEAP()->rt_calloc
+
+/* device */
+#define rt_device_register IDEVICE()->rt_device_register
+#define rt_device_unregister IDEVICE()->rt_device_unregister
+#define rt_device_init_all IDEVICE()->rt_device_init_all
+#define rt_device_find IDEVICE()->rt_device_find
+#define rt_device_init IDEVICE()->rt_device_init
+#define rt_device_open IDEVICE()->rt_device_open
+#define rt_device_close IDEVICE()->rt_device_close
+#define rt_device_read IDEVICE()->rt_device_read
+#define rt_device_write IDEVICE()->rt_device_write
+#define rt_device_control IDEVICE()->rt_device_control
+#define rt_device_set_rx_indicate IDEVICE()->rt_device_set_rx_indicate
+#define rt_device_set_tx_complete IDEVICE()->rt_device_set_tx_complete
+
+/* timer */
+#define rt_tick_get ITIMER()->rt_tick_get
+#define rt_system_timer_init ITIMER()->rt_system_timer_init
+#define rt_timer_init ITIMER()->rt_timer_init
+#define rt_timer_detach ITIMER()->rt_timer_detach
+#define rt_timer_create ITIMER()->rt_timer_create
+#define rt_timer_delete ITIMER()->rt_timer_delete
+#define rt_timer_start ITIMER()->rt_timer_start
+#define rt_timer_stop ITIMER()->rt_timer_stop
+#define rt_timer_control ITIMER()->rt_timer_control
+#define rt_tick_from_millisecond ITIMER()->rt_tick_from_millisecond
+#define rt_system_timer_thread_init ITIMER()->rt_system_timer_thread_init
diff --git a/components/module/interface/include/interface_kernel.h b/components/module/interface/include/interface_kernel.h new file mode 100644 index 0000000000..3a00d52005 --- /dev/null +++ b/components/module/interface/include/interface_kernel.h @@ -0,0 +1,244 @@ +#include <rtdef.h>
+#include <rtthread.h>
+
+/* RT-Thread kernel component guid */
+#define RTTHREAD_GUID_KERNEL 1000
+#define RTTHREAD_GUID_KSERVICE RTTHREAD_GUID_KERNEL
+#define RTTHREAD_GUID_THREAD (RTTHREAD_GUID_KERNEL + 1)
+#define RTTHREAD_GUID_SEMAPHORE (RTTHREAD_GUID_KERNEL + 2)
+#define RTTHREAD_GUID_MUTEX (RTTHREAD_GUID_KERNEL + 3)
+#define RTTHREAD_GUID_MAILBOX (RTTHREAD_GUID_KERNEL + 4)
+#define RTTHREAD_GUID_MESSAGEQUEUE (RTTHREAD_GUID_KERNEL + 5)
+#define RTTHREAD_GUID_MEMPOOL (RTTHREAD_GUID_KERNEL + 6)
+#define RTTHREAD_GUID_DEVICE (RTTHREAD_GUID_KERNEL + 7)
+#define RTTHREAD_GUID_TIMER (RTTHREAD_GUID_KERNEL + 8)
+
+/* file system component guid */
+#define RTTHREAD_GUID_FILESYSTEM 2000
+/* net component guid */
+#define RTTHREAD_GUID_NET 3000
+/* gui component guid */
+#define RTTHREAD_GUID_GUI 4000
+/* application guid */
+#define RTTHREAD_GUID_APP_START 10000
+/* service guid */
+#define RTTHREAD_GUID_SEVICE_START 20000
+
+/*
+ * kservice interface
+ */
+struct rt_kservice_interface
+{
+ void (*rt_kprintf)(const char *fmt, ...);
+};
+typedef struct rt_kservice_interface* rt_kservice_interface_t;
+
+/*
+ * thread interface
+ */
+struct rt_thread_interface
+{
+ rt_err_t (*rt_thread_init)(struct rt_thread* thread,
+ const char* name,
+ void (*entry)(void* parameter), void* parameter,
+ void* stack_start, rt_uint32_t stack_size,
+ rt_uint8_t priority, rt_uint32_t tick);
+ rt_err_t (*rt_thread_detach)(rt_thread_t thread);
+ rt_thread_t (*rt_thread_create)(const char* name,
+ void (*entry)(void* parameter), void* parameter,
+ rt_uint32_t stack_size,
+ rt_uint8_t priority,
+ rt_uint32_t tick);
+ rt_thread_t (*rt_thread_self)(void);
+ rt_thread_t (*rt_thread_find)(char* name);
+ rt_err_t (*rt_thread_startup)(rt_thread_t thread);
+ rt_err_t (*rt_thread_delete)(rt_thread_t thread);
+ rt_err_t (*rt_thread_yield)(void);
+ rt_err_t (*rt_thread_delay)(rt_tick_t tick);
+ rt_err_t (*rt_thread_control)(rt_thread_t thread, rt_uint8_t cmd, void* arg);
+ rt_err_t (*rt_thread_suspend)(rt_thread_t thread);
+ rt_err_t (*rt_thread_resume)(rt_thread_t thread);
+ void (*rt_thread_timeout)(void* parameter);
+};
+typedef struct rt_thread_interface* rt_thread_interface_t;
+
+#ifdef RT_USING_SEMAPHORE
+/*
+ * semaphore interface
+ */
+ struct rt_sem_interface
+{
+ rt_err_t (*rt_sem_init)(rt_sem_t sem, const char* name, rt_uint32_t value, rt_uint8_t flag);
+ rt_err_t (*rt_sem_detach)(rt_sem_t sem);
+ rt_sem_t (*rt_sem_create)(const char* name, rt_uint32_t value, rt_uint8_t flag);
+ rt_err_t (*rt_sem_delete)(rt_sem_t sem);
+ rt_err_t (*rt_sem_take)(rt_sem_t sem, rt_int32_t time);
+ rt_err_t (*rt_sem_trytake)(rt_sem_t sem);
+ rt_err_t (*rt_sem_release)(rt_sem_t sem);
+ rt_err_t (*rt_sem_control)(rt_sem_t sem, rt_uint8_t cmd, void* arg);
+};
+typedef struct rt_sem_interface* rt_sem_interface_t;
+#endif
+
+#ifdef RT_USING_MUTEX
+/*
+ * mutex interface
+ */
+ struct rt_mutex_interface
+{
+ rt_err_t (*rt_mutex_init) (rt_mutex_t mutex, const char* name, rt_uint8_t flag);
+ rt_err_t (*rt_mutex_detach)(rt_mutex_t mutex);
+ rt_mutex_t (*rt_mutex_create)(const char* name, rt_uint8_t flag);
+ rt_err_t (*rt_mutex_delete)(rt_mutex_t mutex);
+ rt_err_t (*rt_mutex_take)(rt_mutex_t mutex, rt_int32_t time);
+ rt_err_t (*rt_mutex_release)(rt_mutex_t mutex);
+ rt_err_t (*rt_mutex_control)(rt_mutex_t mutex, rt_uint8_t cmd, void* arg);
+};
+typedef struct rt_mutex_interface* rt_mutex_interface_t;
+#endif
+
+#ifdef RT_USING_EVENT
+/*
+ * event interface
+ */
+ struct rt_event_interface
+{
+ rt_err_t (*rt_event_init)(rt_event_t event, const char* name, rt_uint8_t flag);
+ rt_err_t (*rt_event_detach)(rt_event_t event);
+ rt_event_t (*rt_event_create)(const char* name, rt_uint8_t flag);
+ rt_err_t (*rt_event_delete)(rt_event_t event);
+ rt_err_t (*rt_event_send)(rt_event_t event, rt_uint32_t set);
+ rt_err_t (*rt_event_recv)(rt_event_t event, rt_uint32_t set, rt_uint8_t option, rt_int32_t timeout, rt_uint32_t* recved);
+ rt_err_t (*rt_event_control)(rt_event_t event, rt_uint8_t cmd, void* arg);
+};
+typedef struct rt_event_interface* rt_event_interface_t;
+#endif
+
+#ifdef RT_USING_MAILBOX
+/*
+ * mailbox interface
+ */
+struct rt_mb_interface
+{
+ rt_err_t (*rt_mb_init)(rt_mailbox_t mb, const char* name, void* msgpool, rt_size_t size, rt_uint8_t flag);
+ rt_err_t (*rt_mb_detach)(rt_mailbox_t mb);
+ rt_mailbox_t (*rt_mb_create)(const char* name, rt_size_t size, rt_uint8_t flag);
+ rt_err_t (*rt_mb_delete)(rt_mailbox_t mb);
+ rt_err_t (*rt_mb_send)(rt_mailbox_t mb, rt_uint32_t value);
+ rt_err_t (*rt_mb_recv)(rt_mailbox_t mb, rt_uint32_t* value, rt_int32_t timeout);
+ rt_err_t (*rt_mb_control)(rt_mailbox_t mb, rt_uint8_t cmd, void* arg);
+};
+typedef struct rt_mb_interface* rt_mb_interface_t;
+#endif
+
+#ifdef RT_USING_MESSAGEQUEUE
+/*
+ * message queue interface
+ */
+struct rt_mq_interface
+{
+ rt_err_t (*rt_mq_init)(rt_mq_t mq, const char* name, void *msgpool, rt_size_t msg_size, rt_size_t pool_size, rt_uint8_t flag);
+ rt_err_t (*rt_mq_detach)(rt_mq_t mq);
+ rt_mq_t (*rt_mq_create)(const char* name, rt_size_t msg_size, rt_size_t max_msgs, rt_uint8_t flag);
+ rt_err_t (*rt_mq_delete)(rt_mq_t mq);
+ rt_err_t (*rt_mq_send)(rt_mq_t mq, void* buffer, rt_size_t size);
+ rt_err_t (*rt_mq_urgent)(rt_mq_t mq, void* buffer, rt_size_t size);
+ rt_err_t (*rt_mq_recv)(rt_mq_t mq, void* buffer, rt_size_t size, rt_int32_t timeout);
+ rt_err_t (*rt_mq_control)(rt_mq_t mq, rt_uint8_t cmd, void* arg);
+};
+typedef struct rt_mq_interface* rt_mq_interface_t;
+#endif
+
+#ifdef RT_USING_MEMPOOL
+/*
+ * memory pool interface
+ */
+struct rt_mp_interface
+{
+ rt_err_t (*rt_mp_init)(struct rt_mempool* mp, const char* name, void *start, rt_size_t size, rt_size_t block_size);
+ rt_err_t (*rt_mp_detach)(struct rt_mempool* mp);
+ rt_mp_t (*rt_mp_create)(const char* name, rt_size_t block_count, rt_size_t block_size);
+ rt_err_t (*rt_mp_delete)(rt_mp_t mp);
+ void* (*rt_mp_alloc)(rt_mp_t mp, rt_int32_t time);
+ void (*rt_mp_free)(void *block);
+};
+typedef struct rt_mp_interface* rt_mp_interface_t;
+#endif
+
+#ifdef RT_USING_HEAP
+/*
+ * heap memory interface
+ */
+struct rt_heap_interface
+{
+ void* (*rt_malloc)(rt_size_t size);
+ void (*rt_free)(void *ptr);
+ void* (*rt_realloc)(void *ptr, rt_size_t size);
+ void* (*rt_calloc)(rt_size_t count, rt_size_t size);
+};
+typedef struct rt_heap_interface* rt_heap_interface_t;
+#endif
+
+#ifdef RT_USING_DEVICE
+/*
+ * device interface
+ */
+struct rt_device_interface
+{
+ rt_err_t (*rt_device_register)(rt_device_t dev, const char* name, rt_uint16_t flags);
+ rt_err_t (*rt_device_unregister)(rt_device_t dev);
+ rt_err_t (*rt_device_init_all)(void);
+ rt_device_t (*rt_device_find)(const char* name);
+ rt_err_t (*rt_device_init)(rt_device_t dev);
+ rt_err_t (*rt_device_open)(rt_device_t dev, rt_uint16_t oflag);
+ rt_err_t (*rt_device_close)(rt_device_t dev);
+ rt_size_t (*rt_device_read)(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size);
+ rt_size_t (*rt_device_write)(rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size);
+ rt_err_t (*rt_device_control)(rt_device_t dev, rt_uint8_t cmd, void* arg);
+ rt_err_t (*rt_device_set_rx_indicate)(rt_device_t dev, rt_err_t (*rx_ind )(rt_device_t dev, rt_size_t size));
+ rt_err_t (*rt_device_set_tx_complete)(rt_device_t dev, rt_err_t (*tx_done)(rt_device_t dev, void *buffer));
+};
+typedef struct rt_device_interface* rt_device_interface_t;
+#endif
+
+/*
+ * clock & timer interface
+ */
+struct rt_timer_interface
+{
+ rt_tick_t (*rt_tick_get)(void);
+ rt_tick_t (*rt_tick_from_millisecond)(rt_uint32_t ms);
+ void (*rt_system_timer_init)(void);
+ void (*rt_system_timer_thread_init)(void);
+ void (*rt_timer_init)(rt_timer_t timer,
+ const char* name,
+ void (*timeout)(void* parameter), void* parameter,
+ rt_tick_t time, rt_uint8_t flag);
+ rt_err_t (*rt_timer_detach)(rt_timer_t timer);
+ rt_timer_t (*rt_timer_create)(const char* name, void (*timeout)(void* parameter), void* parameter, rt_tick_t time, rt_uint8_t flag);
+ rt_err_t (*rt_timer_delete)(rt_timer_t timer);
+ rt_err_t (*rt_timer_start)(rt_timer_t timer);
+ rt_err_t (*rt_timer_stop)(rt_timer_t timer);
+ rt_err_t (*rt_timer_control)(rt_timer_t timer, rt_uint8_t cmd, void* arg);
+};
+typedef struct rt_timer_interface* rt_timer_interface_t;
+
+/*
+ * kernel interface
+ */
+struct rt_shell
+{
+ const rt_kservice_interface_t i_kservice;
+ const rt_thread_interface_t i_thread;
+ const rt_sem_interface_t i_sem;
+ const rt_mutex_interface_t i_mutex;
+ const rt_event_interface_t i_event;
+ const rt_mb_interface_t i_mb;
+ const rt_mq_interface_t i_mq;
+ const rt_mp_interface_t i_mp;
+ const rt_heap_interface_t i_heap;
+ const rt_device_interface_t i_device;
+ const rt_timer_interface_t i_timer;
+};
+typedef struct rt_shell* rt_shell_t;
+
diff --git a/components/module/interface/include/interface_module.h b/components/module/interface/include/interface_module.h new file mode 100644 index 0000000000..c1eb4d6ecb --- /dev/null +++ b/components/module/interface/include/interface_module.h @@ -0,0 +1 @@ +Imodule
\ No newline at end of file diff --git a/components/module/interface/src/interface_filesys.c b/components/module/interface/src/interface_filesys.c new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/components/module/interface/src/interface_filesys.c diff --git a/components/module/interface/src/interface_gui.c b/components/module/interface/src/interface_gui.c new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/components/module/interface/src/interface_gui.c diff --git a/components/module/interface/src/interface_kernel.c b/components/module/interface/src/interface_kernel.c new file mode 100644 index 0000000000..ad897035a7 --- /dev/null +++ b/components/module/interface/src/interface_kernel.c @@ -0,0 +1,195 @@ +#include <interface_kernel.h>
+
+const struct rt_kservice_interface ikservice =
+{
+ rt_kprintf
+};
+
+/*
+ * thread interface
+ */
+const struct rt_thread_interface ithread =
+{
+ rt_thread_init,
+ rt_thread_detach,
+ rt_thread_create,
+ rt_thread_self,
+ rt_thread_find,
+ rt_thread_startup,
+ rt_thread_delete,
+ rt_thread_yield,
+ rt_thread_delay,
+ rt_thread_control,
+ rt_thread_suspend,
+ rt_thread_resume,
+ rt_thread_timeout
+};
+
+
+#ifdef RT_USING_SEMAPHORE
+/*
+ * semaphore interface
+ */
+const struct rt_sem_interface isem =
+{
+ rt_sem_init,
+ rt_sem_detach,
+ rt_sem_create,
+ rt_sem_delete,
+ rt_sem_take,
+ rt_sem_trytake,
+ rt_sem_release,
+ rt_sem_control
+};
+#endif
+
+#ifdef RT_USING_MUTEX
+/*
+ * mutex interface
+ */
+const struct rt_mutex_interface imutex =
+{
+ rt_mutex_init,
+ rt_mutex_detach,
+ rt_mutex_create,
+ rt_mutex_delete,
+ rt_mutex_take,
+ rt_mutex_release,
+ rt_mutex_control
+};
+#endif
+
+#ifdef RT_USING_EVENT
+/*
+ * event interface
+ */
+const struct rt_event_interface ievent =
+{
+ rt_event_init,
+ rt_event_detach,
+ rt_event_create,
+ rt_event_delete,
+ rt_event_send,
+ rt_event_recv,
+ rt_event_control
+};
+#endif
+
+#ifdef RT_USING_MAILBOX
+/*
+ * mailbox interface
+ */
+const struct rt_mb_interface imb =
+{
+ rt_mb_init,
+ rt_mb_detach,
+ rt_mb_create,
+ rt_mb_delete,
+ rt_mb_send,
+ rt_mb_recv,
+ rt_mb_control
+};
+#endif
+
+#ifdef RT_USING_MESSAGEQUEUE
+/*
+ * message queue interface
+ */
+const struct rt_mq_interface imq =
+{
+ rt_mq_init,
+ rt_mq_detach,
+ rt_mq_create,
+ rt_mq_delete,
+ rt_mq_send,
+ rt_mq_urgent,
+ rt_mq_recv,
+ rt_mq_control
+};
+#endif
+
+#ifdef RT_USING_MEMPOOL
+/*
+ * memory pool interface
+ */
+const struct rt_mp_interface imp =
+{
+ rt_mp_init,
+ rt_mp_detach,
+ rt_mp_create,
+ rt_mp_delete,
+ rt_mp_alloc,
+ rt_mp_free
+};
+#endif
+
+#ifdef RT_USING_HEAP
+/*
+ * heap memory interface
+ */
+const struct rt_heap_interface iheap =
+{
+ rt_malloc,
+ rt_free,
+ rt_realloc,
+ rt_calloc
+};
+#endif
+
+#ifdef RT_USING_DEVICE
+/*
+ * device interface
+ */
+const struct rt_device_interface idevice =
+{
+ rt_device_register,
+ rt_device_unregister,
+ rt_device_init_all,
+ rt_device_find,
+ rt_device_init,
+ rt_device_open,
+ rt_device_close,
+ rt_device_read,
+ rt_device_write,
+ rt_device_control,
+ rt_device_set_rx_indicate,
+ rt_device_set_tx_complete
+};
+#endif
+
+/*
+ * clock & timer interface
+ */
+const struct rt_timer_interface itimer =
+{
+ rt_tick_get,
+ rt_tick_from_millisecond,
+ rt_system_timer_init,
+ rt_system_timer_thread_init,
+ rt_timer_init,
+ rt_timer_detach,
+ rt_timer_create,
+ rt_timer_delete,
+ rt_timer_start,
+ rt_timer_stop,
+ rt_timer_control
+};
+
+/*
+ * kernel interface
+ */
+const struct rt_shell ishell =
+{
+ (const rt_kservice_interface_t )&ikservice,
+ (const rt_thread_interface_t )&ithread,
+ (const rt_sem_interface_t )&isem,
+ (const rt_mutex_interface_t )&imutex,
+ (const rt_event_interface_t )&ievent,
+ (const rt_mb_interface_t )&imb,
+ (const rt_mq_interface_t )&imq,
+ (const rt_mp_interface_t )&imp,
+ (const rt_heap_interface_t )&iheap,
+ (const rt_device_interface_t )&idevice,
+ (const rt_timer_interface_t )&itimer,
+};
+
diff --git a/components/module/interface/src/interface_net.c b/components/module/interface/src/interface_net.c new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/components/module/interface/src/interface_net.c diff --git a/include/rtdef.h b/include/rtdef.h index 4e414d3041..b85f0b8b84 100644 --- a/include/rtdef.h +++ b/include/rtdef.h @@ -360,17 +360,37 @@ struct rt_thread }; /*@}*/ -/* module clean types */ -#define RT_MODULE_FLAG_AUTO_CLEAN 0x01 /* auto clean */ -#define RT_MODULE_FLAG_MANUAL_CLEAN 0x02 /* manual clean */ - #ifdef RT_USING_MODULE +/* + * module system + */ +enum rt_module_class_type +{ + RT_Module_Class_APP = 0, /* application module */ + RT_Module_Class_EXTENSION, + RT_Module_Class_SERVICE, /* service module */ + RT_Module_Class_Unknown /* unknown module */ +}; + +struct rt_module_info +{ + /* export interface */ + void *module_interface; + /* refence count */ + rt_uint32_t module_refs; + /* module type */ + enum rt_module_class_type module_type; + /* module guid */ + rt_uint32_t module_guid; + /* application entry */ + void* exec_entry; +}; + struct rt_module { /* inherit from object */ struct rt_object parent; - rt_uint32_t module_data; void* module_space; void* module_entry; @@ -382,6 +402,8 @@ struct rt_module rt_uint32_t mempool_size; void* module_mempool; + struct rt_module_info *module_info; + /* object in this module, module object is the last basic object type */ struct rt_object_information module_object[RT_Object_Class_Module]; }; diff --git a/include/rtm.h b/include/rtm.h index 596d5f7f07..653d94327f 100644 --- a/include/rtm.h +++ b/include/rtm.h @@ -2,6 +2,7 @@ #define __RTM_H__
#include <rtdef.h>
+#include <rtthread.h>
#ifdef RT_USING_MODULE
#define RTM_EXPORT(symbol) \
@@ -11,6 +12,7 @@ const struct rt_module_symtab __rtmsym_##symbol SECTION("RTMSymTab")= \ (rt_uint32_t)&symbol, \
__rtmsym_##symbol##_name, \
};
+
#else
#define RTM_EXPORT(symbol)
#endif
diff --git a/src/idle.c b/src/idle.c index b5cccf1260..453f6bc409 100644 --- a/src/idle.c +++ b/src/idle.c @@ -97,7 +97,7 @@ static void rt_thread_idle_entry(void* parameter) /* if sub thread list and main thread are null */ if((module->module_thread == RT_NULL) && rt_list_isempty(&module->module_object[RT_Object_Class_Thread].object_list) && - (module->parent.flag & RT_MODULE_FLAG_AUTO_CLEAN)) + (module->module_info->module_type == RT_Module_Class_APP)) { /* unload module */ rt_module_unload(module); diff --git a/src/module.c b/src/module.c index 19fbd04fb2..decd8e6222 100644 --- a/src/module.c +++ b/src/module.c @@ -19,7 +19,8 @@ #include "module.h" #include "kservice.h" -/* #define RT_MODULE_DEBUG */ +#define RT_MODULE_DEBUG +#ifdef RT_USING_MODULE #define elf_module ((Elf32_Ehdr *)module_ptr) #define shdr ((Elf32_Shdr *)((rt_uint8_t *)module_ptr + elf_module->e_shoff)) @@ -32,10 +33,11 @@ #define IS_AX(s) ((s.sh_flags & SHF_ALLOC) && (s.sh_flags & SHF_EXECINSTR)) #define IS_AW(s) ((s.sh_flags & SHF_ALLOC) && (s.sh_flags & SHF_WRITE)) -#ifdef RT_USING_MODULE rt_list_t rt_module_symbol_list; struct rt_module* rt_current_module; struct rt_module_symtab *_rt_module_symtab_begin = RT_NULL, *_rt_module_symtab_end = RT_NULL; +extern const struct rt_shell ishell; + void rt_system_module_init() { #ifdef __CC_ARM @@ -101,6 +103,11 @@ int rt_module_arm_relocate(struct rt_module* module, Elf32_Rel *rel, Elf32_Addr #endif break; + case R_ARM_V4BX: + *where &= 0xf000000f; + *where |= 0x01a0f000; + break; + default: return -1; } @@ -174,7 +181,7 @@ static void rt_module_init_object_container(struct rt_module* module) struct rt_module* rt_module_load(void* module_ptr, const rt_uint8_t* name) { - rt_uint32_t index, rodata_addr = 0, bss_addr = 0; + rt_uint32_t index, rodata_addr = 0, data_addr = 0, bss_addr = 0; rt_uint32_t module_addr = 0, module_size = 0; struct rt_module* module = RT_NULL; rt_uint8_t *ptr, *strtab, *shstrab; @@ -219,7 +226,7 @@ struct rt_module* rt_module_load(void* module_ptr, const rt_uint8_t* name) /* allocate module */ module = (struct rt_module *)rt_object_allocate(RT_Object_Class_Module, (const char*)name); - if (module == RT_NULL) return module; + if (module == RT_NULL) return RT_NULL; /* allocate module space */ module->module_space = rt_malloc(module_size); @@ -254,7 +261,8 @@ struct rt_module* rt_module_load(void* module_ptr, const rt_uint8_t* name) /* load data section */ if (IS_PROG(shdr[index]) && IS_AW(shdr[index])) { - module->module_data = (rt_uint32_t)ptr; + data_addr = (rt_uint32_t)ptr; + rt_kprintf("data section address 0x%x\n", data_addr); rt_memcpy(ptr, (rt_uint8_t*)elf_module + shdr[index].sh_offset, shdr[index].sh_size); ptr += shdr[index].sh_size; } @@ -263,6 +271,7 @@ struct rt_module* rt_module_load(void* module_ptr, const rt_uint8_t* name) if (IS_NOPROG(shdr[index]) && IS_AW(shdr[index])) { bss_addr = (rt_uint32_t)ptr; + rt_kprintf("bss section address 0x%x\n", bss_addr); rt_memset(ptr, 0, shdr[index].sh_size); } } @@ -293,24 +302,35 @@ struct rt_module* rt_module_load(void* module_ptr, const rt_uint8_t* name) { Elf32_Sym *sym = &symtab[ELF32_R_SYM(rel->r_info)]; #ifdef RT_MODULE_DEBUG - rt_kprintf("relocate symbol: %s\n", strtab + sym->st_name); + rt_kprintf("relocate symbol %s\n", strtab + sym->st_name); #endif if (sym->st_shndx != STN_UNDEF) { - if(ELF_ST_TYPE(sym->st_info) == STT_SECTION) + if((ELF_ST_TYPE(sym->st_info) == STT_SECTION) + || (ELF_ST_TYPE(sym->st_info) == STT_OBJECT)) { + rt_kprintf("section name %s\n", shstrab + shdr[sym->st_shndx].sh_name); if (rt_strncmp(shstrab + shdr[sym->st_shndx].sh_name, ELF_RODATA, 8) == 0) { /* relocate rodata section */ rt_module_arm_relocate(module, rel, - (Elf32_Addr)(rodata_addr), + (Elf32_Addr)(rodata_addr + sym->st_value), module_addr); } else if(strncmp(shstrab + shdr[sym->st_shndx].sh_name, ELF_BSS, 5) == 0) { /* relocate bss section */ - rt_module_arm_relocate(module, rel, (Elf32_Addr)bss_addr, module_addr); - } + rt_module_arm_relocate(module, rel, + (Elf32_Addr)bss_addr + sym->st_value, + module_addr); + } + else if(strncmp(shstrab + shdr[sym->st_shndx].sh_name, ELF_DATA, 6) == 0) + { + /* relocate bss section */ + rt_module_arm_relocate(module, rel, + (Elf32_Addr)data_addr + sym->st_value, + module_addr); + } } else if(ELF_ST_TYPE(sym->st_info) == STT_FUNC ) { @@ -319,25 +339,26 @@ struct rt_module* rt_module_load(void* module_ptr, const rt_uint8_t* name) (Elf32_Addr)((rt_uint8_t*)module->module_space - module_addr + sym->st_value), module_addr); } - else if(ELF_ST_TYPE(sym->st_info) == STT_OBJECT) - { - /* relocate object in data section */ - rt_module_arm_relocate(module, rel, - (Elf32_Addr)(module->module_data + sym->st_value), - module_addr); - } } else { Elf32_Addr addr; + + if(ELF32_R_TYPE(rel->r_info) != R_ARM_V4BX) + { #ifdef RT_MODULE_DEBUG - rt_kprintf("unresolved relocate symbol: %s\n", strtab + sym->st_name); + rt_kprintf("unresolved relocate symbol: %s\n", strtab + sym->st_name); #endif - /* need to resolve symbol in kernel symbol table */ - addr = rt_module_symbol_find(strtab + sym->st_name); - if (addr != (Elf32_Addr)RT_NULL) + /* need to resolve symbol in kernel symbol table */ + addr = rt_module_symbol_find(strtab + sym->st_name); + if (addr != (Elf32_Addr)RT_NULL) + rt_module_arm_relocate(module, rel, addr, module_addr); + else rt_kprintf("can't find %s in kernel symbol table\n", strtab + sym->st_name); + } + else + { rt_module_arm_relocate(module, rel, addr, module_addr); - else rt_kprintf("can't find %s in kernel symbol table\n", strtab + sym->st_name); + } } rel ++; @@ -347,27 +368,50 @@ struct rt_module* rt_module_load(void* module_ptr, const rt_uint8_t* name) /* init module object container */ rt_module_init_object_container(module); - - /* set module defalut clean type */ - module->parent.flag |= RT_MODULE_FLAG_AUTO_CLEAN; - - /* create module main thread */ - module->module_thread = rt_thread_create((const char*)name, - module->module_entry, RT_NULL, - 512, 90, 10); - module->module_thread->module_parent = module; - rt_thread_startup(module->module_thread); + /* enter elf entry */ + ((elf_entry)module->module_entry)(&ishell, &module->module_info); return module; } +void rt_module_run(struct rt_module* module) +{ + struct rt_module_info *info; + + /* check parameter */ + RT_ASSERT(module != RT_NULL); + RT_ASSERT(module->module_info != RT_NULL); + + info = module->module_info; + if(info->module_type == RT_Module_Class_APP) + { + /* application */ + module->module_thread = rt_thread_create(module->parent.name, + module->module_entry, RT_NULL, + 512, 90, 10); + module->module_thread->module_parent = module; + rt_thread_startup(module->module_thread); + } + else if(info->module_type == RT_Module_Class_EXTENSION) + { + /* extension */ + } + else if(info->module_type == RT_Module_Class_SERVICE) + { + /* service */ + } +} + void rt_module_unload(struct rt_module* module) { int i; struct rt_object* object; struct rt_timer *timer; struct rt_list_node *list, *node; - + + /* check parameter */ + RT_ASSERT(module != RT_NULL); + /* suspend module main thread */ if (module->module_thread->stat == RT_THREAD_READY) rt_thread_suspend(module->module_thread); @@ -379,7 +423,16 @@ void rt_module_unload(struct rt_module* module) for (node = list->next; node != list; node = node->next) { object = rt_list_entry(node, struct rt_object, list); - rt_object_delete(object); + if (rt_object_is_systemobject(object) == RT_EOK) + { + /* detach static objcet */ + rt_object_detach(object); + } + else + { + /* delete dynamic object */ + rt_object_delete(object); + } } } diff --git a/src/module.h b/src/module.h index ae2e8b83a8..486e956b4f 100644 --- a/src/module.h +++ b/src/module.h @@ -155,11 +155,12 @@ typedef struct { * Relocation type for arm
*/
#define R_ARM_NONE 0
-#define R_ARM_PC24 1
+#define R_ARM_PC24 1
#define R_ARM_ABS32 2
#define R_ARM_PLT32 27
-#define R_ARM_CALL 28
-#define R_ARM_JUMP24 29
+#define R_ARM_CALL 28
+#define R_ARM_JUMP24 29
+#define R_ARM_V4BX 40
/* Program Header */
typedef struct {
@@ -202,4 +203,6 @@ typedef struct { /* Symbol table index */
#define STN_UNDEF 0 /* undefined */
+typedef rt_err_t (*elf_entry)( const void * env, struct rt_module_info **module_info;);
+
#endif
@@ -14,132 +14,3 @@ #include <rtthread.h>
#include <rtm.h>
-
-/* some buildin kernel symbol */
-#ifdef RT_USING_MODULE
-/*
- * thread interface symbol
- */
-RTM_EXPORT(rt_thread_init)
-RTM_EXPORT(rt_thread_detach)
-RTM_EXPORT(rt_thread_create)
-RTM_EXPORT(rt_thread_self)
-RTM_EXPORT(rt_thread_find)
-RTM_EXPORT(rt_thread_startup)
-RTM_EXPORT(rt_thread_delete)
-RTM_EXPORT(rt_thread_yield)
-RTM_EXPORT(rt_thread_delay)
-RTM_EXPORT(rt_thread_control)
-RTM_EXPORT(rt_thread_suspend)
-RTM_EXPORT(rt_thread_resume)
-RTM_EXPORT(rt_thread_timeout)
-
-#ifdef RT_USING_SEMAPHORE
-/*
- * semaphore interface symbol
- */
-RTM_EXPORT(rt_sem_init)
-RTM_EXPORT(rt_sem_detach)
-RTM_EXPORT(rt_sem_create)
-RTM_EXPORT(rt_sem_delete)
-RTM_EXPORT(rt_sem_take)
-RTM_EXPORT(rt_sem_trytake)
-RTM_EXPORT(rt_sem_release)
-RTM_EXPORT(rt_sem_control)
-#endif
-
-#ifdef RT_USING_MUTEX
-/*
- * mutex interface symbol
- */
-RTM_EXPORT(rt_mutex_init)
-RTM_EXPORT(rt_mutex_detach)
-RTM_EXPORT(rt_mutex_create)
-RTM_EXPORT(rt_mutex_delete)
-RTM_EXPORT(rt_mutex_take)
-RTM_EXPORT(rt_mutex_release)
-RTM_EXPORT(rt_mutex_control)
-#endif
-
-#ifdef RT_USING_EVENT
-/*
- * event interface symbol
- */
-RTM_EXPORT(rt_event_init)
-RTM_EXPORT(rt_event_detach)
-RTM_EXPORT(rt_event_create)
-RTM_EXPORT(rt_event_delete)
-RTM_EXPORT(rt_event_send)
-RTM_EXPORT(rt_event_recv)
-RTM_EXPORT(rt_event_control)
-#endif
-
-#ifdef RT_USING_MAILBOX
-/*
- * mailbox interface symbol
- */
-RTM_EXPORT(rt_mb_init)
-RTM_EXPORT(rt_mb_detach)
-RTM_EXPORT(rt_mb_create)
-RTM_EXPORT(rt_mb_delete)
-RTM_EXPORT(rt_mb_send)
-RTM_EXPORT(rt_mb_recv)
-RTM_EXPORT(rt_mb_control)
-#endif
-
-#ifdef RT_USING_MESSAGEQUEUE
-/*
- * message queue interface symbol
- */
-RTM_EXPORT(rt_mq_init)
-RTM_EXPORT(rt_mq_detach)
-RTM_EXPORT(rt_mq_create)
-RTM_EXPORT(rt_mq_delete)
-RTM_EXPORT(rt_mq_send)
-RTM_EXPORT(rt_mq_urgent)
-RTM_EXPORT(rt_mq_recv)
-RTM_EXPORT(rt_mq_control)
-#endif
-
-#ifdef RT_USING_MEMPOOL
-/*
- * memory pool interface symbol
- */
-RTM_EXPORT(rt_mp_init)
-RTM_EXPORT(rt_mp_detach)
-RTM_EXPORT(rt_mp_create)
-RTM_EXPORT(rt_mp_delete)
-RTM_EXPORT(rt_mp_alloc)
-RTM_EXPORT(rt_mp_free)
-#endif
-
-#ifdef RT_USING_HEAP
-/*
- * heap memory interface symbol
- */
-RTM_EXPORT(rt_malloc)
-RTM_EXPORT(rt_free)
-RTM_EXPORT(rt_realloc)
-RTM_EXPORT(rt_calloc)
-#endif
-/*
- * clock & timer interface symbol
- */
-RTM_EXPORT(rt_tick_get)
-RTM_EXPORT(rt_tick_from_millisecond)
-RTM_EXPORT(rt_system_timer_init)
-RTM_EXPORT(rt_system_timer_thread_init)
-RTM_EXPORT(rt_timer_init)
-RTM_EXPORT(rt_timer_detach)
-RTM_EXPORT(rt_timer_create)
-RTM_EXPORT(rt_timer_delete)
-RTM_EXPORT(rt_timer_start)
-RTM_EXPORT(rt_timer_stop)
-RTM_EXPORT(rt_timer_control)
-
-/*
- * kservice interface symbol
- */
-RTM_EXPORT(rt_kprintf)
-
-#endif
|
