add lwp support
This commit is contained in:
parent
56c0df1e58
commit
a8953e9211
|
@ -48,7 +48,7 @@ _vector_reset:
|
||||||
_vector_undef:
|
_vector_undef:
|
||||||
.word vector_undef
|
.word vector_undef
|
||||||
_vector_swi:
|
_vector_swi:
|
||||||
.word vector_swi
|
.word SVC_Handler
|
||||||
_vector_pabt:
|
_vector_pabt:
|
||||||
.word vector_pabt
|
.word vector_pabt
|
||||||
_vector_dabt:
|
_vector_dabt:
|
||||||
|
@ -314,7 +314,9 @@ rt_hw_context_switch_interrupt_do:
|
||||||
str lr, [r0, #14*4]
|
str lr, [r0, #14*4]
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
.align 5
|
.align 5
|
||||||
|
.weak SVC_Handler
|
||||||
|
SVC_Handler:
|
||||||
vector_swi:
|
vector_swi:
|
||||||
push_svc_reg
|
push_svc_reg
|
||||||
bl rt_hw_trap_swi
|
bl rt_hw_trap_swi
|
||||||
|
|
|
@ -66,6 +66,7 @@ CONFIG_RT_USING_INTERRUPT_INFO=y
|
||||||
CONFIG_RT_USING_CONSOLE=y
|
CONFIG_RT_USING_CONSOLE=y
|
||||||
CONFIG_RT_CONSOLEBUF_SIZE=128
|
CONFIG_RT_CONSOLEBUF_SIZE=128
|
||||||
CONFIG_RT_CONSOLE_DEVICE_NAME="uart0"
|
CONFIG_RT_CONSOLE_DEVICE_NAME="uart0"
|
||||||
|
CONFIG_RT_VER_NUM=0x40000
|
||||||
CONFIG_ARCH_ARM=y
|
CONFIG_ARCH_ARM=y
|
||||||
CONFIG_ARCH_ARM_CORTEX_A=y
|
CONFIG_ARCH_ARM_CORTEX_A=y
|
||||||
CONFIG_ARCH_ARM_CORTEX_A9=y
|
CONFIG_ARCH_ARM_CORTEX_A9=y
|
||||||
|
@ -109,7 +110,7 @@ CONFIG_FINSH_ARG_MAX=10
|
||||||
CONFIG_RT_USING_DFS=y
|
CONFIG_RT_USING_DFS=y
|
||||||
CONFIG_DFS_USING_WORKDIR=y
|
CONFIG_DFS_USING_WORKDIR=y
|
||||||
CONFIG_DFS_FILESYSTEMS_MAX=2
|
CONFIG_DFS_FILESYSTEMS_MAX=2
|
||||||
CONFIG_DFS_FILESYSTEM_TYPES_MAX=2
|
CONFIG_DFS_FILESYSTEM_TYPES_MAX=8
|
||||||
CONFIG_DFS_FD_MAX=16
|
CONFIG_DFS_FD_MAX=16
|
||||||
# CONFIG_RT_USING_DFS_MNTTABLE is not set
|
# CONFIG_RT_USING_DFS_MNTTABLE is not set
|
||||||
CONFIG_RT_USING_DFS_ELMFAT=y
|
CONFIG_RT_USING_DFS_ELMFAT=y
|
||||||
|
@ -165,10 +166,12 @@ CONFIG_RT_MMCSD_THREAD_PREORITY=22
|
||||||
CONFIG_RT_MMCSD_MAX_PARTITION=16
|
CONFIG_RT_MMCSD_MAX_PARTITION=16
|
||||||
# CONFIG_RT_SDIO_DEBUG is not set
|
# CONFIG_RT_SDIO_DEBUG is not set
|
||||||
CONFIG_RT_USING_SPI=y
|
CONFIG_RT_USING_SPI=y
|
||||||
|
# CONFIG_RT_USING_QSPI is not set
|
||||||
CONFIG_RT_USING_SPI_MSD=y
|
CONFIG_RT_USING_SPI_MSD=y
|
||||||
CONFIG_RT_USING_SFUD=y
|
CONFIG_RT_USING_SFUD=y
|
||||||
CONFIG_RT_SFUD_USING_SFDP=y
|
CONFIG_RT_SFUD_USING_SFDP=y
|
||||||
CONFIG_RT_SFUD_USING_FLASH_INFO_TABLE=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_DEBUG_SFUD is not set
|
||||||
# CONFIG_RT_USING_W25QXX is not set
|
# CONFIG_RT_USING_W25QXX is not set
|
||||||
# CONFIG_RT_USING_GD 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_LOG_TRACE_USING_MEMLOG is not set
|
||||||
# CONFIG_RT_USING_RYM is not set
|
# CONFIG_RT_USING_RYM is not set
|
||||||
# CONFIG_RT_USING_ULOG is not set
|
# CONFIG_RT_USING_ULOG is not set
|
||||||
|
CONFIG_RT_USING_LWP=y
|
||||||
|
|
||||||
#
|
#
|
||||||
# RT-Thread online packages
|
# 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_SQLITE is not set
|
||||||
# CONFIG_PKG_USING_RTI is not set
|
# CONFIG_PKG_USING_RTI is not set
|
||||||
# CONFIG_PKG_USING_LITTLEVGL2RTT is not set
|
# CONFIG_PKG_USING_LITTLEVGL2RTT is not set
|
||||||
|
# CONFIG_PKG_USING_CMSIS is not set
|
||||||
|
|
||||||
#
|
#
|
||||||
# peripheral libraries and drivers
|
# 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_REALTEK_AMEBA is not set
|
||||||
# CONFIG_PKG_USING_SHT2X is not set
|
# CONFIG_PKG_USING_SHT2X is not set
|
||||||
# CONFIG_PKG_USING_AHT10 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
|
# miscellaneous packages
|
||||||
|
@ -409,7 +417,14 @@ CONFIG_LOG_TRACE_USING_LEVEL_INFO=y
|
||||||
#
|
#
|
||||||
# sample package
|
# 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
|
# example package: hello
|
||||||
|
|
|
@ -63,6 +63,11 @@ rt_hw_context_switch_to:
|
||||||
bl rt_cpus_lock_status_restore
|
bl rt_cpus_lock_status_restore
|
||||||
#endif /*RT_USING_SMP*/
|
#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
|
ldmfd sp!, {r4} @ pop new task spsr
|
||||||
msr spsr_cxsf, r4
|
msr spsr_cxsf, r4
|
||||||
|
|
||||||
|
@ -89,6 +94,11 @@ rt_hw_context_switch:
|
||||||
|
|
||||||
stmfd sp!, {r4} @ push cpsr
|
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
|
str sp, [r0] @ store sp in preempted tasks TCB
|
||||||
ldr sp, [r1] @ get new task stack pointer
|
ldr sp, [r1] @ get new task stack pointer
|
||||||
|
|
||||||
|
@ -97,6 +107,11 @@ rt_hw_context_switch:
|
||||||
bl rt_cpus_lock_status_restore
|
bl rt_cpus_lock_status_restore
|
||||||
#endif /*RT_USING_SMP*/
|
#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
|
ldmfd sp!, {r4} @ pop new task cpsr to spsr
|
||||||
msr spsr_cxsf, r4
|
msr spsr_cxsf, r4
|
||||||
ldmfd sp!, {r0-r12, lr, pc}^ @ pop new task r0-r12, lr & pc, copy spsr to cpsr
|
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!, {r4-r7} @ push old task's r0-r3
|
||||||
stmfd sp!, {r3} @ push old task's cpsr
|
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
|
msr cpsr_c, #I_Bit|F_Bit|Mode_IRQ
|
||||||
pop {r1 - r3}
|
pop {r1 - r3}
|
||||||
mov sp, r0
|
mov sp, r0
|
||||||
|
@ -152,6 +172,11 @@ rt_hw_context_switch_interrupt:
|
||||||
mov r0, r3
|
mov r0, r3
|
||||||
bl rt_cpus_lock_status_restore
|
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
|
ldmfd sp!, {r4} @ pop new task's cpsr to spsr
|
||||||
msr spsr_cxsf, r4
|
msr spsr_cxsf, r4
|
||||||
|
|
||||||
|
|
|
@ -51,13 +51,17 @@ rt_uint8_t *rt_hw_stack_init(void *tentry, void *parameter,
|
||||||
*(--stk) = 0; /* r2 */
|
*(--stk) = 0; /* r2 */
|
||||||
*(--stk) = 0; /* r1 */
|
*(--stk) = 0; /* r1 */
|
||||||
*(--stk) = (rt_uint32_t)parameter; /* r0 : argument */
|
*(--stk) = (rt_uint32_t)parameter; /* r0 : argument */
|
||||||
|
|
||||||
/* cpsr */
|
/* cpsr */
|
||||||
if ((rt_uint32_t)tentry & 0x01)
|
if ((rt_uint32_t)tentry & 0x01)
|
||||||
*(--stk) = SVCMODE | 0x20; /* thumb mode */
|
*(--stk) = SVCMODE | 0x20; /* thumb mode */
|
||||||
else
|
else
|
||||||
*(--stk) = SVCMODE; /* arm mode */
|
*(--stk) = SVCMODE; /* arm mode */
|
||||||
|
|
||||||
|
#ifdef RT_USING_LWP
|
||||||
|
*(--stk) = 0; /* user lr */
|
||||||
|
*(--stk) = 0; /* user sp*/
|
||||||
|
#endif
|
||||||
|
|
||||||
/* return task's current stack address */
|
/* return task's current stack address */
|
||||||
return (rt_uint8_t *)stk;
|
return (rt_uint8_t *)stk;
|
||||||
}
|
}
|
||||||
|
|
|
@ -288,6 +288,11 @@ rt_hw_context_switch_interrupt_do:
|
||||||
stmfd sp!, {r1-r4} @ push old task's r0-r3
|
stmfd sp!, {r1-r4} @ push old task's r0-r3
|
||||||
stmfd sp!, {r0} @ push old task's cpsr
|
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 r4, =rt_interrupt_from_thread
|
||||||
ldr r5, [r4]
|
ldr r5, [r4]
|
||||||
str sp, [r5] @ store sp in preempted tasks's TCB
|
str sp, [r5] @ store sp in preempted tasks's TCB
|
||||||
|
@ -296,6 +301,11 @@ rt_hw_context_switch_interrupt_do:
|
||||||
ldr r6, [r6]
|
ldr r6, [r6]
|
||||||
ldr sp, [r6] @ get new task's stack pointer
|
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
|
ldmfd sp!, {r4} @ pop new task's cpsr to spsr
|
||||||
msr spsr_cxsf, r4
|
msr spsr_cxsf, r4
|
||||||
|
|
||||||
|
@ -317,6 +327,8 @@ rt_hw_context_switch_interrupt_do:
|
||||||
|
|
||||||
.align 5
|
.align 5
|
||||||
.globl vector_swi
|
.globl vector_swi
|
||||||
|
.weak SVC_Handler
|
||||||
|
SVC_Handler:
|
||||||
vector_swi:
|
vector_swi:
|
||||||
push_svc_reg
|
push_svc_reg
|
||||||
bl rt_hw_trap_swi
|
bl rt_hw_trap_swi
|
||||||
|
@ -400,8 +412,8 @@ irq_stack_2:
|
||||||
irq_stack_2_limit:
|
irq_stack_2_limit:
|
||||||
|
|
||||||
.data
|
.data
|
||||||
#define DEVICE_MEM 0x10406
|
#define DEVICE_MEM 0x10c06
|
||||||
#define NORMAL_MEM 0x1140e
|
#define NORMAL_MEM 0x11c0e
|
||||||
.align 14
|
.align 14
|
||||||
mtbl:
|
mtbl:
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
* Date Author Notes
|
* Date Author Notes
|
||||||
* 2013-07-05 Bernard the first version
|
* 2013-07-05 Bernard the first version
|
||||||
*/
|
*/
|
||||||
|
|
||||||
.section .vectors, "ax"
|
.section .vectors, "ax"
|
||||||
.code 32
|
.code 32
|
||||||
|
|
||||||
|
@ -49,7 +50,7 @@ _vector_reset:
|
||||||
_vector_undef:
|
_vector_undef:
|
||||||
.word vector_undef
|
.word vector_undef
|
||||||
_vector_swi:
|
_vector_swi:
|
||||||
.word vector_swi
|
.word SVC_Handler
|
||||||
_vector_pabt:
|
_vector_pabt:
|
||||||
.word vector_pabt
|
.word vector_pabt
|
||||||
_vector_dabt:
|
_vector_dabt:
|
||||||
|
|
|
@ -63,6 +63,7 @@
|
||||||
#define RT_USING_CONSOLE
|
#define RT_USING_CONSOLE
|
||||||
#define RT_CONSOLEBUF_SIZE 128
|
#define RT_CONSOLEBUF_SIZE 128
|
||||||
#define RT_CONSOLE_DEVICE_NAME "uart0"
|
#define RT_CONSOLE_DEVICE_NAME "uart0"
|
||||||
|
#define RT_VER_NUM 0x40000
|
||||||
#define ARCH_ARM
|
#define ARCH_ARM
|
||||||
#define ARCH_ARM_CORTEX_A
|
#define ARCH_ARM_CORTEX_A
|
||||||
#define ARCH_ARM_CORTEX_A9
|
#define ARCH_ARM_CORTEX_A9
|
||||||
|
@ -102,7 +103,7 @@
|
||||||
#define RT_USING_DFS
|
#define RT_USING_DFS
|
||||||
#define DFS_USING_WORKDIR
|
#define DFS_USING_WORKDIR
|
||||||
#define DFS_FILESYSTEMS_MAX 2
|
#define DFS_FILESYSTEMS_MAX 2
|
||||||
#define DFS_FILESYSTEM_TYPES_MAX 2
|
#define DFS_FILESYSTEM_TYPES_MAX 8
|
||||||
#define DFS_FD_MAX 16
|
#define DFS_FD_MAX 16
|
||||||
/* RT_USING_DFS_MNTTABLE is not set */
|
/* RT_USING_DFS_MNTTABLE is not set */
|
||||||
#define RT_USING_DFS_ELMFAT
|
#define RT_USING_DFS_ELMFAT
|
||||||
|
@ -156,10 +157,12 @@
|
||||||
#define RT_MMCSD_MAX_PARTITION 16
|
#define RT_MMCSD_MAX_PARTITION 16
|
||||||
/* RT_SDIO_DEBUG is not set */
|
/* RT_SDIO_DEBUG is not set */
|
||||||
#define RT_USING_SPI
|
#define RT_USING_SPI
|
||||||
|
/* RT_USING_QSPI is not set */
|
||||||
#define RT_USING_SPI_MSD
|
#define RT_USING_SPI_MSD
|
||||||
#define RT_USING_SFUD
|
#define RT_USING_SFUD
|
||||||
#define RT_SFUD_USING_SFDP
|
#define RT_SFUD_USING_SFDP
|
||||||
#define RT_SFUD_USING_FLASH_INFO_TABLE
|
#define RT_SFUD_USING_FLASH_INFO_TABLE
|
||||||
|
/* RT_SFUD_USING_QSPI is not set */
|
||||||
/* RT_DEBUG_SFUD is not set */
|
/* RT_DEBUG_SFUD is not set */
|
||||||
/* RT_USING_W25QXX is not set */
|
/* RT_USING_W25QXX is not set */
|
||||||
/* RT_USING_GD is not set */
|
/* RT_USING_GD is not set */
|
||||||
|
@ -276,6 +279,7 @@
|
||||||
/* LOG_TRACE_USING_MEMLOG is not set */
|
/* LOG_TRACE_USING_MEMLOG is not set */
|
||||||
/* RT_USING_RYM is not set */
|
/* RT_USING_RYM is not set */
|
||||||
/* RT_USING_ULOG is not set */
|
/* RT_USING_ULOG is not set */
|
||||||
|
#define RT_USING_LWP
|
||||||
|
|
||||||
/* RT-Thread online packages */
|
/* RT-Thread online packages */
|
||||||
|
|
||||||
|
@ -348,6 +352,7 @@
|
||||||
/* PKG_USING_SQLITE is not set */
|
/* PKG_USING_SQLITE is not set */
|
||||||
/* PKG_USING_RTI is not set */
|
/* PKG_USING_RTI is not set */
|
||||||
/* PKG_USING_LITTLEVGL2RTT is not set */
|
/* PKG_USING_LITTLEVGL2RTT is not set */
|
||||||
|
/* PKG_USING_CMSIS is not set */
|
||||||
|
|
||||||
/* peripheral libraries and drivers */
|
/* peripheral libraries and drivers */
|
||||||
|
|
||||||
|
@ -356,6 +361,9 @@
|
||||||
/* PKG_USING_REALTEK_AMEBA is not set */
|
/* PKG_USING_REALTEK_AMEBA is not set */
|
||||||
/* PKG_USING_SHT2X is not set */
|
/* PKG_USING_SHT2X is not set */
|
||||||
/* PKG_USING_AHT10 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 */
|
/* miscellaneous packages */
|
||||||
|
|
||||||
|
@ -371,7 +379,12 @@
|
||||||
|
|
||||||
/* sample package */
|
/* 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 */
|
/* example package: hello */
|
||||||
|
|
||||||
|
|
|
@ -39,4 +39,6 @@ source "$RTT_DIR/components/utilities/Kconfig"
|
||||||
|
|
||||||
source "$RTT_DIR/components/CMSIS/Kconfig"
|
source "$RTT_DIR/components/CMSIS/Kconfig"
|
||||||
|
|
||||||
|
source "$RTT_DIR/components/lwp/Kconfig"
|
||||||
|
|
||||||
endmenu
|
endmenu
|
||||||
|
|
|
@ -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.
|
|
@ -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')
|
|
@ -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
|
|
@ -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.
|
|
@ -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
|
|
@ -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
|
|
@ -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.
|
|
@ -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
|
|
@ -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
|
|
@ -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.
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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;
|
||||||
|
}
|
|
@ -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
|
|
@ -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;
|
||||||
|
}
|
|
@ -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
|
|
@ -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;
|
||||||
|
}
|
|
@ -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
|
|
@ -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;
|
||||||
|
}
|
|
@ -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
|
Loading…
Reference in New Issue