Jelajahi Sumber

add lwp support

shaojinchun 6 tahun lalu
induk
melakukan
a8953e9211

+ 4 - 2
bsp/allwinner_tina/libcpu/start_gcc.S

@@ -48,7 +48,7 @@ _vector_reset:
 _vector_undef:
     .word vector_undef
 _vector_swi:
-    .word vector_swi
+    .word SVC_Handler
 _vector_pabt:
     .word vector_pabt
 _vector_dabt:
@@ -314,7 +314,9 @@ rt_hw_context_switch_interrupt_do:
     str     lr, [r0, #14*4]
 .endm
 
-    .align  5
+    .align 5
+.weak SVC_Handler
+SVC_Handler:
 vector_swi:
     push_svc_reg
     bl      rt_hw_trap_swi

+ 17 - 2
bsp/qemu-vexpress-a9/.config

@@ -66,6 +66,7 @@ CONFIG_RT_USING_INTERRUPT_INFO=y
 CONFIG_RT_USING_CONSOLE=y
 CONFIG_RT_CONSOLEBUF_SIZE=128
 CONFIG_RT_CONSOLE_DEVICE_NAME="uart0"
+CONFIG_RT_VER_NUM=0x40000
 CONFIG_ARCH_ARM=y
 CONFIG_ARCH_ARM_CORTEX_A=y
 CONFIG_ARCH_ARM_CORTEX_A9=y
@@ -109,7 +110,7 @@ CONFIG_FINSH_ARG_MAX=10
 CONFIG_RT_USING_DFS=y
 CONFIG_DFS_USING_WORKDIR=y
 CONFIG_DFS_FILESYSTEMS_MAX=2
-CONFIG_DFS_FILESYSTEM_TYPES_MAX=2
+CONFIG_DFS_FILESYSTEM_TYPES_MAX=8
 CONFIG_DFS_FD_MAX=16
 # CONFIG_RT_USING_DFS_MNTTABLE is not set
 CONFIG_RT_USING_DFS_ELMFAT=y
@@ -165,10 +166,12 @@ CONFIG_RT_MMCSD_THREAD_PREORITY=22
 CONFIG_RT_MMCSD_MAX_PARTITION=16
 # CONFIG_RT_SDIO_DEBUG is not set
 CONFIG_RT_USING_SPI=y
+# CONFIG_RT_USING_QSPI is not set
 CONFIG_RT_USING_SPI_MSD=y
 CONFIG_RT_USING_SFUD=y
 CONFIG_RT_SFUD_USING_SFDP=y
 CONFIG_RT_SFUD_USING_FLASH_INFO_TABLE=y
+# CONFIG_RT_SFUD_USING_QSPI is not set
 # CONFIG_RT_DEBUG_SFUD is not set
 # CONFIG_RT_USING_W25QXX is not set
 # CONFIG_RT_USING_GD is not set
@@ -298,6 +301,7 @@ CONFIG_LOG_TRACE_USING_LEVEL_INFO=y
 # CONFIG_LOG_TRACE_USING_MEMLOG is not set
 # CONFIG_RT_USING_RYM is not set
 # CONFIG_RT_USING_ULOG is not set
+CONFIG_RT_USING_LWP=y
 
 #
 # RT-Thread online packages
@@ -383,6 +387,7 @@ CONFIG_LOG_TRACE_USING_LEVEL_INFO=y
 # CONFIG_PKG_USING_SQLITE is not set
 # CONFIG_PKG_USING_RTI is not set
 # CONFIG_PKG_USING_LITTLEVGL2RTT is not set
+# CONFIG_PKG_USING_CMSIS is not set
 
 #
 # peripheral libraries and drivers
@@ -392,6 +397,9 @@ CONFIG_LOG_TRACE_USING_LEVEL_INFO=y
 # CONFIG_PKG_USING_REALTEK_AMEBA is not set
 # CONFIG_PKG_USING_SHT2X is not set
 # CONFIG_PKG_USING_AHT10 is not set
+# CONFIG_PKG_USING_AP3216C is not set
+# CONFIG_PKG_USING_STM32_SDIO is not set
+# CONFIG_PKG_USING_ICM20608 is not set
 
 #
 # miscellaneous packages
@@ -409,7 +417,14 @@ CONFIG_LOG_TRACE_USING_LEVEL_INFO=y
 #
 # sample package
 #
-# CONFIG_PKG_USING_SAMPLES is not set
+
+#
+# samples: kernel and components samples
+#
+# CONFIG_PKG_USING_KERNEL_SAMPLES is not set
+# CONFIG_PKG_USING_FILESYSTEM_SAMPLES is not set
+# CONFIG_PKG_USING_NETWORK_SAMPLES is not set
+# CONFIG_PKG_USING_PERIPHERAL_SAMPLES is not set
 
 #
 # example package: hello

+ 25 - 0
bsp/qemu-vexpress-a9/cpu/context_gcc.S

@@ -63,6 +63,11 @@ rt_hw_context_switch_to:
     bl      rt_cpus_lock_status_restore
 #endif /*RT_USING_SMP*/
 
+#ifdef RT_USING_LWP
+    ldmfd sp, {r13, r14}^   @ pop usr_sp usr_lr
+    add sp, #8
+#endif
+
     ldmfd sp!, {r4}         @ pop new task spsr
     msr spsr_cxsf, r4
 
@@ -89,6 +94,11 @@ rt_hw_context_switch:
 
     stmfd sp!, {r4}         @ push cpsr
 
+#ifdef RT_USING_LWP
+    stmfd sp, {r13, r14}^   @ push usr_sp usr_lr
+    sub sp, #8
+#endif
+
     str sp, [r0]            @ store sp in preempted tasks TCB
     ldr sp, [r1]            @ get new task stack pointer
 
@@ -97,6 +107,11 @@ rt_hw_context_switch:
     bl      rt_cpus_lock_status_restore
 #endif /*RT_USING_SMP*/
 
+#ifdef RT_USING_LWP
+    ldmfd sp, {r13, r14}^   @ pop usr_sp usr_lr
+    add sp, #8
+#endif
+
     ldmfd sp!, {r4}         @ pop new task cpsr to spsr
     msr spsr_cxsf, r4
     ldmfd sp!, {r0-r12, lr, pc}^  @ pop new task r0-r12, lr & pc, copy spsr to cpsr
@@ -142,6 +157,11 @@ rt_hw_context_switch_interrupt:
     stmfd   sp!, {r4-r7}    @ push old task's r0-r3
     stmfd   sp!, {r3}       @ push old task's cpsr
 
+#ifdef RT_USING_LWP
+    stmfd sp, {r13,r14}^    @push usr_sp usr_lr
+    sub sp, #8
+#endif
+
     msr     cpsr_c, #I_Bit|F_Bit|Mode_IRQ
     pop     {r1 - r3}
     mov     sp, r0
@@ -152,6 +172,11 @@ rt_hw_context_switch_interrupt:
     mov     r0, r3
     bl      rt_cpus_lock_status_restore
 
+#ifdef RT_USING_LWP
+    ldmfd sp, {r13,r14}^  @pop usr_sp usr_lr
+    add sp, #8
+#endif
+
     ldmfd   sp!, {r4}       @ pop new task's cpsr to spsr
     msr     spsr_cxsf, r4
 

+ 5 - 1
bsp/qemu-vexpress-a9/cpu/stack.c

@@ -51,13 +51,17 @@ rt_uint8_t *rt_hw_stack_init(void *tentry, void *parameter,
 	*(--stk) = 0;							/* r2 */
 	*(--stk) = 0;							/* r1 */
 	*(--stk) = (rt_uint32_t)parameter;		/* r0 : argument */
-
 	/* cpsr */
 	if ((rt_uint32_t)tentry & 0x01)
 		*(--stk) = SVCMODE | 0x20;			/* thumb mode */
 	else
 		*(--stk) = SVCMODE;					/* arm mode   */
 
+#ifdef RT_USING_LWP
+	*(--stk) = 0;		/* user lr */
+	*(--stk) = 0;		/* user sp*/
+#endif
+
 	/* return task's current stack address */
 	return (rt_uint8_t *)stk;
 }

+ 14 - 2
bsp/qemu-vexpress-a9/cpu/start_gcc.S

@@ -288,6 +288,11 @@ rt_hw_context_switch_interrupt_do:
     stmfd   sp!, {r1-r4}    @ push old task's r0-r3
     stmfd   sp!, {r0}       @ push old task's cpsr
 
+#ifdef RT_USING_LWP
+    stmfd sp, {r13, r14}^  @push usr_sp, usr_lr
+    sub sp, #8
+#endif
+
     ldr     r4,  =rt_interrupt_from_thread
     ldr     r5,  [r4]
     str     sp,  [r5]       @ store sp in preempted tasks's TCB
@@ -296,6 +301,11 @@ rt_hw_context_switch_interrupt_do:
     ldr     r6,  [r6]
     ldr     sp,  [r6]       @ get new task's stack pointer
 
+#ifdef RT_USING_LWP
+    ldmfd sp, {r13, r14}^  @pop usr_sp, usr_lr
+    add sp, #8
+#endif
+
     ldmfd   sp!, {r4}       @ pop new task's cpsr to spsr
     msr     spsr_cxsf, r4
 
@@ -317,6 +327,8 @@ rt_hw_context_switch_interrupt_do:
 
     .align  5
     .globl  vector_swi
+.weak SVC_Handler
+SVC_Handler:
 vector_swi:
     push_svc_reg
     bl      rt_hw_trap_swi
@@ -400,8 +412,8 @@ irq_stack_2:
 irq_stack_2_limit:
 
 .data
-#define DEVICE_MEM  0x10406
-#define NORMAL_MEM  0x1140e
+#define DEVICE_MEM  0x10c06
+#define NORMAL_MEM  0x11c0e
 .align 14
 mtbl:
 

+ 2 - 1
bsp/qemu-vexpress-a9/cpu/vector_gcc.S

@@ -21,6 +21,7 @@
  * Date           Author       Notes
  * 2013-07-05     Bernard      the first version
  */
+
 .section .vectors, "ax"
 .code 32
 
@@ -49,7 +50,7 @@ _vector_reset:
 _vector_undef:
     .word vector_undef
 _vector_swi:
-    .word vector_swi
+    .word SVC_Handler
 _vector_pabt:
     .word vector_pabt
 _vector_dabt:

+ 15 - 2
bsp/qemu-vexpress-a9/rtconfig.h

@@ -63,6 +63,7 @@
 #define RT_USING_CONSOLE
 #define RT_CONSOLEBUF_SIZE 128
 #define RT_CONSOLE_DEVICE_NAME "uart0"
+#define RT_VER_NUM 0x40000
 #define ARCH_ARM
 #define ARCH_ARM_CORTEX_A
 #define ARCH_ARM_CORTEX_A9
@@ -102,7 +103,7 @@
 #define RT_USING_DFS
 #define DFS_USING_WORKDIR
 #define DFS_FILESYSTEMS_MAX 2
-#define DFS_FILESYSTEM_TYPES_MAX 2
+#define DFS_FILESYSTEM_TYPES_MAX 8
 #define DFS_FD_MAX 16
 /* RT_USING_DFS_MNTTABLE is not set */
 #define RT_USING_DFS_ELMFAT
@@ -156,10 +157,12 @@
 #define RT_MMCSD_MAX_PARTITION 16
 /* RT_SDIO_DEBUG is not set */
 #define RT_USING_SPI
+/* RT_USING_QSPI is not set */
 #define RT_USING_SPI_MSD
 #define RT_USING_SFUD
 #define RT_SFUD_USING_SFDP
 #define RT_SFUD_USING_FLASH_INFO_TABLE
+/* RT_SFUD_USING_QSPI is not set */
 /* RT_DEBUG_SFUD is not set */
 /* RT_USING_W25QXX is not set */
 /* RT_USING_GD is not set */
@@ -276,6 +279,7 @@
 /* LOG_TRACE_USING_MEMLOG is not set */
 /* RT_USING_RYM is not set */
 /* RT_USING_ULOG is not set */
+#define RT_USING_LWP
 
 /* RT-Thread online packages */
 
@@ -348,6 +352,7 @@
 /* PKG_USING_SQLITE is not set */
 /* PKG_USING_RTI is not set */
 /* PKG_USING_LITTLEVGL2RTT is not set */
+/* PKG_USING_CMSIS is not set */
 
 /* peripheral libraries and drivers */
 
@@ -356,6 +361,9 @@
 /* PKG_USING_REALTEK_AMEBA is not set */
 /* PKG_USING_SHT2X is not set */
 /* PKG_USING_AHT10 is not set */
+/* PKG_USING_AP3216C is not set */
+/* PKG_USING_STM32_SDIO is not set */
+/* PKG_USING_ICM20608 is not set */
 
 /* miscellaneous packages */
 
@@ -371,7 +379,12 @@
 
 /* sample package */
 
-/* PKG_USING_SAMPLES is not set */
+/* samples: kernel and components samples */
+
+/* PKG_USING_KERNEL_SAMPLES is not set */
+/* PKG_USING_FILESYSTEM_SAMPLES is not set */
+/* PKG_USING_NETWORK_SAMPLES is not set */
+/* PKG_USING_PERIPHERAL_SAMPLES is not set */
 
 /* example package: hello */
 

+ 2 - 0
components/Kconfig

@@ -39,4 +39,6 @@ source "$RTT_DIR/components/utilities/Kconfig"
 
 source "$RTT_DIR/components/CMSIS/Kconfig"
 
+source "$RTT_DIR/components/lwp/Kconfig"
+
 endmenu

+ 8 - 0
components/lwp/Kconfig

@@ -0,0 +1,8 @@
+config RT_USING_LWP
+    bool "Using light-weight process"
+    select RT_USING_DFS
+    select RT_USING_LIBC
+    depends on ARCH_ARM_CORTEX_M || ARCH_ARM_ARM9 || ARCH_ARM_CORTEX_A
+    default n
+    help
+        The lwP is a light weight process running in user mode.

+ 20 - 0
components/lwp/SConscript

@@ -0,0 +1,20 @@
+Import('rtconfig')
+from building import *
+
+cwd     = GetCurrentDir()
+src     = []
+CPPPATH = []
+
+support_arch  = {"arm": ["cortex-m3", "cortex-m4", "cortex-m7", "R6", "vexpress-a9"]}
+platform_file = {'armcc': 'rvds.S', 'gcc': 'gcc.S', 'iar': 'iar.S'}
+
+if rtconfig.PLATFORM in platform_file.keys():	# support platforms
+    if rtconfig.ARCH in support_arch.keys() and rtconfig.CPU in support_arch[rtconfig.ARCH]:
+        # arch/arm/cortex-m7/lwp_gcc.S
+        asm_path = 'arch/' + rtconfig.ARCH + '/' + rtconfig.CPU + '/*_' + platform_file[rtconfig.PLATFORM]
+        src = Glob('*.c') + Glob(asm_path)
+        CPPPATH = [cwd]
+
+group = DefineGroup('lwP', src, depend = ['RT_USING_LWP'], CPPPATH = CPPPATH)
+
+Return('group')

+ 94 - 0
components/lwp/arch/arm/R6/lwp_gcc.S

@@ -0,0 +1,94 @@
+/*
+ * File      : lwp_gcc.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ */
+
+#define  Mode_USR       0x10
+#define  Mode_FIQ       0x11
+#define  Mode_IRQ       0x12
+#define  Mode_SVC       0x13
+#define  Mode_MON       0x16
+#define  Mode_ABT       0x17
+#define  Mode_UDF       0x1B
+#define  Mode_SYS       0x1F
+
+#define A_Bit        0x100 
+#define I_Bit        0x80 @; when I bit is set, IRQ is disabled
+#define F_Bit        0x40 @; when F bit is set, FIQ is disabled
+#define T_Bit        0x20
+
+.cpu arm9
+.syntax unified
+.text
+
+/*
+ * void lwp_user_entry(args, text, data);
+ */
+.global lwp_user_entry
+.type lwp_user_entry, % function
+lwp_user_entry:
+    mrs     r9, cpsr
+    mov     r8, r9
+    bic     r9, #0x1f
+    orr     r9, #Mode_USR
+
+    orr     r8, #I_Bit
+    msr     cpsr_c, r8
+
+    msr     spsr, r9
+
+    /* set data address. */
+    mov     r9, r2
+    movs    pc, r1
+
+/*
+ * void SVC_Handler(void);
+ */
+.global SVC_Handler
+.type SVC_Handler, % function
+SVC_Handler:
+    push {lr}
+    mrs lr, spsr
+    push {r4, r5, lr}
+
+    mrs r4, cpsr
+    bic r4, #I_Bit
+    msr cpsr_c, r4
+
+    push {r0 - r3, r12}
+    and r0, r7, #0xff
+    bl lwp_get_sys_api
+    cmp r0, #0           /* r0 = api */
+    mov r4, r0
+    pop {r0 - r3, r12}
+    beq svc_exit
+    ldr lr, = svc_exit
+    bx  r4
+
+svc_exit:
+    mrs r4, cpsr
+    orr r4, #I_Bit
+    msr cpsr_c, r4
+
+    pop {r4, r5, lr}
+    msr spsr_cxsf, lr
+    pop {lr}
+    movs pc, lr

+ 137 - 0
components/lwp/arch/arm/cortex-m3/lwp_gcc.S

@@ -0,0 +1,137 @@
+/*
+ * File      : lwp_gcc.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ */
+
+.cpu cortex-m3
+.syntax unified
+.thumb
+.text
+
+/*
+ * void* lwp_get_sys_api(rt_uint32_t number);
+ */
+.global lwp_get_sys_api
+.global lwp_get_kernel_sp
+.global lwp_set_kernel_sp
+
+
+/*
+ * void lwp_user_entry(args, text, data);
+ */
+.global lwp_user_entry
+.type lwp_user_entry, % function
+lwp_user_entry:
+    PUSH    {R0-R3}             @; push text&data addr.
+
+    MOV     R0, SP              @; v1 = SP
+    BL      lwp_set_kernel_sp   @; lwp_set_kernel_sp(v1)
+
+    @; set CPU to user-thread mode.
+    MRS     R2, CONTROL
+    ORR     R2, R2, #0x03       @; use PSP, user-thread mode.
+    MSR     CONTROL, R2
+
+    POP     {R0-R3}             @; pop app address to R1.
+    @; set data address.
+    MOV     R9, R2
+
+    @; run app, only Thumb-mode.
+    ORR     R1, R1, #0x01
+    BX      R1
+
+/*
+ * void SVC_Handler(void);
+ */
+.global SVC_Handler
+.type SVC_Handler, % function
+SVC_Handler:
+    PUSH    {LR}
+
+    @; get user SP.
+    TST     LR, #0x4
+    ITE     EQ
+    MRSEQ   R1, MSP
+    MRSNE   R1, PSP
+    PUSH    {R1}           @; push app SP.
+
+    @; get SVC number.
+    mov     R0, R7
+
+    @; get kernel system API
+    BL      lwp_get_sys_api
+    
+    PUSH    {R0}            @; push api
+
+    @; get kernel SP to R0.
+    BL lwp_get_kernel_sp
+
+    POP     {R2}             @; pop api to R2.
+    POP     {R1}             @; pop app SP to R1.
+
+    stmfd     r0!, {r1}      @; save app SP to kernel SP
+
+    @;push app parm5~6 to kernel SP
+    STMFD   R0!,  {R4 - R5}
+    @; copy R1(app SP) to R0(kernel SP).
+    push {r8-r11}
+    LDMFD   R1,   {R4 - R11}     @; pop exception_stack_frame to r4 - r11 register
+    STMFD   R0!,  {R4 - R11}     @; push exception_stack_frame to server SP.
+    pop {r8-r11}
+
+    LDR     R3, =svc_exit
+    STR     R3, [R0, #20]       @; update LR
+    STR     R2, [R0, #24]       @; update api to PC
+    MSR     PSP, R0             @; update SP, API is executed with kernel SP
+
+    @; set to thread-privilege mode.
+    MRS     R3, CONTROL
+    BIC     R3, R3, #0x01
+    ORR     R3, R3, #0x02
+    MSR     CONTROL, R3
+
+    POP     {LR}                @; 0xFFFFFFED
+    ORR     LR, LR, #0x10
+    BX      LR
+/*
+* void svc_exit(void);
+*/
+.global svc_exit
+.type svc_exit, % function
+svc_exit:
+    @; get user SP.
+    PUSH    {R0}                    @; push result to SP.
+    BL      lwp_get_kernel_sp
+    ldr     r3, [r0, #-4]
+    pop {r0}
+
+    ldr     lr, [r3, #20]
+    ldr     r1, [r3, #24]           @; load pc
+    add     r3, #32                 @; exception_stack_frame size
+    MSR     PSP, R3                 @; restore app stack pointer
+    @; restore to PSP & thread-unprivilege mode.
+    MRS     R2, CONTROL
+    ORR     R2, R2, #0x03
+    MSR     CONTROL, R2
+
+    @; return to lwp.
+    ORR     R1, R1, #0x01           @; only Thumb-mode.
+    BX      R1                      @; return to user app.

+ 136 - 0
components/lwp/arch/arm/cortex-m3/lwp_iar.S

@@ -0,0 +1,136 @@
+;/*
+; * File      : lwp_iar.S
+; * This file is part of RT-Thread RTOS
+; * COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team
+; *
+; *  This program is free software; you can redistribute it and/or modify
+; *  it under the terms of the GNU General Public License as published by
+; *  the Free Software Foundation; either version 2 of the License, or
+; *  (at your option) any later version.
+; *
+; *  This program is distributed in the hope that it will be useful,
+; *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+; *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; *  GNU General Public License for more details.
+; *
+; *  You should have received a copy of the GNU General Public License along
+; *  with this program; if not, write to the Free Software Foundation, Inc.,
+; *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+; *
+; * Change Logs:
+; * Date           Author       Notes
+; */
+
+    SECTION    .text:CODE(2)
+    THUMB
+    REQUIRE8
+    PRESERVE8
+
+;/*
+; * void* lwp_get_sys_api(rt_uint32_t number);
+; */
+    IMPORT lwp_get_sys_api
+    IMPORT lwp_get_kernel_sp
+    IMPORT lwp_set_kernel_sp
+
+;/*
+; * void lwp_user_entry(args, text, data);
+; */
+    EXPORT  lwp_user_entry
+lwp_user_entry:
+    PUSH    {R0-R3}             ; push text&data addr.
+
+    MOV     R0, SP              ; v1 = SP
+    BL      lwp_set_kernel_sp   ; lwp_set_kernel_sp(v1)
+
+    ; set CPU to user-thread mode.
+    MRS     R2, CONTROL
+    ORR     R2, R2, #0x03       ; use PSP, user-thread mode.
+    MSR     CONTROL, R2
+
+    POP     {R0-R3}             ; pop app address to R1.
+    ; set data address.
+    MOV     R9, R2
+
+    ; run app, only Thumb-mode.
+    ORR     R1, R1, #0x01
+    BX      R1
+
+;/*
+; * void SVC_Handler(void);
+; */
+    EXPORT SVC_Handler
+SVC_Handler:
+    PUSH    {LR}
+
+    ; get user SP.
+    TST     LR, #0x4
+    ITE     EQ
+    MRSEQ   R1, MSP
+    MRSNE   R1, PSP
+    PUSH    {R1}           ; push app SP.
+
+    ; get SVC number.
+    mov     R0, R7
+
+    ; get kernel system API
+    BL      lwp_get_sys_api
+    
+    PUSH    {R0}            ; push api
+
+    ; get kernel SP to R0.
+    BL lwp_get_kernel_sp
+
+    POP     {R2}             ; pop api to R2.
+    POP     {R1}             ; pop app SP to R1.
+
+    stmfd     r0!, {r1}      ; save app SP to kernel SP
+
+    ;push app parm5~6 to kernel SP
+    STMFD   R0!,  {R4 - R5}
+    ; copy R1(app SP) to R0(kernel SP).
+    push {r8-r11}
+    LDMFD   R1,   {R4 - R11}     ; pop exception_stack_frame to r4 - r11 register
+    STMFD   R0!,  {R4 - R11}     ; push exception_stack_frame to server SP.
+    pop {r8-r11}
+
+    LDR     R3, =svc_exit
+    STR     R3, [R0, #20]       ; update LR
+    STR     R2, [R0, #24]       ; update api to PC
+    MSR     PSP, R0             ; update SP, API is executed with kernel SP
+
+    ; set to thread-privilege mode.
+    MRS     R3, CONTROL
+    BIC     R3, R3, #0x01
+    ORR     R3, R3, #0x02
+    MSR     CONTROL, R3
+
+    POP     {LR}                ; 0xFFFFFFED
+    ORR     LR, LR, #0x10
+    BX      LR
+
+;/*
+; * void svc_exit(void);
+; */
+    EXPORT svc_exit
+svc_exit:
+    ; get user SP.
+    PUSH    {R0}                    ; push result to SP.
+    BL      lwp_get_kernel_sp
+    ldr     r3, [r0, #-4]
+    pop {r0}
+
+    ldr     lr, [r3, #20]
+    ldr     r1, [r3, #24]           ; load pc
+    add     r3, r3, #32                 ; exception_stack_frame size
+    MSR     PSP, R3                 ; restore app stack pointer
+    ; restore to PSP & thread-unprivilege mode.
+    MRS     R2, CONTROL
+    ORR     R2, R2, #0x03
+    MSR     CONTROL, R2
+
+    ; return to lwp.
+    ORR     R1, R1, #0x01           ; only Thumb-mode.
+    BX      R1                      ; return to user app.
+
+    END

+ 148 - 0
components/lwp/arch/arm/cortex-m3/lwp_rvds.S

@@ -0,0 +1,148 @@
+;/*
+; * File      : lwp_rvds.S
+; * This file is part of RT-Thread RTOS
+; * COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team
+; *
+; *  This program is free software; you can redistribute it and/or modify
+; *  it under the terms of the GNU General Public License as published by
+; *  the Free Software Foundation; either version 2 of the License, or
+; *  (at your option) any later version.
+; *
+; *  This program is distributed in the hope that it will be useful,
+; *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+; *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; *  GNU General Public License for more details.
+; *
+; *  You should have received a copy of the GNU General Public License along
+; *  with this program; if not, write to the Free Software Foundation, Inc.,
+; *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+; *
+; * Change Logs:
+; * Date           Author       Notes
+; */
+
+    AREA |.text|, CODE, READONLY, ALIGN=2
+    THUMB
+    REQUIRE8
+    PRESERVE8
+
+;/*
+; * void* lwp_get_sys_api(rt_uint32_t number);
+; */
+    IMPORT lwp_get_sys_api
+    IMPORT lwp_get_kernel_sp
+    IMPORT lwp_set_kernel_sp
+
+;/*
+; * void lwp_user_entry(args, text, data);
+; */
+lwp_user_entry    PROC
+    EXPORT  lwp_user_entry
+
+    PUSH    {R0-R3}             ; push text&data addr.
+
+    MOV     R0, SP              ; v1 = SP
+    BL      lwp_set_kernel_sp   ; lwp_set_kernel_sp(v1)
+
+    ; set CPU to user-thread mode.
+    MRS     R2, CONTROL
+    ORR     R2, R2, #0x03       ; use PSP, user-thread mode.
+    MSR     CONTROL, R2
+
+    POP     {R0-R3}             ; pop app address to R1.
+    ; set data address.
+    MOV     R9, R2
+
+    ; run app, only Thumb-mode.
+    ORR     R1, R1, #0x01
+    BX      R1
+
+    ; never reach here!
+    ENDP
+
+;/*
+; * void SVC_Handler(void);
+; */
+SVC_Handler    PROC
+    EXPORT SVC_Handler
+
+    PUSH    {LR}
+
+    ; get user SP.
+    TST     LR, #0x4
+    ITE     EQ
+    MRSEQ   R1, MSP
+    MRSNE   R1, PSP
+    PUSH    {R1}           ; push app SP.
+
+    ; get SVC number.
+    mov     R0, R7
+
+    ; get kernel system API
+    BL      lwp_get_sys_api
+    
+    PUSH    {R0}            ; push api
+
+    ; get kernel SP to R0.
+    BL lwp_get_kernel_sp
+
+    POP     {R2}             ; pop api to R2.
+    POP     {R1}             ; pop app SP to R1.
+
+    stmfd     r0!, {r1}      ; save app SP to kernel SP
+
+    ;push app parm5~6 to kernel SP
+    STMFD   R0!,  {R4 - R5}
+    ; copy R1(app SP) to R0(kernel SP).
+    push {r8-r11}
+    LDMFD   R1,   {R4 - R11}     ; pop exception_stack_frame to r4 - r11 register
+    STMFD   R0!,  {R4 - R11}     ; push exception_stack_frame to server SP.
+    pop {r8-r11}
+
+    LDR     R3, =svc_exit
+    STR     R3, [R0, #20]       ; update LR
+    STR     R2, [R0, #24]       ; update api to PC
+    MSR     PSP, R0             ; update SP, API is executed with kernel SP
+
+    ; set to thread-privilege mode.
+    MRS     R3, CONTROL
+    BIC     R3, R3, #0x01
+    ORR     R3, R3, #0x02
+    MSR     CONTROL, R3
+
+    POP     {LR}                ; 0xFFFFFFED
+    ORR     LR, LR, #0x10
+    BX      LR
+
+    ENDP
+
+;/*
+; * void svc_exit(void);
+; */
+svc_exit     PROC
+    EXPORT svc_exit
+
+    ; get user SP.
+    PUSH    {R0}                    ; push result to SP.
+    BL      lwp_get_kernel_sp
+    ldr     r3, [r0, #-4]
+    pop {r0}
+
+    ldr     lr, [r3, #20]
+    ldr     r1, [r3, #24]           ; load pc
+    add     r3, #32                 ; exception_stack_frame size
+    MSR     PSP, R3                 ; restore app stack pointer
+    ; restore to PSP & thread-unprivilege mode.
+    MRS     R2, CONTROL
+    ORR     R2, R2, #0x03
+    MSR     CONTROL, R2
+
+    ; return to lwp.
+    ORR     R1, R1, #0x01           ; only Thumb-mode.
+    BX      R1                      ; return to user app.
+
+    ENDP
+
+    ALIGN
+
+    END

+ 137 - 0
components/lwp/arch/arm/cortex-m4/lwp_gcc.S

@@ -0,0 +1,137 @@
+/*
+ * File      : lwp_gcc.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ */
+
+.cpu cortex-m4
+.syntax unified
+.thumb
+.text
+
+/*
+ * void* lwp_get_sys_api(rt_uint32_t number);
+ */
+.global lwp_get_sys_api
+.global lwp_get_kernel_sp
+.global lwp_set_kernel_sp
+
+
+/*
+ * void lwp_user_entry(args, text, data);
+ */
+.global lwp_user_entry
+.type lwp_user_entry, % function
+lwp_user_entry:
+    PUSH    {R0-R3}             @; push text&data addr.
+
+    MOV     R0, SP              @; v1 = SP
+    BL      lwp_set_kernel_sp   @; lwp_set_kernel_sp(v1)
+
+    @; set CPU to user-thread mode.
+    MRS     R2, CONTROL
+    ORR     R2, R2, #0x03       @; use PSP, user-thread mode.
+    MSR     CONTROL, R2
+
+    POP     {R0-R3}             @; pop app address to R1.
+    @; set data address.
+    MOV     R9, R2
+
+    @; run app, only Thumb-mode.
+    ORR     R1, R1, #0x01
+    BX      R1
+
+/*
+ * void SVC_Handler(void);
+ */
+.global SVC_Handler
+.type SVC_Handler, % function
+SVC_Handler:
+    PUSH    {LR}
+
+    @; get user SP.
+    TST     LR, #0x4
+    ITE     EQ
+    MRSEQ   R1, MSP
+    MRSNE   R1, PSP
+    PUSH    {R1}           @; push app SP.
+
+    @; get SVC number.
+    mov     R0, R7
+
+    @; get kernel system API
+    BL      lwp_get_sys_api
+    
+    PUSH    {R0}            @; push api
+
+    @; get kernel SP to R0.
+    BL lwp_get_kernel_sp
+
+    POP     {R2}             @; pop api to R2.
+    POP     {R1}             @; pop app SP to R1.
+
+    stmfd     r0!, {r1}      @; save app SP to kernel SP
+
+    @;push app parm5~6 to kernel SP
+    STMFD   R0!,  {R4 - R5}
+    @; copy R1(app SP) to R0(kernel SP).
+    push {r8-r11}
+    LDMFD   R1,   {R4 - R11}     @; pop exception_stack_frame to r4 - r11 register
+    STMFD   R0!,  {R4 - R11}     @; push exception_stack_frame to server SP.
+    pop {r8-r11}
+
+    LDR     R3, =svc_exit
+    STR     R3, [R0, #20]       @; update LR
+    STR     R2, [R0, #24]       @; update api to PC
+    MSR     PSP, R0             @; update SP, API is executed with kernel SP
+
+    @; set to thread-privilege mode.
+    MRS     R3, CONTROL
+    BIC     R3, R3, #0x01
+    ORR     R3, R3, #0x02
+    MSR     CONTROL, R3
+
+    POP     {LR}                @; 0xFFFFFFED
+    ORR     LR, LR, #0x10
+    BX      LR
+/*
+* void svc_exit(void);
+*/
+.global svc_exit
+.type svc_exit, % function
+svc_exit:
+    @; get user SP.
+    PUSH    {R0}                    @; push result to SP.
+    BL      lwp_get_kernel_sp
+    ldr     r3, [r0, #-4]
+    pop {r0}
+
+    ldr     lr, [r3, #20]
+    ldr     r1, [r3, #24]           @; load pc
+    add     r3, #32                 @; exception_stack_frame size
+    MSR     PSP, R3                 @; restore app stack pointer
+    @; restore to PSP & thread-unprivilege mode.
+    MRS     R2, CONTROL
+    ORR     R2, R2, #0x03
+    MSR     CONTROL, R2
+
+    @; return to lwp.
+    ORR     R1, R1, #0x01           @; only Thumb-mode.
+    BX      R1                      @; return to user app.

+ 136 - 0
components/lwp/arch/arm/cortex-m4/lwp_iar.S

@@ -0,0 +1,136 @@
+;/*
+; * File      : lwp_iar.S
+; * This file is part of RT-Thread RTOS
+; * COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team
+; *
+; *  This program is free software; you can redistribute it and/or modify
+; *  it under the terms of the GNU General Public License as published by
+; *  the Free Software Foundation; either version 2 of the License, or
+; *  (at your option) any later version.
+; *
+; *  This program is distributed in the hope that it will be useful,
+; *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+; *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; *  GNU General Public License for more details.
+; *
+; *  You should have received a copy of the GNU General Public License along
+; *  with this program; if not, write to the Free Software Foundation, Inc.,
+; *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+; *
+; * Change Logs:
+; * Date           Author       Notes
+; */
+
+    SECTION    .text:CODE(2)
+    THUMB
+    REQUIRE8
+    PRESERVE8
+
+;/*
+; * void* lwp_get_sys_api(rt_uint32_t number);
+; */
+    IMPORT lwp_get_sys_api
+    IMPORT lwp_get_kernel_sp
+    IMPORT lwp_set_kernel_sp
+
+;/*
+; * void lwp_user_entry(args, text, data);
+; */
+    EXPORT  lwp_user_entry
+lwp_user_entry:
+    PUSH    {R0-R3}             ; push text&data addr.
+
+    MOV     R0, SP              ; v1 = SP
+    BL      lwp_set_kernel_sp   ; lwp_set_kernel_sp(v1)
+
+    ; set CPU to user-thread mode.
+    MRS     R2, CONTROL
+    ORR     R2, R2, #0x03       ; use PSP, user-thread mode.
+    MSR     CONTROL, R2
+
+    POP     {R0-R3}             ; pop app address to R1.
+    ; set data address.
+    MOV     R9, R2
+
+    ; run app, only Thumb-mode.
+    ORR     R1, R1, #0x01
+    BX      R1
+
+;/*
+; * void SVC_Handler(void);
+; */
+    EXPORT SVC_Handler
+SVC_Handler:
+    PUSH    {LR}
+
+    ; get user SP.
+    TST     LR, #0x4
+    ITE     EQ
+    MRSEQ   R1, MSP
+    MRSNE   R1, PSP
+    PUSH    {R1}           ; push app SP.
+
+    ; get SVC number.
+    mov     R0, R7
+
+    ; get kernel system API
+    BL      lwp_get_sys_api
+    
+    PUSH    {R0}            ; push api
+
+    ; get kernel SP to R0.
+    BL lwp_get_kernel_sp
+
+    POP     {R2}             ; pop api to R2.
+    POP     {R1}             ; pop app SP to R1.
+
+    stmfd     r0!, {r1}      ; save app SP to kernel SP
+
+    ;push app parm5~6 to kernel SP
+    STMFD   R0!,  {R4 - R5}
+    ; copy R1(app SP) to R0(kernel SP).
+    push {r8-r11}
+    LDMFD   R1,   {R4 - R11}     ; pop exception_stack_frame to r4 - r11 register
+    STMFD   R0!,  {R4 - R11}     ; push exception_stack_frame to server SP.
+    pop {r8-r11}
+
+    LDR     R3, =svc_exit
+    STR     R3, [R0, #20]       ; update LR
+    STR     R2, [R0, #24]       ; update api to PC
+    MSR     PSP, R0             ; update SP, API is executed with kernel SP
+
+    ; set to thread-privilege mode.
+    MRS     R3, CONTROL
+    BIC     R3, R3, #0x01
+    ORR     R3, R3, #0x02
+    MSR     CONTROL, R3
+
+    POP     {LR}                ; 0xFFFFFFED
+    ORR     LR, LR, #0x10
+    BX      LR
+
+;/*
+; * void svc_exit(void);
+; */
+    EXPORT svc_exit
+svc_exit:
+    ; get user SP.
+    PUSH    {R0}                    ; push result to SP.
+    BL      lwp_get_kernel_sp
+    ldr     r3, [r0, #-4]
+    pop {r0}
+
+    ldr     lr, [r3, #20]
+    ldr     r1, [r3, #24]           ; load pc
+    add     r3, r3, #32                 ; exception_stack_frame size
+    MSR     PSP, R3                 ; restore app stack pointer
+    ; restore to PSP & thread-unprivilege mode.
+    MRS     R2, CONTROL
+    ORR     R2, R2, #0x03
+    MSR     CONTROL, R2
+
+    ; return to lwp.
+    ORR     R1, R1, #0x01           ; only Thumb-mode.
+    BX      R1                      ; return to user app.
+
+    END

+ 148 - 0
components/lwp/arch/arm/cortex-m4/lwp_rvds.S

@@ -0,0 +1,148 @@
+;/*
+; * File      : lwp_rvds.S
+; * This file is part of RT-Thread RTOS
+; * COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team
+; *
+; *  This program is free software; you can redistribute it and/or modify
+; *  it under the terms of the GNU General Public License as published by
+; *  the Free Software Foundation; either version 2 of the License, or
+; *  (at your option) any later version.
+; *
+; *  This program is distributed in the hope that it will be useful,
+; *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+; *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; *  GNU General Public License for more details.
+; *
+; *  You should have received a copy of the GNU General Public License along
+; *  with this program; if not, write to the Free Software Foundation, Inc.,
+; *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+; *
+; * Change Logs:
+; * Date           Author       Notes
+; */
+
+    AREA |.text|, CODE, READONLY, ALIGN=2
+    THUMB
+    REQUIRE8
+    PRESERVE8
+
+;/*
+; * void* lwp_get_sys_api(rt_uint32_t number);
+; */
+    IMPORT lwp_get_sys_api
+    IMPORT lwp_get_kernel_sp
+    IMPORT lwp_set_kernel_sp
+
+;/*
+; * void lwp_user_entry(args, text, data);
+; */
+lwp_user_entry    PROC
+    EXPORT  lwp_user_entry
+
+    PUSH    {R0-R3}             ; push text&data addr.
+
+    MOV     R0, SP              ; v1 = SP
+    BL      lwp_set_kernel_sp   ; lwp_set_kernel_sp(v1)
+
+    ; set CPU to user-thread mode.
+    MRS     R2, CONTROL
+    ORR     R2, R2, #0x03       ; use PSP, user-thread mode.
+    MSR     CONTROL, R2
+
+    POP     {R0-R3}             ; pop app address to R1.
+    ; set data address.
+    MOV     R9, R2
+
+    ; run app, only Thumb-mode.
+    ORR     R1, R1, #0x01
+    BX      R1
+
+    ; never reach here!
+    ENDP
+
+;/*
+; * void SVC_Handler(void);
+; */
+SVC_Handler    PROC
+    EXPORT SVC_Handler
+
+    PUSH    {LR}
+
+    ; get user SP.
+    TST     LR, #0x4
+    ITE     EQ
+    MRSEQ   R1, MSP
+    MRSNE   R1, PSP
+    PUSH    {R1}           ; push app SP.
+
+    ; get SVC number.
+    mov     R0, R7
+
+    ; get kernel system API
+    BL      lwp_get_sys_api
+    
+    PUSH    {R0}            ; push api
+
+    ; get kernel SP to R0.
+    BL lwp_get_kernel_sp
+
+    POP     {R2}             ; pop api to R2.
+    POP     {R1}             ; pop app SP to R1.
+
+    stmfd     r0!, {r1}      ; save app SP to kernel SP
+
+    ;push app parm5~6 to kernel SP
+    STMFD   R0!,  {R4 - R5}
+    ; copy R1(app SP) to R0(kernel SP).
+    push {r8-r11}
+    LDMFD   R1,   {R4 - R11}     ; pop exception_stack_frame to r4 - r11 register
+    STMFD   R0!,  {R4 - R11}     ; push exception_stack_frame to server SP.
+    pop {r8-r11}
+
+    LDR     R3, =svc_exit
+    STR     R3, [R0, #20]       ; update LR
+    STR     R2, [R0, #24]       ; update api to PC
+    MSR     PSP, R0             ; update SP, API is executed with kernel SP
+
+    ; set to thread-privilege mode.
+    MRS     R3, CONTROL
+    BIC     R3, R3, #0x01
+    ORR     R3, R3, #0x02
+    MSR     CONTROL, R3
+
+    POP     {LR}                ; 0xFFFFFFED
+    ORR     LR, LR, #0x10
+    BX      LR
+
+    ENDP
+
+;/*
+; * void svc_exit(void);
+; */
+svc_exit     PROC
+    EXPORT svc_exit
+
+    ; get user SP.
+    PUSH    {R0}                    ; push result to SP.
+    BL      lwp_get_kernel_sp
+    ldr     r3, [r0, #-4]
+    pop {r0}
+
+    ldr     lr, [r3, #20]
+    ldr     r1, [r3, #24]           ; load pc
+    add     r3, #32                 ; exception_stack_frame size
+    MSR     PSP, R3                 ; restore app stack pointer
+    ; restore to PSP & thread-unprivilege mode.
+    MRS     R2, CONTROL
+    ORR     R2, R2, #0x03
+    MSR     CONTROL, R2
+
+    ; return to lwp.
+    ORR     R1, R1, #0x01           ; only Thumb-mode.
+    BX      R1                      ; return to user app.
+
+    ENDP
+
+    ALIGN
+
+    END

+ 137 - 0
components/lwp/arch/arm/cortex-m7/lwp_gcc.S

@@ -0,0 +1,137 @@
+/*
+ * File      : lwp_gcc.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ */
+
+.cpu cortex-m7
+.syntax unified
+.thumb
+.text
+
+/*
+ * void* lwp_get_sys_api(rt_uint32_t number);
+ */
+.global lwp_get_sys_api
+.global lwp_get_kernel_sp
+.global lwp_set_kernel_sp
+
+
+/*
+ * void lwp_user_entry(args, text, data);
+ */
+.global lwp_user_entry
+.type lwp_user_entry, % function
+lwp_user_entry:
+    PUSH    {R0-R3}             @; push text&data addr.
+
+    MOV     R0, SP              @; v1 = SP
+    BL      lwp_set_kernel_sp   @; lwp_set_kernel_sp(v1)
+
+    @; set CPU to user-thread mode.
+    MRS     R2, CONTROL
+    ORR     R2, R2, #0x03       @; use PSP, user-thread mode.
+    MSR     CONTROL, R2
+
+    POP     {R0-R3}             @; pop app address to R1.
+    @; set data address.
+    MOV     R9, R2
+
+    @; run app, only Thumb-mode.
+    ORR     R1, R1, #0x01
+    BX      R1
+
+/*
+ * void SVC_Handler(void);
+ */
+.global SVC_Handler
+.type SVC_Handler, % function
+SVC_Handler:
+    PUSH    {LR}
+
+    @; get user SP.
+    TST     LR, #0x4
+    ITE     EQ
+    MRSEQ   R1, MSP
+    MRSNE   R1, PSP
+    PUSH    {R1}           @; push app SP.
+
+    @; get SVC number.
+    mov     R0, R7
+
+    @; get kernel system API
+    BL      lwp_get_sys_api
+    
+    PUSH    {R0}            @; push api
+
+    @; get kernel SP to R0.
+    BL lwp_get_kernel_sp
+
+    POP     {R2}             @; pop api to R2.
+    POP     {R1}             @; pop app SP to R1.
+
+    stmfd     r0!, {r1}      @; save app SP to kernel SP
+
+    @;push app parm5~6 to kernel SP
+    STMFD   R0!,  {R4 - R5}
+    @; copy R1(app SP) to R0(kernel SP).
+    push {r8-r11}
+    LDMFD   R1,   {R4 - R11}     @; pop exception_stack_frame to r4 - r11 register
+    STMFD   R0!,  {R4 - R11}     @; push exception_stack_frame to server SP.
+    pop {r8-r11}
+
+    LDR     R3, =svc_exit
+    STR     R3, [R0, #20]       @; update LR
+    STR     R2, [R0, #24]       @; update api to PC
+    MSR     PSP, R0             @; update SP, API is executed with kernel SP
+
+    @; set to thread-privilege mode.
+    MRS     R3, CONTROL
+    BIC     R3, R3, #0x01
+    ORR     R3, R3, #0x02
+    MSR     CONTROL, R3
+
+    POP     {LR}                @; 0xFFFFFFED
+    ORR     LR, LR, #0x10
+    BX      LR
+/*
+* void svc_exit(void);
+*/
+.global svc_exit
+.type svc_exit, % function
+svc_exit:
+    @; get user SP.
+    PUSH    {R0}                    @; push result to SP.
+    BL      lwp_get_kernel_sp
+    ldr     r3, [r0, #-4]
+    pop {r0}
+
+    ldr     lr, [r3, #20]
+    ldr     r1, [r3, #24]           @; load pc
+    add     r3, #32                 @; exception_stack_frame size
+    MSR     PSP, R3                 @; restore app stack pointer
+    @; restore to PSP & thread-unprivilege mode.
+    MRS     R2, CONTROL
+    ORR     R2, R2, #0x03
+    MSR     CONTROL, R2
+
+    @; return to lwp.
+    ORR     R1, R1, #0x01           @; only Thumb-mode.
+    BX      R1                      @; return to user app.

+ 136 - 0
components/lwp/arch/arm/cortex-m7/lwp_iar.S

@@ -0,0 +1,136 @@
+;/*
+; * File      : lwp_iar.S
+; * This file is part of RT-Thread RTOS
+; * COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team
+; *
+; *  This program is free software; you can redistribute it and/or modify
+; *  it under the terms of the GNU General Public License as published by
+; *  the Free Software Foundation; either version 2 of the License, or
+; *  (at your option) any later version.
+; *
+; *  This program is distributed in the hope that it will be useful,
+; *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+; *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; *  GNU General Public License for more details.
+; *
+; *  You should have received a copy of the GNU General Public License along
+; *  with this program; if not, write to the Free Software Foundation, Inc.,
+; *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+; *
+; * Change Logs:
+; * Date           Author       Notes
+; */
+
+    SECTION    .text:CODE(2)
+    THUMB
+    REQUIRE8
+    PRESERVE8
+
+;/*
+; * void* lwp_get_sys_api(rt_uint32_t number);
+; */
+    IMPORT lwp_get_sys_api
+    IMPORT lwp_get_kernel_sp
+    IMPORT lwp_set_kernel_sp
+
+;/*
+; * void lwp_user_entry(args, text, data);
+; */
+    EXPORT  lwp_user_entry
+lwp_user_entry:
+    PUSH    {R0-R3}             ; push text&data addr.
+
+    MOV     R0, SP              ; v1 = SP
+    BL      lwp_set_kernel_sp   ; lwp_set_kernel_sp(v1)
+
+    ; set CPU to user-thread mode.
+    MRS     R2, CONTROL
+    ORR     R2, R2, #0x03       ; use PSP, user-thread mode.
+    MSR     CONTROL, R2
+
+    POP     {R0-R3}             ; pop app address to R1.
+    ; set data address.
+    MOV     R9, R2
+
+    ; run app, only Thumb-mode.
+    ORR     R1, R1, #0x01
+    BX      R1
+
+;/*
+; * void SVC_Handler(void);
+; */
+    EXPORT SVC_Handler
+SVC_Handler:
+    PUSH    {LR}
+
+    ; get user SP.
+    TST     LR, #0x4
+    ITE     EQ
+    MRSEQ   R1, MSP
+    MRSNE   R1, PSP
+    PUSH    {R1}           ; push app SP.
+
+    ; get SVC number.
+    mov     R0, R7
+
+    ; get kernel system API
+    BL      lwp_get_sys_api
+    
+    PUSH    {R0}            ; push api
+
+    ; get kernel SP to R0.
+    BL lwp_get_kernel_sp
+
+    POP     {R2}             ; pop api to R2.
+    POP     {R1}             ; pop app SP to R1.
+
+    stmfd     r0!, {r1}      ; save app SP to kernel SP
+
+    ;push app parm5~6 to kernel SP
+    STMFD   R0!,  {R4 - R5}
+    ; copy R1(app SP) to R0(kernel SP).
+    push {r8-r11}
+    LDMFD   R1,   {R4 - R11}     ; pop exception_stack_frame to r4 - r11 register
+    STMFD   R0!,  {R4 - R11}     ; push exception_stack_frame to server SP.
+    pop {r8-r11}
+
+    LDR     R3, =svc_exit
+    STR     R3, [R0, #20]       ; update LR
+    STR     R2, [R0, #24]       ; update api to PC
+    MSR     PSP, R0             ; update SP, API is executed with kernel SP
+
+    ; set to thread-privilege mode.
+    MRS     R3, CONTROL
+    BIC     R3, R3, #0x01
+    ORR     R3, R3, #0x02
+    MSR     CONTROL, R3
+
+    POP     {LR}                ; 0xFFFFFFED
+    ORR     LR, LR, #0x10
+    BX      LR
+
+;/*
+; * void svc_exit(void);
+; */
+    EXPORT svc_exit
+svc_exit:
+    ; get user SP.
+    PUSH    {R0}                    ; push result to SP.
+    BL      lwp_get_kernel_sp
+    ldr     r3, [r0, #-4]
+    pop {r0}
+
+    ldr     lr, [r3, #20]
+    ldr     r1, [r3, #24]           ; load pc
+    add     r3, r3, #32                 ; exception_stack_frame size
+    MSR     PSP, R3                 ; restore app stack pointer
+    ; restore to PSP & thread-unprivilege mode.
+    MRS     R2, CONTROL
+    ORR     R2, R2, #0x03
+    MSR     CONTROL, R2
+
+    ; return to lwp.
+    ORR     R1, R1, #0x01           ; only Thumb-mode.
+    BX      R1                      ; return to user app.
+
+    END

+ 148 - 0
components/lwp/arch/arm/cortex-m7/lwp_rvds.S

@@ -0,0 +1,148 @@
+;/*
+; * File      : lwp_rvds.S
+; * This file is part of RT-Thread RTOS
+; * COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team
+; *
+; *  This program is free software; you can redistribute it and/or modify
+; *  it under the terms of the GNU General Public License as published by
+; *  the Free Software Foundation; either version 2 of the License, or
+; *  (at your option) any later version.
+; *
+; *  This program is distributed in the hope that it will be useful,
+; *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+; *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+; *  GNU General Public License for more details.
+; *
+; *  You should have received a copy of the GNU General Public License along
+; *  with this program; if not, write to the Free Software Foundation, Inc.,
+; *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+; *
+; * Change Logs:
+; * Date           Author       Notes
+; */
+
+    AREA |.text|, CODE, READONLY, ALIGN=2
+    THUMB
+    REQUIRE8
+    PRESERVE8
+
+;/*
+; * void* lwp_get_sys_api(rt_uint32_t number);
+; */
+    IMPORT lwp_get_sys_api
+    IMPORT lwp_get_kernel_sp
+    IMPORT lwp_set_kernel_sp
+
+;/*
+; * void lwp_user_entry(args, text, data);
+; */
+lwp_user_entry    PROC
+    EXPORT  lwp_user_entry
+
+    PUSH    {R0-R3}             ; push text&data addr.
+
+    MOV     R0, SP              ; v1 = SP
+    BL      lwp_set_kernel_sp   ; lwp_set_kernel_sp(v1)
+
+    ; set CPU to user-thread mode.
+    MRS     R2, CONTROL
+    ORR     R2, R2, #0x03       ; use PSP, user-thread mode.
+    MSR     CONTROL, R2
+
+    POP     {R0-R3}             ; pop app address to R1.
+    ; set data address.
+    MOV     R9, R2
+
+    ; run app, only Thumb-mode.
+    ORR     R1, R1, #0x01
+    BX      R1
+
+    ; never reach here!
+    ENDP
+
+;/*
+; * void SVC_Handler(void);
+; */
+SVC_Handler    PROC
+    EXPORT SVC_Handler
+
+    PUSH    {LR}
+
+    ; get user SP.
+    TST     LR, #0x4
+    ITE     EQ
+    MRSEQ   R1, MSP
+    MRSNE   R1, PSP
+    PUSH    {R1}           ; push app SP.
+
+    ; get SVC number.
+    mov     R0, R7
+
+    ; get kernel system API
+    BL      lwp_get_sys_api
+    
+    PUSH    {R0}            ; push api
+
+    ; get kernel SP to R0.
+    BL lwp_get_kernel_sp
+
+    POP     {R2}             ; pop api to R2.
+    POP     {R1}             ; pop app SP to R1.
+
+    stmfd     r0!, {r1}      ; save app SP to kernel SP
+
+    ;push app parm5~6 to kernel SP
+    STMFD   R0!,  {R4 - R5}
+    ; copy R1(app SP) to R0(kernel SP).
+    push {r8-r11}
+    LDMFD   R1,   {R4 - R11}     ; pop exception_stack_frame to r4 - r11 register
+    STMFD   R0!,  {R4 - R11}     ; push exception_stack_frame to server SP.
+    pop {r8-r11}
+
+    LDR     R3, =svc_exit
+    STR     R3, [R0, #20]       ; update LR
+    STR     R2, [R0, #24]       ; update api to PC
+    MSR     PSP, R0             ; update SP, API is executed with kernel SP
+
+    ; set to thread-privilege mode.
+    MRS     R3, CONTROL
+    BIC     R3, R3, #0x01
+    ORR     R3, R3, #0x02
+    MSR     CONTROL, R3
+
+    POP     {LR}                ; 0xFFFFFFED
+    ORR     LR, LR, #0x10
+    BX      LR
+
+    ENDP
+
+;/*
+; * void svc_exit(void);
+; */
+svc_exit     PROC
+    EXPORT svc_exit
+
+    ; get user SP.
+    PUSH    {R0}                    ; push result to SP.
+    BL      lwp_get_kernel_sp
+    ldr     r3, [r0, #-4]
+    pop {r0}
+
+    ldr     lr, [r3, #20]
+    ldr     r1, [r3, #24]           ; load pc
+    add     r3, #32                 ; exception_stack_frame size
+    MSR     PSP, R3                 ; restore app stack pointer
+    ; restore to PSP & thread-unprivilege mode.
+    MRS     R2, CONTROL
+    ORR     R2, R2, #0x03
+    MSR     CONTROL, R2
+
+    ; return to lwp.
+    ORR     R1, R1, #0x01           ; only Thumb-mode.
+    BX      R1                      ; return to user app.
+
+    ENDP
+
+    ALIGN
+
+    END

+ 83 - 0
components/lwp/arch/arm/vexpress-a9/lwp_gcc.S

@@ -0,0 +1,83 @@
+/*
+ * File      : lwp_gcc.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ */
+
+#define  Mode_USR       0x10
+#define  Mode_FIQ       0x11
+#define  Mode_IRQ       0x12
+#define  Mode_SVC       0x13
+#define  Mode_MON       0x16
+#define  Mode_ABT       0x17
+#define  Mode_UDF       0x1B
+#define  Mode_SYS       0x1F
+
+#define A_Bit        0x100 
+#define I_Bit        0x80 @; when I bit is set, IRQ is disabled
+#define F_Bit        0x40 @; when F bit is set, FIQ is disabled
+#define T_Bit        0x20
+
+.cpu cortex-a9
+.syntax unified
+.text
+
+/*
+ * void lwp_user_entry(args, text, data);
+ */
+.global lwp_user_entry
+.type lwp_user_entry, % function
+lwp_user_entry:
+    mrs     r9, cpsr
+    bic     r9, #0x1f
+    orr     r9, #Mode_USR
+    cpsid i
+    msr     spsr, r9
+
+    /* set data address. */
+    mov     r9, r2
+    movs    pc, r1
+
+/*
+ * void SVC_Handler(void);
+ */
+.global SVC_Handler
+.type SVC_Handler, % function
+SVC_Handler:
+    push {lr}
+    mrs lr, spsr
+    push {r4, r5, lr}
+    cpsie i
+
+    push {r0 - r3, r12}
+    and r0, r7, #0xff
+    bl lwp_get_sys_api
+    cmp r0, #0           /* r0 = api */
+    mov lr, r0
+    pop {r0 - r3, r12}
+    beq svc_exit
+    blx lr
+
+svc_exit:
+    cpsid i
+    pop {r4, r5, lr}
+    msr spsr_cxsf, lr
+    pop {lr}
+    movs pc, lr

+ 392 - 0
components/lwp/lwp.c

@@ -0,0 +1,392 @@
+/*
+ * File      : clock.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ */
+
+#include <rtthread.h>
+#include <rthw.h>
+#include <dfs_posix.h>
+
+#ifndef RT_USING_DFS
+    #error  "lwp need file system(RT_USING_DFS)"
+#endif
+
+#include "lwp.h"
+
+#define DBG_ENABLE
+#define DBG_SECTION_NAME    "LWP"
+#define DBG_COLOR
+#define DBG_LEVEL           DBG_WARNING
+#include <rtdbg.h>
+
+extern void lwp_user_entry(void *args, const void *text, void *data);
+
+/**
+ * RT-Thread light-weight process
+ */
+void lwp_set_kernel_sp(uint32_t *sp)
+{
+    struct rt_lwp *user_data;
+    user_data = (struct rt_lwp *)rt_thread_self()->lwp;
+    user_data->kernel_sp = sp;
+}
+
+uint32_t *lwp_get_kernel_sp(void)
+{
+    struct rt_lwp *user_data;
+    user_data = (struct rt_lwp *)rt_thread_self()->lwp;
+
+    return user_data->kernel_sp;
+}
+
+static int lwp_argscopy(struct rt_lwp *lwp, int argc, char **argv)
+{
+    int size = sizeof(int)*3; /* store argc, argv, NULL */
+    int *args;
+    char *str;
+    char **new_argv;
+    int i;
+    int len;
+
+    for (i = 0; i < argc; i ++)
+    {
+        size += (rt_strlen(argv[i]) + 1);
+    }
+    size  += (sizeof(int) * argc);
+
+    args = (int*)rt_malloc(size);
+    if (args == RT_NULL)
+        return -1;
+
+    str = (char*)((int)args + (argc + 3) * sizeof(int));
+    new_argv = (char**)&args[2];
+    args[0] = argc;
+    args[1] = (int)new_argv;
+
+    for (i = 0; i < argc; i ++)
+    {
+        len = rt_strlen(argv[i]) + 1;
+        new_argv[i] = str;
+        rt_memcpy(str, argv[i], len);
+        str += len;
+    }
+    new_argv[i] = 0;
+    lwp->args = args;
+
+    return 0;
+}
+
+static int lwp_load(const char *filename, struct rt_lwp *lwp, uint8_t *load_addr, size_t addr_size)
+{
+    int fd;
+    uint8_t *ptr;
+    int result = RT_EOK;
+    int nbytes;
+    struct lwp_header header;
+    struct lwp_chunk  chunk;
+
+    /* check file name */
+    RT_ASSERT(filename != RT_NULL);
+    /* check lwp control block */
+    RT_ASSERT(lwp != RT_NULL);
+
+    if (load_addr != RT_NULL)
+    {
+        lwp->lwp_type = LWP_TYPE_FIX_ADDR;
+        ptr = load_addr;
+    }
+    else
+    {
+        lwp->lwp_type = LWP_TYPE_DYN_ADDR;
+        ptr = RT_NULL;
+    }
+
+    /* open lwp */
+    fd = open(filename, 0, O_RDONLY);
+    if (fd < 0)
+    {
+        dbg_log(DBG_ERROR, "open file:%s failed!\n", filename);
+        result = -RT_ENOSYS;
+        goto _exit;
+    }
+
+    /* read lwp header */
+    nbytes = read(fd, &header, sizeof(struct lwp_header));
+    if (nbytes != sizeof(struct lwp_header))
+    {
+        dbg_log(DBG_ERROR, "read lwp header return error size: %d!\n", nbytes);
+        result = -RT_EIO;
+        goto _exit;
+    }
+
+    /* check file header */
+    if (header.magic != LWP_MAGIC)
+    {
+        dbg_log(DBG_ERROR, "erro header magic number: 0x%02X\n", header.magic);
+        result = -RT_EINVAL;
+        goto _exit;
+    }
+
+    /* read text chunk info */
+    nbytes = read(fd, &chunk, sizeof(struct lwp_chunk));
+    if (nbytes != sizeof(struct lwp_chunk))
+    {
+        dbg_log(DBG_ERROR, "read text chunk info failed!\n");
+        result = -RT_EIO;
+        goto _exit;
+    }
+
+    dbg_log(DBG_LOG, "chunk name: %s, total len %d, data %d, need space %d!\n",
+            "text", /*chunk.name*/ chunk.total_len, chunk.data_len, chunk.data_len_space);
+
+    /* load text */
+    {
+        lwp->text_size = RT_ALIGN(chunk.data_len_space, 4);
+        if (load_addr)
+            lwp->text_entry = ptr;
+        else
+        {
+#ifdef RT_USING_CACHE
+            lwp->text_entry = (rt_uint8_t *)rt_malloc_align(lwp->text_size, RT_CPU_CACHE_LINE_SZ);
+#else
+            lwp->text_entry = (rt_uint8_t *)rt_malloc(lwp->text_size);
+#endif
+
+            if (lwp->text_entry == RT_NULL)
+            {
+                dbg_log(DBG_ERROR, "alloc text memory faild!\n");
+                result = -RT_ENOMEM;
+                goto _exit;
+            }
+            else
+            {
+                dbg_log(DBG_LOG, "lwp text malloc : %p, size: %d!\n", lwp->text_entry, lwp->text_size);
+            }
+        }
+        dbg_log(DBG_INFO, "load text %d  => (0x%08x, 0x%08x)\n", lwp->text_size, (uint32_t)lwp->text_entry, (uint32_t)lwp->text_entry + lwp->text_size);
+
+        nbytes = read(fd, lwp->text_entry, chunk.data_len);
+        if (nbytes != chunk.data_len)
+        {
+            dbg_log(DBG_ERROR, "read text region from file failed!\n");
+            result = -RT_EIO;
+            goto _exit;
+        }
+#ifdef RT_USING_CACHE
+        else
+        {
+            rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, lwp->text_entry, lwp->text_size);
+            rt_hw_cpu_icache_ops(RT_HW_CACHE_INVALIDATE, lwp->text_entry, lwp->text_size);
+        }
+#endif
+
+        if (ptr != RT_NULL) ptr += nbytes;
+
+        /* skip text hole */
+        if ((chunk.total_len - sizeof(struct lwp_chunk) - chunk.data_len))
+        {
+            dbg_log(DBG_LOG, "skip text hole %d!\n", (chunk.total_len - sizeof(struct lwp_chunk) - chunk.data_len));
+            lseek(fd, (chunk.total_len - sizeof(struct lwp_chunk) - chunk.data_len), SEEK_CUR);
+        }
+    }
+
+    /* load data */
+    nbytes = read(fd, &chunk, sizeof(struct lwp_chunk));
+    if (nbytes != sizeof(struct lwp_chunk))
+    {
+        dbg_log(DBG_ERROR, "read data chunk info failed!\n");
+        result = -RT_EIO;
+        goto _exit;
+    }
+
+    dbg_log(DBG_LOG, "chunk name: %s, total len %d, data %d, need space %d!\n",
+            chunk.name, chunk.total_len, chunk.data_len, chunk.data_len_space);
+
+    {
+        lwp->data_size = RT_ALIGN(chunk.data_len_space, 4);
+        if (load_addr)
+            lwp->data = ptr;
+        else
+        {
+            lwp->data = rt_malloc(lwp->data_size);
+            if (lwp->data == RT_NULL)
+            {
+                dbg_log(DBG_ERROR, "alloc data memory faild!\n");
+                result = -RT_ENOMEM;
+                goto _exit;
+            }
+            else
+            {
+                dbg_log(DBG_LOG, "lwp data malloc : %p, size: %d!\n", lwp->data, lwp->data_size);
+                rt_memset(lwp->data, 0, lwp->data_size);
+            }
+        }
+
+        dbg_log(DBG_INFO, "load data %d => (0x%08x, 0x%08x)\n", lwp->data_size, (uint32_t)lwp->data, (uint32_t)lwp->data + lwp->data_size);
+        nbytes = read(fd, lwp->data, chunk.data_len);
+        if (nbytes != chunk.data_len)
+        {
+            dbg_log(DBG_ERROR, "read data region from file failed!\n");
+            result = -RT_ERROR;
+            goto _exit;
+        }
+    }
+
+_exit:
+    if (fd >= 0)
+        close(fd);
+
+    if (result != RT_EOK)
+    {
+        if (lwp->lwp_type == LWP_TYPE_DYN_ADDR)
+        {
+            dbg_log(DBG_ERROR, "lwp dynamic load faild, %d\n", result);
+            if (lwp->text_entry)
+            {
+                dbg_log(DBG_LOG, "lwp text free: %p\n", lwp->text_entry);
+#ifdef RT_USING_CACHE
+                rt_free_align(lwp->text_entry);
+#else
+                rt_free(lwp->text_entry);
+#endif
+            }
+            if (lwp->data)
+            {
+                dbg_log(DBG_LOG, "lwp data free: %p\n", lwp->data);
+                rt_free(lwp->data);
+            }
+        }
+    }
+
+    return result;
+}
+
+static void lwp_cleanup(struct rt_thread *tid)
+{
+    struct rt_lwp *lwp;
+
+    dbg_log(DBG_INFO, "thread: %s, stack_addr: %08X\n", tid->name, tid->stack_addr);
+
+    lwp = (struct rt_lwp *)tid->lwp;
+
+    if (lwp->lwp_type == LWP_TYPE_DYN_ADDR)
+    {
+        dbg_log(DBG_INFO, "dynamic lwp\n");
+        if (lwp->text_entry)
+        {
+            dbg_log(DBG_LOG, "lwp text free: %p\n", lwp->text_entry);
+#ifdef RT_USING_CACHE
+            rt_free_align(lwp->text_entry);
+#else
+            rt_free(lwp->text_entry);
+#endif
+        }
+        if (lwp->data)
+        {
+            dbg_log(DBG_LOG, "lwp data free: %p\n", lwp->data);
+            rt_free(lwp->data);
+        }
+    }
+
+    dbg_log(DBG_LOG, "lwp free memory pages\n");
+    rt_lwp_mem_deinit(lwp);
+
+    /* cleanup fd table */
+    rt_free(lwp->fdt.fds);
+    rt_free(lwp->args);
+
+    dbg_log(DBG_LOG, "lwp free: %p\n", lwp);
+    rt_free(lwp);
+
+    /* TODO: cleanup fd table */
+}
+
+static void lwp_thread(void *parameter)
+{
+    rt_thread_t tid;
+    struct rt_lwp *lwp;
+
+    lwp = (struct rt_lwp *)parameter;
+    rt_lwp_mem_init(lwp);
+    tid = rt_thread_self();
+    tid->lwp = lwp;
+    tid->cleanup = lwp_cleanup;
+
+    lwp_user_entry(lwp->args, lwp->text_entry, lwp->data);
+}
+
+struct rt_lwp *rt_lwp_self(void)
+{
+    return (struct rt_lwp *)rt_thread_self()->lwp;
+}
+
+int exec(char *filename, int argc, char **argv)
+{
+    struct rt_lwp *lwp;
+    int result;
+
+    if (filename == RT_NULL)
+        return -RT_ERROR;
+
+    lwp = (struct rt_lwp *)rt_malloc(sizeof(struct rt_lwp));
+    if (lwp == RT_NULL)
+    {
+        dbg_log(DBG_ERROR, "lwp struct out of memory!\n");
+        return -RT_ENOMEM;
+    }
+    dbg_log(DBG_INFO, "lwp malloc : %p, size: %d!\n", lwp, sizeof(struct rt_lwp));
+
+    rt_memset(lwp, 0, sizeof(*lwp));
+    if (lwp_argscopy(lwp, argc, argv) != 0)
+    {
+        rt_free(lwp);
+        return -ENOMEM;
+    }
+
+    result = lwp_load(filename, lwp, RT_NULL, 0);
+    if (result == RT_EOK)
+    {
+        rt_thread_t tid;
+
+        tid = rt_thread_create("user", lwp_thread, (void *)lwp,
+                               1024 * 4, 2, 200);
+        if (tid != RT_NULL)
+        {
+            dbg_log(DBG_LOG, "lwp kernel => (0x%08x, 0x%08x)\n", (rt_uint32_t)tid->stack_addr, (rt_uint32_t)tid->stack_addr + tid->stack_size);
+            rt_thread_startup(tid);
+            return RT_EOK;
+        }
+        else
+        {
+#ifdef RT_USING_CACHE
+            rt_free_align(lwp->text_entry);
+#else
+            rt_free(lwp->text_entry);
+#endif
+            rt_free(lwp->data);
+        }
+    }
+
+    rt_free(lwp->args);
+    rt_free(lwp);
+
+    return -RT_ERROR;
+}

+ 84 - 0
components/lwp/lwp.h

@@ -0,0 +1,84 @@
+/*
+ * File      : lwp.h
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ */
+
+#ifndef __LWP_H__
+#define __LWP_H__
+
+#define LWP_MAGIC           0x5A
+
+#define LWP_TYPE_FIX_ADDR   0x01
+#define LWP_TYPE_DYN_ADDR   0x02
+
+#define LWP_ARG_MAX         8
+
+#include <stdint.h>
+#include <rtthread.h>
+#include <dfs.h>
+#include <lwp_memheap.h>
+
+struct rt_lwp
+{
+    uint8_t lwp_type;
+    uint8_t heap_cnt;
+    uint8_t reserv[2];
+
+    rt_list_t hlist;                                    /**< headp list */
+
+    uint8_t *text_entry;
+    uint32_t text_size;
+
+    uint8_t *data;
+    uint32_t data_size;
+
+    uint32_t *kernel_sp;                                /**< kernel stack point */
+    struct dfs_fdtable fdt;
+    void *args;
+};
+
+struct lwp_header
+{
+    uint8_t magic;
+    uint8_t compress_encrypt_algo;
+    uint16_t reserved;
+
+    uint32_t crc32;
+};
+
+struct lwp_chunk
+{
+    uint32_t total_len;
+
+    char name[4];
+    uint32_t data_len;
+    uint32_t data_len_space;
+};
+
+extern struct rt_lwp *rt_lwp_self(void);
+
+extern void rt_lwp_mem_init(struct rt_lwp *lwp);
+extern void rt_lwp_mem_deinit(struct rt_lwp *lwp);
+extern void *rt_lwp_mem_malloc(rt_uint32_t size);
+extern void rt_lwp_mem_free(void *addr);
+extern void *rt_lwp_mem_realloc(void *rmem, rt_size_t newsize);
+
+#endif

+ 236 - 0
components/lwp/lwp_mem.c

@@ -0,0 +1,236 @@
+/*
+ * File      : lwp_mem.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2012, RT-Thread Development Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2018-03-24     Tanek        the first version
+ */
+
+#include <rtthread.h>
+#include <lwp.h>
+
+#define DBG_ENABLE
+#define DBG_SECTION_NAME    "LWPMEM"
+#define DBG_COLOR
+#define DBG_LEVEL           DBG_WARNING
+#include <rtdbg.h>
+
+// todo: remove repleat code
+#define RT_MEMHEAP_SIZE         RT_ALIGN(sizeof(struct rt_lwp_memheap_item), RT_ALIGN_SIZE)
+#define MEMITEM_SIZE(item)      ((rt_uint32_t)item->next - (rt_uint32_t)item - RT_MEMHEAP_SIZE)
+
+#ifndef LWP_MEM_PAGE_SIZE
+    #define LWP_MEM_PAGE_SIZE       (4 * 1024)
+#endif
+
+#ifndef LWP_MEM_MAX_PAGE_COUNT
+    #define LWP_MEM_MAX_PAGE_COUNT  (256 * 4)
+#endif
+
+static void *rt_lwp_malloc_page(struct rt_lwp *lwp, rt_size_t npages)
+{
+    void *chunk;
+    char name[6];
+    struct rt_lwp_memheap *lwp_heap;
+    rt_size_t page_cnt;
+
+    RT_ASSERT(lwp != RT_NULL);
+
+    page_cnt = lwp->heap_cnt + npages;
+    if (page_cnt > LWP_MEM_MAX_PAGE_COUNT)
+    {
+        dbg_log(DBG_ERROR, "alloc new page failed, lwp memory size out of limited: %d\n", page_cnt);
+        return RT_NULL;
+    }
+
+    lwp_heap = rt_malloc(sizeof(struct rt_lwp_memheap));
+    if (lwp_heap == RT_NULL)
+    {
+        dbg_log(DBG_ERROR, "alloc new page head failed, out of memory : %d\n", page_cnt);
+        return RT_NULL;
+    }
+
+    chunk = rt_malloc(npages * LWP_MEM_PAGE_SIZE);
+    if (chunk == RT_NULL)
+    {
+        dbg_log(DBG_ERROR, "alloc new page buffer failed, out of memory : %d\n", page_cnt);
+        rt_free(lwp_heap);
+        return RT_NULL;
+    }
+
+    dbg_log(DBG_LOG, "lwp alloc page: %d\n", npages);
+
+    rt_sprintf(name, "lwp%02x", lwp->heap_cnt);
+    rt_lwp_memheap_init(lwp_heap, name, chunk, npages * LWP_MEM_PAGE_SIZE);
+
+    rt_list_insert_before(&lwp->hlist, &lwp_heap->mlist);
+
+    lwp->heap_cnt += npages;
+
+    return chunk;
+}
+
+static void rt_lwp_free_page(struct rt_lwp *lwp, struct rt_lwp_memheap *lwp_heap)
+{
+    rt_size_t npages;
+
+    RT_ASSERT(lwp != RT_NULL);
+    RT_ASSERT(lwp_heap != RT_NULL);
+    RT_ASSERT(lwp_heap->start_addr != RT_NULL);
+
+    npages = lwp_heap->pool_size / LWP_MEM_PAGE_SIZE;
+    lwp->heap_cnt -= npages;
+
+    dbg_log(DBG_LOG, "lwp free page: %d\n", npages);
+
+    rt_list_remove(&lwp_heap->mlist);
+
+    rt_free(lwp_heap->start_addr);
+    rt_free(lwp_heap);
+}
+
+void rt_lwp_mem_init(struct rt_lwp *lwp)
+{
+    RT_ASSERT(lwp != RT_NULL);
+    rt_list_init(&lwp->hlist);
+}
+
+void rt_lwp_mem_deinit(struct rt_lwp *lwp)
+{
+    struct rt_list_node *node;
+    
+    RT_ASSERT(lwp != RT_NULL);
+
+    node = lwp->hlist.next;
+
+    while (node != &(lwp->hlist))
+    {
+        struct rt_lwp_memheap *lwp_heap;
+
+        lwp_heap = rt_list_entry(node, struct rt_lwp_memheap, mlist);
+        RT_ASSERT(lwp_heap != RT_NULL);
+
+        /* update note before free page*/
+        node = node->next;
+
+        rt_lwp_free_page(lwp, lwp_heap);
+    }
+}
+
+void *rt_lwp_mem_malloc(rt_uint32_t size)
+{
+    struct rt_lwp *lwp;
+    struct rt_list_node *node;
+    void *addr = RT_NULL;
+    rt_uint32_t npages;
+
+    if (size == 0)
+        return RT_NULL;
+
+    lwp = rt_lwp_self();
+    RT_ASSERT(lwp != RT_NULL);
+
+    for (node  = lwp->hlist.next; node != &(lwp->hlist); node = node->next)
+    {
+        struct rt_lwp_memheap *lwp_heap;
+        lwp_heap = rt_list_entry(node, struct rt_lwp_memheap, mlist);
+
+        addr = rt_lwp_memheap_alloc(lwp_heap, size);
+        if (addr != RT_NULL)
+        {
+            dbg_log(DBG_LOG, "lwp alloc 0x%x/%d\n", addr, size);
+            return addr;
+        }
+    }
+
+    npages = (size + rt_lwp_memheap_unavailable_size_get() + LWP_MEM_PAGE_SIZE) / LWP_MEM_PAGE_SIZE;
+    if (RT_NULL != rt_lwp_malloc_page(lwp, npages))
+        return rt_lwp_mem_malloc(size);
+    else
+        return RT_NULL;
+}
+
+void rt_lwp_mem_free(void *addr)
+{
+    struct rt_lwp_memheap_item *header_ptr;
+    struct rt_lwp_memheap *lwp_heap;
+
+    if (addr == RT_NULL)
+        return ;
+
+    /* get memory item */
+    header_ptr = (struct rt_lwp_memheap_item *)((rt_uint8_t *)addr - RT_MEMHEAP_SIZE);
+    RT_ASSERT(header_ptr);
+    
+    lwp_heap = header_ptr->pool_ptr;
+    RT_ASSERT(lwp_heap);
+
+    dbg_log(DBG_LOG, "lwp free 0x%x\n", addr);
+    rt_lwp_memheap_free((void *)addr);
+
+    if (rt_lwp_memheap_is_empty(lwp_heap))
+    {
+        rt_lwp_free_page(rt_lwp_self(), lwp_heap);
+    }
+}
+
+void *rt_lwp_mem_realloc(void *rmem, rt_size_t newsize)
+{
+    void *new_ptr;
+    struct rt_lwp_memheap_item *header_ptr;
+
+    if (rmem == RT_NULL)
+        return rt_lwp_mem_malloc(newsize);
+
+    if (newsize == 0)
+    {
+        rt_lwp_mem_free(rmem);
+        return RT_NULL;
+    }
+
+    /* get old memory item */
+    header_ptr = (struct rt_lwp_memheap_item *)
+                 ((rt_uint8_t *)rmem - RT_MEMHEAP_SIZE);
+
+    new_ptr = rt_lwp_memheap_realloc(header_ptr->pool_ptr, rmem, newsize);
+    if (new_ptr == RT_NULL)
+    {
+        /* allocate memory block from other memheap */
+        new_ptr = rt_lwp_mem_malloc(newsize);
+        if (new_ptr != RT_NULL && rmem != RT_NULL)
+        {
+            rt_size_t oldsize;
+
+            /* get the size of old memory block */
+            oldsize = MEMITEM_SIZE(header_ptr);
+            if (newsize > oldsize)
+                rt_memcpy(new_ptr, rmem, oldsize);
+            else
+                rt_memcpy(new_ptr, rmem, newsize);
+
+            dbg_log(DBG_LOG, "lwp realloc with memcpy 0x%x -> 0x%x/%d\n", rmem, new_ptr, newsize);
+            rt_lwp_mem_free(rmem);
+
+        }
+    }
+
+    dbg_log(DBG_LOG, "lwp realloc in same address 0x%x/%d\n", rmem, newsize);
+
+    return new_ptr;
+}

+ 34 - 0
components/lwp/lwp_mem.h

@@ -0,0 +1,34 @@
+/*
+ * File      : lwp_mem.h
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ */
+
+#ifndef __LWP_MEM_H__
+#define __LWP_MEM_H__
+
+extern void rt_lwp_mem_init(struct rt_lwp *lwp);
+extern void rt_lwp_mem_deinit(struct rt_lwp *lwp);
+
+extern void *rt_lwp_mem_malloc(rt_uint32_t size);
+extern void rt_lwp_mem_free(void *addr);
+extern void *rt_lwp_mem_realloc(void *rmem, rt_size_t newsize);
+
+#endif

+ 590 - 0
components/lwp/lwp_memheap.c

@@ -0,0 +1,590 @@
+/*
+ * File      : lwp_memheap.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2012, RT-Thread Development Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2012-04-10     Bernard      first implementation
+ * 2012-10-16     Bernard      add the mutex lock for heap object.
+ * 2012-12-29     Bernard      memheap can be used as system heap.
+ *                             change mutex lock to semaphore lock.
+ * 2013-04-10     Bernard      add rt_lwp_memheap_realloc function.
+ * 2013-05-24     Bernard      fix the rt_lwp_memheap_realloc issue.
+ * 2013-07-11     Grissiom     fix the memory block splitting issue.
+ * 2013-07-15     Grissiom     optimize rt_lwp_memheap_realloc
+ */
+
+#include <rthw.h>
+#include <rtthread.h>
+#include <lwp.h>
+
+/* dynamic pool magic and mask */
+#define RT_MEMHEAP_MAGIC        0x1ea01ea0
+#define RT_MEMHEAP_MASK         0xfffffffe
+#define RT_MEMHEAP_USED         0x01
+#define RT_MEMHEAP_FREED        0x00
+
+#define RT_MEMHEAP_IS_USED(i)   ((i)->magic & RT_MEMHEAP_USED)
+#define RT_MEMHEAP_MINIALLOC    12
+
+#define RT_MEMHEAP_SIZE         RT_ALIGN(sizeof(struct rt_lwp_memheap_item), RT_ALIGN_SIZE)
+#define MEMITEM_SIZE(item)      ((rt_uint32_t)item->next - (rt_uint32_t)item - RT_MEMHEAP_SIZE)
+
+/*
+ * The initialized memory pool will be:
+ * +-----------------------------------+--------------------------+
+ * | whole freed memory block          | Used Memory Block Tailer |
+ * +-----------------------------------+--------------------------+
+ *
+ * block_list --> whole freed memory block
+ *
+ * The length of Used Memory Block Tailer is 0,
+ * which is prevents block merging across list
+ */
+rt_err_t rt_lwp_memheap_init(struct rt_lwp_memheap *memheap,
+                         const char        *name,
+                         void              *start_addr,
+                         rt_uint32_t        size)
+{
+    struct rt_lwp_memheap_item *item;
+
+    RT_ASSERT(memheap != RT_NULL);
+
+    /* initialize pool object */
+    memheap->start_addr     = start_addr;
+    memheap->pool_size      = RT_ALIGN_DOWN(size, RT_ALIGN_SIZE);
+    memheap->available_size = memheap->pool_size - (2 * RT_MEMHEAP_SIZE);
+    memheap->max_used_size  = memheap->pool_size - memheap->available_size;
+
+    /* initialize the free list header */
+    item            = &(memheap->free_header);
+    item->magic     = RT_MEMHEAP_MAGIC;
+    item->pool_ptr  = memheap;
+    item->next      = RT_NULL;
+    item->prev      = RT_NULL;
+    item->next_free = item;
+    item->prev_free = item;
+
+    /* set the free list to free list header */
+    memheap->free_list = item;
+
+    /* initialize the first big memory block */
+    item            = (struct rt_lwp_memheap_item *)start_addr;
+    item->magic     = RT_MEMHEAP_MAGIC;
+    item->pool_ptr  = memheap;
+    item->next      = RT_NULL;
+    item->prev      = RT_NULL;
+    item->next_free = item;
+    item->prev_free = item;
+
+    item->next = (struct rt_lwp_memheap_item *)
+                 ((rt_uint8_t *)item + memheap->available_size + RT_MEMHEAP_SIZE);
+    item->prev = item->next;
+
+    /* block list header */
+    memheap->block_list = item;
+
+    /* place the big memory block to free list */
+    item->next_free = memheap->free_list->next_free;
+    item->prev_free = memheap->free_list;
+    memheap->free_list->next_free->prev_free = item;
+    memheap->free_list->next_free            = item;
+
+    /* move to the end of memory pool to build a small tailer block,
+     * which prevents block merging
+     */
+    item = item->next;
+    /* it's a used memory block */
+    item->magic     = RT_MEMHEAP_MAGIC | RT_MEMHEAP_USED;
+    item->pool_ptr  = memheap;
+    item->next      = (struct rt_lwp_memheap_item *)start_addr;
+    item->prev      = (struct rt_lwp_memheap_item *)start_addr;
+    /* not in free list */
+    item->next_free = item->prev_free = RT_NULL;
+
+    /* initialize semaphore lock */
+    rt_sem_init(&(memheap->lock), name, 1, RT_IPC_FLAG_FIFO);
+
+    RT_DEBUG_LOG(RT_DEBUG_MEMHEAP,
+                 ("memory heap: start addr 0x%08x, size %d, free list header 0x%08x\n",
+                  start_addr, size, &(memheap->free_header)));
+
+    return RT_EOK;
+}
+
+void *rt_lwp_memheap_alloc(struct rt_lwp_memheap *heap, rt_uint32_t size)
+{
+    rt_err_t result;
+    rt_uint32_t free_size;
+    struct rt_lwp_memheap_item *header_ptr;
+
+    RT_ASSERT(heap != RT_NULL);
+
+    /* align allocated size */
+    size = RT_ALIGN(size, RT_ALIGN_SIZE);
+    if (size < RT_MEMHEAP_MINIALLOC)
+        size = RT_MEMHEAP_MINIALLOC;
+
+    RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, ("allocate %d on heap:%8.*s",
+                                    size, RT_NAME_MAX, heap->parent.name));
+
+    if (size < heap->available_size)
+    {
+        /* search on free list */
+        free_size = 0;
+
+        /* lock memheap */
+        result = rt_sem_take(&(heap->lock), RT_WAITING_FOREVER);
+        if (result != RT_EOK)
+        {
+            rt_set_errno(result);
+
+            return RT_NULL;
+        }
+
+        /* get the first free memory block */
+        header_ptr = heap->free_list->next_free;
+        while (header_ptr != heap->free_list && free_size < size)
+        {
+            /* get current freed memory block size */
+            free_size = MEMITEM_SIZE(header_ptr);
+            if (free_size < size)
+            {
+                /* move to next free memory block */
+                header_ptr = header_ptr->next_free;
+            }
+        }
+
+        /* determine if the memory is available. */
+        if (free_size >= size)
+        {
+            /* a block that satisfies the request has been found. */
+
+            /* determine if the block needs to be split. */
+            if (free_size >= (size + RT_MEMHEAP_SIZE + RT_MEMHEAP_MINIALLOC))
+            {
+                struct rt_lwp_memheap_item *new_ptr;
+
+                /* split the block. */
+                new_ptr = (struct rt_lwp_memheap_item *)
+                          (((rt_uint8_t *)header_ptr) + size + RT_MEMHEAP_SIZE);
+
+                RT_DEBUG_LOG(RT_DEBUG_MEMHEAP,
+                             ("split: block[0x%08x] nextm[0x%08x] prevm[0x%08x] to new[0x%08x]\n",
+                              header_ptr,
+                              header_ptr->next,
+                              header_ptr->prev,
+                              new_ptr));
+
+                /* mark the new block as a memory block and freed. */
+                new_ptr->magic = RT_MEMHEAP_MAGIC;
+
+                /* put the pool pointer into the new block. */
+                new_ptr->pool_ptr = heap;
+
+                /* break down the block list */
+                new_ptr->prev          = header_ptr;
+                new_ptr->next          = header_ptr->next;
+                header_ptr->next->prev = new_ptr;
+                header_ptr->next       = new_ptr;
+
+                /* remove header ptr from free list */
+                header_ptr->next_free->prev_free = header_ptr->prev_free;
+                header_ptr->prev_free->next_free = header_ptr->next_free;
+                header_ptr->next_free = RT_NULL;
+                header_ptr->prev_free = RT_NULL;
+
+                /* insert new_ptr to free list */
+                new_ptr->next_free = heap->free_list->next_free;
+                new_ptr->prev_free = heap->free_list;
+                heap->free_list->next_free->prev_free = new_ptr;
+                heap->free_list->next_free            = new_ptr;
+                RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, ("new ptr: next_free 0x%08x, prev_free 0x%08x\n",
+                                                new_ptr->next_free,
+                                                new_ptr->prev_free));
+
+                /* decrement the available byte count.  */
+                heap->available_size = heap->available_size -
+                                       size -
+                                       RT_MEMHEAP_SIZE;
+                if (heap->pool_size - heap->available_size > heap->max_used_size)
+                    heap->max_used_size = heap->pool_size - heap->available_size;
+            }
+            else
+            {
+                /* decrement the entire free size from the available bytes count. */
+                heap->available_size = heap->available_size - free_size;
+                if (heap->pool_size - heap->available_size > heap->max_used_size)
+                    heap->max_used_size = heap->pool_size - heap->available_size;
+
+                /* remove header_ptr from free list */
+                RT_DEBUG_LOG(RT_DEBUG_MEMHEAP,
+                             ("one block: block[0x%08x], next_free 0x%08x, prev_free 0x%08x\n",
+                              header_ptr,
+                              header_ptr->next_free,
+                              header_ptr->prev_free));
+
+                header_ptr->next_free->prev_free = header_ptr->prev_free;
+                header_ptr->prev_free->next_free = header_ptr->next_free;
+                header_ptr->next_free = RT_NULL;
+                header_ptr->prev_free = RT_NULL;
+            }
+
+            /* Mark the allocated block as not available. */
+            header_ptr->magic |= RT_MEMHEAP_USED;
+
+            /* release lock */
+            rt_sem_release(&(heap->lock));
+
+            /* Return a memory address to the caller.  */
+            RT_DEBUG_LOG(RT_DEBUG_MEMHEAP,
+                         ("alloc mem: memory[0x%08x], heap[0x%08x], size: %d\n",
+                          (void *)((rt_uint8_t *)header_ptr + RT_MEMHEAP_SIZE),
+                          header_ptr,
+                          size));
+
+            return (void *)((rt_uint8_t *)header_ptr + RT_MEMHEAP_SIZE);
+        }
+
+        /* release lock */
+        rt_sem_release(&(heap->lock));
+    }
+
+    RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, ("allocate memory: failed\n"));
+
+    /* Return the completion status.  */
+    return RT_NULL;
+}
+
+void *rt_lwp_memheap_realloc(struct rt_lwp_memheap *heap, void *ptr, rt_size_t newsize)
+{
+    rt_err_t result;
+    rt_size_t oldsize;
+    struct rt_lwp_memheap_item *header_ptr;
+    struct rt_lwp_memheap_item *new_ptr;
+
+    if (newsize == 0)
+    {
+        rt_lwp_memheap_free(ptr);
+
+        return RT_NULL;
+    }
+    /* align allocated size */
+    newsize = RT_ALIGN(newsize, RT_ALIGN_SIZE);
+    if (newsize < RT_MEMHEAP_MINIALLOC)
+        newsize = RT_MEMHEAP_MINIALLOC;
+
+    if (ptr == RT_NULL)
+    {
+        return rt_lwp_memheap_alloc(heap, newsize);
+    }
+
+    /* get memory block header and get the size of memory block */
+    header_ptr = (struct rt_lwp_memheap_item *)
+                 ((rt_uint8_t *)ptr - RT_MEMHEAP_SIZE);
+    oldsize = MEMITEM_SIZE(header_ptr);
+    /* re-allocate memory */
+    if (newsize > oldsize)
+    {
+        void *new_ptr;
+        struct rt_lwp_memheap_item *next_ptr;
+
+        /* lock memheap */
+        result = rt_sem_take(&(heap->lock), RT_WAITING_FOREVER);
+        if (result != RT_EOK)
+        {
+            rt_set_errno(result);
+            return RT_NULL;
+        }
+
+        next_ptr = header_ptr->next;
+
+        /* header_ptr should not be the tail */
+        RT_ASSERT(next_ptr > header_ptr);
+
+        /* check whether the following free space is enough to expand */
+        if (!RT_MEMHEAP_IS_USED(next_ptr))
+        {
+            rt_int32_t nextsize;
+
+            nextsize = MEMITEM_SIZE(next_ptr);
+            RT_ASSERT(next_ptr > 0);
+
+            /* Here is the ASCII art of the situation that we can make use of
+             * the next free node without alloc/memcpy, |*| is the control
+             * block:
+             *
+             *      oldsize           free node
+             * |*|-----------|*|----------------------|*|
+             *         newsize          >= minialloc
+             * |*|----------------|*|-----------------|*|
+             */
+            if (nextsize + oldsize > newsize + RT_MEMHEAP_MINIALLOC)
+            {
+                /* decrement the entire free size from the available bytes count. */
+                heap->available_size = heap->available_size - (newsize - oldsize);
+                if (heap->pool_size - heap->available_size > heap->max_used_size)
+                    heap->max_used_size = heap->pool_size - heap->available_size;
+
+                /* remove next_ptr from free list */
+                RT_DEBUG_LOG(RT_DEBUG_MEMHEAP,
+                             ("remove block: block[0x%08x], next_free 0x%08x, prev_free 0x%08x",
+                              next_ptr,
+                              next_ptr->next_free,
+                              next_ptr->prev_free));
+
+                next_ptr->next_free->prev_free = next_ptr->prev_free;
+                next_ptr->prev_free->next_free = next_ptr->next_free;
+                next_ptr->next->prev = next_ptr->prev;
+                next_ptr->prev->next = next_ptr->next;
+
+                /* build a new one on the right place */
+                next_ptr = (struct rt_lwp_memheap_item *)((char *)ptr + newsize);
+
+                RT_DEBUG_LOG(RT_DEBUG_MEMHEAP,
+                             ("new free block: block[0x%08x] nextm[0x%08x] prevm[0x%08x]",
+                              next_ptr,
+                              next_ptr->next,
+                              next_ptr->prev));
+
+                /* mark the new block as a memory block and freed. */
+                next_ptr->magic = RT_MEMHEAP_MAGIC;
+
+                /* put the pool pointer into the new block. */
+                next_ptr->pool_ptr = heap;
+
+                next_ptr->prev          = header_ptr;
+                next_ptr->next          = header_ptr->next;
+                header_ptr->next->prev = next_ptr;
+                header_ptr->next       = next_ptr;
+
+                /* insert next_ptr to free list */
+                next_ptr->next_free = heap->free_list->next_free;
+                next_ptr->prev_free = heap->free_list;
+                heap->free_list->next_free->prev_free = next_ptr;
+                heap->free_list->next_free            = next_ptr;
+                RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, ("new ptr: next_free 0x%08x, prev_free 0x%08x",
+                                                next_ptr->next_free,
+                                                next_ptr->prev_free));
+
+                /* release lock */
+                rt_sem_release(&(heap->lock));
+
+                return ptr;
+            }
+        }
+
+        /* release lock */
+        rt_sem_release(&(heap->lock));
+
+        /* re-allocate a memory block */
+        new_ptr = (void *)rt_lwp_memheap_alloc(heap, newsize);
+        if (new_ptr != RT_NULL)
+        {
+            rt_memcpy(new_ptr, ptr, oldsize < newsize ? oldsize : newsize);
+            rt_lwp_memheap_free(ptr);
+        }
+
+        return new_ptr;
+    }
+
+    /* don't split when there is less than one node space left */
+    if (newsize + RT_MEMHEAP_SIZE + RT_MEMHEAP_MINIALLOC >= oldsize)
+        return ptr;
+
+    /* lock memheap */
+    result = rt_sem_take(&(heap->lock), RT_WAITING_FOREVER);
+    if (result != RT_EOK)
+    {
+        rt_set_errno(result);
+
+        return RT_NULL;
+    }
+
+    /* split the block. */
+    new_ptr = (struct rt_lwp_memheap_item *)
+              (((rt_uint8_t *)header_ptr) + newsize + RT_MEMHEAP_SIZE);
+
+    RT_DEBUG_LOG(RT_DEBUG_MEMHEAP,
+                 ("split: block[0x%08x] nextm[0x%08x] prevm[0x%08x] to new[0x%08x]\n",
+                  header_ptr,
+                  header_ptr->next,
+                  header_ptr->prev,
+                  new_ptr));
+
+    /* mark the new block as a memory block and freed. */
+    new_ptr->magic = RT_MEMHEAP_MAGIC;
+    /* put the pool pointer into the new block. */
+    new_ptr->pool_ptr = heap;
+
+    /* break down the block list */
+    new_ptr->prev          = header_ptr;
+    new_ptr->next          = header_ptr->next;
+    header_ptr->next->prev = new_ptr;
+    header_ptr->next       = new_ptr;
+
+    /* determine if the block can be merged with the next neighbor. */
+    if (!RT_MEMHEAP_IS_USED(new_ptr->next))
+    {
+        struct rt_lwp_memheap_item *free_ptr;
+
+        /* merge block with next neighbor. */
+        free_ptr = new_ptr->next;
+        heap->available_size = heap->available_size - MEMITEM_SIZE(free_ptr);
+
+        RT_DEBUG_LOG(RT_DEBUG_MEMHEAP,
+                     ("merge: right node 0x%08x, next_free 0x%08x, prev_free 0x%08x\n",
+                      header_ptr, header_ptr->next_free, header_ptr->prev_free));
+
+        free_ptr->next->prev = new_ptr;
+        new_ptr->next   = free_ptr->next;
+
+        /* remove free ptr from free list */
+        free_ptr->next_free->prev_free = free_ptr->prev_free;
+        free_ptr->prev_free->next_free = free_ptr->next_free;
+    }
+
+    /* insert the split block to free list */
+    new_ptr->next_free = heap->free_list->next_free;
+    new_ptr->prev_free = heap->free_list;
+    heap->free_list->next_free->prev_free = new_ptr;
+    heap->free_list->next_free            = new_ptr;
+    RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, ("new free ptr: next_free 0x%08x, prev_free 0x%08x\n",
+                                    new_ptr->next_free,
+                                    new_ptr->prev_free));
+
+    /* increment the available byte count.  */
+    heap->available_size = heap->available_size + MEMITEM_SIZE(new_ptr);
+
+    /* release lock */
+    rt_sem_release(&(heap->lock));
+
+    /* return the old memory block */
+    return ptr;
+}
+
+void rt_lwp_memheap_free(void *ptr)
+{
+    rt_err_t result;
+    struct rt_lwp_memheap *heap;
+    struct rt_lwp_memheap_item *header_ptr, *new_ptr;
+    rt_uint32_t insert_header;
+
+    /* NULL check */
+    if (ptr == RT_NULL) return;
+
+    /* set initial status as OK */
+    insert_header = 1;
+    new_ptr       = RT_NULL;
+    header_ptr    = (struct rt_lwp_memheap_item *)
+                    ((rt_uint8_t *)ptr - RT_MEMHEAP_SIZE);
+
+    RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, ("free memory: memory[0x%08x], block[0x%08x]\n",
+                                    ptr, header_ptr));
+
+    /* check magic */
+    RT_ASSERT((header_ptr->magic & RT_MEMHEAP_MASK) == RT_MEMHEAP_MAGIC);
+    RT_ASSERT(header_ptr->magic & RT_MEMHEAP_USED);
+    /* check whether this block of memory has been over-written. */
+    RT_ASSERT((header_ptr->next->magic & RT_MEMHEAP_MASK) == RT_MEMHEAP_MAGIC);
+
+    /* get pool ptr */
+    heap = header_ptr->pool_ptr;
+
+    /* lock memheap */
+    result = rt_sem_take(&(heap->lock), RT_WAITING_FOREVER);
+    if (result != RT_EOK)
+    {
+        rt_set_errno(result);
+
+        return ;
+    }
+
+    /* Mark the memory as available. */
+    header_ptr->magic &= ~RT_MEMHEAP_USED;
+    /* Adjust the available number of bytes. */
+    heap->available_size = heap->available_size + MEMITEM_SIZE(header_ptr);
+
+    /* Determine if the block can be merged with the previous neighbor. */
+    if (!RT_MEMHEAP_IS_USED(header_ptr->prev))
+    {
+        RT_DEBUG_LOG(RT_DEBUG_MEMHEAP, ("merge: left node 0x%08x\n",
+                                        header_ptr->prev));
+
+        /* adjust the available number of bytes. */
+        heap->available_size = heap->available_size + RT_MEMHEAP_SIZE;
+
+        /* yes, merge block with previous neighbor. */
+        (header_ptr->prev)->next = header_ptr->next;
+        (header_ptr->next)->prev = header_ptr->prev;
+
+        /* move header pointer to previous. */
+        header_ptr = header_ptr->prev;
+        /* don't insert header to free list */
+        insert_header = 0;
+    }
+
+    /* determine if the block can be merged with the next neighbor. */
+    if (!RT_MEMHEAP_IS_USED(header_ptr->next))
+    {
+        /* adjust the available number of bytes. */
+        heap->available_size = heap->available_size + RT_MEMHEAP_SIZE;
+
+        /* merge block with next neighbor. */
+        new_ptr = header_ptr->next;
+
+        RT_DEBUG_LOG(RT_DEBUG_MEMHEAP,
+                     ("merge: right node 0x%08x, next_free 0x%08x, prev_free 0x%08x\n",
+                      new_ptr, new_ptr->next_free, new_ptr->prev_free));
+
+        new_ptr->next->prev = header_ptr;
+        header_ptr->next    = new_ptr->next;
+
+        /* remove new ptr from free list */
+        new_ptr->next_free->prev_free = new_ptr->prev_free;
+        new_ptr->prev_free->next_free = new_ptr->next_free;
+    }
+
+    if (insert_header)
+    {
+        /* no left merge, insert to free list */
+        header_ptr->next_free = heap->free_list->next_free;
+        header_ptr->prev_free = heap->free_list;
+        heap->free_list->next_free->prev_free = header_ptr;
+        heap->free_list->next_free            = header_ptr;
+
+        RT_DEBUG_LOG(RT_DEBUG_MEMHEAP,
+                     ("insert to free list: next_free 0x%08x, prev_free 0x%08x\n",
+                      header_ptr->next_free, header_ptr->prev_free));
+    }
+
+    /* release lock */
+    rt_sem_release(&(heap->lock));
+}
+
+rt_bool_t rt_lwp_memheap_is_empty(struct rt_lwp_memheap *memheap)
+{
+    RT_ASSERT(memheap != RT_NULL);
+
+    return (memheap->available_size + 2 * sizeof(struct rt_lwp_memheap_item)) == memheap->pool_size;
+}
+
+rt_bool_t rt_lwp_memheap_unavailable_size_get(void)
+{
+    return 2 * RT_MEMHEAP_SIZE + 3;
+}

+ 74 - 0
components/lwp/lwp_memheap.h

@@ -0,0 +1,74 @@
+/*
+ * File      : lwp_memheap.h
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ */
+
+#ifndef __LWP_MEMHEAP_H__
+#define __LWP_MEMHEAP_H__
+
+#include <stdint.h>
+#include <rtthread.h>
+
+/**
+ * memory item on the heap
+ */
+struct rt_lwp_memheap_item
+{
+    rt_uint32_t                 magic;                  /**< magic number for memheap */
+    struct rt_lwp_memheap      *pool_ptr;               /**< point of pool */
+
+    struct rt_lwp_memheap_item *next;                   /**< next memheap item */
+    struct rt_lwp_memheap_item *prev;                   /**< prev memheap item */
+
+    struct rt_lwp_memheap_item *next_free;              /**< next free memheap item */
+    struct rt_lwp_memheap_item *prev_free;              /**< prev free memheap item */
+};
+
+/**
+ * Base structure of memory heap object
+ */
+struct rt_lwp_memheap
+{
+    struct rt_object        parent;                     /**< inherit from rt_object */
+
+    void                   *start_addr;                 /**< pool start address and size */
+
+    rt_uint32_t             pool_size;                  /**< pool size */
+    rt_uint32_t             available_size;             /**< available size */
+    rt_uint32_t             max_used_size;              /**< maximum allocated size */
+
+    struct rt_lwp_memheap_item *block_list;             /**< used block list */
+    struct rt_lwp_memheap_item *free_list;              /**< free block list */
+    struct rt_lwp_memheap_item  free_header;            /**< free block list header */
+
+    struct rt_semaphore     lock;                       /**< semaphore lock */
+
+    rt_list_t mlist;
+};
+
+extern rt_err_t rt_lwp_memheap_init(struct rt_lwp_memheap *memheap, const char *name, void *start_addr, rt_uint32_t size);
+extern void *rt_lwp_memheap_alloc(struct rt_lwp_memheap *heap, rt_uint32_t size);
+extern void rt_lwp_memheap_free(void *ptr);
+extern void *rt_lwp_memheap_realloc(struct rt_lwp_memheap *heap, void *ptr, rt_size_t newsize);
+extern rt_bool_t rt_lwp_memheap_is_empty(struct rt_lwp_memheap *memheap);
+extern rt_bool_t rt_lwp_memheap_unavailable_size_get(void);
+
+#endif

+ 297 - 0
components/lwp/lwp_syscall.c

@@ -0,0 +1,297 @@
+/*
+ * File      : lwp_syscall.c
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ */
+
+/* RT-Thread System call */
+#include <lwp.h>
+#include <lwp_mem.h>
+#include <lwp_syscall.h>
+
+#include <dfs_poll.h>
+#include <dfs_select.h>
+
+#if (defined(RT_USING_SAL) && defined(SAL_USING_POSIX))
+#include <sys/socket.h>
+
+#define SYSCALL_NET(f) ((void*)(f))
+#else
+#define SYSCALL_NET(f) ((void*)sys_notimpl)
+#endif
+
+#define DBG_ENABLE
+#define DBG_SECTION_NAME    "LWP_CALL"
+#define DBG_COLOR
+#define DBG_LEVEL           DBG_WARNING
+#include <rtdbg.h>
+
+static void __exit_files(rt_thread_t tid)
+{
+    struct rt_lwp *lwp;
+
+    lwp = (struct rt_lwp *)tid->lwp;
+    while (lwp->fdt.maxfd > 0)
+    {
+        lwp->fdt.maxfd --;
+        close(lwp->fdt.maxfd);
+    }
+}
+
+/* thread/process */
+void sys_exit(int value)
+{
+    rt_thread_t tid;
+
+    /* TODO: handle the return_value */
+    dbg_log(DBG_LOG, "enter sys_exit\n");
+    tid = rt_thread_self();
+    __exit_files(tid);
+    rt_thread_delete(tid);
+
+    rt_schedule();
+
+    return;
+}
+
+/* syscall: "read" ret: "ssize_t" args: "int" "void *" "size_t" */
+ssize_t sys_read(int fd, void *buf, size_t nbyte)
+{
+    return read(fd, buf, nbyte);
+}
+
+/* syscall: "write" ret: "ssize_t" args: "int" "const void *" "size_t" */
+ssize_t sys_write(int fd, const void *buf, size_t nbyte)
+{
+    return write(fd, buf, nbyte);
+}
+
+/* syscall: "lseek" ret: "off_t" args: "int" "off_t" "int" */
+off_t sys_lseek(int fd, off_t offset, int whence)
+{
+    return lseek(fd, offset, whence);
+}
+
+/* syscall: "open" ret: "int" args: "const char *" "int" "..." */
+int sys_open(const char *name, int mode, ...)
+{
+    return open(name, mode, 0);
+}
+
+/* syscall: "close" ret: "int" args: "int" */
+int sys_close(int fd)
+{
+    return close(fd);
+}
+
+/* syscall: "ioctl" ret: "int" args: "int" "u_long" "..." */
+int sys_ioctl(int fd, unsigned long cmd, void* data)
+{
+    return ioctl(fd, cmd, data);
+}
+
+/* syscall: "nanosleep" ret: "int" args: "const struct timespec *" "struct timespec *" */
+int sys_nanosleep(const struct timespec *rqtp, struct timespec *rmtp)
+{
+    rt_tick_t tick;
+
+    dbg_log(DBG_LOG, "sys_nanosleep\n");
+
+    tick = rqtp->tv_sec * RT_TICK_PER_SECOND + (rqtp->tv_nsec * RT_TICK_PER_SECOND)/ 1000000000;
+    rt_thread_delay(tick);
+
+    if (rmtp)
+    {
+        tick = rt_tick_get() - tick;
+        /* get the passed time */
+        rmtp->tv_sec = tick/RT_TICK_PER_SECOND;
+        rmtp->tv_nsec = (tick%RT_TICK_PER_SECOND) * (1000000000/RT_TICK_PER_SECOND);
+    }
+
+    return 0;
+}
+
+/* syscall: "getpriority" ret: "int" args: "int" "id_t" */
+int sys_getpriority(int which, id_t who)
+{
+    if (which == PRIO_PROCESS)
+    {
+        rt_thread_t tid;
+
+        tid = rt_thread_self();
+        if (who == (id_t)tid || who == 0xff)
+        {
+            return tid->current_priority;
+        }
+    }
+
+    return 0xff;
+}
+
+/* syscall: "setpriority" ret: "int" args: "int" "id_t" "int" */
+int sys_setpriority(int which, id_t who, int prio)
+{
+    if (which == PRIO_PROCESS)
+    {
+        rt_thread_t tid;
+
+        tid = rt_thread_self();
+        if ((who == (id_t)tid || who == 0xff) && (prio >= 0 && prio < RT_THREAD_PRIORITY_MAX))
+        {
+            rt_thread_control(tid, RT_THREAD_CTRL_CHANGE_PRIORITY, &prio);
+            return 0;
+        }
+    }
+
+    return -1;
+}
+
+/* syscall: "gettimeofday" ret: "int" args: "struct timeval *" "struct timezone *" */
+int sys_gettimeofday(struct timeval *tp, struct timezone *tzp)
+{
+    if (tp)
+    {
+        tp->tv_sec = rt_tick_get() / RT_TICK_PER_SECOND;
+        tp->tv_usec = (rt_tick_get() % RT_TICK_PER_SECOND) * (1000000 / RT_TICK_PER_SECOND);
+    }
+
+    return 0;
+}
+
+/* syscall: "settimeofday" ret: "int" args: "const struct timeval *" "const struct timezone *" */
+int sys_settimeofday(const struct timeval *tv, const struct timezone *tzp)
+{
+    return 0;
+}
+
+/* syscall: "msgget" ret: "int" args: "key_t" "int" */
+int sys_msgget(key_t key, int msgflg)
+{
+    return -1;
+}
+
+/* syscall: "msgsnd" ret: "int" args: "int" "const void *" "size_t" "int" */
+int sys_msgsend(int msqid, const void *msgp, size_t msgsz, int msgflg)
+{
+    return -1;
+}
+
+/* syscall: "msgrcv" ret: "int" args: "int" "void *" "size_t" "long" "int" */
+int sys_msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg)
+{
+    return -1;
+}
+
+/* syscall: "sys_log" ret: "int" args: "const char*" "size" */
+int sys_log(const char* log, int size)
+{
+    rt_device_t console = rt_console_get_device();
+
+    if (console) rt_device_write(console, -1, log, size);
+
+    return 0;
+}
+
+void *sys_malloc(size_t size)
+{
+    return rt_lwp_mem_malloc(size);
+}
+
+void sys_free(void *addr)
+{
+    rt_lwp_mem_free(addr);
+}
+
+void *sys_realloc(void *rmem, size_t newsize)
+{
+    return rt_lwp_mem_realloc(rmem, newsize);
+}
+
+int sys_fstat(int file, struct stat *buf)
+{
+    return fstat(file, buf);
+}
+
+int sys_notimpl(void)
+{
+    return -ENOSYS;
+}
+
+const static void* func_table[] =
+{
+    (void *)sys_exit,           // 0x01
+    (void *)sys_read,           // 0x02
+    (void *)sys_write,          // 0x03
+    (void *)sys_lseek,          // 0x04
+    (void *)sys_open,           // 0x05
+    (void *)sys_close,          // 0x06
+    (void *)sys_ioctl,          // 0x07
+
+    (void *)sys_nanosleep,      // 0x08
+
+    (void *)sys_getpriority,    // 0x09
+    (void *)sys_setpriority,    // 0x0a
+
+    (void *)sys_gettimeofday,   // 0x0b
+    (void *)sys_settimeofday,   // 0x0c
+
+    (void *)sys_malloc,         // 0x0d
+    (void *)sys_free,           // 0x0e
+    (void *)sys_realloc,        //0x0f
+    (void *)sys_fstat,          // 0x10
+    (void *)poll,               // 0x11
+
+    SYSCALL_NET(accept),     // 0x12
+    SYSCALL_NET(bind),       // 0x13
+    SYSCALL_NET(shutdown),   // 0x14
+    SYSCALL_NET(getpeername),// 0x15
+    SYSCALL_NET(getsockname),// 0x16
+    SYSCALL_NET(getsockopt), // 0x17
+    SYSCALL_NET(setsockopt), // 0x18
+    SYSCALL_NET(connect),    // 0x19
+    SYSCALL_NET(listen),     // 0x1a
+    SYSCALL_NET(recv),       // 0x1b
+    SYSCALL_NET(recvfrom),   // 0x1c
+    SYSCALL_NET(send),       // 0x1d
+    SYSCALL_NET(sendto),     // 0x1e
+    SYSCALL_NET(socket),     // 0x1f
+
+    (void *)select,          // 0x20
+};
+
+const void *lwp_get_sys_api(rt_uint32_t number)
+{
+    const void *func = (const void*)sys_notimpl;
+
+    if (number == 0xff)
+    {
+        func = (void *)sys_log;
+    }
+    else
+    {
+        number -= 1;
+        if (number < sizeof(func_table)/sizeof(func_table[0]))
+        {
+            func = func_table[number];
+        }
+    }
+
+    return func;
+}

+ 77 - 0
components/lwp/lwp_syscall.h

@@ -0,0 +1,77 @@
+/*
+ * File      : lwp_syscall.h
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006 - 2018, RT-Thread Development Team
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2006-03-18     Bernard      the first version
+ * 2006-04-25     Bernard      add rt_hw_context_switch_interrupt declaration
+ * 2006-09-24     Bernard      add rt_hw_context_switch_to declaration
+ * 2012-12-29     Bernard      add rt_hw_exception_install declaration
+ * 2017-10-17     Hichard      add some micros
+ */
+
+#ifndef __LWP_SYSCALL_H__
+#define __LWP_SYSCALL_H__
+
+#include <stdint.h>
+#include <rtthread.h>
+#include <dfs_posix.h>
+#include <sys/time.h>
+#include <sys/types.h>
+
+typedef long suseconds_t;       /* microseconds (signed) */
+typedef uint32_t id_t;          /* may contain pid, uid or gid */
+
+/*
+ * Process priority specifications to get/setpriority.
+ */
+#define	PRIO_MIN	    (-20)
+#define	PRIO_MAX	    20
+
+#define	PRIO_PROCESS	0       /* only support lwp process */
+#define	PRIO_PGRP	    1
+#define	PRIO_USER	    2
+
+#define TIMEVAL_TO_TIMESPEC(tv, ts) {                   \
+    (ts)->tv_sec = (tv)->tv_sec;                        \
+    (ts)->tv_nsec = (tv)->tv_usec * 1000;               \
+}
+#define TIMESPEC_TO_TIMEVAL(tv, ts) {                   \
+    (tv)->tv_sec = (ts)->tv_sec;                        \
+    (tv)->tv_usec = (ts)->tv_nsec / 1000;               \
+}
+
+void sys_exit(int value);
+ssize_t sys_read(int fd, void *buf, size_t nbyte);
+ssize_t sys_write(int fd, const void *buf, size_t nbyte);
+off_t sys_lseek(int fd, off_t offset, int whence);
+int sys_open(const char *name, int mode, ...);
+int sys_close(int fd);
+int sys_nanosleep(const struct timespec *rqtp, struct timespec *rmtp);
+int sys_getpriority(int which, id_t who);
+int sys_setpriority(int which, id_t who, int prio);
+int sys_gettimeofday(struct timeval *tp, struct timezone *tzp);
+int sys_settimeofday(const struct timeval *tv, const struct timezone *tzp);
+int sys_msgget(key_t key, int msgflg);
+int sys_msgsend(int msqid, const void *msgp, size_t msgsz, int msgflg);
+int sys_msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
+
+int sys_log(const char* log, int size);
+
+#endif