Skip to content
Snippets Groups Projects
Unverified Commit e11e28a1 authored by Bernard Xiong's avatar Bernard Xiong Committed by GitHub
Browse files

Merge pull request #1 from Guozhanxin/main

更新用户态app开发环境
parents 3476b699 76be0815
No related branches found
No related tags found
No related merge requests found
Showing
with 425 additions and 30 deletions
.config 0 → 100644
#
# Automatically generated file; DO NOT EDIT.
# Configuration
#
# CONFIG_CORTEX_A is not set
# CONFIG_CORTEX_M is not set
# CONFIG_AARCH64 is not set
CONFIG_RISCV64=y
# CONFIG_I386 is not set
CONFIG_ARCH="RISCV64"
# CONFIG_GNU_GCC is not set
CONFIG_GNU_GCC_MUSL=y
# CONFIG_GNU_GCC_NEWLIB is not set
CONFIG_Toolchain="gcc_musl"
CONFIG_EXEC_PATH="/opt/rtt/riscv64-linux-musleabi_for_x86_64-pc-linux-gnu/bin"
CONFIG_CUSTOM_PREFIX=y
CONFIG_PREFIX="riscv64-unknown-linux-musl-"
CONFIG_TARGET_FILE=""
*.pyc
*.map
*.dblite
*.dbsqlite
pkgs.json
pkgs_error.json
*.elf
*.bin
*.hex
*.axf
*.exe
*.pdb
*.pyc
*.idb
*.ilk
*.old
......@@ -24,3 +22,4 @@ build
*.i
*.d
GPUCache
/tools/gnu_gcc
......@@ -7,26 +7,38 @@ choice
config CORTEX_M
bool "ARM Cortex-M"
config AARCH64
bool "ARM AArch64"
config RISCV64
bool "RISC-V 64"
config I386
bool "I386"
endchoice
config ARCH
string
default "Cortex-A" if CORTEX_A
default "AArch64" if AARCH64
default "Cortex-M" if CORTEX_M
default "RISCV64" if RISCV64
default "I386" if I386
default "Cortex-A"
choice
prompt "Compiler"
default GNU_GCC
default GNU_GCC_MUSL
config GNU_GCC
bool "GNU GCC"
bool "GNU GCC (with RT-Thread ulibc)"
config GNU_GCC_MUSL
bool "GNU GCC with musl libc"
bool "GNU GCC with builtin musl libc"
config GNU_GCC_NEWLIB
bool "GNU GCC with newlib libc"
bool "GNU GCC with builtin newlib libc"
endchoice
config Toolchain
......@@ -38,7 +50,7 @@ config Toolchain
config EXEC_PATH
string "Toolchain Path"
default "/opt/arm-none-eabi-elf/bin"
default "/opt/bin"
config CUSTOM_PREFIX
bool "Using specific prefix of toolchain"
......@@ -47,6 +59,10 @@ config CUSTOM_PREFIX
if CUSTOM_PREFIX
config PREFIX
string "Prefix of toolchain"
default "arm-linux-musleabi-" if GNU_GCC_MUSL && CORTEX_A
default "aarch64-linux-musleabi-" if GNU_GCC_MUSL && AARCH64
default "riscv64-unknown-linux-musl-" if GNU_GCC_MUSL && RISCV64
default "i386-unknown-linux-musl-" if GNU_GCC_MUSL && I386
default "arm-none-eabi-"
endif
......@@ -54,7 +70,10 @@ if !CUSTOM_PREFIX
config PREFIX
string
default "arm-none-eabi-" if GNU_GCC_NEWLIB
default "arm-linux-musleabi-" if GNU_GCC_MUSL
default "arm-linux-musleabi-" if GNU_GCC_MUSL && CORTEX_A
default "aarch64-linux-musleabi-" if GNU_GCC_MUSL && AARCH64
default "riscv64-unknown-linux-musl-" if GNU_GCC_MUSL && RISCV64
default "i386-unknown-linux-musl-" if GNU_GCC_MUSL && I386
default "arm-none-eabi-"
endif
......
# userapps
user applications for rt-smart
# RT-Smart 用户态应用开发SDK
## 如何构建用户态应用
### 下载代码
下载smart 用户态应用代码:
```
git clone https://github.com/RT-Thread/userapps.git
```
源码目录说明:
```
.
├── apps ---- app体验示例
├── configs ---- 不同平台app的通用配置
├── linker_scripts ---- 编译app使用的链接脚本
├── prebuilt ---- 预编译好的内核镜像
├── rtconfig.h ---- app使用的公共配置文件
├── sdk ---- 开发app使用的sdk
├── smart-env.bat ---- 配置Win上环境变量的脚本
├── smart-env.sh ---- 配置Linux上环境变量的脚本
└── tools ---- 开发app使用的脚本工具
├── get_toolchain.py ---- 下载工具链的脚本
└── gnu_gcc ---- 下载下来的工具链存放的路径
```
### 配置工具链
在userapps\tools目录下运行get_toolchain.py的脚本,会下载对应的工具链并展开到userapps\tools\gun_gcc目录。后面的工具链名称可以是 arm | aarch64 | riscv64。
本文以RISC-V平台为例,输入下面的命令:
```
python get_toolchain.py riscv64
```
在userapps目录下,运行smart-env.bat配置工具链路径
```
smart-env.bat
```
可使用set命令检查RTT_EXEC_PATH是否设置成功
![img](figures/set.png)
### 编译用户态应用
在rtthread-smart\userapps目录下使用scons编译,编译顺利的话,将在root文件夹中得到一系列可执行elf文件。
![img](figures/build_app.png)
## 运行用户态应用
在本仓库的 prebuilt 目录下存放有预构建好的针对 QEMU RISC-V 平台的内核镜像 qemu-virt64-riscv\rtthread.bin,可以直接运行体验。
### 更新QEMU
由于 Env 自带的 QEMU 版本过低,因此需要更新 QEMU(Env更新QEMU后可删除本步骤)
1. 下载安装 QEMU(推荐qemu-w32-setup-20220831.exe ):https://qemu.weilnetz.de/w32/
2. 将 Env 里的 QEMU 替换为新版本。
### 制作QEMU SD卡
在 Env 工具的 tools\fatdisk 目录下有一个打包 FAT 格式文件的工具 fatdisk.exe,我们可以利用这个工具将我们要存储到QEMU SD卡里的文件打包成 sd.bin 文件。
1. 将userapps下的root目录复制到env\tools\fatdisk目录下
![img](figures/build_sd1.png)
2. 修改 env\tools\fatdisk 目录下 fatdisk.xml 文件为下面的内容
```
<?xml version="1.0" encoding="UTF-8"?>
<fatdisk>
<disk_size>65536</disk_size>
<sector_size>512</sector_size>
<root_dir>root</root_dir>
<output>sd.bin</output>
<strip>0</strip>
</fatdisk>
```
3. 在 env\tools\fatdisk 目录下右键打开 Env 工具,输入命令 fatdisk运行,就会在当前目录下生成 sd.bin 文件了。
![img](figures/build_sd2.png)
4. 将新生成的 sd.bin 放入userapps\prebuilt\qemu-virt64-riscv目录。
### 运行QEMU
在userapps\prebuilt\qemu-virt64-riscv目录下打开Env,执行qemu-norgraphic.bat运行QEMU。
![img](figures/qemu_run.png)
Smart运行起来后输入 ls 可以看到我们存储到 QEMU SD 卡里的文件和文件夹了。
![img](figures/qemu_run2.png)
在最后执行了hello示例,输出"hello world!"。
执行ctrl c可退出QEMU。
## 构建内核镜像
当需要更新内核镜像文件时,查看本节内容。
下载rt-thread源码(如有则跳过),之后切换到rt-smart分支并从远端同步更新。
```
git clone https://github.com/RT-Thread/rt-thread.git
git checkout rt-smart
# update kernel's rt-smart branch to the latest version
git pull origin rt-smart
```
基于rt-thread仓库rt-smart分支的 qemu-virt64-riscv BSP构建内核镜像。
![img](figures/build_kernel1.png)
![img](figures/build_kernel2.png)
将生成的内核镜像rtthread.bin更新到userapps\prebuilt\qemu-virt64-riscv目录即可。
## QA
### scons时找不到工具链
编译时出现如下信息:
```
> scons
scons: Reading SConscript files ...
scons: done reading SConscript files.
scons: Building targets ...
CC apps\webclient\packages\webclient-v2.1.2\src\webclient.o
Error in calling command:riscv64-unknown-linux-musl-gcc
Exception: No such file or directory
Please check Toolchains PATH setting.
scons: *** [apps\webclient\packages\webclient-v2.1.2\src\webclient.o] Error 2
scons: building terminated because of errors.
```
请检查工具链路径是否设置正确,按照文中步骤进行设置。
### scons时出现zlib1.dll丢失的弹窗
重新下载[zlib1.dll文件](https://www.dlldownloader.com/zlib1-dll/)并分别放在C:\Windows\System32与C:\Windows\SysWOW64文件夹中。
\ No newline at end of file
......@@ -2,11 +2,26 @@ import sys
import os
# add building.py path
sys.path = sys.path + [os.path.join('..', 'tools')]
tools_path = os.path.normpath(os.getcwd())
if os.path.exists(os.path.dirname(tools_path) + '/tools'):
tools_path = os.path.dirname(tools_path)
sys.path = sys.path + [os.path.join(tools_path, 'tools')]
from building import *
LaunchMenuconfig()
cwd = GetCurrentDir()
list = os.listdir(os.path.join(cwd, 'apps'))
def BuildDir(dir):
if os.path.isdir(dir):
list = os.listdir(dir)
for item in list:
path = os.path.join(dir, item)
if os.path.isfile(os.path.join(path, 'SConscript')):
BuildApplication(item, path + '/SConscript', usr_root = '.')
AddOption('--app',
dest = 'make-application',
......@@ -14,18 +29,31 @@ AddOption('--app',
default = None,
help = 'make application')
app = None
if GetOption('make-application'):
app = GetOption('make-application')
AddOption('--dir',
dest = 'make-in-directory',
type = 'string',
default = None,
help = 'make in directory')
AddOption('--sdk-libc',
dest='sdk-libc',
action='store_true',
default=False,
help='build with sdk libc')
if app:
item = app
if GetOption('sdk-libc'):
AddDepend('SDK_LIBC')
if GetOption('make-application'):
item = GetOption('make-application')
path = os.path.join(cwd, 'apps', item)
if os.path.isfile(os.path.join(path, 'SConscript')):
BuildApplication(item, path + '/SConscript', usr_root = '.')
elif GetOption('make-in-directory'):
dir = GetOption('make-in-directory')
BuildDir(os.path.join(cwd, dir))
else:
for item in list:
path = os.path.join(cwd, 'apps', item)
if os.path.isfile(os.path.join(path, 'SConscript')):
BuildApplication(item, path + '/SConscript', usr_root = '.')
BuildDir(os.path.join(cwd, 'apps'))
# BuildDir(os.path.join(cwd, 'testcases'))
BuildDir(os.path.join(cwd, 'services'))
{
"RT-Thread Smart.Program": "hello.elf",
"RT-Thread Smart.Target Path": "/root/bin/",
"RT-Thread Smart.SDK ROOT": "../../.."
}
\ No newline at end of file
{
"env": {
"windows": {
"VENV_MODE": true,
"PATH": "%PATH%;%RTT_EXEC_PATH%"
},
"linux": {
"PATH": "$PATH:$RTT_EXEC_PATH"
}
},
"statusBarItem": {
"build": {
"icon": "$(zap)",
"enable": true,
"commands": [
"scons"
],
"label": "编译",
"tooltip": "编译 RT-Thread Smart 工程"
},
"clean": {
"icon": "$(clear-all)",
"enable": true,
"commands": [
"scons -c"
],
"label": "清理",
"tooltip": "清理 RT-Thread Smart 工程"
},
"download": {
"icon": "$(cloud-download)",
"enable": true,
"commands": [
"udb tcp ${SERVER_IP} 5555",
"udb devices",
"udb push ${EXECUTABLE_PROGRAM} ${TARGET_PATH}"
],
"label": "下载",
"tooltip": "下载 RT-Thread Smart 工程"
}
}
}
\ No newline at end of file
......@@ -7,8 +7,7 @@ src = Glob('*.c')
CPPPATH = [cwd]
CPPDEFINES = [
'RT_USING_NEWLIB',
'HAVE_CCONFIG_H',
'HAVE_CCONFIG_H',
]
group = DefineGroup('hello', src, depend = [''], CPPPATH = CPPPATH, CPPDEFINES = CPPDEFINES)
......
import os
import sys
# add building.py path
tools_path = os.path.normpath(os.getcwd() + '/../..')
if os.path.exists(os.path.dirname(tools_path) + '/tools'):
tools_path = os.path.dirname(tools_path)
sys.path = sys.path + [os.path.join(tools_path, 'tools')]
from building import *
BuildApplication('hello', 'SConscript', usr_root = '../../..')
{
"RT-Thread Smart.Program": "ping.elf",
"RT-Thread Smart.Target Path": "/root/bin/",
"RT-Thread Smart.SDK ROOT": "../../.."
}
\ No newline at end of file
{
"env": {
"windows": {
"VENV_MODE": true,
"PATH": "%PATH%;%RTT_EXEC_PATH%"
},
"linux": {
"PATH": "$PATH:$RTT_EXEC_PATH"
}
},
"statusBarItem": {
"build": {
"icon": "$(zap)",
"enable": true,
"commands": [
"scons"
],
"label": "编译",
"tooltip": "编译 RT-Thread Smart 工程"
},
"clean": {
"icon": "$(clear-all)",
"enable": true,
"commands": [
"scons -c"
],
"label": "清理",
"tooltip": "清理 RT-Thread Smart 工程"
},
"download": {
"icon": "$(cloud-download)",
"enable": true,
"commands": [
"udb tcp ${SERVER_IP} 5555",
"udb devices",
"udb push ${EXECUTABLE_PROGRAM} ${TARGET_PATH}"
],
"label": "下载",
"tooltip": "下载 RT-Thread Smart 工程"
}
}
}
\ No newline at end of file
......@@ -4,7 +4,7 @@ cwd = GetCurrentDir()
src = Glob('*.c')
CPPPATH = [cwd]
CPPDEFINES = [ 'RT_USING_NEWLIB', 'HAVE_CCONFIG_H' ]
CPPDEFINES = [ 'HAVE_CCONFIG_H' ]
group = DefineGroup('ping', src, depend = [''], CPPPATH = CPPPATH,
CPPDEFINES = CPPDEFINES)
......
import os
import sys
# add building.py path
tools_path = os.path.normpath(os.getcwd() + '/../..')
if os.path.exists(os.path.dirname(tools_path) + '/tools'):
tools_path = os.path.dirname(tools_path)
sys.path = sys.path + [os.path.join(tools_path, 'tools')]
from building import *
BuildApplication('ping', 'SConscript', usr_root = '../..')
......@@ -88,14 +88,14 @@ int main(int argc, char **argv)
printf("Ping: fail to prepare the ping message.\n");
continue;
}
ch_msg.u.d = (void *)shmid;
ch_msg.u.d = (void *)(size_t)shmid;
#else
ch_msg.u.d = ping;
#endif
printf("Ping: send %s\n", ping);
rt_channel_send_recv(pong_ch, &ch_msg, &ch_msg_ret);
printf("Ping: receive the reply %d\n", (int) ch_msg_ret.u.d);
printf("Ping: receive the reply %d\n", (int)(size_t) ch_msg_ret.u.d);
#ifdef RT_USING_USERSPACE
lwp_shmrm(shmid);
......
{
"RT-Thread Smart.Program": "pong.elf",
"RT-Thread Smart.Target Path": "/root/bin/",
"RT-Thread Smart.SDK ROOT": "../../.."
}
\ No newline at end of file
{
"env": {
"windows": {
"VENV_MODE": true,
"PATH": "%PATH%;%RTT_EXEC_PATH%"
},
"linux": {
"PATH": "$PATH:$RTT_EXEC_PATH"
}
},
"statusBarItem": {
"build": {
"icon": "$(zap)",
"enable": true,
"commands": [
"scons"
],
"label": "编译",
"tooltip": "编译 RT-Thread Smart 工程"
},
"clean": {
"icon": "$(clear-all)",
"enable": true,
"commands": [
"scons -c"
],
"label": "清理",
"tooltip": "清理 RT-Thread Smart 工程"
},
"download": {
"icon": "$(cloud-download)",
"enable": true,
"commands": [
"udb tcp ${SERVER_IP} 5555",
"udb devices",
"udb push ${EXECUTABLE_PROGRAM} ${TARGET_PATH}"
],
"label": "下载",
"tooltip": "下载 RT-Thread Smart 工程"
}
}
}
\ No newline at end of file
......@@ -4,7 +4,7 @@ cwd = GetCurrentDir()
src = Glob('*.c')
CPPPATH = [cwd]
CPPDEFINES = [ 'RT_USING_NEWLIB', 'HAVE_CCONFIG_H' ]
CPPDEFINES = [ 'HAVE_CCONFIG_H' ]
group = DefineGroup('pong', src, depend = [''], CPPPATH = CPPPATH,
CPPDEFINES = CPPDEFINES)
......
import os
import sys
# add building.py path
tools_path = os.path.normpath(os.getcwd() + '/../..')
if os.path.exists(os.path.dirname(tools_path) + '/tools'):
tools_path = os.path.dirname(tools_path)
sys.path = sys.path + [os.path.join(tools_path, 'tools')]
from building import *
BuildApplication('pong', 'SConscript', usr_root = '../..')
......@@ -37,7 +37,7 @@ int main(int argc, char **argv)
rt_channel_recv(pong_ch, &msg_text);
#ifdef RT_USING_USERSPACE
shmid = (int)msg_text.u.d;
shmid = (int)(size_t)msg_text.u.d;
if (shmid < 0 || !(str = (char *)lwp_shmat(shmid, NULL)))
{
msg_text.u.d = (void *)-1;
......@@ -56,7 +56,7 @@ int main(int argc, char **argv)
/* prepare the reply message */
printf("Pong: reply count = %d\n", i);
msg_text.type = RT_CHANNEL_RAW;
msg_text.u.d = (void *)i;
msg_text.u.d = (void *)(size_t)i;
rt_channel_reply(pong_ch, &msg_text);
}
......
{
"RT-Thread Smart.Program": "vi.elf",
"RT-Thread Smart.Target Path": "/root/bin/",
"RT-Thread Smart.SDK ROOT": "../../.."
}
\ No newline at end of file
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment