能够启动新的应用了,但是ipc有问题
This commit is contained in:
4
.vscode/launch.json
vendored
4
.vscode/launch.json
vendored
@@ -46,9 +46,9 @@
|
||||
"environment": [],
|
||||
"externalConsole": false,
|
||||
// "miDebuggerPath": "/opt/homebrew/bin/arm-none-eabi-gdb",
|
||||
"miDebuggerPath": "/home/mkrtos-smart/toolchains/gcc-arm-10.3-2021.07-x86_64-aarch64-none-elf/bin/aarch64-none-elf-gdb",
|
||||
"miDebuggerPath": "/home/zhangzheng/gcc-arm-10.3-2021.07-aarch64-aarch64-none-elf/bin/aarch64-none-elf-gdb",
|
||||
// "miDebuggerPath": "/home/zhangzheng/gcc-arm-none-eabi-5_4-2016q3/bin/arm-none-eabi-gdb",
|
||||
"miDebuggerServerAddress": "127.0.0.1:33333",
|
||||
"miDebuggerServerAddress": "127.0.0.1:3333",
|
||||
"MIMode": "gdb",
|
||||
"setupCommands": [
|
||||
{
|
||||
|
||||
@@ -40,7 +40,7 @@ void thread_sync_entry(entry_frame_t *regs)
|
||||
|
||||
if (task_vma_page_fault(&tk->mm_space.mem_vma, ALIGN_DOWN(addr, PAGE_SIZE)) < 0)
|
||||
{
|
||||
printk("0x20 pfa:0x%x\n", addr);
|
||||
printk("[knl]0x20 pfa:0x%x\n", addr);
|
||||
printk("pc:0x%x x29:0x%x\n", regs->pc, regs->regs[29]);
|
||||
// dump_stack(regs->pc, regs->regs[29]);
|
||||
task_knl_kill(th, FALSE);
|
||||
@@ -53,7 +53,7 @@ void thread_sync_entry(entry_frame_t *regs)
|
||||
|
||||
if (task_vma_page_fault(&tk->mm_space.mem_vma, ALIGN_DOWN(addr, PAGE_SIZE)) < 0)
|
||||
{
|
||||
printk("0x24 pfa:0x%x\n", addr);
|
||||
printk("[knl]0x24 pfa:0x%x\n", addr);
|
||||
// dump_stack(regs->pc, regs->regs[29]);
|
||||
task_knl_kill(th, FALSE);
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ typedef struct msg_tag
|
||||
.map_buf_len = (buf_words), \
|
||||
.prot = (p)})
|
||||
#define msg_tag_get_prot(tag) \
|
||||
((int16_t)((tag).prot))
|
||||
((int)((tag).prot))
|
||||
#define msg_tag_get_val(tag) msg_tag_get_prot(tag)
|
||||
|
||||
typedef union syscall_prot
|
||||
|
||||
@@ -1,29 +1,30 @@
|
||||
/**
|
||||
* @file access.c
|
||||
* @author zhangzheng (1358745329@qq.com)
|
||||
* @brief
|
||||
* @brief
|
||||
* @version 0.1
|
||||
* @date 2023-12-05
|
||||
*
|
||||
*
|
||||
* @copyright Copyright (c) 2023
|
||||
*
|
||||
*
|
||||
*/
|
||||
#include "types.h"
|
||||
#include <task.h>
|
||||
#include <mm_space.h>
|
||||
#include <thread.h>
|
||||
|
||||
#include <util.h>
|
||||
/**
|
||||
* @brief 检测内存是否可访问
|
||||
*
|
||||
*
|
||||
* @param tg_task 目标进程
|
||||
* @param addr 开始地址
|
||||
* @param size 大小
|
||||
* @param ignore_null 是否忽略nullptr
|
||||
* @param ignore_null 是否忽略nullptr
|
||||
* @return bool_t TRUE:可访问,FALSE:不可访问
|
||||
*/
|
||||
bool_t is_rw_access(task_t *tg_task, void *addr, size_t size, bool_t ignore_null)
|
||||
{
|
||||
#if !IS_ENABLED(CONFIG_MMU)
|
||||
if (tg_task == NULL)
|
||||
{
|
||||
return FALSE;
|
||||
@@ -43,4 +44,7 @@ bool_t is_rw_access(task_t *tg_task, void *addr, size_t size, bool_t ignore_null
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
#else
|
||||
return TRUE;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -272,6 +272,7 @@ void *buddy_alloc(buddy_order_t *buddy, size_t size)
|
||||
}
|
||||
end:
|
||||
spinlock_set(&buddy->lock, l_state);
|
||||
//printk("alloc addr 0x%x.\n", ret_mem);
|
||||
return ret_mem;
|
||||
}
|
||||
static inline addr_t get_buddy_addr(buddy_entry_t *merge_be, size_t size)
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
#include <task.h>
|
||||
|
||||
static slab_t *vma_slab;
|
||||
|
||||
static int vma_idl_tree_insert_cmp_handler(const void *key, const void *data);
|
||||
/**
|
||||
* @brief 在系统初始化时调用,初始化vma的内存
|
||||
*
|
||||
@@ -82,6 +82,7 @@ int task_vma_init(task_vma_t *vma)
|
||||
vma_addr_create(0, 0, 0x1000),
|
||||
0x100000000 - 0x1000,
|
||||
0);
|
||||
vma->idle_tree.cmp = vma_idl_tree_insert_cmp_handler;
|
||||
mln_rbtree_insert(&vma->idle_tree, node);
|
||||
}
|
||||
|
||||
@@ -429,7 +430,7 @@ int task_vma_alloc(task_vma_t *task_vma, vma_addr_t vaddr, size_t size,
|
||||
//!< 设置分配后的地址
|
||||
*ret_vaddr = alloc_addr;
|
||||
}
|
||||
printk("alloc:[0x%x 0x%x]\n", alloc_addr, alloc_addr + size - 1);
|
||||
// printk("alloc:[0x%x 0x%x] size:0x%x\n", alloc_addr, alloc_addr + size - 1, size);
|
||||
ret = 0;
|
||||
end:
|
||||
task_vma_unlock(task_vma, lock_status);
|
||||
@@ -485,6 +486,8 @@ static int rbtree_iterate_tree_grant(mln_rbtree_node_t *node, void *udata)
|
||||
vma_idl_tree_iter_grant_params_t *param = udata;
|
||||
vma_t *node_data = mln_rbtree_node_data_get(node);
|
||||
|
||||
// printk("[grant][0x%lx 0x%lx] [0x%lx:0x%lx]\n", vma_addr_get_addr(node_data->vaddr), vma_addr_get_addr(node_data->vaddr) + node_data->size,
|
||||
// param->addr, param->size);
|
||||
if (vma_addr_get_addr(node_data->vaddr) >= param->addr &&
|
||||
vma_addr_get_addr(node_data->vaddr) + node_data->size <= param->addr + param->size)
|
||||
{
|
||||
@@ -496,19 +499,22 @@ static int rbtree_iterate_tree_grant(mln_rbtree_node_t *node, void *udata)
|
||||
vaddr_t dst_addr;
|
||||
|
||||
dst_addr = vma_addr_get_addr(node_data->vaddr) - param->addr + param->dst_addr;
|
||||
|
||||
|
||||
// 解除映射
|
||||
unmap_mm(mm_space_get_pdir(src_mm_space),
|
||||
vma_addr_get_addr(node_data->vaddr), PAGE_SHIFT, 1);
|
||||
|
||||
int ret = map_mm(mm_space_get_pdir(src_mm_space), dst_addr,
|
||||
(addr_t)vma_node_get_paddr(node_data), PAGE_SHIFT, 1,
|
||||
vpage_attrs_to_page_attrs(vma_addr_get_prot(node_data->vaddr)));
|
||||
|
||||
if (ret >= 0) {
|
||||
int ret = map_mm(mm_space_get_pdir(dst_mm_space), dst_addr,
|
||||
(addr_t)vma_node_get_paddr(node_data), PAGE_SHIFT, 1,
|
||||
vpage_attrs_to_page_attrs(vma_addr_get_prot(node_data->vaddr)));
|
||||
|
||||
if (ret >= 0)
|
||||
{
|
||||
param->grant_size += PAGE_SIZE;
|
||||
}
|
||||
//printk("vaddr:0x%x grant vaddr:0x%x 0x%x\n", vma_addr_get_addr(node_data->vaddr), dst_addr, PAGE_SIZE);
|
||||
vma_addr_set_addr(&node_data->vaddr, dst_addr);
|
||||
param->r_dst_tree->cmp = vma_idl_tree_insert_cmp_handler;
|
||||
mln_rbtree_insert(param->r_dst_tree, node);
|
||||
}
|
||||
return 0;
|
||||
@@ -566,7 +572,7 @@ int task_vma_grant(task_vma_t *src_task_vma, task_vma_t *dst_task_vma, vaddr_t s
|
||||
goto end;
|
||||
}
|
||||
// 查找目的
|
||||
dst_task_vma->idle_tree.cmp = vma_idl_tree_eq_cmp_handler;
|
||||
dst_task_vma->idle_tree.cmp = vma_idl_tree_eq_cmp_handler; /**TODO:应该检查是否被包裹 */
|
||||
dst_node = mln_rbtree_search(
|
||||
&dst_task_vma->idle_tree,
|
||||
&(vma_idl_tree_insert_params_t){
|
||||
@@ -575,12 +581,22 @@ int task_vma_grant(task_vma_t *src_task_vma, task_vma_t *dst_task_vma, vaddr_t s
|
||||
}); //!< 查找是否存在
|
||||
if (!mln_rbtree_null(dst_node, &dst_task_vma->idle_tree))
|
||||
{
|
||||
// vma_t *dst_node_dat = mln_rbtree_node_data_get(dst_node);
|
||||
|
||||
// if (!vma_node_get_used(dst_node_dat))
|
||||
// {
|
||||
// mln_rbtree_delete(&dst_task_vma->idle_tree, dst_node);
|
||||
// vma_node_free(&dst_task_vma->idle_tree, dst_node);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
ret = -EEXIST;
|
||||
goto end;
|
||||
// }
|
||||
}
|
||||
|
||||
/*转移映射*/
|
||||
mln_rbtree_delete(&src_task_vma->idle_tree,src_node);
|
||||
mln_rbtree_delete(&src_task_vma->idle_tree, src_node);
|
||||
|
||||
vma_idl_tree_iter_grant_params_t params = {
|
||||
.addr = src_addr,
|
||||
@@ -591,10 +607,11 @@ int task_vma_grant(task_vma_t *src_task_vma, task_vma_t *dst_task_vma, vaddr_t s
|
||||
.src_mm_vma = src_task_vma,
|
||||
.dst_mm_vma = dst_task_vma,
|
||||
};
|
||||
//从源task的分配树中转移到目的task的分配树中。
|
||||
// 从源task的分配树中转移到目的task的分配树中。
|
||||
mln_rbtree_iterate(&src_task_vma->alloc_tree, rbtree_iterate_tree_grant, ¶ms);
|
||||
|
||||
mln_rbtree_insert(&src_task_vma->idle_tree,src_node);
|
||||
dst_task_vma->idle_tree.cmp = vma_idl_tree_insert_cmp_handler;
|
||||
mln_rbtree_insert(&dst_task_vma->idle_tree, src_node);
|
||||
ret = params.grant_size;
|
||||
end:
|
||||
task_vma_unlock_two(src_task_vma, dst_task_vma, lock_status0, lock_status1);
|
||||
@@ -804,7 +821,7 @@ int task_vma_page_fault(task_vma_t *task_vma, vaddr_t addr)
|
||||
{
|
||||
return lock_status;
|
||||
}
|
||||
// printk("page fault:0x%x.\n", addr);
|
||||
//printk("page fault:0x%x.\n", addr);
|
||||
// 1.查找
|
||||
task = container_of(container_of(task_vma, mm_space_t, mem_vma), task_t, mm_space);
|
||||
task_vma->idle_tree.cmp = vma_idl_tree_wrap_cmp_handler;
|
||||
|
||||
@@ -85,7 +85,12 @@ void mm_limit_free_align(ram_limit_t *limit, void *mem, size_t size)
|
||||
#include <buddy.h>
|
||||
void *mm_buddy_alloc_one_page(void)
|
||||
{
|
||||
return buddy_alloc(buddy_get_alloter(), PAGE_SIZE);
|
||||
void *mem = buddy_alloc(buddy_get_alloter(), PAGE_SIZE);
|
||||
|
||||
if (mem) {
|
||||
memset(mem, 0, PAGE_SIZE);
|
||||
}
|
||||
return mem;
|
||||
}
|
||||
void *mm_limit_alloc_buddy(ram_limit_t *limit, size_t size)
|
||||
{
|
||||
|
||||
@@ -27,7 +27,6 @@ slab_t *slab_create(size_t align_size, const char *name)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
printk("alloc addr 0x%x.\n", mem);
|
||||
slab_t *tmp_slab = (slab_t *)mem;
|
||||
|
||||
spinlock_init(&tmp_slab->lock);
|
||||
@@ -113,6 +112,10 @@ again:
|
||||
|
||||
for (size_t i = 0; i < alloc_size / (slab->align_size + sizeof(slab_block_head_t)); i++)
|
||||
{
|
||||
if ((i + 1) * (slab->align_size + sizeof(slab_block_head_t)) + (slab->align_size + sizeof(slab_block_head_t)) > alloc_size)
|
||||
{
|
||||
break;
|
||||
}
|
||||
slab_block_head_t *slab_block = (slab_block_head_t *)((mem + sizeof(slab_head_t)) +
|
||||
(i * (slab->align_size + sizeof(slab_block_head_t))));
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
#!/bin/bash
|
||||
|
||||
# export TOOLCHAIN=/home/zhangzheng/gcc-arm-10.3-2021.07-aarch64-aarch64-none-elf/bin/
|
||||
# export TOOLCHAIN_LIB=/home/zhangzheng/gcc-arm-10.3-2021.07-aarch64-aarch64-none-elf/lib/gcc/aarch64-none-elf/10.3.1
|
||||
export TOOLCHAIN=/home/mkrtos-smart/toolchains/gcc-arm-10.3-2021.07-x86_64-aarch64-none-elf/bin/
|
||||
export TOOLCHAIN_LIB=/home/mkrtos-smart/toolchains/gcc-arm-10.3-2021.07-x86_64-aarch64-none-elf/lib/gcc/aarch64-none-elf/10.3.1
|
||||
export TOOLCHAIN=/home/zhangzheng/gcc-arm-10.3-2021.07-aarch64-aarch64-none-elf/bin/
|
||||
export TOOLCHAIN_LIB=/home/zhangzheng/gcc-arm-10.3-2021.07-aarch64-aarch64-none-elf/lib/gcc/aarch64-none-elf/10.3.1
|
||||
# export TOOLCHAIN=/home/mkrtos-smart/toolchains/gcc-arm-10.3-2021.07-x86_64-aarch64-none-elf/bin/
|
||||
# export TOOLCHAIN_LIB=/home/mkrtos-smart/toolchains/gcc-arm-10.3-2021.07-x86_64-aarch64-none-elf/lib/gcc/aarch64-none-elf/10.3.1
|
||||
|
||||
export BOARD=aarch64_qemu
|
||||
export CROSS_COMPILE_NAME=aarch64-none-elf-
|
||||
|
||||
@@ -48,7 +48,7 @@ typedef union msg_tag
|
||||
.map_buf_len = (buf_words), \
|
||||
.prot = (p)})
|
||||
#define msg_tag_get_prot(tag) \
|
||||
((int16_t)((tag).prot))
|
||||
((int)((tag).prot))
|
||||
#define msg_tag_get_val(tag) msg_tag_get_prot(tag)
|
||||
|
||||
typedef union syscall_prot
|
||||
|
||||
@@ -70,8 +70,9 @@ static void *app_stack_push_str(obj_handler_t task_obj, umword_t **stack, const
|
||||
int len = strlen(str) + 1;
|
||||
|
||||
*stack -= ALIGN(len, sizeof(void *)) / sizeof(void *);
|
||||
for (int i = 0; i < len; i++) {
|
||||
((char*)(*stack))[i] = str[i];
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
((char *)(*stack))[i] = str[i];
|
||||
}
|
||||
|
||||
return *stack;
|
||||
@@ -95,7 +96,7 @@ static int thread_set_msg_buf(obj_handler_t hd_task, obj_handler_t hd_thread)
|
||||
{
|
||||
addr_t mem;
|
||||
msg_tag_t tag;
|
||||
|
||||
|
||||
tag = u_vmam_alloc(VMA_PROT, vma_addr_create(VPAGE_PROT_RW, 0, 0), PAGE_SIZE, 0, (addr_t *)(&mem));
|
||||
if (msg_tag_get_val(tag) < 0)
|
||||
{
|
||||
@@ -107,7 +108,7 @@ static int thread_set_msg_buf(obj_handler_t hd_task, obj_handler_t hd_thread)
|
||||
{
|
||||
return msg_tag_get_val(tag);
|
||||
}
|
||||
//设置msgbuff,TODO:内核需要获取到对应的物理地址
|
||||
// 设置msgbuff,TODO:内核需要获取到对应的物理地址
|
||||
tag = thread_msg_buf_set(hd_thread, (void *)(CONFIG_MSG_BUF_VADDR));
|
||||
if (msg_tag_get_val(tag) < 0)
|
||||
{
|
||||
@@ -163,7 +164,8 @@ int app_load(const char *name, uenv_t *cur_env, pid_t *pid, char *argv[], int ar
|
||||
}
|
||||
|
||||
ret = elf_load(addr, size, &entry_addr, hd_task);
|
||||
if (ret < 0) {
|
||||
if (ret < 0)
|
||||
{
|
||||
goto end_del_obj;
|
||||
}
|
||||
|
||||
@@ -227,10 +229,10 @@ int app_load(const char *name, uenv_t *cur_env, pid_t *pid, char *argv[], int ar
|
||||
{
|
||||
goto end_del_obj;
|
||||
}
|
||||
ret = thread_set_msg_buf(hd_task, hd_thread);
|
||||
if (ret < 0) {
|
||||
ret = thread_set_msg_buf(hd_task, hd_thread);
|
||||
if (ret < 0)
|
||||
{
|
||||
goto end_del_obj;
|
||||
|
||||
}
|
||||
tag = task_set_pid(hd_task, hd_task); //!< 设置进程的pid就是进程hd号码
|
||||
if (msg_tag_get_prot(tag) < 0)
|
||||
@@ -244,15 +246,18 @@ int app_load(const char *name, uenv_t *cur_env, pid_t *pid, char *argv[], int ar
|
||||
void *sp_addr;
|
||||
void *sp_addr_top;
|
||||
|
||||
tag = u_vmam_alloc(VMA_PROT, vma_addr_create(VPAGE_PROT_RWX, 0, 0), CONFIG_PAGE_SHIFT * 8, 0, (addr_t *)(&sp_addr));
|
||||
#define MAIN_THREAD_STACK_SIZE ((1 << CONFIG_PAGE_SHIFT) * 8)
|
||||
|
||||
tag = u_vmam_alloc(VMA_PROT, vma_addr_create(VPAGE_PROT_RWX, 0, 0),
|
||||
MAIN_THREAD_STACK_SIZE, 0, (addr_t *)(&sp_addr));
|
||||
if (msg_tag_get_val(tag) < 0)
|
||||
{
|
||||
goto end_del_obj;
|
||||
}
|
||||
sp_addr_top = (char *)sp_addr_top + CONFIG_PAGE_SHIFT * 8;
|
||||
sp_addr_top = (char *)sp_addr + MAIN_THREAD_STACK_SIZE;
|
||||
|
||||
printf("stack:0x%x size:%d.\n", sp_addr, CONFIG_PAGE_SHIFT * 8);
|
||||
umword_t *usp_top = (umword_t *)((umword_t)((umword_t)sp_addr_top - 8) & ~0x7UL);
|
||||
printf("stack:0x%x size:%d.\n", sp_addr, MAIN_THREAD_STACK_SIZE);
|
||||
umword_t *usp_top = (umword_t *)((umword_t)((umword_t)sp_addr_top - sizeof(void *)) & ~0x7UL);
|
||||
uenv_t uenv = {
|
||||
.log_hd = cur_env->ns_hd,
|
||||
.ns_hd = cur_env->ns_hd,
|
||||
@@ -284,7 +289,7 @@ int app_load(const char *name, uenv_t *cur_env, pid_t *pid, char *argv[], int ar
|
||||
app_stack_push_umword(hd_task, &usp_top, 0);
|
||||
for (int i = 0; i < envp_cn; i++)
|
||||
{
|
||||
app_stack_push_umword(hd_task, &usp_top, (umword_t)cp_envp);
|
||||
app_stack_push_umword(hd_task, &usp_top, (umword_t)cp_envp - (addr_t)sp_addr + 0x8000000);
|
||||
cp_envp += ALIGN(strlen(envp[i]), sizeof(void *));
|
||||
}
|
||||
if (arg_cn)
|
||||
@@ -292,21 +297,34 @@ int app_load(const char *name, uenv_t *cur_env, pid_t *pid, char *argv[], int ar
|
||||
app_stack_push_umword(hd_task, &usp_top, 0);
|
||||
for (int i = 0; i < arg_cn; i++)
|
||||
{
|
||||
app_stack_push_umword(hd_task, &usp_top, (umword_t)cp_args);
|
||||
app_stack_push_umword(hd_task, &usp_top, (umword_t)cp_args - (addr_t)sp_addr + 0x8000000);
|
||||
cp_args += ALIGN(strlen(argv[i]) + 1, sizeof(void *));
|
||||
}
|
||||
}
|
||||
app_stack_push_umword(hd_task, &usp_top, arg_cn);
|
||||
|
||||
printf("pid:%d stack:%p\n", hd_task, usp_top);
|
||||
tag = thread_exec_regs(hd_thread, (umword_t)addr, (umword_t)usp_top, 0, 0);
|
||||
tag = thread_exec_regs(hd_thread, (umword_t)entry_addr, (umword_t)usp_top - (addr_t)sp_addr + 0x8000000, 0, 0);
|
||||
assert(msg_tag_get_prot(tag) >= 0);
|
||||
|
||||
tag = u_vmam_grant(VMA_PROT, hd_task, (addr_t)sp_addr, 0x8000000, MAIN_THREAD_STACK_SIZE);
|
||||
if (msg_tag_get_prot(tag) < 0)
|
||||
{
|
||||
goto free_data;
|
||||
}
|
||||
|
||||
/*启动线程运行*/
|
||||
tag = thread_run(hd_thread, 2);
|
||||
assert(msg_tag_get_prot(tag) >= 0);
|
||||
task_unmap(TASK_THIS, vpage_create_raw3(0, 0, hd_thread));
|
||||
handler_free(hd_thread);
|
||||
return 0;
|
||||
|
||||
free_data:
|
||||
if (sp_addr)
|
||||
{
|
||||
u_vmam_free(VMA_PROT, (addr_t)sp_addr, MAIN_THREAD_STACK_SIZE);
|
||||
}
|
||||
end_del_obj:
|
||||
if (hd_thread != HANDLER_INVALID)
|
||||
{
|
||||
|
||||
@@ -12,6 +12,7 @@ target_link_libraries(sh.elf
|
||||
${LIBC_NAME}
|
||||
${START_LIB}
|
||||
--whole-archive
|
||||
libc_be
|
||||
sys
|
||||
sys_util
|
||||
sys_svr
|
||||
|
||||
@@ -11,7 +11,7 @@ SEARCH_DIR("//aarch64-none-elf/lib");
|
||||
SECTIONS
|
||||
{
|
||||
/* Read-only sections, merged into text segment: */
|
||||
PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x00400000)); . = SEGMENT_START("text-segment", 0x00400000);
|
||||
PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x01400000)); . = SEGMENT_START("text-segment", 0x01400000);
|
||||
.interp : { *(.interp) }
|
||||
.note.gnu.build-id : { *(.note.gnu.build-id) }
|
||||
.hash : { *(.hash) }
|
||||
|
||||
@@ -9,7 +9,7 @@ int main(int argc, char *args[])
|
||||
{
|
||||
for (int i = 0; i < argc; i++)
|
||||
{
|
||||
printf("args[%d]:%s\n", i, args[i]);
|
||||
printf("args[%d]:%s\n ", i, args[i]);
|
||||
}
|
||||
// pm_run_app("lcd_drv", 0);
|
||||
userShellInit();
|
||||
|
||||
Reference in New Issue
Block a user