1.獲取RT-Thread以及env工具
1.1 源碼包獲取
RT-Thread源碼的獲取方式有多種,可以是官網(wǎng)瀏覽器下載、云盤下載、git獲取,強烈推薦git,因為使用git可以很方便的切換各種版本的rtthread,但是前提是要先安裝git,linux下的安裝方法不多敘述。這里不推薦拷貝windows系統(tǒng)里面的源碼包,因為windows與linux的文件換行符等差異,會導致各種坑,所以還是老老實實的重新下載源碼包吧。
git方式國內(nèi)建議使用gitee。
在終端輸入
git clone http://gitee.com/rtthread/rt-thread.git
即可獲取rtthread最新版的源碼包,但是由于兼容問題不太推薦最新的包,終端輸入cd rt-thread 進入源碼包后,使用git reset —hard + 某舊版本id可以快速切換到改舊版本的源碼包,以4.1.1為例,在終端輸入
git reset --hard aab2428d4177a02cd3b0fd020e47a88de379a6ab
版本的id號可以通過 git log查看,commit后的就是該版本
1.2 env工具
對于中國大陸用戶,請使用以下三行命令進行下載,第一行是下載,第二行修改權限,第三行安裝
wget https://gitee.com/RT-Thread-Mirror/env/raw/master/install_ubuntu.sh
chmod 777 install_ubuntu.sh
./install_ubuntu.sh --gitee
Prepare Env
PLAN A: Whenever start the ubuntu system, you need to type command source ~/.env/env.sh to activate the environment variables.
or PLAN B: open ~/.bashrc file, and attach the command source ~/.env/env.sh at the end of the file. It will be automatically executed when you log in the ubuntu, and you don’t need to execute that command any more.
意思就是有兩種方法來配置env,推薦第二種,輸入
gedit ~/.bashrc
再在文件最后一行輸入source ~/.env/env.sh
1.3 編譯調(diào)試所需工具
除此之外,需安裝編譯工具gcc-arm-none-eabi、scons、gdb調(diào)試工具等,輸入以下指令下載安裝
sudo apt-get install gcc-arm-none-eabi
sudo apt-get install qemu-system-arm
sudo apt-get install scons
sudo apt-get install binutils-arm-none-eabi
通常編譯器都自動安裝到/usr/bin下了,安裝好之后需進入rt-thread/bsp/qemu-vexpress-a9,打開rtconfig.py文件,37行左右會指定編譯工具,設置為gcc,路徑為/usr/bin
PLATFORM = 'gcc'
EXEC_PATH = r'/usr/bin'
2.運行QEMU看看效果
在windows下是運行qemu.bat,linux下則是qemu.sh。進入到rt-thread/bsp/qemu-vexpress-a9下,輸入
./qemu.sh
即可啟動虛擬的開發(fā)板。如果運行不了qemu.sh,則需要使用
chmod +x qemu.sh
為該文件增加“可執(zhí)行”的屬性。
如果還是運行不了,可能是沒有生成rtthread.elf的文件,qemu.sh腳本里面就一句話,作用是使用qemu創(chuàng)建機器,運行rtthread.elf。
輸入scons可編譯工程生成rtthread.elf
運行效果如下圖,已經(jīng)進入了虛擬開發(fā)板的命令行界面。
輸入 Ctrl + c 可退出
3.修改main.c并編譯運行
打開rt-thread/bsp/qemu-vexpress-a9/application下的main.c,可以看到如下內(nèi)容,經(jīng)典的hello world
#include
#include
#include
int main(void)
{
printf("Hello RT-Thread!n");
return 0;
}
嘗試修改一下,printf(“Hello RT-Thread this is a test n”);
保存后,再linux終端rt-thread/bsp/qemu-vexpress-a9/目錄下,輸入scons,工程便開始編譯
最終提示生成了rtthread.elf文件。運行./qemu.sh,可以看到啟動后打印修改的內(nèi)容
4.搭建VSCode,開發(fā)更方便
很多人不習慣使用vi編輯器、gedit編輯器修改文件,不習慣使用gdb進行調(diào)試(我就是),搭建VSCode是很有必要的,看代碼很方便,調(diào)試界面也很友好。
VSCode的下載安裝不多作介紹,簡介就是宇宙最強萬能寫代碼工具。
這里還要借助VSCode里面的插件: RT-Thread Studio
安裝好之后,按照擴展設置,添加幾個必要的路徑:
1.rtthread源碼包路徑
2.gdb路徑:/usr/bin/arm-none-eabi-gdb
3.Toolchain_Loacation工具鏈 gcc編譯器的路徑:/usr/bin
使用左側的RT按鈕,即可打開一個工程。鼠標懸停再工程上,可看到編譯、調(diào)試等選項:
如此,就很方便了。調(diào)試起來毫無壓力。
5.為QEMU增加網(wǎng)卡
到這里,基本的環(huán)境就已經(jīng)搭建好了。但是需要使用更多的接口,還需要了解以下QEMU。
QEMU的本質(zhì)是使用電腦的硬件,虛擬出一個開發(fā)板,也就是說這個開發(fā)板使用的接口實際上都是你的電腦的接口。
這一步,為QEMU增加網(wǎng)卡。根據(jù)RT-Thread文檔中心的指引,在windows下使用qemu,添加網(wǎng)卡是首先安裝一個虛擬網(wǎng)卡,然后將真實的可上網(wǎng)的網(wǎng)卡共享到虛擬網(wǎng)卡,然后再啟動虛擬開發(fā)板的時候設置啟動參數(shù),將虛擬網(wǎng)卡作為啟動項,當作虛擬開發(fā)板的網(wǎng)卡。
Linux中也是如此。大概的示意圖如下圖所示。
需要先安裝網(wǎng)橋軟件包
sudo apt-get install bridge-utils
sudo apt-get install uml-utilities
參照網(wǎng)上的例子改寫了qemu.sh,如下。其中ens33和ens36為我電腦上的兩個網(wǎng)卡,一個是以太網(wǎng)(VMware實體window和linux虛擬機NET模式),一個是WIFI(VMware橋接模式,linux和windows共用wifi)。
if [ ! -f "sd.bin" ]; then
dd if=/dev/zero of=sd.bin bs=1024 count=65536
fi
#檢測是否可上網(wǎng)
function network()
{
local ret_code=curl -I -s --connect-timeout 1 www.baidu.com -w %{http_code} | tail -n1
if [ "x$ret_code" = "x200" ]; then
return 1 #網(wǎng)絡暢通
else
return 0 #不通
fi
return 0
}
network
if [ $? -eq 0 ];then
echo "網(wǎng)絡不通暢" #不使用dhcp
sudo ifconfig ens33 down
if [ ! -d /sys/class/net/br0 ];then
sudo brctl addbr br0 #添加名為br0的網(wǎng)橋
sudo brctl addif br0 ens33 #網(wǎng)橋上添加接口ens33
sudo brctl stp br0 off #關閉生成樹協(xié)議
sudo brctl setfd br0 1 #設置轉發(fā)延遲
sudo brctl sethello br0 1 #設置hello時間
fi
sudo ifconfig br0 192.168.75.12 promisc up #啟用br0接口
sudo ifconfig ens33 192.168.75.128 promisc up #啟用網(wǎng)卡接口
sudo dhclient br0 #從dhcp服務器獲得br0IP地址
sudo brctl show br0 #查看虛擬網(wǎng)橋列表
sudo brctl showstp br0 #查看br0各接口信息
tunctl -t tap0 -u root
brctl addif br0 tap0
ifconfig tap0 0.0.0.0 promisc up
brctl showstp br0
else
sudo ifconfig ens36 down #關閉能連接的主機網(wǎng)卡
if [ ! -d /sys/class/net/br0 ];then
sudo brctl addbr br0 #添加名為br0的網(wǎng)橋
sudo brctl addif br0 ens36 #網(wǎng)橋上添加接口ens36
sudo brctl stp br0 off #關閉生成樹協(xié)議
sudo brctl setfd br0 1 #設置轉發(fā)延遲
sudo brctl sethello br0 1 #設置hello時間
fi
sudo ifconfig br0 0.0.0.0 promisc up #啟用br0接口
sudo ifconfig ens36 0.0.0.0 promisc up #啟用網(wǎng)卡接口
sudo dhclient br0 #從dhcp服務器獲得br0IP地址
sudo brctl show br0 #查看虛擬網(wǎng)橋列表
sudo brctl showstp br0 #查看br0各接口信息
tunctl -t tap0 -u root
brctl addif br0 tap0
ifconfig tap0 0.0.0.0 promisc up
brctl showstp br0
fi
sudo qemu-system-arm
-M vexpress-a9
-smp cpus=2
-kernel rtthread.bin
-serial stdio
-sd sd.bin
-net nic -net tap,ifname=tap0
修改完之后,保存,運行qemu.sh,在rtthread終端ping一個網(wǎng)站即可ping通,到此就可以進行下一步學習了。B站上RTThread官方賬號有網(wǎng)絡課程專欄【7天入門網(wǎng)絡編程】,搭配使用真香。若ping不通則有可能是你的linux系統(tǒng)本身就上不了網(wǎng),所以網(wǎng)橋一定要連接到可以上網(wǎng)的網(wǎng)卡才能往下走。ping不通移步第6節(jié) VMWare虛擬機網(wǎng)卡配置簡介,參考一下我的配置。
此時啟動另一個終端,輸入ifconfig,可以看到網(wǎng)卡的信息,里面有qemu.sh文件里新建的br0網(wǎng)橋、本機網(wǎng)卡ens33、ens36、lo回環(huán)、tap0虛擬網(wǎng)卡
6.VMWare虛擬機網(wǎng)卡配置簡介
以下給出我的參考配置
在windows平臺下使用VMware,windos下網(wǎng)絡適配器為如下配置,其中WLAN就是可以上網(wǎng)的Wifi,虛擬網(wǎng)卡VMnet8用于NET模式進行windows和Ubuntu的文件共享、SSH等
在虛擬機設置里面使用VMnet8和VMnet0,其中VMnet8設置為NAT模式,VMnet0設置為自定義橋接模式。在虛擬網(wǎng)絡編輯器里設置VMnet0橋接目標為我的WIFI,即RZ608 Wi-Fi 6E 80MHz。
設置完成后,在Ubuntu中使用ifconfig就可以看到這兩個網(wǎng)卡了,或者在圖形界面中也可以設置,但是Ubuntu都認為這兩個網(wǎng)卡都是有線網(wǎng)卡
這時在去ping一個網(wǎng)站就可以ping通了,如果ping不通可以嘗試關閉再重新打開。
7.TCP客戶端示例
演示TCP客戶端示例。
在windows下打開一個TCP服務器(咱也不知道為什么用windows,正好電腦上有,用著方便)
在RT-Thread命令行中輸入tcp_client命令 + 服務器IP +服務器端口號
msh /> tcp_client 192.168.75.1 7001
源碼見文末尾,該源碼包通過sons —menuconfig彈出裁剪配置界面,添加
RT-Thread online packages ---->
miscellaneous packages ---->
samples:kernel and components samples --->
a network_samples package for rt-thread ---->
[network] tcp client
即可獲得,添加完成之后,在終端輸入
pkgs --update
自動下載TCP示例源代碼,然后直接scons編譯即可使用
/*
Copyright (c) 2006-2022, RT-Thread Development Team
SPDX-License-Identifier: Apache-2.0
Change Logs:
Date Author Notes
/
/
程序清單:tcp 客戶端
這是一個 tcp 客戶端的例程
導出 tcpclient 命令到控制終端
命令調(diào)用格式:tcpclient URL PORT
URL:服務器地址 PORT::端口號
程序功能:接收并顯示從服務端發(fā)送過來的信息,接收到開頭是 'q' 或 'Q' 的信息退出程序
/
#include
#include / 使用BSD socket,需要包含socket.h頭文件 /
#include
#include
#include
#include
#define BUFSZ 1024
static const char send_data[] = "This is TCP Client from RT-Thread."; / 發(fā)送用到的數(shù)據(jù) */
static void tcpclient(int argc, char **argv)
{
int ret;
char *recv_data;
struct hostent *host;
int sock, bytes_received;
struct sockaddr_in server_addr;
const char url;
int port;
if (argc < 3)
{
rt_kprintf("Usage: tcpclient URL PORTn");
rt_kprintf("Like: tcpclient 192.168.12.44 5000n");
return ;
}
url = argv[1];
port = strtoul(argv[2], 0, 10);//第2個參數(shù)字符串轉為整形 端口號
/ 通過函數(shù)入口參數(shù)url獲得host地址(如果是域名,會做域名解析) /
host = gethostbyname(url);
/ 分配用于存放接收數(shù)據(jù)的緩沖 /
recv_data = rt_malloc(BUFSZ);
if (recv_data == RT_NULL)
{
rt_kprintf("No memoryn");
return;
}
/ 創(chuàng)建一個socket,類型是SOCKET_STREAM,TCP類型 /
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
/ 創(chuàng)建socket失敗 /
rt_kprintf("Socket errorn");
/ 釋放接收緩沖 /
rt_free(recv_data);
return;
}
/ 初始化預連接的服務端地址 */
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(port);
server_addr.sin_addr = *((struct in_addr )host->h_addr);
rt_memset(&(server_addr.sin_zero), 0, sizeof(server_addr.sin_zero));
/ 連接到服務端 */
if (connect(sock, (struct sockaddr )&server_addr, sizeof(struct sockaddr)) == -1)
{
/ 連接失敗 */
rt_kprintf("Connect fail!n");
closesocket(sock);
/*釋放接收緩沖 /
rt_free(recv_data);
return;
}
else
{
/ 連接成功 /
rt_kprintf("Connect successfuln");
}
while (1)
{
/ 從sock連接中接收最大BUFSZ - 1字節(jié)數(shù)據(jù) /
bytes_received = recv(sock, recv_data, BUFSZ - 1, 0);
if (bytes_received < 0)
{
/ 接收失敗,關閉這個連接 /
closesocket(sock);
rt_kprintf("nreceived error,close the socket.rn");
/ 釋放接收緩沖 /
rt_free(recv_data);
break;
}
else if (bytes_received == 0)
{
/ 默認 recv 為阻塞模式,此時收到0認為連接出錯,關閉這個連接 /
closesocket(sock);
rt_kprintf("nreceived error,close the socket.rn");
/ 釋放接收緩沖 /
rt_free(recv_data);
break;
}
/ 有接收到數(shù)據(jù),把末端清零 /
recv_data[bytes_received] = '?';
if (strncmp(recv_data, "q", 1) == 0 || strncmp(recv_data, "Q", 1) == 0)
{
/ 如果是首字母是q或Q,關閉這個連接 /
closesocket(sock);
rt_kprintf("n got a 'q' or 'Q',close the socket.rn");
/ 釋放接收緩沖 /
rt_free(recv_data);
break;
}
else
{
/ 在控制終端顯示收到的數(shù)據(jù) /
rt_kprintf("nReceived data = %s ", recv_data);
}
/ 發(fā)送數(shù)據(jù)到sock連接 /
ret = send(sock, send_data, strlen(send_data), 0);
if (ret < 0)
{
/ 接收失敗,關閉這個連接 /
closesocket(sock);
rt_kprintf("nsend error,close the socket.rn");
rt_free(recv_data);
break;
}
else if (ret == 0)
{
/ 打印send函數(shù)返回值為0的警告信息 */
rt_kprintf("n Send warning,send function return 0.rn");
}
}
return;
}
MSH_CMD_EXPORT(tcpclient, a tcp client sample);
-
ARM
+關注
關注
134文章
9027瀏覽量
366495 -
Linux系統(tǒng)
+關注
關注
4文章
590瀏覽量
27318 -
gcc編譯器
+關注
關注
0文章
78瀏覽量
3346 -
RTThread
+關注
關注
7文章
132瀏覽量
40776 -
qemu
+關注
關注
0文章
57瀏覽量
5320
發(fā)布評論請先 登錄
相關推薦
評論