- 2024-11-22
-
发表了主题帖:
全志T113双核异构处理器的使用基于Tina Linux5.0——RTOS系统定制开发
**8、RTOS系统定制开发**
此处以在rtos/components/aw目录下创建一个简单的软件包为例,帮助客户了解RTOS环境,为RTOS系统定制开发提供基础。
RTOS环境下的软件包主要由三部分组成,源文件,Makefile,Kconfig,如下:
```
hello_world
├──hello_world.c
├──Kconfig
└──Makefile
```
其中Makefile指定该模块的编译规则,Kconfig则指定该模块的编译配置,从而达到功能可裁剪,镜像文件大小可灵活配置的目的。
示例软件包实现简单的打印字符串“hello,world!”的功能,如下:
```
#include#include<
intcmd_hello_world(void)
{
printf("hello,world!\n");return0;
}
FINSH_FUNCTION_EXPORT_CMD(cmd_hello_world,hello_world,helpforhello_world)
/*这一行表示将函数cmd_hello_world封装成一个名为hello_world的命令,在RV控制台输入hello_world,即运行cmd_hello_world函数,最后一个参数为帮助信息。此外,头文件需要加上hal_cmd.h.*/
```
Kconfig的写法如下:
```
configCOMPONENT_HELLO_WORLD
bool"HELLO_WORLDSupport"defaultn
defaultn
help
supporthello_worldcommand.
```
Kconfile的写法如下:
```
obj-$(CONFIGCOMPONENTHELLOWORLD)+=hello_world.o
```
此外,需要在上层目录的Kconfile以及Kconfig中加上该软件包,如下:
```
上层Makefile
obj-$(CONFIGCOMPONENT_HELLO_WORLD)+=helloworld
上层Kconfig
sourcecomponents/aw/hello_world/Kconfig
```
开发完成后,运行mrtos_menuconfig,选中该模块对应的CONFIG后退出,然后mrtos进行编译,这样新增的软件包便可以编译到RTOS镜像文件中了。
将RTOS镜像文件移动到TinaLinux环境下重新编译打包,新生成的固件打包烧录进开发板后,启动RV核,在RV核控制台输入help命令。
![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://bbs.aw-ol.com/assets/uploads/files/1731986106891-ca1b9cd8-13d0-4c04-8044-b0484894ee2c-image.png)
可以看到有新增的hello_world命令,控制台输入hello_world命令,控制台输出如下:
```
hello,world!
```
RTOS下一个简单的软件包便创建成功了。
-
发表了主题帖:
全志T113双核异构处理器的使用基于Tina Linux5.0——RTOS新增方案
**7、RTOS新增方案**
此处以在t113_s3p_c906 芯片下创建一个example_demo方案为例,帮助客户快速创建定制方案。
第一步:进入rtos/board/t113_s3p_c906目录,创建 example_demo 文件夹(从evb1_auto方案拷贝过来)
![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://bbs.aw-ol.com/assets/uploads/files/1731985181313-7fc09581-42af-4d90-adfd-6ee0f6a87990-image.png)
第二步:进入rtos/lichee/rtos/projects/t113_s3p_c906目录,创建example_demo文件夹(从evb1_auto方案拷贝过来)
![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://bbs.aw-ol.com/assets/uploads/files/1731985192308-be496c61-e43e-4d69-839c-dd4557ef6f1e-image.png)
第三步:修改rtos/lichee/rtos/projects/Kconfig,新增example_demo配置项(从evb1_auto配置项拷贝过来)
![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://bbs.aw-ol.com/assets/uploads/files/1731985204030-45d5e227-21c1-48cd-9022-0c7be628398a-image.png)
第四步:修改rtos/lichee/rtos/projects/t113_s3p_c906/Makefile,关联了example_demo方案编译
![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://bbs.aw-ol.com/assets/uploads/files/1731985216073-228bcb7d-f89e-48d5-ae4f-7217e89b5216-image.png)
第五步:进入rtos目录,重新配置方案选择,这时候我们发现会多了t113_s3p_c906_example_demo 方案选择,我们重新选择t113_s3p_c906_example_demo 方案
```
source envsetup.sh
lunch_rtos
You're building on Linux
Lunch menu... pick a combo:
1. t113_i_c906_evb1_auto
2. t113_s3p_c906_evb1_auto
3. t113_s3p_c906_evb1_auto_fastboot
4. t113_s3p_c906_evb1_auto_fastboot_video
5. t113_s3p_c906_evb1_auto_non_os
6. t113_s3p_c906_example_demo
7. t113_s4_c906_evb1_auto
8. t113_s4_c906_evb1_auto_fastboot_video
9. t113_s4p_c906_evb1_auto
Which would you like? [Default t113_s3p_c906_example_demo]:
```
第六步:打开配置defconfig文件,选择正确方案配置项
```
mrtos_menuconfig
```
![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://bbs.aw-ol.com/assets/uploads/files/1731985268822-ef170378-33a5-48b1-af90-cf39c9298a23-image.png)
![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://bbs.aw-ol.com/assets/uploads/files/1731985275109-fb443d12-8369-475d-b9e7-2afecd27e915-image.png)
![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://bbs.aw-ol.com/assets/uploads/files/1731985282049-3be9ef3b-20e3-432c-81c9-aa1365d77b24-image.png)
第七步:重新编译
```
mrtos clean
mrtos
```
- 2024-11-20
-
发表了主题帖:
全志T113双核异构处理器的使用基于Tina Linux5.0——异构双核通信验证
**6、双核通信验证**
**6.1、C906小核创建通讯节点**
在C906小核串口终端建立两个通讯节点用于监听数据,输入eptdev_bind test 2
```
cpu0 >eptdev_bind test 2
```
查看监听节点,输入rpmsg_list_listen
```
cpu0 >rpmsg_list_listen
name listen alive
test 2 0
console 100 0
```
**6.2、大核创建通讯节点**
在Tina Linux下也创建两个通讯监听节点,输入以下两个命令
```
echo test > /sys/class/rpmsg/rpmsg_ctrl-c906_rproc@0/open
echo test > /sys/class/rpmsg/rpmsg_ctrl-c906_rproc@0/open
```
输入后,如下所示:
```
root@TinaLinux:/sys/class/rpmsg# echo test > /sys/class/rpmsg/rpmsg_ctrl-c906_rp
roc@0/open
[ 946.762321] virtio_rpmsg_bus virtio0: creating channel sunxi,rpmsg_client addr 0x403
root@TinaLinux:/sys/class/rpmsg# echo test > /sys/class/rpmsg/rpmsg_ctrl-c906_rp
roc@0/open
[ 951.246499] virtio_rpmsg_bus virtio0: creating channel sunxi,rpmsg_client addr 0x404
root@TinaLinux:/sys/class/rpmsg#
```
在大核TIna Linux中也创建了两个监听节点,输入ls /dev/rpmsg*查看节点信息
```
root@TinaLinux:~# ls /dev/rpmsg*
/dev/rpmsg0 /dev/rpmsg1 /dev/rpmsg_ctrl-c906_rproc@0
```
创建完成后,可以在C906小核终端中查看自动输出的信息
```
cpu0 >ctrldev: Rx 44 Bytes
client: Rx 8 Bytes
rpmsg0: binding
send 0x13131411 to rpmsg0
create rpmsg0 client success
ctrldev: Rx 44 Bytes
client: Rx 8 Bytes
rpmsg1: binding
send 0x13131411 to rpmsg1
create rpmsg1 client success
```
**6.3、大核传输至C906小核**
在Tina Linux下输入
```
echo "hello Embfly SBC-T113S Board" > /dev/rpmsg0
echo "hello Tina Linux" > /dev/rpmsg1
```
将Linux Message 0信息通过创建的监听节点传输到C906小核,例如:
```
root@TinaLinux:~# echo "hello Embfly SBC-T113S Board" > /dev/rpmsg0
root@TinaLinux:~# echo "hello Tina Linux" > /dev/rpmsg1
```
输入后,打开C906串口终端可以发现,大核传输过来的信息。
```
rpmsg0: Rx 22 Bytes
Data:hello Embfly SBC-T113S Board
rpmsg1: Rx 17 Bytes
Data:hello Tina Linux
```
**6.4、C906小核传输至大核**
在小核端需要使用命令 eptdev_send 用法 eptdev_send ,这里的id号从0开始,我们设置有两个通信节点,所以id号分别为0和1。
在小核的串口终端输入以下命令:
```
eptdev_send 0 "hello C906"
eptdev_send 1 "hello C906"
```
例如:
```
cpu0 >eptdev_send 0 "hello C906"
will send hello C906 to rpmsg0
cpu0 >eptdev_send 1 "hello C906"
will send hello C906 to rpmsg1
```
输入完成后,小核会将信息分别传入rpmsg0和rpmsg1两个通讯节点。可以在大核Tina Linux端输入
```
cat /dev/rpmsg0
cat /dev/rpmsg1
```
可查看从C906小核传输过来的信息。例如:
```
root@TinaLinux:~# cat /dev/rpmsg0
hello C906
^C
root@TinaLinux:~# cat /dev/rpmsg1
hello C906
^C
```
按下Crtl+C结束监听前持续监听该节点。
您可以在小核端多次传输信息到该节点,该节点支持持续接受小核传输的信息,例如:
在C906小核,多次传输信息到监听节点rpmsg0
```
cpu0 >eptdev_send 0 "hello C906 "
will send hello C906 to rpmsg0
cpu0 >eptdev_send 0 "hello C906 "
will send hello C906 to rpmsg0
cpu0 >eptdev_send 0 "hello C906 "
will send hello C906 to rpmsg0
cpu0 >eptdev_send 0 "hello C906 "
will send hello C906 to rpmsg0
cpu0 >eptdev_send 0 "hello C906 "
will send hello C906 to rpmsg0
cpu0 >eptdev_send 0 "hello C906 "
will send hello C906 to rpmsg0
cpu0 >eptdev_send 0 "hello C906 "
will send hello C906 to rpmsg0
```
在大核端则会一直接收到小核传输过来的信息
```
root@TinaLinux:~# cat /dev/rpmsg0
hello C906 hello C906 hello C906 hello C906 hello C906 hello C906 hello C906
```
**6.5、关闭相互通讯**
要关闭通信,只要在大核Tina Linux端操作节点即可。输入以下命令,echo 给到rpmsg的控制关闭节点即可。
```
echo 0 > /sys/class/rpmsg/rpmsg_ctrl-c906_rproc@0/close
echo 1 > /sys/class/rpmsg/rpmsg_ctrl-c906_rproc@0/close
```
例如:
```
root@TinaLinux:~# echo 0 > /sys/class/rpmsg/rpmsg_ctrl-c906_rproc@0/close
[ 6783.156899] virtio_rpmsg_bus virtio0: destroying channel sunxi,rpmsg_client addr 0x403
root@TinaLinux:~# echo 1 > /sys/class/rpmsg/rpmsg_ctrl-c906_rproc@0/close
root@TinaLinux:~# [ 6784.224740] virtio_rpmsg_bus virtio0: destroying channel sunxi,rpmsg_client addr 0x404
```
此时C906小核端也会自动关闭通信节点,自动输出以下信息
```
send 0x13131411 to rpmsg0
rpmsg0: unbinding
ctrldev: Rx 44 Bytes
send 0x13131411 to rpmsg1
rpmsg1: unbinding
```
-
发表了主题帖:
全志T113双核异构处理器的使用基于Tina Linux5.0——异构双核通信的具体实现
**5、TinaLinux异构双核通信的具体实现:**
本章节以SBC-T113S4主板的TinaLinux为例,介绍异构双核通信的实现。该方法也同样适用于T113i平台。
本章节主要涉及到Tina Linux内核的配置、Tina Linux文件系统(openwrt)的配置、Freertos的配置。其中Tina Linux内核的配置包括设备树的配置及相关内核驱动及协议的配置;Tina Linux文件系统(openwrt)的配置包括异构双核通信测试程序和小核C906终端的配置;Freertos的配置包括通信协议的配置。
**5.1、TinaLinux的配置**
**5.1.1、Tina内核设备树配置**
在Tina根目录下,进入设备树目录(根据不同的处理器,进入不同的处理器目录),如下演示的是以SBC-T113S主板为例,该主板的主处理器是T113-S4,其配置文件都放在device/config/chips/t113_s4/configs/sbc_t113s4_nand/的目录下,内核的设备树则放在device/config/chips/t113_s4/configs/sbc_t113s4_nand/linux-5.4目录:
```
xxx@xxx:~/workspaces/t113_tina5.0$ cd device/config/chips/t113_s4/configs/sbc_t113s4_nand/
```
**编辑设备树**
```
xxx@xxx:~/workspaces/t113_tina5.0/device/config/chips t113_s4/configs/sbc_t113s4_nand/linux-5.4 $ vi board.dts
```
在设备树文件中找到C906相关的设备树节点,设备树默认设置为:
```
reserved-memory {
#address-cells = ;
#size-cells = ;
ranges;
/* c906 */
c906_ddr: c906_ddr@42300000 {
reg = ;
no-map;
};
/*
* The name should be "vdev%dbuffer".
* Its size should be not less than
* RPMSG_BUF_SIZE * (num of buffers in a vring) * 2
* = 512 * (num of buffers in a vring) * 2
*/
rv_vdev0buffer: vdev0buffer@42900000 {
compatible = "shared-dma-pool";
reg = ;
no-map;
};
/*
* The name should be "vdev%dvring%d".
* The size of each should be not less than
* PAGE_ALIGN(vring_size(num, align))
* = PAGE_ALIGN(16 * num + 6 + 2 * num + (pads for align) + 6 + 8 * num)
*
* (Please refer to the vring layout in include/uapi/linux/virtio_ring.h)
*/
rv_vdev0vring0: vdev0vring0@42940000 {
reg = ;
no-map;
};
rv_vdev0vring1: vdev0vring1@42942000 {
reg = ;
no-map;
};
/* dsp0 */
dsp0ddr: dsp0ddr@42000000 {
reg = ;
no-map;
};
dsp0_rpbuf_reserved: dsp0_rpbuf@42244000 {
compatible = "shared-dma-pool";
no-map;
reg = ;
};
/*
* The name should be "vdev%dbuffer".
* Its size should be not less than
* RPMSG_BUF_SIZE * (num of buffers in a vring) * 2
* = 512 * (num of buffers in a vring) * 2
*/
vdev0buffer: vdev0buffer@42200000 {
compatible = "shared-dma-pool";
reg = ;
no-map;
};
/*
* The name should be "vdev%dvring%d".
* The size of each should be not less than
* PAGE_ALIGN(vring_size(num, align))
* = PAGE_ALIGN(16 * num + 6 + 2 * num + (pads for align) + 6 + 8 * num)
*
* (Please refer to the vring layout in include/uapi/linux/virtio_ring.h)
*/
vdev0vring0: vdev0vring0@42240000 {
reg = ;
no-map;
};
vdev0vring1: vdev0vring1@42242000 {
reg = ;
no-map;
};
/*
* dsp ram addr
*/
dsp0dram: dsp0dram@400000 {
reg = ;
no-map;
};
dsp0iram0: dsp0iram0@420000 {
reg = ;
no-map;
};
dsp0iram1: dsp0iram1@440000 {
reg = ;
no-map;
};
};
mailbox_heartbeat: mailbox_heartbeat@0 {
compatible = "mailbox-heartbeat";
rproc-np = ;
mboxes = , ;
mbox-names = "tx", "rx";
status = "okay";
};
dsp0_rproc: dsp_rproc@0 {
compatible = "allwinner,hifi4-rproc", "simple-bus";
clock-frequency = ;
clocks = , , , ;
clock-names = "pll", "mod", "cfg", "ahbs";
resets = , , , ;
reset-names = "mod-rst", "cfg-rst", "dbg-rst", "msg-rst";
reg = ,
;
reg-names = "sram-for-cpux", "hifi4-cfg";
mboxes = ;
mbox-names = "arm-kick";
memory-region = , , , ,
, , ;
memory-mappings =
/* < DA len PA > */
/* local SRAM via external bus */
< 0x28000 0x20000 0x28000 >,
/* local SRAM via internal bus */
< 0x400000 0x10000 0x400000 >,
< 0x420000 0x8000 0x420000 >,
< 0x440000 0x8000 0x440000 >,
/* DDR front 256MB */
< 0x10000000 0x10000000 0x40000000 >,
/* local SRAM via internal bus */
< 0x20028000 0x10000 0x400000 >,
< 0x20038000 0x8000 0x420000 >,
< 0x20040000 0x8000 0x440000 >,
/* DDR front 256MB */
< 0x30000000 0x10000000 0x40000000 >,
/* DDR front 1GB */
< 0x40000000 0x40000000 0x40000000 >,
/* DDR front 1GB */
< 0x80000000 0x40000000 0x40000000 >,
/* DDR front 1GB */
< 0xC0000000 0x40000000 0x40000000 >;
id = ;
status = "okay";
};
rpbuf_controller0: rpbuf_controller@0 {
compatible = "allwinner,rpbuf-controller";
remoteproc = ;
ctrl_id = ; /* index of /dev/rpbuf_ctrl */
//iommus = ;
memory-region = ;
status = "okay";
};
rpbuf_sample: rpbuf_sample@0 {
compatible = "allwinner,rpbuf-sample";
rpbuf = ;
status = "okay";
};
c906_rproc: c906_rproc@0 {
compatible = "allwinner,c906-rproc";
clock-frequency = ;
clocks = , , , , ;
clock-names = "pll", "mod", "cfg", "riscv-rst", "riscv-gate";
resets = , ;
reset-names = "cfg-rst", "msg-rst";
memory-region = , , , ;
reg = ;
reg-names = "c906-cfg";
mboxes = ;
mbox-names = "arm-kick";
memory-mappings =
/* DA len PA */
/* DDR for c906 */
< 0x40000000 0x10000000 0x40000000 >;
firmware-name = "amp_rv0.bin";
status = "okay";
};
```
SBC-T113S主板暂时使用uart3打印C906小核的打印信息(可以分配其他串口作为C906的终端,只要大核和小核的分配不冲突即可),为防止Tina内核抢占uart3,所以务必禁用uart3节点。
```
&uart3 {
pinctrl-names = "default", "sleep";
pinctrl-0 = ;
pinctrl-1 = ;
status = "disabled";
};
```
**5.1.2、Tina内核配置**
在Tina根目录下,执行make kernel_menuconfig,例如:
```
xxx@xxx:~/workspaces/t113_tina5.0$ make kernel_menuconfig
```
* **使能硬件支持**
进入内核配置界面后,进入Device Drivers 目录,选中Mailbox Hardware Support:
![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://bbs.aw-ol.com/assets/uploads/files/1731979568775-9140a6ef-b546-41b4-968d-4766c0248be4-image.png)
选中后进入Mailbox Hardware Support选项中,选中Allwinner Mailbox support:
![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://bbs.aw-ol.com/assets/uploads/files/1731979583564-459fda62-69d7-4b3f-999c-92af0dddccc8-image.png)
* **使能RPMsg驱动**
进入如下目录中
→ Device Drivers
→ Rpmsg drivers
选中如下配置
allwinnertech rpmsg hearbeat driver
allwinner rpmsg tty driver
sunxi rpmsg ctrl driver
Virtio RPMSG bus driver
选中完成后如下图所示:
![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://bbs.aw-ol.com/assets/uploads/files/1731979619834-5fe56d87-3005-4552-aa3b-5398d3390679-image.png)
* **使能RPBuf驱动**
进入如下目录中
→ Device Drivers
→ Rpbuf drivers
-*- Rpbuf device interface
Rpmsg-based Rpbuf service driver
Allwinner Rpbuf controller driver
Allwinner Rpbuf sample driver
注:
1)Allwinner Rpbuf sample driver只是内核层的一个demo程序,可以不选。
2)如果异构双核不进行大数据传输,RPBuf驱动可以不选。
选中完成后如下图所示:
![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://bbs.aw-ol.com/assets/uploads/files/1731979662300-8810021b-226a-4785-b61f-4fc582b3cef5-image.png)
* **使能共享内存驱动**
进入如下目录中
→ Device Drivers
→ Remoteproc drivers
选中如下配置
SUNXI remote processor support --->
Allwinner remoteproc support
Allwinner remoteproc hifi4 boot //控制hifi4 dsp小核
Allwinner remoteproc c906 boot ////控制c906小核
如下图所示:
![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://bbs.aw-ol.com/assets/uploads/files/1731979694675-07da5097-ed02-4f1e-a62f-b09002e00414-image.png)
修改完成后,保存内核配置并退出。
**5.1.3、Tina文件系统配置(Openwrt)**
配置中增加了amp_shell,这个是C906的控制台。另外也增加了rpbuf和rpmsg的演示程序,便于后续测试验证。
![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://bbs.aw-ol.com/assets/uploads/files/1731979735077-8a7bfefd-5684-48dc-8f8b-bd56a7c69c54-image.png)
**5.1.4、编译Tina新固件**
在Tina根目录下,输入mkernel指令编译刚刚选中的内核驱动,编译完成后,输入pack,打包生成新镜像(此时RTOS的固件并没有进行更新),例如:
```
xxx@xxx:~/workspaces/t113_tina5.0$ mkernel
...
xxx@xxx:~/workspaces/t113_tina5.0$ pack
...
```
如果需要将RTOS更新一并打包到固件,只要执行make –j32(32表示计算机处理器的线程数,根据具体计算机而定),编译结束后执行pack指令将生成的t113_s4_linux_sbc_t113s4_xxx.img(以SBC-T113S4主板为例)文件拷贝到Windows主机端,此时Tina的固件里面已经包含了新配置的RTOS。
**5.2、C906 FreeRTOS内核配置及应用**
麻雀虽小,一应俱全!FreeRTOS是一个实时的微型操作系统,它和大多数操作系统都一样,都具备内核和文件系统两个部分,内核重点是任务调度和文件系统管理等,文件系统则集成部分现成的指令和相关应用库并方便启动应用(APP)。另外,FreeRTOS还可以配置终端,刚刚说的指令,就是在终端里面执行的。有了调试终端给FreeRTOS应用调试带来了很大的方便。以下将如何配置FreeRTOS终端、如何配置FreeRTOS驱动组件、如何配置FreeRTOS异构通信演示程序等进行说明。
**5.2.1、修改C906链接脚本**
C906的FreeRTOS是有运行地址的,该运行地址在Tina内核的DTS中有明确,在RTOS对应的项目中也必须一致。以t113_s4_c906_evb1_auto项目为例,这里说的项目该项目涉及的相关代码核配置信息在SDK所在目录/rtos/lichee/rtos/projects/t113_s4_c906/evb1_auto中,该目录中有如下文件:
```
xxx@xxx:~/workspace/t113_tina5.0/rtos/lichee/rtos/projects/t113_s4_c906/evb1_auto$ tree -l
.
├── defconfig
├── defconfig_org
├── freertos.lds.S
├── Kconfig
├── Makefile
└── src
├── alsa_config.c
├── assert.c
├── card_default.c
├── FreeRTOSConfig.h
├── hooks.c
└── main.c
```
找到freertos.lds.S文件,该文件保存有C906小核的链接信息。
修改freertos.lds.S,找到MEMORY节点,确认起始地址为0x42300000,长度为0x00600000。此参数需要和Tina设备树中的C906内存参数一致,查看kernel.lds 中MEMORY节点参数为:
```
/* Linker script to configure memory regions. */
MEMORY
{
RAM (rwx) : ORIGIN = CONFIG_ARCH_START_ADDRESS, LENGTH = CONFIG_ARCH_MEM_LENGTH
}
```
CONFIG_ARCH_START_ADDRESS和CONFIG_ARCH_MEM_LENGTH这两个参数在defconfig(和freertos.lds.S同一目录)中,查看defconfig内容如下:
```
#
# Architecture Options
#
# CONFIG_ARCH_ARM is not set
CONFIG_ARCH_RISCV=y
CONFIG_ARCH_START_ADDRESS=0x42300000
CONFIG_ARCH_MEM_LENGTH=0x600000
CONFIG_LITTLE_ENDIAN=y
CONFIG_BITS_PER_LONG=64
# CONFIG_CACHE_ALIGN_CHECK is not set
CONFIG_TOOLCHAIN_FLOAT_HARD=y
CONFIG_PANIC_CLI=y
CONFIG_PANIC_CLI_PWD=y
CONFIG_IMG_VERSION_MESSAGE=y
```
确认和Tina Linux内核的dts配置一致。
Tina Linux内核的dts的配置如下:
```
/* c906 */
c906_ddr: c906_ddr@42300000 {
reg = ;
no-map;
};
```
**5.2.2、RTOS终端使用uart3**
在RTOS定制中,修改引脚分配也是通过修改sys_config.fex来完成的,以t113_s4_c906_evb1_auto项目为例,该文件在在SDK所在目录/rtos/board/t113_s4_c906/evb1_auto/configs目录下。
通过查询数据手册,查看引脚复用功能,假如我们使用PE8和PE9作为uart3作为终端串口:
![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://bbs.aw-ol.com/assets/uploads/files/1731979924630-51d97141-803f-4c54-8324-2a9a0fa12fb8-image.png)
修改uart3节点作为终端串口:
```
[uart_para]
uart_debug_port = 3
uart_debug_tx = port:PE08
uart_debug_rx = port:PE09
```
**5.3、修改RTOS相关组件的配置并编译**
进入SDK所在目录/rtos/,执行source envsetup.sh,单独开起RTOS的编译环境。
然后按照3.2.2章节进入RTOS方案的选择和配置,执行配置指令mrtos_menuconfig,
进入后选中如下配置:
```
→ Drivers Options
→ soc related device drviers
→ UART Decives
[*] support uart3 device
[3] cli uart port number
```
![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://bbs.aw-ol.com/assets/uploads/files/1731979983847-3eae4129-7af5-49ac-801b-03b6b807a05a-image.png)
进入如下目录,选中[*] enable sysconfig,启用读取解析 sys_config.fex 功能
```
→ Drivers Options
→ soc related device drivers
→ Common Option
[*] enable sysconfig
```
![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://bbs.aw-ol.com/assets/uploads/files/1731980011889-c75c4609-f137-4a3e-a944-1be021dccca6-image.png)
分别进入如下界面,选择对应的rpmsg/rpbuf/messagebox驱动,这些驱动与Tina Linux中的驱动对应。
![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://bbs.aw-ol.com/assets/uploads/files/1731980023832-22f32ad2-0dd7-4991-99ac-c48d8f1d31e9-image.png)
![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://bbs.aw-ol.com/assets/uploads/files/1731980029764-720ad873-a333-457f-be05-b4754dba8a71-image.png)
![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://bbs.aw-ol.com/assets/uploads/files/1731980040628-c593e5d8-7f5e-4409-8fad-253e08086cc9-image.png)
![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://bbs.aw-ol.com/assets/uploads/files/1731980046634-c6cb74ef-097e-48c1-9968-bdc9f25fb65b-image.png)
进入如下界面,选中Freertos终端相关配置
[*] Multi Console Support
[*] Uart Multi Console Support
[ ] Uart Multi Console As Main Console
[*] Rpmsg Multi Console Support
[*] Rpmsg Multi Console Enable Cache Cmd
![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://bbs.aw-ol.com/assets/uploads/files/1731980088972-0285106f-cb98-47ab-9887-f331d1814fe5-image.png)
注:Rpmsg Multi Console Support这个配置是和Tina Linux中的amp_shell控制台对应。
本次演示主要为了演示异构双核通信,配置基本完成。如果用户有其他应用需求,用户可以根据自己的需求进行配置。保存配置退出后,接下来进行编译。
```
ping@embedall:~/workspace/t113_tina5.0/t113_tinasdk5.0-v1/rtos$ m
build rtos ...
===There isn't tina environment.===
Note: will use shell command origin rather than the functon.
Dark Builder
Version (1.6.0 - BiCEP2 (Gravitational Waves))
*[CC] [SCRIPT] build/t113_s4_c906_evb1_auto/img/sys_config.fex
[LDS] [Linker] projects/t113_s4_c906/evb1_auto/freertos.lds
CC build/t113_s4_c906_evb1_auto/arch/common/common.o
CC build/t113_s4_c906_evb1_auto/arch/risc-v/common/exception.o
CC build/t113_s4_c906_evb1_auto/arch/risc-v/common/clocksource.o
AS build/t113_s4_c906_evb1_auto/arch/common/sys_config.o
CC build/t113_s4_c906_evb1_auto/arch/common/version.o
CC build/t113_s4_c906_evb1_auto/arch/risc-v/sun8iw20p1/sun8i.o
AS build/t113_s4_c906_evb1_auto/arch/risc-v/c906/head_s.o
CC build/t113_s4_c906_evb1_auto/arch/risc-v/c906/plic.o
CC build/t113_s4_c906_evb1_auto/arch/risc-v/c906/cache.o
CC build/t113_s4_c906_evb1_auto/arch/risc-v/c906/spinlock.o
CC build/t113_s4_c906_evb1_auto/arch/risc-v/c906/clic.o
CC build/t113_s4_c906_evb1_auto/arch/risc-v/c906/platform/platform_sun8iw20.o
CC build/t113_s4_c906_evb1_auto/arch/risc-v/c906/interrupt.o
CC build/t113_s4_c906_evb1_auto/components/thirdparty/console/FreeRTOS_CLI.o
CC build/t113_s4_c906_evb1_auto/components/common/thirdparty/md5/md5.o
……
LD build/t113_s4_c906_evb1_auto/components/common/thirdparty/openamp/open-amp/obj-in.o
LD build/t113_s4_c906_evb1_auto/components/common/thirdparty/openamp/obj-in.o
LD build/t113_s4_c906_evb1_auto/components/common/thirdparty/obj-in.o
LD build/t113_s4_c906_evb1_auto/components/obj-in.o
LD build/t113_s4_c906_evb1_auto/drivers/rtos-hal/hal/source/ccmu/sunxi-ng/obj-in.o
LD build/t113_s4_c906_evb1_auto/drivers/rtos-hal/hal/source/ccmu/obj-in.o
LD build/t113_s4_c906_evb1_auto/drivers/rtos-hal/hal/source/twi/obj-in.o
LD build/t113_s4_c906_evb1_auto/drivers/rtos-hal/hal/source/obj-in.o
LD build/t113_s4_c906_evb1_auto/drivers/rtos-hal/hal/obj-in.o
LD build/t113_s4_c906_evb1_auto/drivers/obj-in.o
LD build/t113_s4_c906_evb1_auto/kernel/FreeRTOS-orig/obj-in.o
LD build/t113_s4_c906_evb1_auto/kernel/obj-in.o
[LD] [Tina-RT-Builder] build/t113_s4_c906_evb1_auto/img/rt_system.elf
if [ -n /home/ping/workspace/t113_tina5.0/t113_tinasdk5.0-v1/rtos/lichee/rtos/build/t113_s4_c906_evb1_auto/img/ ]; then mkdir -p /home/ping/workspace/t113_tina5.0/t113_tinasdk5.0-v1/rtos/lichee/rtos/build/t113_s4_c906_evb1_auto/img; fi
Memory region Used Size Region Size %age Used
RAM: 214096 B 6 MB 3.40%
*[IMAGE] [Tina-RT-Builder] build/t113_s4_c906_evb1_auto/img/rt_system.bin
*[SYMS] [Tina-RT-Builder] build/t113_s4_c906_evb1_auto/img/rt_system.syms
text data bss dec hex filename
134576 69048 10472 214096 34450 build/t113_s4_c906_evb1_auto/img/rt_system.elf
copying /home/ping/workspace/t113_tina5.0/t113_tinasdk5.0-v1/rtos/lichee/rtos/build/t113_s4_c906_evb1_auto/img/rt_system.bin to /home/ping/workspace/t113_tina5.0/t113_tinasdk5.0-v1/rtos/board/t113_s4_c906/evb1_auto/bin/freertos.fex
#### make completed successfully
'/home/ping/workspace/t113_tina5.0/t113_tinasdk5.0-v1/rtos/lichee/rtos/build/t113_s4_c906_evb1_auto/img/rt_system.bin' -> '/home/ping/workspace/t113_tina5.0/t113_tinasdk5.0-v1/rtos/board/t113_s4_c906/evb1_auto/bin/rtos_riscv_sun8iw20p1.f
```
编译完成后会在SDK目录下的/rtos/board/t113_s4_c906/evb1_auto/bin目录生成rtos_riscv_sun8iw20p1.fex和freertos.fex,这两个文件是一样的。
**5.4、核对所选FreeRTOS组件**
配置FreeRTOS组件是为了完成FreeRTOS APP的开发。本次的APP要完成的是异构通信,我们查看t113_s4_c906_evb1_auto项目代码了解其运行过程。
t113_s4_c906_evb1_auto项目的相关代码核配置信息在SDK所在目录/rtos/lichee/rtos/projects/t113_s4_c906/evb1_auto中,该目录中有如下文件:
```
xxx@xxx:~/workspace/t113_tina5.0/rtos/lichee/rtos/projects/t113_s4_c906/evb1_auto$ tree -l
.
├── defconfig
├── defconfig_org
├── freertos.lds.S
├── Kconfig
├── Makefile
└── src
├── alsa_config.c
├── assert.c
├── card_default.c
├── FreeRTOSConfig.h
├── hooks.c
└── main.c
```
重点查看main.c文件,该文件内容如下:
```
#include
#include
#include
#include
#include "interrupt.h"
#include
#include "FreeRTOS.h"
#include "task.h"
#include
#include
#ifdef CONFIG_DRIVERS_MSGBOX
#include
#endif
#ifdef CONFIG_COMPONENTS_AW_DEVFS
#include
#endif
#ifdef CONFIG_COMPONENTS_OPENAMP
#include
extern int openamp_init(void);
extern int rpbuf_init(void);
void openamp_init_thread(void *param)
{
(void)param;
openamp_init();
#ifdef CONFIG_RPMSG_CLIENT
rpmsg_ctrldev_create();
#endif
#ifdef CONFIG_RPMSG_HEARBEAT
extern int rpmsg_heart_init(void);
rpmsg_heart_init();
#endif
#ifdef CONFIG_MULTI_CONSOLE
extern int multiple_console_init(void);
multiple_console_init();
#endif
#ifdef CONFIG_COMPONENTS_RPBUF
extern int rpbuf_init(void);
rpbuf_init();
#endif
hal_thread_stop(NULL);
}
#endif
void cpu0_app_entry(void *param)
{
(void)param;
#ifdef CONFIG_COMPONENTS_AW_DEVFS
devfs_mount("/dev");
#endif
#if defined CONFIG_COMPONENTS_OPENAMP
void *thread;
thread = hal_thread_create(openamp_init_thread, NULL,
"amp_init", 8 * 1024, HAL_THREAD_PRIORITY_SYS);
if (thread != NULL)
hal_thread_start(thread);
#endif
#ifdef CONFIG_COMPONENT_CLI
vCommandConsoleStart(0x1000, HAL_THREAD_PRIORITY_CLI, NULL);
#endif
vTaskDelete(NULL);
}
```
该程序的入口函数是cpu0_app_entry,该程序通过函数hal_thread_create建立了openamp_init_thread线程。该线程通过openamp_init函数进行了openamp框架的初始化,同时如果选择了rpmsg通信,也进行了rpmsg通信的初始化等。可判定所选的FreeRTOS相关组件可以满足要求。
**5.5、主板内使能C906**
启动主板,打开串口终端进入主板控制台,将freertos.fex拷贝到/lib/firmware目录下。假设使用ADB功能将文件拷贝到主板的root/目录下
```
root@TinaLinux:~# cd /root/
root@TinaLinux:~# ls
freertos.fex
```
将root目录下的freertos.fex拷贝到/lib/firmware目录下
```
root@TinaLinux:~# cp freertos.fex /lib/firmware/
root@TinaLinux:~# ls /lib/firmware/
boot_xr829.bin fw_xr829.bin freertos.fex sdd_xr829.bin
etf_xr829.bin fw_xr829_bt.bin regulatory.db
```
拷贝完成后,可以在/lib/firmware目录下看到小核固件。接下来把主板的UART3(在RTOS配置中已经把UART3配置成终端串口)与计算机的串口连接起来,并配置计算机串口波特率为115200,通过计算机串口可以查看小核的相关信息。在Tina Linux主板串口终端输入指令:
```
root@TinaLinux:~# echo freertos.fex > /sys/class/remoteproc/remoteproc1/firmware
```
这一步是将freertos.fex固件放在硬件节点firmware 。接下来启动C906固件,指令如下:
```
root@TinaLinux:~#echo start > /sys/class/remoteproc/remoteproc1/state
remoteproc remoteproc1: powering up c906_rproc
[ 1489.549950] remoteproc remoteproc1: Booting fw image amp_rv0.bin, size 224392
[ 1489.558282] remoteproc remoteproc1: the version: UTS - Thu, 24 Oct 2024 14:39:36 +0800
[ 1489.558282] Compile Time - 14:39:36
[ 1489.571527] remoteproc1#vdev0buffer: assigned reserved memory node vdev0buffer@42900000
[ 1489.581143] virtio_rpmsg_bus virtio0: rpmsg host is online
[ 1489.587680] remoteproc1#vdev0buffer: registered virtio0 (type 7)
[ 1489.594617] remoteproc remoteproc1: remote processor c906_rproc is now up
root@TinaLinux:/# [ 1489.695824] virtio_rpmsg_bus virtio0: creating channel sunxi,rpmsg_ctrl addr 0x400
[ 1489.715788] virtio_rpmsg_bus virtio0: creating channel rpbuf-service addr 0x401
[ 1489.724381] rpbuf_service_rpmsg virtio0.rpbuf-service.-1.1025: rpmsg device parent 0: virtio0
[ 1489.734036] rpbuf_service_rpmsg virtio0.rpbuf-service.-1.1025: rpmsg device parent 1: remoteproc1#vdev0buffer
[ 1489.745237] rpbuf_service_rpmsg virtio0.rpbuf-service.-1.1025: rpmsg device parent 2: remoteproc1
[ 1489.755242] rpbuf_service_rpmsg virtio0.rpbuf-service.-1.1025: rpmsg device parent 3: 6010000.c906_rproc
[ 1489.766110] virtio_rpmsg_bus virtio0: creating channel sunxi,rpmsg_heartbeat addr 0x402
使能后可以在UART3上查看RV核的信息:
cpu0>help
Lists all the registered commands
[ help-built-in]--------------Lists all the built-in registered commands
[ ts]--------------Displays a table showing the state of each FreeRTOS task
[ run-time-stats]--------------Displays a table showing how much processing time each FreeRTOS task has used
[ echo-3-parameters]--------------echo-3-parameters : Expects three parameters, echos each in turn
[ echo-parameters]--------------echo-parameters : Take variable number of parameters, echos each in turn
[ rpbuf_demo]--------------rpbuf demo
[ rpbuf_test]--------------rpbuf test demo
[ console_dump]--------------dum all cli console info
[ exit]--------------Console Exit Command
[ msgbox_demo]--------------msgbox demo
[ help]--------------List all registered commands
[ backtrace]--------------Backtrace Command
[ md5sum]--------------Calculate md5sum
[ rproc_dump_mapping]--------------rproc dump mapping
[ eptdev_send]--------------send data used by rpmsg ept test
[ eptdev_close]--------------close rpmsg ept client
[ rpmsg_list_epts]--------------list endpoints
[ rpmsg_list_listen]--------------list listen
[ jtag]--------------init jtag gpio
[rpmsg_ctrlde_release]--------------release rpmsg ctrldev
[ rpmsg_ctrldev_init]--------------init rpmsg ctrldev
[ eptdev_reset]--------------reset rpmsg ctrl
[ eptdev_clear]--------------clear rpmsg name group
[ eptdev_unbind]--------------unbind rpmsg ept listen
[ eptdev_bind]--------------bind rpmsg ept name
[ rpmsg_test]--------------rpmsg test
[ rpmsg_test_send]--------------rpmsg test send
[ rpmsg_test_init]--------------init rpmsg test
[ rpmsg_test_extend]--------------rpmsg test with another rproc
[ hal_msgbox]--------------hal msgbox
cpu0>
查看RV核目前的任务:
cpu0>ts
Task State Priority Stack #
************************************************
Name State Pri HWM Idx StkCur StkBot
CLI X 18 3742 5 0x42363e30 0 x4235c510
IDLE R 0 980 2 0x42348250 0 x423463b0
Tmr Svc B 31 1978 3 0x4234c220 0 x423483c0
ctrldev B 6 4026 8 0x4237d460 0 x42375690
cpu-vring-ipi B 31 8128 7 0x42374780 0 x42364950
```
- 2024-11-18
-
发表了主题帖:
全志T113双核异构处理器的使用基于Tina Linux5.0——RTOS编译开发说明
**3、RTOS编译开发说明**
**3.1、RTOS SDK与TinaLinux开发环境**
RTOS SDK相关代码已集成到Tina Linux开发环境,Tina Linux开发环境下的rtos子目录即为RTOS开发环境。
```
├──brandy
├──bsp
├──build
├──buildroot
├──build.sh >build/top_build.sh
├──device
├──kernel
├──openwrt
├──out
├──platform
├──prebuilt
├──rtos #RTOS环境
├──tee_kit
├──test
└──tools
```
**3.2、RTOS编译**
Tina集成了RTOS的编译、打包功能,而且适用于openwrt、buildroot等文件系统。这里以T113 S4平台作为例子进行阐述。
**3.2.1、关联RTOS方案**
TinaLinux的SDK中,SDK根目录下有device目录,该目录存放的是不同处理器平台及主板的配置,以SBC-T113S4_NAND为例,它是以T113_S4为主控制器的,其配置文件就存放在device/config/chips/t113_s4/configs/sbc_t113s4_nand目录下,那么该主板如何关联RTOS方案呢?
```
xxx@xxx:~/workspace/t113_tina5.0/t113_tinasdk5.0-v1/device/config/chips/t113_s4/configs/sbc_t113s4_nand$ tree -l
.
├── bin
│ ├── amp_dsp0.bin
│ └── amp_rv0.bin
├── BoardConfig.mk //关联RTOS项目的关键
├── board.dts -> linux-5.4/board.dts
├── bsp
│ ├── env.cfg
│ └── sys_partition.fex
├── buildroot
│ ├── BoardConfig.mk
│ ├── BoardConfig_nor.mk
│ ├── bootlogo.bmp
│ ├── env_nor.cfg
│ ├── swupdate
│ │ ├── env_ab.cfg
│ │ ├── sw-description-ab
│ │ ├── sw-description-ab-rdiff
│ │ ├── sw-description-recovery
│ │ ├── sw-description-recovery-sign
│ │ ├── sw-subimgs-ab.cfg
│ │ ├── sw-subimgs-ab-rdiff.cfg
│ │ ├── sw-subimgs-recovery.cfg
│ │ ├── sw-subimgs-recovery-secure.cfg
│ │ ├── sw-subimgs-recovery-sign.cfg
│ │ ├── sys_partition_ab.fex
│ │ └── sys_partition_recovery.fex
│ ├── sys_partition.fex
│ └── sys_partition_nor.fex
├── linux-5.4
│ ├── board_backup.dts
│ ├── board.dts
│ ├── board_lvds1024x600.dts
│ ├── board_lvds1024x768.dts
│ ├── board_old.dts
│ ├── board_spi4bit_drv30.dts
│ ├── board_spi4bit.dts
│ ├── board_spi_sbc-t113s_v1p0.dts
│ ├── board_tft1024x600.dts
│ ├── board_uart3.dts
│ ├── board_xr829_sbc-t113s_v1p1.dts
│ ├── config-5.4
│ ├── config-5.4-recovery
│ ├── config_uart3-5.4
│ ├── env.cfg
│ ├── env_uart3.cfg
│ └── sys_partition.fex
├── openwrt
│ ├── bootlogo.bmp
│ ├── sys_partition.fex
│ └── sys_partition_nor.fex
├── sys_config.fex
├── sys_config_old.fex
├── sys_config_uart3.fex
├── uboot-board_backup.dts
├── uboot-board.dts
├── uboot-board-lvds-lcd1024x600.dts
├── uboot-board_spi0_1wire.dts
├── uboot-board_spi_sbc-t113s_v1p0.dts
├── uboot-board_spi_sbc-t113s_v1p1.dts
└── uboot-board-tft-lcd1024x600.dts
```
在这些配置文件中有一个文件BoardConfig.mk,它就是关联RTOS应用的关键,这个文件的内容如下:
![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://bbs.aw-ol.com/assets/uploads/files/1731640284360-a7612410-1de1-45b4-aa50-de4f5ded5cc2-image.png)
配置RTOS方案名的关键字段LICHEE_RTOS_PROJECT_NAME:=xxxxx。以我司SBC-T113S主板为例,在BoardConfig.mk中配置的是t113_s4_c906_evb1_auto的RTOS方案。开发者可以通过修改LICHEE_RTOS_PROJECT_NAME字段,更改构建RTOS方案。
先进入Tina的rtos目录,rtos目录的内容如下:
```
├──board
├──envsetup.sh >tools/scripts/source_envsetup.sh
├──lichee
├──out
└──tools
```
执行如下指令进行RTOS的环境配置
```
source envsetup.sh #配置环境变量
```
我们看到可以选择的RTOS方案,即是LICHEE_RTOS_PROJECT_NAME字段可以配置的RTOS方案。
```
last=t113_s4_c906_evb1_auto
You're building on Linux
Lunch menu... pick a combo:
1. t113_i_c906_evb1_auto
2. t113_s3p_c906_evb1_auto
3. t113_s3p_c906_evb1_auto_fastboot
4. t113_s3p_c906_evb1_auto_fastboot_video
5. t113_s3p_c906_evb1_auto_non_os
6. t113_s3p_c906_example_demo
7. t113_s4_c906_evb1_auto
8. t113_s4_c906_evb1_auto_fastboot_video
9. t113_s4p_c906_evb1_auto
Which would you like? [Default t113_s4_c906_evb1_auto]:
```
从以上RTOS的方案中,可以看到有支持t113-i处理器的,也有支持t113_s4处理器的,当前默认是t113_s4_c906_evb1_auto,这个是基于t113_s4处理器的方案。另外,这个方案是可以添加的,如果主板是基于T113I的,可以把t113_i_c906_evb1_auto作为蓝本增加自己方案,如果主板是基于T113-S4的,可以把t113_i_c906_evb1_auto作为蓝本增加自己方案。如何添加方案请看本手册的第六章节。
**3.2.2、单独编译RTOS方案**
执行lunch_rtos进行编译方案选择后,可以通过mrtos_menuconfig进行方案的配置,配置完成后即可通过m或者mrtos指令进行RTOS的编译。
```
xxx@xxx:~/workspace/t113_tina5.0/t113_tinasdk5.0-v1/rtos$ lunch_rtos
last=t113_s4_c906_evb1_auto
You're building on Linux
Lunch menu... pick a combo:
1. t113_i_c906_evb1_auto
2. t113_s3p_c906_evb1_auto
3. t113_s3p_c906_evb1_auto_fastboot
4. t113_s3p_c906_evb1_auto_fastboot_video
5. t113_s3p_c906_evb1_auto_non_os
6. t113_s3p_c906_example_demo
7. t113_s4_c906_evb1_auto
8. t113_s4_c906_evb1_auto_fastboot_video
9. t113_s4p_c906_evb1_auto
Which would you like? [Default t113_s4_c906_evb1_auto]: 7
select=7...
t113_s4_c906/evb1_auto
'/home/ping/workspace/t113_tina5.0/t113_tinasdk5.0-v1/rtos/lichee/rtos/projects/t113_s4_c906/evb1_auto/defconfig' -> '/home/ping/workspace/t113_tina5.0/t113_tinasdk5.0-v1/rtos/lichee/rtos/.config'
============================================
RTOS_BUILD_TOP=/home/ping/workspace/t113_tina5.0/t113_tinasdk5.0-v1/rtos
RTOS_TARGET_ARCH=riscv
RTOS_TARGET_CHIP=sun8iw20p1
RTOS_TARGET_DEVICE=t113_s4_c906
RTOS_PROJECT_NAME=t113_s4_c906_evb1_auto
============================================
Run mrtos_menuconfig to config rtos
Run m or mrtos to build rtos
```
以上提示我们通过mrtos_menuconfig可以进行应用的配置,执行结果如下:
![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://bbs.aw-ol.com/assets/uploads/files/1731640399111-b6e0e6d4-a8f7-4b86-85fc-9e49dc078c0e-image.png)
从配置情况看,和Linux的内核配置比较接近,也是可以配置各种驱动外设,见下图:
![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://bbs.aw-ol.com/assets/uploads/files/1731640414907-c84cfc5d-79b7-4699-89a1-1bc1e79d3863-image.png)
T113系列拥有双核Cortex-A7核心,也拥有RV64-C906核心,这两个核心使用的外设是共通的,因此选择C906选择外设的时候,要避开Cortex-A7已经使用的外设。例如:Cortex-A7核心已经把PE2/PE3这两个GPIO作为UART来使用,C906就不能再使用PE2/PE3。
另外,这里要明确的一点是:每个RTOS应用也是有对应的配置文件的,对于t113_s4_c906_evb1_auto这个项目的配置文件在如下目录:
```
TinaSDK所在目录/rtos/lichee/rtos/projects/t113_s4_c906/evb1_auto/defconfig
```
配置完成后即可执行m或者mrtos执行进行编译,指令执行结果如下:
```
xxx@xxx:~/workspace/t113_tina5.0/t113_tinasdk5.0-v1/rtos$ mrtos
build rtos ...
===There isn't tina environment.===
Note: will use shell command origin rather than the functon.
Dark Builder
Version (1.6.0 - BiCEP2 (Gravitational Waves))
*[CC] [SCRIPT] build/t113_s4_c906_evb1_auto/img/sys_config.fex
[CONF] [Tina-RT-Builder] .dbuild/..//include/generated/t113_s4_c906_evb1_aut o/autoconf.h
[LDS] [Linker] projects/t113_s4_c906/evb1_auto/freertos.lds
CC build/t113_s4_c906_evb1_auto/arch/common/version.o
LD build/t113_s4_c906_evb1_auto/arch/common/obj-in.o
LD build/t113_s4_c906_evb1_auto/arch/obj-in.o
[LD] [Tina-RT-Builder] build/t113_s4_c906_evb1_auto/img/rt_system.elf
if [ -n /home/ping/workspace/t113_tina5.0/t113_tinasdk5.0-v1/rtos/lichee/rtos/bu ild/t113_s4_c906_evb1_auto/img/ ]; then mkdir -p /home/ping/workspace/t113_tina 5.0/t113_tinasdk5.0-v1/rtos/lichee/rtos/build/t113_s4_c906_evb1_auto/img; fi
Memory region Used Size Region Size %age Used
RAM: 214096 B 6 MB 3.40%
*[SYMS] [Tina-RT-Builder] build/t113_s4_c906_evb1_auto/img/rt_system.syms
*[IMAGE] [Tina-RT-Builder] build/t113_s4_c906_evb1_auto/img/rt_system.bin
text data bss dec hex filename
134576 69048 10472 214096 34450 build/t113_s4_c906_evb1_auto/img/rt_syst em.elf
copying /home/ping/workspace/t113_tina5.0/t113_tinasdk5.0-v1/rtos/lichee/rtos/bu ild/t113_s4_c906_evb1_auto/img/rt_system.bin to /home/ping/workspace/t113_tina5. 0/t113_tinasdk5.0-v1/rtos/board/t113_s4_c906/evb1_auto/bin/freertos.fex
#### make completed successfully
'/home/ping/workspace/t113_tina5.0/t113_tinasdk5.0-v1/rtos/lichee/rtos/build/t11 3_s4_c906_evb1_auto/img/rt_system.bin' -> '/home/ping/workspace/t113_tina5.0/t11 3_tinasdk5.0-v1/rtos/board/t113_s4_c906/evb1_auto/bin/rtos_riscv_sun8iw20p1.fex'
ping@embedall:~/workspace/t113_tina5.0/t113_tinasdk5.0-v1/rtos$
```
从以上信息我们得到一些信息,编译出来的固件名字是freertos.fex/rtos_riscv_sun8iw20p1.fex,其实两个固件是一样的。固件是编译出来,但是这个固件如何打包到Tina生成的根文件系统中呢?请看下一章。
**3.2.3、在Tina下编译RTOS方案**
在TinaSDK根目录中,先选择好整体平台方案,见如下说明:
* buildroot方案
1、首先使用如下命令选择整体平台方案
```
./build.sh config
```
2、然后RTOS相关操作命令如下
```
./build.sh rtos #单独编译RTOS方案
./build.sh rtos menuconfig #修改RTOS配置文件
./build.sh rtos clean #清除RTOS编译中间文件
```
注意:执行./build.sh不会编译RTOS
* openwrt方案
1、首先使用如下命令选择整体平台方案
```
source build/envsetup.sh #生效环境变量
lunch #选择openwrt方案
```
2、执行make会先编译RTOS,再编译Tina
* 快捷命令
在Tina根目录下,执行了source build/envsetup.sh配置环境后,可使用RTOS快捷命令进行RTOS的配置和编译等。
![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://bbs.aw-ol.com/assets/uploads/files/1731640728957-20b3f0e3-505c-4e2a-b368-f7b0e9e0b542-image.png)
**3.3、RTOS固件打包**
我们以编译openwrt方案为例,在的编译openwrt的过程中,会首先编译RTOS,然后将生成的镜像文件自动拷贝到对应平台方案中,并且rt_system.elf重名为amp_rv0.bin,见如下信息:
```
xxx@xxx:~/workspace/t113_tina5.0/t113_tinasdk5.0-v1$ make -j32
===There is tina environment.===
Note: make is the shell functon in envsetup.sh.
== action: openwrt_build, action_args: -j32 ==
========ACTION List: build_rtos ;========
options :
INFO: build rtos ...
Setup env done!
Run lunch_rtos to select project
last=t113_s4_c906_evb1_auto
select=t113_s4_c906_evb1_auto...
t113_s4_c906/evb1_auto
'/home/ping/workspace/t113_tina5.0/t113_tinasdk5.0-v1/rtos/lichee/rtos/projects/t113_s4_c906/evb1_auto/defconfig' -> '/home/ping/workspace/t113_tina5.0/t113_tinasdk5.0-v1/rtos/lichee/rtos/.config'
============================================
RTOS_BUILD_TOP=/home/ping/workspace/t113_tina5.0/t113_tinasdk5.0-v1/rtos
RTOS_TARGET_ARCH=riscv
RTOS_TARGET_CHIP=sun8iw20p1
RTOS_TARGET_DEVICE=t113_s4_c906
RTOS_PROJECT_NAME=t113_s4_c906_evb1_auto
============================================
Run mrtos_menuconfig to config rtos
Run m or mrtos to build rtos
build rtos ...
Dark Builder
Version (1.6.0 - BiCEP2 (Gravitational Waves))
*[CC] [SCRIPT] build/t113_s4_c906_evb1_auto/img/sys_config.fex
[CONF] [Tina-RT-Builder] .dbuild/..//include/generated/t113_s4_c906_evb1_auto/autoconf.h
[LDS] [Linker] projects/t113_s4_c906/evb1_auto/freertos.lds
CC build/t113_s4_c906_evb1_auto/arch/common/version.o
LD build/t113_s4_c906_evb1_auto/arch/common/obj-in.o
LD build/t113_s4_c906_evb1_auto/arch/obj-in.o
[LD] [Tina-RT-Builder] build/t113_s4_c906_evb1_auto/img/rt_system.elf
if [ -n /home/ping/workspace/t113_tina5.0/t113_tinasdk5.0-v1/rtos/lichee/rtos/build/t113_s4_c906_evb1_auto/img/ ]; then mkdir -p /home/ping/workspace/t113_tina5.0/t113_tinasdk5.0-v1/rtos/lichee/rtos/build/t113_s4_c906_evb1_auto/img; fi
Memory region Used Size Region Size %age Used
RAM: 214096 B 6 MB 3.40%
*[IMAGE] [Tina-RT-Builder] build/t113_s4_c906_evb1_auto/img/rt_system.bin
*[SYMS] [Tina-RT-Builder] build/t113_s4_c906_evb1_auto/img/rt_system.syms
text data bss dec hex filename
134576 69048 10472 214096 34450 build/t113_s4_c906_evb1_auto/img/rt_system.elf
copying /home/ping/workspace/t113_tina5.0/t113_tinasdk5.0-v1/rtos/lichee/rtos/build/t113_s4_c906_evb1_auto/img/rt_system.bin to /home/ping/workspace/t113_tina5.0/t113_tinasdk5.0-v1/rtos/board/t113_s4_c906/evb1_auto/bin/freertos.fex
#### make completed successfully
'/home/ping/workspace/t113_tina5.0/t113_tinasdk5.0-v1/rtos/lichee/rtos/build/t113_s4_c906_evb1_auto/img/rt_system.bin' -> '/home/ping/workspace/t113_tina5.0/t113_tinasdk5.0-v1/rtos/board/t113_s4_c906/evb1_auto/bin/rtos_riscv_sun8iw20p1.fex'
'/home/ping/workspace/t113_tina5.0/t113_tinasdk5.0-v1/rtos/lichee/rtos/build/t113_s4_c906_evb1_auto/img/rt_system.elf' -> '/home/ping/workspace/t113_tina5.0/t113_tinasdk5.0-v1/device/config/chips/t113_s4/configs/sbc_t113s4_nand/bin/amp_rv0.bin'
```
然后在Tina环境中打包,确保RTOS编译固件amp_rv0.bin打包到根文件系统中。
说明:
1)buildroot需要执行./build.sh&&./build.sh pack命令
2)openwrt需要执行make&&pack命令
打包完成后,生产的固件位于tina5.0/out/t113_s4_linux_sbc_t113s4_uart0.img,可以使用PhoenixSuit工具烧录到主板上。
**3.4、RISC-V核启动**
进入主核Linux控制台后,执行如下命令即可完成RV核异构通信框架的初始化:
```
echo start>/sys/class/remoteproc/remoteproc1/state
```
注:T113-S4处理器包括了DSP HIFI核心,也包括了RISC-V核心,因此它应该具备remoteproc0/remoteproc1两个节点(这两个节点在内核的DTS中是可配置的,可以删除任何一个节点)。如果两个节点都在,那么remoteproc0节点是DSP核心,remoteproc1节点是RISC-V核心。
**3.5、RTOS镜像文件更新**
更新RTOS镜像文件的方法有以下两种:
1、Tina Linux环境下,按照RTOS编译、RTOS固件打包步骤重新编译固件,并烧录进开发板,之后再启动RV核。
2、通过adb push将新生成的镜像文件amp_rv0.bin推到/lib/firmware目录下,在Linux控制台依执行如下命令:
```
echo stop>/sys/class/remoteproc/remoteproc1/state #关闭RV。
echo amp_rv0.bin>/sys/class/remoteproc/remoteproc1/firmware
echo start>/sys/class/remoteproc/remoteproc1/state #启动RV
```
-
发表了主题帖:
全志T113双核异构处理器的使用基于Tina Linux5.0——RTOS简介
全志T113-i是一款双核Cortex-A7国产工业级处理器平台,并内置玄铁C906 RISC-V和HiFi4 DSP双副核心,可流畅运行Linux系统与Qt界面,并已适配OpenWRT系统、Preempt Linux系统。
而其中的RISC-V属于超高能效副核心,标配内存管理单元,可运行RTOS或裸机程序。T113的主核运行Linux(Openwrt或者Preempt Linux)进行人机界面的交互和应用流程,而RISC-V则是后台
英雄,可进行大数据数据采集,或者相关编码器的控制等,降低主核被中断的次数,大大提供了主核的运行效率。
以盈鹏飞嵌入式SBC-T113主板为例(以T113-i为主控的主板),我们先介绍下主板特性:
**产品特性**
* 采用全志Cortex-A7双核T113-i处理器,运行最高速度为1.2GHZ;
* 列表内置64-bit XuanTie C906 RISC-V协处理器;
* 列表支持JPEG/MJPEG视频编码,最大分辨率1080p@60fps;支持多格式1080P@60fps视频解码 (H.265,H.264, MPEG-1/2/4);
* 列表支持双通道LVDS/MIPI-DSI,分辨率最高1920x1080;
* 列表支持512-1G Bytes DDR3 SDRAM;
* 列表支持SPI NAND存储和启动(默认:256MB;可选128MB)或者EMMC启动(默认:4GB,最大32GB);
* 列表支持四路USB2.0 HOST;
* 列表支持六路RS232通信;
* 列表支持双路CAN BUS通信(隔离);
* 列表支持双路以太网,一路10/100M;一路10/100/1000M;
* 列表稳定的操作系统的支持,可预装Ubuntu20.04/LINUX 5.4 Preempt/Tina5.0;
* 列表标准3.5寸主板, 尺寸为:146*102MM;
**SBC-T113产品功能图:**
![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://bbs.aw-ol.com/assets/uploads/files/1731634940802-sbc-t113.png)
****1、RTOS系统概述****
****1.1、概述****
全志Tina Linux SDK中包含了RTOS系统,该系统是基于FreeRTOS内核的软件开发包,包含了系统开发用到的内核源码、驱动、工具、组件与应用程序包。通过Makefile脚本和Kconfig配置文件,使得用户可以通过menuconfig进行个性化裁减,编译出一个可以直接烧写到机器上运行的RTOS系统软件。
**1.2、系统框图**
![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://bbs.aw-ol.com/assets/uploads/files/1731635049377-e28014db-faf1-40b1-8aee-4c82580cf06e-image.png)
RTOS 系统框图如图所示,仅从软件的角度来看,从下至上分为内核层、组件层、应用层三个层次。各层次主要内容如下:
* Kernel:内核层包括 FreeRTOS核心系统、文件系统、网络系统、BSP驱动等。
* Component:组件层包括控制台、多媒体、功耗管理、OTA、音频系统、显示系统、图像采集等。
* APP:应用层包括各种应用 demo。
**2、RTOS SDK目录结构**
```
rtos
├──board #包含各SoC板级配置目录
│└──mr527_e906 #mr527_e906板级配置目录
│└──t113_s3p_c906 #t113_s3p_c906板级配置目录
│└──t113_s4_c906 #t113_s4_c906板级配置目录
│└──t113_s4p_c906 #t113_s4p_c906板级配置目录
│└──XXX #XXX平台板级配置目录
├──envsetup.sh #SDK环境初始化脚本
├──lichee
│├──dsp #DSP FreeRTOS系统
│├──rtos #C906/E906FreeRTOS系统
│├──rtos components#FreeRTOS公共组件
│└──rtos hal #BSP驱动
└──tools #打包相关工具脚本目录
```
所使用RTOS SDK目录结构如上所示,主要包括如下几个关键目录:
board:板级配置目录,用于存放芯片方案的配置文件,主要包括系统配置文件sys_config.fex等。
lichee/dsp:存放DSPFreeRTOS系统、组件、应用。
lichee/rtos:存放E906FreeRTOS系统、组件、应用。
lichee/rtos components:公共组件目录,lichee/dsp与lichee/rtos都可以使用该组件。
lichee/rtos hal:BSP驱动目录,用于存放各种驱动代码。对lichee/dsp与lichee/rtos通用。
tools:工具目录,用于存放编译打包相关的脚本、工具等。
下面对lichee/rtos、lichee/rtos hal目录进行详细说明。lichee/dsp目录与lichee/rtos目录类似,此处不做介绍。
**2.1、lichee/rtos目录**
```
├──arch #处理器架构相关
├──build #编译临时文件输出目录
├──components #组件
├──drivers#驱动
├──include#头文件
├──kernel#FreeRTOS内核#方案工程
├──projects
├──scripts
└──tools#工具链
```
lichee/rtos目录主要包括arch(架构相关)、components(组件)、drivers(驱动)、include(头文件)、kernel(内核)、projects(工程)、toos(工具链)等目录,下面对常用重要目录分别进行介绍。
**2.1.1、arch目录**
arch目录主要放置跟SoC架构相关的内容,每个SoC单独目录管理,主要包括跟risc v架构相关的ARCH初始化、中断处理、异常处理、内存映射相关功能的实现。
```
lichee/rtos/arch/
├──common
└──risc v
├──arch.mk
├──c906
├──common
├──e906
├──includes
├──Kconfig
├──Makefile
├──sun55iw3p1
└──sun8iw20p1
```
**2.1.2、components目录**
components 目录包含 allwinner 和第三方的组件。
```
lichee/rtos/components/
├──aw
│├──blkpart
│├──bluetooth
│├──csi
│├──devfs
│├──healthd
│├──......
│├──watchpoint
│└──wireless_video
├──common >../../rtos components
└──thirdparty
├──common
├──console
├──cplusplus
├──elmfat
├──finsh_cli
├──......
└──vfs
```
**2.1.3、drivers目录**
drivers目录包含所需的外设驱动,主要包括各外设控制器驱动的具体实现(hal软连接)以及OSAL层接口(osal)。
```
lichee/rtos/drivers/
├──drv
├─ CPUfreq #POSIX头文件
├──leds
├── uart
├──.....
├── wireless
├─hal ->.../../rtos-hal/
└──osal
```
**2.1.4、include 目录**
include 目录统一管理各模块提供的数据结构定义及函数声明。
```
lichee/rtos/include/
├── arch
# 架构相关头文件
├── FreeRTOS_POSIX # POSIX头文件
├── ......
└── vsprintf.h
```
**2.1.5、kernel目录**
kernel目录主要包含FreeRTOS的kernel源码,全志实现的系统功能相关代码。
```
lichee/rtos/kernel/
├──FreeRTOS orig
│└──Source
└──Posix
```
**2.1.6 projects 目录**
projects目录下的每一个子目录代表一个project,实现main入口,选择不同的project编译出来的bin具有不同功能,每个project有独立的FreeRTOSConfig配置。例如t113-s4,其对应于t113_s4_c906子目录,这个子目录下面根据应用的不同建立不同的应用配置,如下有evb1_auto应用和evb1_auto_fastboot_video应用。
```
rtos/lichee/rtos/projects/t113_s4_c906/
├── evb1_auto
│ ├── defconfig
│ ├── defconfig_org
│ ├── freertos.lds.S
│ ├── Kconfig
│ ├── Makefile
│ └── src
│ ├── alsa_config.c
│ ├── assert.c
│ ├── card_default.c
│ ├── FreeRTOSConfig.h
│ ├── hooks.c
│ └── main.c
├── evb1_auto_fastboot_video
│ ├── defconfig
│ ├── freertos.lds.S
│ ├── Kconfig
│ ├── Makefile
│ └── src
│ ├── alsa_config.c
│ ├── assert.c
│ ├── card_default.c
│ ├── FreeRTOSConfig.h
│ ├── hooks.c
│ └── main.c
└── Makefile
```
**2.1.7、tools目录**
这个目录主要包含一些预编译好的交叉编译工具链。
```
xxx@xxx:lichee/rtos/tools$ ls -al
total 663248
drwxrwxr-x 3 ping ping 4096 Oct 21 14:28 .
drwxrwxr-x 13 ping ping 4096 Oct 21 16:02 ..
-rw-rw-r-- 1 ping ping 103333888 Jan 8 2024 gcc-arm-melis-eabi-8-2019-q3-update-linux.tar.bz2
-rw-rw-r-- 1 ping ping 106566166 Jan 8 2024 gcc-arm-none-eabi-8-2019-q3-update-linux.tar.bz2
-rwxrwxr-x 1 ping ping 137020992 Jan 8 2024 gcc-arm-none-eabi-8-2019-q3-update-win32.zip
drwxr-xr-x 9 ping ping 4096 Oct 21 14:29 riscv64-elf-x86_64-20201104
-rwxrwxr-x 1 ping ping 164604965 Jan 8 2024 riscv64-elf-x86_64-20201104.tar.gz
-rwxrwxr-x 1 ping ping 167614189 Jan 8 2024 Xuantie-900-gcc-elf-newlib-mingw-V2.6.1-20220906.tar.gz
xxx@xxx:lichee/rtos/tools$
```
目前risc v基于GCC8.4.0的交叉编译器。
```
xxx@xxx:lichee/rtos/tools$./riscv64-elf-x86_64-20201104/bin/riscv64-unknown-elf-gcc -v
Using built-in specs.
COLLECT_GCC=./riscv64-elf-x86_64-20201104/bin/riscv64-unknown-elf-gcc
COLLECT_LTO_WRAPPER=/home/ping/workspace/t113_tina5.0/t113_tinasdk5.0-v1/rtos/lichee/rtos/tools/riscv64-elf-x86_64-20201104/bin/../libexec/gcc/riscv64-unknown-elf/8.4.0/lto-wrapper
Target: riscv64-unknown-elf
Configured with: /ldhome/software/toolsbuild/slave/workspace/riscv64_build_elf_x86_64/build/../source/riscv/riscv-gcc/configure --target=riscv64-unknown-elf --with-mpc=/ldhome/software/toolsbuild/slave/workspace/riscv64_build_elf_x86_64/lib-for-gcc-x86_64-linux/ --with-mpfr=/ldhome/software/toolsbuild/slave/workspace/riscv64_build_elf_x86_64/lib-for-gcc-x86_64-linux/ --with-gmp=/ldhome/software/toolsbuild/slave/workspace/riscv64_build_elf_x86_64/lib-for-gcc-x86_64-linux/ --prefix=/ldhome/software/toolsbuild/slave/workspace/riscv64_build_elf_x86_64/install --disable-shared --disable-threads --enable-languages=c,c++ --with-system-zlib --enable-tls --enable-libgcctf --with-newlib --with-sysroot=/ldhome/software/toolsbuild/slave/workspace/riscv64_build_elf_x86_64/install/riscv64-unknown-elf --with-native-system-header-dir=/include --disable-libmudflap --disable-libssp --disable-libquadmath --disable-libgomp --disable-nls --src=../../source/riscv/riscv-gcc --with-pkgversion='T-HEAD RISCV Tools V1.10.2 B20201104' --enable-multilib --with-abi=lp64d --with-arch=rv64gcxthead 'CFLAGS_FOR_TARGET=-Os -mcmodel=medany' 'CXXFLAGS_FOR_TARGET=-Os -mcmodel=medany' CC=gcc CXX=g++
Thread model: single
gcc version 8.4.0 (T-HEAD RISCV Tools V1.10.2 B20201104)
```
**2.2、lichee/rtos hal目录**
lichee/rtos hal目录为BSP驱动目录,用于存放各种驱动代码。lichee/rtos/drivers目录下的rtos hal子目录软链接到该目录,下面对该目录进行介绍。
```
lichee/rtos hal
├──hal #BSP驱动代码
├──include #驱动相关头文件
└──tools
```
lichee/rtos hal目录主要包括hal(BSP驱动代码)、include(驱动相关头文件)等目录,下面分别对其进行介绍。
**2.2.1、hal目录**
hal目录主要包含各外设驱动代码以及驱动测试代码,source子目录为驱动代码,test子目录为驱动测试代码
```
lichee/rtos hal/hal
├──Makefile
├──source
│├──ccmu
│├──gpio
│├──......
│├──uart
│└──watchdog
└──test
├──ccmu
├──gpio
├──......
├──uart
└──watchdog
```
**2.2.2、include目录**
include目录主要包含驱动相关头文件以及系统相关接口头文件。
```
lichee/rtos hal/include
├──hal
│├──aw alsa lib
│├──aw_common.h
│├──......
│├──sunxi_hal_usb.h
│├──sunxi_hal_watchdog.h
│└──video
└──osal
├──hal_atomic.h
├──hal_cache.h
├──......
├──hal_waitqueue.h
└──hal_workqueue.h
```
- 2024-11-13
-
发表了主题帖:
DIY了一台无人机,用全志T113芯片
无人机飞控是无人机的核心部分,一般包括传感器、机载计算机和伺服作动设备三大部分,能否在对重量和体积有严苛要求的无人机结构上部署具有稳定功能的飞控,是影响无人机飞行表现的重要因素。
基于此,作者就基于全志T113-S3设计了一款仅有30x30孔距的超轻量无人机飞控,可以实现无人机的自稳飞行及远距离图传。
![在这里插入图片描述](https://www.aw-ol.com/storage/portal/83_BCDD_3_F_4_BC_5_46f6_BB_68_620053580440_fa8f4d8483.png)
![在这里插入图片描述](https://www.aw-ol.com/storage/portal/10142_ezgif_com_optimize_b4454ac037.gif)
![在这里插入图片描述](https://www.aw-ol.com/storage/portal/101411_ezgif_com_optimize_e72a1f479f.gif)
# 飞控设置
这款使用全志T113-S3处理器制作的PX4飞控整体硬件设计并不复杂,飞控板载主控、IMU、磁力计、气压计以及其它常见的元件,并由T113直接输出PWM控制飞行器,并使用1路ADC来采集电池的电压,PCB孔距30x30,可以与市面上常见的四合一电调搭配使用。
![在这里插入图片描述](https://www.aw-ol.com/storage/portal/D677_F783_958_D_40eb_BBA_1_AA_68_EB_9_C5300_7969347431.png)
远程通信方面,T113通过USB直接与WiFi模块连接,接收机则是连接串口通过SBUS和T113直接连接,收到指令信号后由4路PWM直接给电机控制输出,以实现自稳飞行的功能。
![在这里插入图片描述](https://www.aw-ol.com/storage/portal/4_E6_D13_A7_2553_429d_8_B8_B_FA_52384_CF_961_0d93dcd395.png)
- 主控:全志T113,双核ARM A7
- 内存:内置128MB DDR
- 磁力计:IST8310
- 气压计:BMP388
- IMU:BMI088
- 操作系统:全志Tina Linux
# 无人机自稳飞行功能测试
无人机通过飞控和WiFi模块结合,形成一个SBUS接收机,来实现本地的数据传输与远程控制。
如下图中的画面所示,左侧是飞控通过WiFi与QGC连接后将无人机姿态数据返回的显示界面,右侧的画面则是T113芯片的负载情况显示,T113是双核处理器,作者这里只把T113的核心1做了隔离,只运行PX4程序,所以可以通过核心1的反馈直接看运行PX4程序的负载情况,核心0是负责系统上的其他程序运行。
![在这里插入图片描述](https://www.aw-ol.com/storage/portal/10141_ezgif_com_video_to_gif_converter_5cc946080d.gif)
首先在自稳模式下将PID参数调稳定,调试Multicopter Rate Control菜单下的相关参数,自稳PID调试完成后,此时飞行会发现飞行器总是会朝某个方向“倾斜”飞行,此时最好先将机体各部位都固定稳定,中心最好在机体中心(电池位置最好也固定,不然电池的拆卸也是影响重心的一个要点)。
然后调试Sensors菜单下的两个参数,最完美的状态是调试到roll和pitch不总是朝一个方向飞行,只会随机朝某个方向缓慢飞行。随后切换到offboard模式进行定位调试,如果设置指定高度后飞行器一直飞行不到指定高度,调试定位的参数。
-
发表了主题帖:
成本400元,DIY一个高刷新率热成像相机
在市面上开源的热成像作品中,有一部分颜值高,但**分辨率太低**;也有一部分把分辨率提高了,但使用起来**却不太流畅**。
基于此,作者本人结合二者的优势,设计了一款**热成像相机——LiThermal**,成本算下来只要400出头,还具备了万全的功能。
![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://bbs.aw-ol.com/assets/uploads/files/1730081760045-ac71b06c-eeb3-47df-920b-d328846fac9d-image.png)
- 拍照
- 录像
- 查看相册
- 查看温度最大值、最小值、中心值
- 温度统计图
- 修改调色板
- 重定向后台管理页面,电脑访问
这款热成像相机不仅拥有高分辨率及丝滑流畅的拍摄,在主控全志T113的加持下,UI界面的几乎所有动画都能达到**90Hz刷新率**,并支持随意的动画打断,最重要的是,作者将热成像相机的**软硬件全部开源**了出来!
![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://bbs.aw-ol.com/assets/uploads/files/1731460913551-%E5%BC%80%E6%9C%BA%E7%95%8C%E9%9D%A2.gif)
热成像相机开机动画演示
![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://bbs.aw-ol.com/assets/uploads/files/1731460937210-%E6%B8%A9%E5%BA%A6%E5%9B%BE%E8%B0%B1.gif)
PCB温度检测演示
![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://bbs.aw-ol.com/assets/uploads/files/1731460950031-%E8%BF%9C%E8%B7%9D%E7%9B%B8%E6%9C%BA%E6%A3%80%E6%B5%8B.gif)
远距相机检测演示
# 热成像相机功能
相机不仅支持高清拍照功能,而且在拍照的同时能够即时捕捉并显示全屏范围内的温度数据,为用户提供直观的温度分布视图,拍摄后的照片和视频都可以在相册中查看。
![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://bbs.aw-ol.com/assets/uploads/files/1731460963424-%E7%9B%B8%E5%86%8C.gif)
此外,该设备还提供了温度数据的最大值、最小值以及中心值的查看功能,帮助快速识别温度异常区域,为了更直观地展示温度变化趋势,设备还贴心配备了温度统计图功能。
为了满足不同用户的需求,设备还支持自定义调色板,根据个人偏好或特定应用场景调整色彩显示方案,重定向后台管理页面的功能,可以通过电脑访问后台管理系统,实现更高级的设置和数据管理操作。
![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://bbs.aw-ol.com/assets/uploads/files/1731460972978-%E7%9B%B8%E6%9C%BA%E8%AE%BE%E7%BD%AE1.gif)
![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://bbs.aw-ol.com/assets/uploads/files/1731460972963-%E7%9B%B8%E6%9C%BA%E8%AE%BE%E7%BD%AE.gif)
# 系统配置
作者直接为相机在全志Tina Linux系统上基于LVGL8设计一套全新的UI界面,并顺利的在2.4寸的320x240分辨率TFT LCD屏幕上以最高94.3 Hz的刷新率流畅运行。
在热成像方面,该设备表现尤为突出,刷新率达到了25Hz,能够实时捕捉温度变化,测温范围也覆盖到0-106.4 ℃,零下的条件下作者未进行测试,但问题不大,基本满足了多种应用场景的需求。传感器方面,设备采用了160*120分辨率的传感器,确保了温度数据的精确捕捉。
- 主控:全志T113
- 存储:SIP 128MB
- 屏幕:2.4寸 TFT LCD, 320x240 @ 94.3 Hz
- 热成像刷新率:25Hz
- 测温范围:0-106.4 ℃ (零下没试过,据说可以测到-20 ℃)
- 传感器分辨率:160*120
- 操作系统:全志Tina Linux,基于OpenWRT
- GUI:LVGL8
![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://bbs.aw-ol.com/assets/uploads/files/1731460985951-%E5%8A%A8%E7%94%BB%E6%89%93%E6%96%AD.gif)
复刻注意事项:本作品难度较大,想要完整复刻需要能够焊接0402元件和0.3毫米间距的QFP引脚,并且需要有一定Linux系统使用经验和计算机网络基础,请做好心理准备。
![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://bbs.aw-ol.com/assets/uploads/files/1731460995553-%E7%84%8A%E6%8E%A5.gif)
- 2024-09-02
-
发表了主题帖:
全志Linux磁盘操作基础命令
# 磁盘操作
## fdisk命令
> fidsk是一个用来创建和维护磁盘设备分区的一个实用工具。
```bash
[ubuntu@book:~]$ fdisk -l //列出当前系统所有的磁盘设备
[ubuntu@book:~]$ fdisk /dev/sdc //操作设备节点为 /dev/sdc的一个设备。
```
* p : 显示所有的分区。
* d: 删除分区。
* n: 创建一个新的分区。
* t : 更改分区类型。
* w: 保存修改并退出。
* m: 显示帮助信息。
## gparted
> 图形化分区操作工具。
```bash
[ubuntu@book:~]$ sudo apt install gparted
```
## mkfs.fat
> 格式化分区为 fat32类型
```bash
[ubuntu@book:~]$ sudo mkfs.fat /dev/sdc1
```
## mkfs.ext2/3/4
> 格式化文件系统类型为 Linux EXT类型。
```bash
[ubuntu@book:~]$ sudo mkfs.ext4 /dev/sdc2
```
## mount命令
> 挂载系统外的磁盘分区或者目录等。
```ba
[ubuntu@book:~]$ sudo mount -t vfat /dev/sdc1 /mnt
[ubuntu@book:~]$ sudo umont /mnt
[ubuntu@book:~]$ sudo umont /dev/sdc1
[ubuntu@book:~]$ sudo mount -t ext4 /dev/sdc2 /mnt
[ubuntu@book:~]$ sudo umont /mnt
[ubuntu@book:~]$ sudo umont /dev/sdc2
```
## df命令
> 显示Linux上文件系统磁盘使用的占用情况。
```bash
[ubuntu@book:~]$ df //显示文件系统的磁盘使用情况。
[ubuntu@book:~]$ df -h //以易读的形式展示输出磁盘的使用情况
```
## du命令
> 用于显示目录或文件大小。
```bash
[ubuntu@book:~]$ du //显示当前目录下的所有文件及目录大小。
[ubuntu@book:~]$ du -h //以比较直观的方式显示所有文件及目录大小。
[ubuntu@book:~]$ du dir -h //以比较直观方式显示dir目录大小。
[ubuntu@book:~]$ du file1 //显示file文件大小。
[ubuntu@book:~]$ du dir -h --max-depth=1 //以比较直观的方式显示dir目录并只显示目录深度为1级。
```
## dd命令
> dd命令用于数据的读取转换等操作。
```ba
[ubuntu@book:~]$ dd --help //查看dd帮助命令。
[ubuntu@book:~]$ dd if=/dev/zero of=dd.img count=1024 bs=1M //生产一个1G大小的dd.img镜像
[ubuntu@book:~]$ mkfs.ext4 dd.img //格式化为 ext4文件系统类型。
[ubuntu@book:~]$ sudo mount -t ext4 dd.img /mnt //挂载到 /mnt目录下,之后进行操作。
[ubuntu@book:~]$ sudo umount /mnt //操作完成后卸载该挂载的镜像。
```
-
发表了主题帖:
8月全志芯片开源项目分享合集
# T113环境温湿度采集与监控板
### 作者:lin_xiaoyan
本项目的基本原理是由下位机采集温湿度信息到监控端,并由T113读取SHT30高精度温湿度芯片,UI采用高仿HomeAssistant的样式显示室内温湿度情况,同时通过网络获取天气、室外温湿度,Lottie动画图标显示当前天气情况和室外温湿度参数,可谓可视化拉满。
T113监控端跑的Tina-Linux系统,Gui使用LVGL,采用10.1寸超大屏,采用高斯模糊(毛玻璃特效)背景,有高大上的动画时钟显示,它可以是天气时钟,也可以是家庭中控,通过TCP通信(后续改成MQTT),可以进行智能家居控制。
在PCB设计时对一些功能进行取舍,去掉了TV功能和TP(电阻触摸)功能,在传输完成后上位机会进行休眠,休眠功耗仅达uA级。
![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://bbs.aw-ol.com/assets/uploads/files/1725241538415-577ab4f5-714a-483f-88aa-1decdccacaef-image.png)
![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://bbs.aw-ol.com/assets/uploads/files/1725241557336-e9bbfb9d-53d7-4a19-b277-a69eca8cc077-image.png)
![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://bbs.aw-ol.com/assets/uploads/files/1725241560285-79cad74f-faad-4905-b169-f0931af2b8b4-image.png)
# 全志T113-S3自稳PX4飞控
### 作者:光轮电子
使用全志T113-S3处理器制作的PX4飞控,飞控板载主控、IMU、磁力计、气压计以及其它常见的元件,并由T113直接输出PWM控制飞行器,PCB孔距30x30,可以与市面上常见的四合一电调搭配使用。
远程通信方面,T113通过USB直接与WiFi模块连接,接收机则是连接串口通过SBUS和T113直接连接,收到指令信号后由4路PWM直接给电机控制输出,以实现自稳飞行的功能。
![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://bbs.aw-ol.com/assets/uploads/files/1725241595827-228959ee-4194-4b68-97c1-6342c87dd68e-image.png)
![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://bbs.aw-ol.com/assets/uploads/files/1725241603653-5e972cf5-5700-490e-b2c7-a736619d82d9-image.png)
![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://bbs.aw-ol.com/assets/uploads/files/1725241608803-a17fda04-f865-4f11-9c95-2eca2492f5c1-image.png)
# 太极派LVGL版USB口袋显示屏
### 作者:新范者1986
上一期开源项目T113太极派的搬运工,作者在上面适配了开源软件参考,可以仅连接一根USB线,实现养宠物、qq放入、视频播放、歌词流动等副屏功能,最重要的是,该显示屏支持多屏同时连接,不受hdmi口限制。
副屏使用全志t113-s3为主控,分辩率480*480,支持win10/win11系统的扩展屏,支持电容屏触,电容屏hid触摸屏软件开发中 。
该项目有开源了windows驱动、lvgl界面app应用、tina Linux内核驱动的源码。
![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://bbs.aw-ol.com/assets/uploads/files/1725241619978-93be30f9-df9a-42e0-b642-11980686078b-image.png)
![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://bbs.aw-ol.com/assets/uploads/files/1725241632371-f4bbe6db-9d49-493b-8337-64cb9cfdc1e4-image.png)
![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://bbs.aw-ol.com/assets/uploads/files/1725241635230-207f6f81-717f-4dcc-9c63-34abd62563eb-image.png)
# linux-card
### 作者:syske
作者本人的第一块全志F1C200S的实验板,踩了很多坑,更新了六个版本的PCB才所完美解决所有的问题,板子成功驱动、u-boot编译运行成功、linux成功运行。
板子本身并没有什么很突出的亮点,但很适合作为初学者小白进行Linux开发板设计学习的第一块开发板,成本25元就可以完整走一趟板子的设计、打板、焊接、编译、烧录,直到完全熟悉整个PCB制作过程。
![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://bbs.aw-ol.com/assets/uploads/files/1725241688093-84b9eb85-ed12-4565-8656-e39e2baced51-image.png)
![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://bbs.aw-ol.com/assets/uploads/files/1725241699891-2c6a1e6c-97cd-4372-bbf7-d88fda21150f-image.png)
- 2024-08-27
-
发表了主题帖:
为了学习内核开发,大佬手搓了一个轻量级操作系统YiYiYa OS
![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://bbs.aw-ol.com/assets/uploads/files/1724635206585-705f822f-02f3-4227-abfc-cfa47c633ff5.png)
YiYiYa操作系统是一个朴实无华的操作系统,追求快速开发,最小实现,同时遵循SOLID原则。编码简洁明了,非常适合学习操作系统的同学。目前既有宏内核,也逐步实现了微内核架构,未来将会是混合内核。
目前YiYiYa OS支持很多种架构和平台,包括ARM-Cortex A7系列的V3s、T113-S3等芯片、ARM9内核的F1C系列芯片以及部分RISC-V内核芯片,所有移植教程及方法都在Github上公开。
![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://bbs.aw-ol.com/assets/uploads/files/1724635230142-2024-01-20-15-53-16.png)
![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://bbs.aw-ol.com/assets/uploads/files/1724635236167-2024-01-20-16-37-45-1.png)
# 系统架构
架构从上而下分层设计,同一层从左到右为模块。越下层与用户离得远,就会变得越通用越公共。分层设计便于扩展,方便维护,每一层的职责单一,让每一层依赖都是固定,不会胡乱调用(实现低耦合)。同时高层依赖底层,依赖接口,不依赖具体细节实现,底层的改动不至于影响太大,这就是基本的设计原则。
![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://bbs.aw-ol.com/assets/uploads/files/1724635252850-arch.png)
## 应用层
应用层直接和用户操作打交道。有图形界面和shell命令交互。此层面对用户开发应用和常用库,对应源码目录为app。
![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://bbs.aw-ol.com/assets/uploads/files/1724635283122-2024-01-21-17-19-45.png)
## 应用层
应用层直接和用户操作打交道。有图形界面和shell命令交互。此层面对用户开发应用和常用库,对应源码目录为app。
## 接口层(C标准库)
接口层为操作系统内核向外核提供的基本功能。通过libc和libmusl可选,实现基本的标准库,方便开发者直接移植代码或者适配应用app。
## 内核层
内核层则为核心领域业务。每一小个模块都提供基本的功能。按各自的职责划分,分别对应与传统内核层则为核心领域业务。每一小个模块都提供基本的功能。按各自的职责划分,分别对应与传统操作系统的内存管理、进程通信、文件系统、进程通信、等等。在演进操作系统时候,可以修改这里,对应源码目录为kernel。
## 基础设施层(公共层和硬件层)
将硬件CPU相关和平台模块相关的单独作为公用库使用。目录为arch、platform、libs/kernel。
在移植适配的时候基本上和这些模块打交道比较多,同时单独一个库可以提高内核代码复用性,内核有专门的内核库,以便增加代码安全,减少出错。
![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://bbs.aw-ol.com/assets/uploads/files/1724635311995-828c40bf93c9-resized.jpg)
* 支持荔枝派系列开发板,全志V3s,F1C200S,T113-S3等芯片,RISC-V的支持在规划中
* 支持uboot引导内核,同时支持不需要uboot引导模式
* 支持lcd屏幕,st7789、st7735、通用40pin rgb屏幕
* 支持vfs,fat32文件格式
* 支持elf文件,ipc管道等
* 支持ahci、gpio、i2c、spi驱动等
# 系统移植教程
作者本人及团队自制的开源掌机FunKey所采用的操作系统就是基于Linux内核和YiYiYa OS,YiYiYa OS内提供了丰富的桌面系统和游戏开发框架,其非常简易的移植过程,也让开发者可以轻松地运用YiYiYa OS裸机开发自己的设备。
以基于T113-S3开发的FunKey掌机为例,在进行平台移植时,需要在新增的duck/platform目录下添加gpio.h头文件以及编写 init.c 包含基本的串口功能,然后再执行以下三个步骤,就可以轻松运行起YiYiYa OS:
克隆项目
```
git clone https://github.com/evilbinary/YiYiYa.git
make pull
```
安装构建工具
```
pip install yymake
```
编译
```
ya -m debug -p t113-s3 -r t113-s3
```
![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://bbs.aw-ol.com/assets/uploads/files/1724635467911-jkjkk.gif)
#其它功能及开源资料获取
整体来说,YiYiYa操作系统非常轻量,支持POSIX操作系统标准协议,同时还支持扩展,方便使用其他语言开发模块。在应用层,可以通过libc/libmusl标准库和常用的库开发应用;在内核层可以调用基本内核模块的功能和共用库,开发者可以在DIY过程中自行选择。
![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://bbs.aw-ol.com/assets/uploads/files/1724635490893-2024-01-20-16-25-29.png)
![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://bbs.aw-ol.com/assets/uploads/files/1724635500117-2024-01-20-16-26-27.png)
![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://bbs.aw-ol.com/assets/uploads/files/1724635505670-2024-01-20-16-26-56.png)
- 2024-08-20
-
发表了主题帖:
飞凌OK-全志T527开发板nbench性能测试
T527芯片采用了8核处理器(4大核+4小核),芯片性能不容小觑,那么实际表现到底如何呢?这里笔者使用nbench作为CPU性能测试工具,对T527芯片的芯片性能进行测试。
首先介绍一下nbench:
nbench是一款专门用于处理器以及存储器性能测试的基准测试程序,即著名的BYTE Magazine杂志的BYTEmark benchmark program,nbench在系统中运行并将结果和一台运行Linux的AMD K6-233电脑比较,得到的比值作为性能指数。由于是完全开源的,爱好者可以在各种平台和操作系统上运行Nbench,并进行优化和测试,是一个简单有效的性能测试工具。Nbench的结果主要分为MEM、INT和FP,其中MEM指数主要体现处理器总线、CACHE和存储器性能,INT整数处理性能,FP则体现双精度浮点性能(大多数嵌入式处理器都没有强大的双精度浮点能力)。
想让nbench运行在我们ARM64平台也是十分简单:
Step1:获取源码
```cpp
wget http://www.math.utah.edu/~mayer/linux/nbench-byte-2.2.3.tar.gz
tar -xvzf nbench-byte-2.2.3.tar.gz
cd nbench-byte-2.2.3
```
Step2:源码编译,此处注意如果需要在arm64平台运行,则需要将Makefile中的CC改为aarch64-linux-gnu-gcc,才可以得到对应平台支持的二进制文件。
```cpp
Make
```
Step3:运行测试
```cpp
./nbench
```
**测试项 含义**
NUMERIC SORT 数字排序——对长整数数组进行排序
STRING SORT 字符串排序——对任意长度的字符串数组进行排序。
BITFIELD 执行各种位操作函数。
FP EMULATION 一个小的软件浮点包。
FOURIER 傅里叶系数-计算波形级数近似的数值分析程序。
ASSIGNMENT 一个著名的任务分配算法。
IDEA 一种比较新的分组密码算法。
HUFFMAN 哈夫曼压缩-一个著名的文本和图形压缩算法。
NEURAL NET 一个小但功能强大的反向传播网络模拟器。
LU DECOMPOSITION 解线性方程组的鲁棒算法。
T527的测试结果如下。
![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://bbs.aw-ol.com/assets/uploads/files/1721665944474-db73260c-8f9f-4a3a-ae47-124011db656d-image.png)
RK3566(4大核)的测试结果如下:
![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://bbs.aw-ol.com/assets/uploads/files/1721665948942-bfade689-87a1-4ae4-abf1-293d0a3248a5-image.png)
PC(AMD 4750G)上的测试结果如下:
![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://bbs.aw-ol.com/assets/uploads/files/1721665952958-8563a7dd-4a7c-4f27-ad91-ea13e9ff6716-image.png)
可以看到部分指标已经有台式机1/3或者1/2的得分了,要知道这可是兼顾了功耗的ARM平台,而且对标的对手是8大核的桌面级CPU,可见T527的芯片性能还是很强大的。
- 2024-08-05
-
发表了主题帖:
全志模块设备开发之PWM编程基础介绍
## 11.1 PWM概述
PWM,英文名Pulse Width Modulation,是脉冲宽度调制缩写,它是通过对一系列脉冲的宽度进行调制,等效出所需要的波形(包含形状以及幅值),对模拟信号电平进行数字编码,也就是说通过调节占空比的变化来调节信号、能量等的变化,占空比就是指在一个周期内,信号处于高电平的时间占据整个信号周期的百分比,例如方波的占空比就是50%。是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术。
![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](http://photos.100ask.net/NewHomeSite/PWM_image1.jpg)
PWM信号把模拟信号转化为数字电路所需要的编码,现在基本是采用数字电路,因此在很多场合都采用PWM信号,我们经常见到的就是交流调光电路,也可以说是无级调速,高电平占多一点,也就是占空比大一点亮度就亮一点,占空比小一点亮度就没有那么亮,前提是PWM的频率要大于我们人眼识别频率,要不然会出现闪烁现象。除了在调光电路应用,还有在直流斩波电路、蜂鸣器驱动、电机驱动、逆变电路、加湿机雾化量等都会有应用。
![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](http://photos.100ask.net/NewHomeSite/PWM_image2.jpg)
### 11.1.1 PWM的参数说明
https://www.kernel.org/doc/Documentation/pwm.txt **period** PWM信号的总周期(读/写)。 值以纳秒为单位,是活动和非活动的总和 PWM的时间。
**duty_cycle(占空比)** PWM信号的有效时间(读/写)。 值以纳秒为单位,且必须小于周期。 在NORMAL模式下,表示一个周期内高电平持续的时间 在INVERTED模式下,表示一个周期中低电平持续的时间
**polarity** 改变PWM信号的极性(读/写)。 写入此属性仅在PWM芯片支持更改时才有效 极性。只有PWM不能改变极性 启用。值是字符串“normal”或“inversed”。
**enable** 启用/禁用PWM信号(读/写)。
* 0 - 禁用
* 1 - 启用
## 11.2 用户层查看PWM
如果在内核配置中启用了CONFIG_SYSFS,则会提供一个简单的sysfs接口来使用用户空间的PWM。它在/ sys / class / pwm /中公开。每个被探测的PWM控制器/芯片将被输出为pwmchipN,其中N是PWM芯片的基础。你在目录里面会发现:
```c
1 echo 0 > /sys/class/pwm/pwmchip0/export /*设置PWM4输出,调出pwm0目录下设备节点,用于以下配置 */
```
```c
2 echo 1000000 >/sys/class/pwm/pwmchip0/pwm0/period /*设置PWM4一个周期的持续时间,单位为ns,即1K Hz */
```
```c
3 echo 500000 >/sys/class/pwm/pwmchip0/pwm0/duty_cycle /*设置一个周期中的”ON”时间,单位为ns,即占空比=duty_cycle/period=50% */
```
```c
4 echo 1 >/sys/class/pwm/pwmchip0/pwm0/enable /*设置PWM4使能 */
```
## 11.3 PWM的SYSFS使用
```c
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define dbmsg(fmt, args ...) printf("%s[%d]: "fmt"\n", __FUNCTION__, __LINE__,##args)
#define DUTY "duty"
#define PERIOD "1000000"
#define DUTYCYCLE "500000"
#define LENGTH 100
int fd_period = 0,fd_duty = 0,fd_enable = 0,duty_m = 0;
int usage()
{
printf("usage:\n");
printf("./pwm-sysfs-test duty : 0-->static; 1-->dynamic \n");
return 0;
}
int pwm_setup()
{
int fd,ret;
fd = open("/sys/class/pwm/pwmchip0/export", O_WRONLY);
if(fd < 0)
{
dbmsg("open export error\n");
return -1;
}
ret = write(fd, "0", strlen("0"));
if(ret < 0)
{
dbmsg("creat pwm0 error\n");
return -1;
}else
dbmsg("export pwm0 ok\n");
fd_period = open("/sys/class/pwm/pwmchip0/pwm0/period", O_RDWR);
fd_duty = open("/sys/class/pwm/pwmchip0/pwm0/duty_cycle", O_RDWR);
fd_enable = open("/sys/class/pwm/pwmchip0/pwm0/enable", O_RDWR);
if((fd_period < 0)||(fd_duty < 0)||(fd_enable < 0))
{
dbmsg("open error\n");
return -1;
}
ret = write(fd_period, PERIOD,strlen(PERIOD));
if(ret < 0)
{
dbmsg("change period error\n");
return -1;
}else
dbmsg("change period ok\n");
ret = write(fd_duty, DUTYCYCLE, strlen(DUTYCYCLE));
if(ret < 0)
{
dbmsg("change duty_cycle error\n");
return -1;
}else
dbmsg("change duty_cycle ok\n");
ret = write(fd_enable, "1", strlen("1"));
if(ret < 0)
{
dbmsg("enable pwm0 error\n");
return -1;
}else
dbmsg("enable pwm0 ok\n");
duty_m = atoi(DUTYCYCLE)/2;
printf("duty_m: %d \n",duty_m);
return 0;
}
int main ( int argc, char *argv[] )
{
int ret;
int num;
if(argc < 2)
{
usage();
return -1;
}
if(strncmp(argv[1],DUTY, sizeof(DUTY)) == 0)
{
dbmsg("%s", DUTY);
if(argc != 3)
{
usage();
return -1;
}
pwm_setup();
}
return 0;
}
```
## 11.4 PWM应用编程
The main useful user API are the following: devm_pwm_get() or pwm_get() / pwm_put(): this API is used to look up, request, then free a PWM device. pwm_init_state(),pwm_get_state(), pwm_apply_state(): this API is used to initialize, retrieve and apply the current PWM device state. pwm_config(): this API updates the PWM device configuration (period and duty cycle).
### 11.4.1 修改设备树
```c
beeper {
compatible = "pwm-beeper";
pwms = ;
pinctrl-names = "default";
pinctrl-0 = ;
};
```
### 11.4.2 修改配置文件
```c
Activate PWM framework in the kernel configuration through the Linux menuconfig tool, Menuconfig or how to configure kernel (CONFIG_PWM=y):
Device Drivers --->
[*] Pulse-Width Modulation (PWM) Support --->
```
### 添加驱动
```c
#include
#include
#include
#include
#include
#include
//#include
#define PWM_ON 0x100001
#define PWM_OFF 0x100002
struct pwm_device *pwm_dev_2;
struct pwm_device *pwm_dev_3;
static long pwm_ioctl(struct file *file,
unsigned int cmd,
unsigned long arg)
{
int ret;
switch(cmd) {
case PWM_ON:
ret = pwm_config(pwm_dev_2,200000,500000);
if(ret < 0){
printk("pwm_dev_2 ioctl fail");
return 0;
}
ret = pwm_config(pwm_dev_3,300000,500000);
if(ret < 0){
printk("pwm_dev_3 ioctl fail");
}
pwm_enable(pwm_dev_2);
pwm_enable(pwm_dev_3);
break;
case PWM_OFF:
ret = pwm_config(pwm_dev_2,0,500000);
if(ret < 0){
printk("pwm_dev_2 ioctl fail");
return 0;
}
ret = pwm_config(pwm_dev_3,0,500000);
if(ret < 0){
printk("pwm_dev_3 ioctl fail");
}
pwm_disable(pwm_dev_2);
pwm_disable(pwm_dev_3);
break;
}
return 0;
}
//定义初始化硬件操作方法
static struct file_operations pwm_fops = {
.owner = THIS_MODULE,
.unlocked_ioctl = pwm_ioctl
};
//定义初始化混杂设备对象
static struct miscdevice pwm_misc = {
.minor = MISC_DYNAMIC_MINOR, //动态分配次设备号
.name = "mypwm", //dev/mypwm
.fops = &pwm_fops
};
static int pwm_init(void)
{
int ret;
printk("regisger pwm_misc device\n");
//1.申请pwm资源,设置输出为0
pwm_dev_2 = pwm_request(1,"pwm_2");
if(pwm_dev_2 == NULL){
printk("pwm_dev_2 register fail\n");
}
pwm_dev_3 = pwm_request(2,"pwm_3");
if(pwm_dev_3 == NULL){
printk("pwn_dev_3 register fail\n");
}
ret = pwm_config(pwm_dev_2,0,500000);
if(ret < 0){
printk("pwm_config_2 init fail\n");
return 0;
}
ret = pwm_config(pwm_dev_3,0,500000);
if(ret < 0){
printk("pwm_config_3 init fail\n");
return 0;
}
ret = pwm_enable(pwm_dev_2);
if(ret == 0){
printk("pwm_enable_dev_2 init success\n");
}
if(ret < 0 ){
printk("pwm_enable_dev_2 init fail\n");
return 0;
}
ret = pwm_enable(pwm_dev_3);
if(ret == 0){
printk("pwm_enable_dev_3 init success\n");
}
if(ret < 0 ){
printk("pwm_enable_dev_3 init fail\n");
return 0;
}
//2.注册混杂设备
misc_register(&pwm_misc);
return 0;
}
static void pwm_exit(void)
{
printk("unregister pwm_misc device\n");
//1.卸载混杂设备
misc_deregister(&pwm_misc);
//2.释放pwm资源
pwm_config(pwm_dev_2,0,500000);
pwm_disable(pwm_dev_2);
pwm_free(pwm_dev_2);
pwm_config(pwm_dev_3,0,500000);
pwm_disable(pwm_dev_3);
pwm_free(pwm_dev_3);
}
module_init(pwm_init);
module_exit(pwm_exit);
MODULE_LICENSE("GPL");
```
### 11.4.4 运行测试
```c
#include
#include
#include
#include
#define PWM_ON 0x100001
#define PWM_OFF 0x100002
int main(void)
{
int fd;
int a;
fd = open("/dev/mypwm", O_RDWR);
if (fd < 0)
return -1;
while(1) {
ioctl(fd, PWM_ON);
}
close(fd);
return 0;
}
```
-
发表了主题帖:
全志模块设备开发之GPIO编程基础介绍
## 9.1 GPIO编程基础介绍
GPIO(General-Purpose IO Ports),即通用IO接口。GPIO的使用较为简单,主要分为输入和输出两种功能。GPIO主要用于实现一些简单设备的控制。在作为输入型GPIO的情况下,我们可以将该IO连接外部按键或者传感器,用于检测外部状态。当作为输出时,我们可以通过输出高低电平来控制外部设备的运转。
由于GPIO的功能多种多样,我们需要首先将引脚设置为GPIO。设置为GPIO之后,我们需要设置GPIO的方向。当设置为输出时,我们可以控制输出高电平或者低电平。当设置为输入时,我们可以读取GPIO的电平来判断外部输入电平的高低。
## 9.2 GPIO编程软件接口
GPIO编程有多种实现方式,在这里,我们通过sysfs方式来实现GPIO的控制实现。
如果要通过sysfs方式控制gpio,首先需要底层内核的支持。为了实现内核对sysfs gpio的支持,我们需要在内核中进行设置。在编译内核的时候,加入 Device Drivers-> GPIO Support ->/sys/class/gpio/… (sysfs interface)。作为GPIO的引脚,不允许在内核中被用作其他用途。
在系统正常运行之后,我们可以在/sys/class/gpio下看到sysfs控制相关的接口。有三种类型的接口, 分别是控制接口,GPIO信号和GPIO控制器三种接口。这部分的具体介绍可参考《kernel\Documentation\gpio\sysfs.txt》。
#### 9.2.1 控制接口
控制接口用于实现在用户空间对GPIO的控制,主要包括/sys/class/gpio/export和/sys/class/gpio/unexport两个接口。这这两个控制接口都是只写的,/sys/class/gpio/export实现将GPIO控制从内核空间导出到用户空间,/sys/class/gpio/unexport用于实现取消GPIO控制从内核空间到用户空间的导出。
下面以引脚编号为19的GPIO为例进行说明,在/sys/class/gpio/目录下,我们执行"echo 19 > export"之后,将会产生一个”gpio19”节点来控制引脚编号为19的GPIO。我们执行"echo 19 > unexport"之后,将会删除之前通过export产生的”gpio19”节点。为了使用gpio,我们需要首先使用/sys/class/gpio/export导出gpio引脚编号。完成使用之后,通过/sys/class/gpio/unexport删除掉之前导出的gpio引脚。
#### 9.2.2 GPIO信号
GPIO信号,即为GPIO本身,其路径为/sys/class/gpio/gpioN/,拥有多个属性。通过对这些属性进行控制,就可以实现对GPIO的控制。
* “direction”属性,读取的值为”in”或者”out”。通过对该属性写入”in”或者”out”可以设置该GPIO为输入或者输出。如果直接写入”out”,则会使GPIO直接输出低电平。也可以通过写入”low”或者”high”来直接设置输出低电平或者高电平。
* ”value”属性,用于读取输入电平或者控制输出电平。如果GPIO为输出,则对value写入0为输出低电平,写入非0为输出高电平。如果设置为输入的话,则读到0表示输入为低电平,1为高电平。
* ”edge”属性,用于设置触发电平,只有在GPIO可以设置为中断输入引脚时才会出现该属性。
#### 9.2.3 GPIO控制器
GPIO控制器,用于表示GPIO 控制实现的初始GPIO,其路径为/sys/class/gpio/gpiochipN/。比如/sys/class/gpio/gpiochip42/ 则表示实现GPIO控制器的初始化编号为42。GPIO控制器的属性为只读属性,包括base、label和ngpio等多个。
* ”base”属性,和gpiochipN的N代表的含义相同,表示被该组GPIO控制器实现的第一个GPIO.
* ” ngpio”属性,用于表示该控制器支持多少个GPIO,支持的GPIO编号为从N到N+ngpio-1
* ” label”属性,用于判断控制器,并不总是唯一的
## 9.3 IMX6ULL开发板GPIO编号的确定
每个芯片可以有N组GPIO,每组GPIO最多有32个GPIO,即最多有N*32个GPIO。但是在实际设计中,每组的GPIO数量各有不同。在IMX6ULL中,实际每组拥有的GPIO数量如下图所示,具体详见《IMX6ULLRM.pdf》手册1347页。
![在这里插入图片描述](http://photos.100ask.net/NewHomeSite/GPIOProgram_Image001.png)
从上图可以看到,在IMX6ULL中,共有5组GPIO,起始GPIO组为GPIO1。因此在实际GPIO编号计算中,第一组GPIO1对应的编号为0~31。以此类推,IMX6ULL的GPION_X(N=1~5,X=0~31对应的编号实际为(N-1)*32+X。接下来,我们以板载的LED和按键各自对应的GPIO为例来说明如何在实际应用中计算GPIO编号。
### 9.3.1 LED的GPIO编号计算
从原理图中找到对应LED的设计,具体的连接如下图所示。从图中我们可以看到,LED连接到的GPIO为GPIO5_3,其对应的GPIO编号实际为(5-1)*32+3 = 131。因此,我们如果要在sys_gpio中操作LED,我们就需要将编号131的GPIO进行导出。
![在这里插入图片描述](http://photos.100ask.net/NewHomeSite/GPIOProgram_Image002.png)
### 9.3.2 按键的GPIO编号计算
从原理图中找到对应按键的设计,底板有2个按键,具体的连接如下图所示。从图中我们可以看到,两个按键连接到的GPIO分别为GPIO5_1和GPIO4_14,第一个按键KEY1对应的GPIO编号为(5-1) *32+1 = 129,第二个按键KEY2对应的GPIO编号为(4-1) *32+14=110。因此,我们如果要在sys_gpio中读取按键KEY1和KEY2的值,,我们就需要将编号129和110的GPIO进行导出。
![在这里插入图片描述](http://photos.100ask.net/NewHomeSite/GPIOProgram_Image003.png)
### 9.3.3 特殊情况下的GPIO编号计算
在有些情况下,起始的gpiochipN不是gpiochip0。这个时候 ,我们就需要在原有的GPIO编号基础上加上起始gpiochipN值进行计算。下图所示的为其实gpiochip为gpiochip0的情况。
![在这里插入图片描述](http://photos.100ask.net/NewHomeSite/GPIOProgram_Image004.png)
## 9.4 实际编程操作
在实际操作中,我们使用LED和按键实现了GPIO输出和输入的实验,相关的实验过程和相关代码如下。
### 9.4.1 导出GPIO口
为了导出GPIO口,我们需要向/sys/class/gpio/export写入需要导出的引脚编号。在使用之后,我们也可以使用/sys/class/gpio/unexport取消导出引脚编号。
导出引脚编号的实现代码如下所示,具体详见《sysfs_gpio_1_export_gpio sysfs_gpio_export.c》的sysfs_gpio_export()函数。
```c
32 int sysfs_gpio_export(unsigned int gpio)
33 {
34 int fd, len;
35 char buf[MAX_BUF];
36 // /sys/class/gpio/export
37 fd = open( "/sys/class/gpio/export", O_WRONLY);//打开文件
38 if (fd < 0) {
39 perror("gpio/export");
40 return fd;
41 }
42
43 len = snprintf(buf, sizeof(buf), "%d", gpio);//从数字变换为字符串,即1 变为”1“
44 write(fd, buf, len);//将需要导出的GPIO引脚编号进行写入
45 close(fd);//关闭文件
46
47 return 0;
48 }
```
取消导出引脚编号的实现代码如下所示,具体详见《sysfs_gpio_export.c》的sysfs_gpio_unexport()函数。
```c
59 int sysfs_gpio_unexport(unsigned int gpio)
60 {
61 int fd, len;
62 char buf[MAX_BUF];
63 // /sys/class/gpio/unexport
64 fd = open("/sys/class/gpio/unexport", O_WRONLY);//打开文件
65 if (fd < 0) {
66 perror("gpio/export");
67 return fd;
68 }
69
70 len = snprintf(buf, sizeof(buf), "%d", gpio);//从数字变换为字符串,即1 变为”1“
71 write(fd, buf, len);//将需要取消导出的GPIO引脚编号进行写入
72 close(fd);//关闭文件
73 return 0;
74 }
```
在实现导出和取消导出引脚编号的函数之后,我们来实现具体的引脚编号的导出。LED和按键各自对应的引脚编号如下所示
```c
11 #define GPIO4_14 110
12 #define GPIO5_1 129
13 #define GPIO5_3 131
14
15 #define GPIO_KEY1 GPIO4_14
16 #define GPIO_KEY2 GPIO5_1
17 #define GPIO_LED GPIO5_3
```
在确定了各自对应的引脚编号,我们就可以进行导出了。具体实现代码在程序文件《sysfs_gpio_1_export_gpio/sysfs_gpio_export.c》中main函数,下为对应代码部分,我们将LED和按键对应的引脚都进行了导出。
```c
183 int main(int argc, char **argv) {
184 unsigned int i;
185 unsigned int value1,value2;
186
187 printf("\t********************************************\n");
188 printf("\t******** SYSFS_GPIO_TEST_DEMO**************\n");
189 printf("\t******** version date: 2020/05 **********\n");
190 printf("\t********************************************\n");
191
192 printf("gpio begin to export gpio\r\n");
193 sysfs_gpio_export(GPIO_KEY1);//export gpio key1
194 sysfs_gpio_export(GPIO_KEY2);//export gpio key2
195 sysfs_gpio_export(GPIO_LED);//export gpio led
196 printf("gpio export gpio ok\r\n");
197
198
199 return 0;
200 }
```
在将代码编译之后,我们将代码在板卡上进行运行。代码运行之后的的结果如下图所示,可以看到成功的将GPIO110、GPIO129和GPIO131进行了导出。
![在这里插入图片描述](http://photos.100ask.net/NewHomeSite/GPIOProgram_Image005.png)
### 9.4.2 设置GPIO方向
为了实现导出的引脚的方向设置,我们需要对/sys/class/gpio/gpioN/direction写入不同的值。写入“in”则表示设置为输入,写入“out”则表示设置为输出。设置引脚编号的的实现代码如下所示,具体详见《sysfs_gpio_2_export_gpio sysfs_gpio_export.c》的sysfs_gpio_set_dir ()函数。
```c
86 int sysfs_gpio_set_dir(unsigned int gpio, unsigned int out_flag)
87 {
88 int fd, len;
89 char buf[MAX_BUF];
90 // /sys/class/gpio/gpioN/direction
91 len = snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/direction", gpio);
92
93 fd = open(buf, O_WRONLY);//打开文件
94 if (fd < 0) {
95 perror(buf);
96 return fd;
97 }
98
99 if (out_flag)//为1,则写入“out",即设置为输出
100 write(fd, "out", 4);
101 else//为0,则写入“in",即设置为输入
102 write(fd, "in", 3);
103
104 close(fd);//关闭文件
105 return 0;
106 }
```
在实现引脚方向的设置函数之后,我们分别针对按键和LED设置各自不同的方向。将按键设置为输入“IN”,将LED设置为输出“out”,对应的代码如下图所示。相关的代码在程序文件《sysfs_gpio_2_export_gpio/sysfs_gpio_export.c》中main函数,下为对应代码部分。
```c
183 int main(int argc, char **argv) {
184 unsigned int i;
185 unsigned int value1,value2;
186
187 printf("\t********************************************\n");
188 printf("\t******** SYSFS_GPIO_TEST_DEMO**************\n");
189 printf("\t******** version date: 2020/05 **********\n");
190 printf("\t********************************************\n");
191
192 printf("begin to export gpio and direction\r\n");
193 sysfs_gpio_export(GPIO_KEY1);//export gpio key1
194 sysfs_gpio_export(GPIO_KEY2);//export gpio key2
195 sysfs_gpio_export(GPIO_LED);//export gpio led
196
197 sysfs_gpio_set_dir(GPIO_KEY1, 0);//set as input
198 sysfs_gpio_set_dir(GPIO_KEY2, 0);//set as input
199 sysfs_gpio_set_dir(GPIO_LED, 1);//set as output
200 printf(" export gpio and direction ok\r\n");
201
202
203
204 return 0;
205 }
```
在将代码编译之后,我们将代码在板卡上进行运行。代码运行之后的的结果如下图所示,我们可以看到按键GPIO110和GPIO129的方向设置成了输入,LED2的GPIO131设置成了输入。
![在这里插入图片描述](http://photos.100ask.net/NewHomeSite/GPIOProgram_Image006.png)
### 9.4.3 GPIO输出实验-LED输出控制
为了设置引脚的输出电平高低,我们需要对/sys/class/gpio/gpioN/value写入不同的值。写入‘1’则表示输出高电平,写入‘0’则表示输出低电平。设置引脚输出高低电平的的实现代码如下所示,具体详见《sysfs_gpio_3_export_gpio sysfs_gpio_export.c》的sysfs_gpio_set_value ()函数。
```c
119 int sysfs_gpio_set_value(unsigned int gpio, unsigned int value)
120 {
121 int fd, len;
122 char buf[MAX_BUF];
123 // /sys/class/gpio/gpioN/value
124 len = snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/value", gpio);
125
126 fd = open(buf, O_WRONLY);//打开文件
127 if (fd < 0) {
128 perror(buf);
129 return fd;
130 }
131
132 if (value)//为1,则写入“1",即设置为输出高电平
133 write(fd, "1", 2);
134 else//为0,则写入“0",即设置为输出低电平
135 write(fd, "0", 2);
136
137 close(fd);//关闭文件
138 return 0;
139 }
```
在实现引脚输出电平的控制函数之后,我们来实现LED的控制。我们通过将“1”或“0”写入value来控制GPIO输出高电平或者低电平,具体相关的代码在程序文件《sysfs_gpio_3_export_gpio/sysfs_gpio_export.c》中main函数,下为对应代码部分。
```c
183 int main(int argc, char **argv) {
184 unsigned int i;
185 unsigned int value1,value2;
186
187 printf("\t********************************************\n");
188 printf("\t******** SYSFS_GPIO_TEST_DEMO**************\n");
189 printf("\t******** version date: 2020/05 **********\n");
190 printf("\t********************************************\n");
191
192 printf("led begin to init\r\n");
193 sysfs_gpio_export(GPIO_LED);//export gpio led
194
195 sysfs_gpio_set_dir(GPIO_LED, 1);//set as output
196 printf("led init ok\r\n");
197
198
199 /* Confirm INIT_B Pin as High */
200 while(1)
201 {
202
203
204 sysfs_gpio_set_value(GPIO_LED, 1);//output high
205 printf("led off\r\n");
206 usleep(500000); //delay
207 sysfs_gpio_set_value(GPIO_LED, 0);//output low
208 printf("led on\r\n");
209 usleep(500000);//delay
210 }
211
212 sysfs_gpio_unexport(GPIO_LED);//unexport gpio led
213
214 return 0;
215 }
```
在将代码编译之后,我们将代码在板卡上进行运行。代码运行之后的的结果如下图所示, 可以看到规律性的打印LED控制信息(实物可以看到LED灯闪烁)。
![在这里插入图片描述](http://photos.100ask.net/NewHomeSite/GPIOProgram_Image007.png)
### 9.4.4 GPIO输入试验-按键值读取
为了读取引脚输入的电平高低,我们需要读取/sys/class/gpio/gpioN/value的值。读到的是‘1’则表输入为高电平,读到的是‘0’则表示输入为低电平。读取引脚输入电平的、的的实现代码如下所示,具体详见《sysfs_gpio_4_export_gpio sysfs_gpio_export.c》的sysfs_gpio_get_value ()函数。
```c
152 int sysfs_gpio_get_value(unsigned int gpio, unsigned int *value)
153 {
154 int fd, len;
155 char buf[MAX_BUF];
156 char ch;
157 // /sys/class/gpio/gpioN/value
158 len = snprintf(buf, sizeof(buf), SYSFS_GPIO_DIR "/gpio%d/value", gpio);
159
160 fd = open(buf, O_RDONLY);//打开文件
161 if (fd < 0) {
162 perror("gpio/get-value");
163 return fd;
164 }
165
166 read(fd, &ch, 1);//读取外部输入电平
167
168 if (ch != '0') {//为'1',则设置为1,即输入为高电平
169 *value = 1;
170 } else {//为'0',则设置为0,即输入为低电平
171 *value = 0;
172 }
173
174 close(fd);//关闭文件
175 return 0;
176 }
```
在实现引脚电平读取函数之后,我们来实现外部按键值得读取,我们通过读取value的值来读取按键值,具体相关的代码在程序文件《sysfs_gpio_4_export_gpio/sysfs_gpio_export.c》中main函数,下为对应代码部分。
```c
183 int main(int argc, char **argv) {
184 unsigned int i;
185 unsigned int value1,value2;
186
187 printf("\t********************************************\n");
188 printf("\t******** SYSFS_GPIO_TEST_DEMO**************\n");
189 printf("\t******** version date: 2020/05 **********\n");
190 printf("\t********************************************\n");
191
192 printf("key begin to init\r\n");
193 sysfs_gpio_export(GPIO_KEY1);//export gpio key1
194 sysfs_gpio_export(GPIO_KEY2);//export gpio key2
195
196 sysfs_gpio_set_dir(GPIO_KEY1, 0);//set as input
197 sysfs_gpio_set_dir(GPIO_KEY2, 0);//set as input
198
199 printf("key init ok\r\n");
200
201
202 /* Confirm INIT_B Pin as High */
203 while(1)
204 {
205
206 sysfs_gpio_get_value(GPIO_KEY1, &value1); //read key1 value
207 //printf("@@key1 value 1is %d \n\r",value1);
208 if(value1==0)//key1 pressed
209 {
210 printf("@@key1 is pressed 0\n\r");
211 }
212 sysfs_gpio_get_value(GPIO_KEY2, &value2);//read key2 value
213 //printf("##key2 value 1is %d \n\r",value2);
214 if(value2==0)//key2 pressed
215 {
216 printf("##key2 is pressed 0\n\r");
217 }
218 usleep(100000);//delay
219
220 }
221
222 sysfs_gpio_unexport(GPIO_KEY1);//unexport gpio key1
223 sysfs_gpio_unexport(GPIO_KEY2);//unexport gpio key2
224
225
226 return 0;
227 }
```
在将代码编译之后,我们将代码在板卡上进行运行。代码运行之后的的结果如下图所示,我们可以看到在按键KEY1和KEY2按下之后打印的值各有不同。
![在这里插入图片描述](http://photos.100ask.net/NewHomeSite/GPIOProgram_Image008.png)
### 9.4.5 LED和按键控制实验
在前几个实验中,我们分别实现了LED和按键各自的控制。在这个实验中,我们将前几个实验进行整合,控制LED得闪烁,并读取按键得值。当按键按下时,打印相关信息。具体相关的代码在程序文件《sysfs_gpio_5_export_gpio/sysfs_gpio_export.c》中main函数,下为对应代码部分
```c
183 int main(int argc, char **argv) {
184 unsigned int i;
185 unsigned int value1,value2;
186
187 printf("\t********************************************\n");
188 printf("\t******** SYSFS_GPIO_TEST_DEMO**************\n");
189 printf("\t******** version date: 2020/05 **********\n");
190 printf("\t********************************************\n");
191
192 printf("led&key begin to init\r\n");
193 sysfs_gpio_export(GPIO_KEY1);//export gpio key1
194 sysfs_gpio_export(GPIO_KEY2);//export gpio key2
195 sysfs_gpio_export(GPIO_LED);//export gpio led
196 sysfs_gpio_set_dir(GPIO_KEY1, 0);//set as input
197 sysfs_gpio_set_dir(GPIO_KEY2, 0);//set as input
198 sysfs_gpio_set_dir(GPIO_LED, 1);//set as output
199 printf("led&key init ok\r\n");
200
201
202 /* Confirm INIT_B Pin as High */
203 while(1)
204 {
205
206 sysfs_gpio_get_value(GPIO_KEY1, &value1); //read key1 value
207 //printf("@@key1 value 1is %d \n\r",value1);
208 if(value1==0)//key1 pressed
209 {
210 printf("@@key1 is pressed 0\n\r");
211 }
212 sysfs_gpio_get_value(GPIO_KEY2, &value2);//read key2 value
213 //printf("##key2 value 1is %d \n\r",value2);
214 if(value2==0)//key2 pressed
215 {
216 printf("##key2 is pressed 0\n\r");
217 }
218 //led flash
219 sysfs_gpio_set_value(GPIO_LED, 1);
220 printf("LED OFF\n\r");
221 usleep(500000);
222 sysfs_gpio_set_value(GPIO_LED, 0);
223 printf("LED ON\n\r");
224 usleep(500000);
225 }
226
227 sysfs_gpio_unexport(GPIO_KEY1);//unexport gpio key1
228 sysfs_gpio_unexport(GPIO_KEY2);//unexport gpio key2
229 sysfs_gpio_unexport(GPIO_LED);//unexport gpio led
230
231 return 0;
232 }
```
在将代码编译之后,我们将代码在板卡上进行运行。代码运行之后的的结果如下图所示,可以看到LED闪烁,按键KEY1和KEY2按下之后打印的值各有不同(因为LED的闪烁导致按键需要经过一次LED闪烁之后才能读取,因此按键必须一直按着才能读取到值的变化)。
![在这里插入图片描述](http://photos.100ask.net/NewHomeSite/GPIOProgram_Image009.png)
- 2024-08-01
-
发表了主题帖:
全志Tina_NPU开发部署说明
## 1 前言
### 1.1 读者对象
本文档(本指南)主要适用于以下人员:
• 技术支持工程师
• 软件开发工程师
• AI 应用案客户
## 2 正文
### 2.1 NPU 开发简介
• 支持int8/uint8/int16 量化精度,运算性能可达1TOPS.
• 相较于GPU 作为AI 运算单元的大型芯片方案,功耗不到GPU 所需要的1%.
• 可直接导入Caffe, TensorFlow, Onnx, TFLite,Keras, Darknet, pyTorch 等模型格式.
• 提供AI 开发工具:支持模型快速转换、支持开发板端侧转换API、支持TensorFlow, TFLite, Caffe, ONNX, Darknet, pyTorch 等模型.
• 提供AI 应用开发接口:提供NPU 跨平台API.
### 2.2 开发流程
NPU 开发完整的流程如下图所示:
![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://img-blog.csdnimg.cn/img_convert/01c702af57dfc0f192d8b0eb56f84ff3.png)
###2.3 模型训练
在模型训练阶段,用户根据需求和实际情况选择合适的框架(如Caffe、TensorFlow 等)进行训练得到符合需求的模型。也可直接使用已经训练好的模型, 对于基
于已有的算法模型部署来讲,可以不用经过模型训练阶段.
### 2.4 模型转换
此阶段为通过Acuity Toolkit 把模型训练中得到的模型转换为NPU 可用的模型NBG 文件。
### 2.5 程序开发
最后阶段为基于VIPLite API 开发程序实现业务逻辑。
### 2.6 acuity Toolkit
Allwinner 提供acuity toolkit 开发套件进行模型转换、推理运行和性能评估。
用户通过提供的python 接口可以便捷地完成以下功能:
1)模型转换:支持Caffe,TensorFlow Lite, Tensorflow, ONNXDarknet NBG 模型导入导出,后续能够在硬件平台上加载使用。
2)模型推理:能够在PC 上模拟运行模型并获取推理结果,也可以在指定硬件平台上运行模型并获取推理结果。
3)性能评估:能够在PC 上模拟运行并获取模型总耗时及每一层的耗时信息,也可以通过联机
调试的方式在指定硬件平台上运行模型,并获取模型在硬件上运行时的总时间和每一层的耗时信息。
此文档主要介绍模型转换和基于NPU 程序开发,不涉及模型训练的内容。
-
发表了主题帖:
百问网全志T113-PRO LVGL环境配置
## 运行LVGL示例
### 启动开发板
按要求接入电源或Type-c数据线,拨动拨码开关,将开发板上电
### 运行LVGL示例
打开串口终端软件,这里我使用MobaXterm软件演示,选择开发板的串口终端号,可以在设备管理中查看
![image-20230707143104904](//file1.elecfans.com/web2/M00/FF/DE/wKgZomaq7FuAG9SDAABbOkbiNCA653.png)
这里我的串口设备号为`COM15`,所以在串口终端软件中也应该使用`COM15`,波特率为115200。操作步骤如下所示:
![100ask-lvgl-serial-demo](http://photos.100ask.net/allwinner-docs/lvgl8-ui/100ask-lvgl-serial-demo.gif)
上面操作以7寸RGB屏作为演示硬件测试指令,输入:
```
root@TinaLinux:/# lv_examples 0
wh=1024x600, vwh=1024x1200, bpp=32, rotated=0
Turn on double buffering.
```
输入后,显示屏上会显示如下如所示的LVGL示例:
![](//file.elecfans.com/web2/M00/4A/B1/poYBAGKoBOiATMJXACTyZ2MYFbM991.gif)
注意:LVGL示例会自动适配屏幕,可能和上面展示的比例不一致。
系统中内置有5个LVGL演示应用,如下所示:
```
lv_examples 0, is lv_demo_widgets
lv_examples 1, is lv_demo_music
lv_examples 2, is lv_demo_benchmark
lv_examples 3, is lv_demo_keypad_encoder
lv_examples 4, is lv_demo_stress
```
## 开发LVGL程序
### 配置编译lvgl环境
**注意:**如果您使用的是前文 `开始使用-->运行虚拟机 方式二` 中 我们提供好的虚拟机,可直接跳过此章节,进入下一小节《编译LVGL源码》;如果您是自己配置的虚拟机,请认准阅读并按此章节进行操作。
假设将下载的工具链和源码tar.gz格式的压缩包文件传入虚拟机的任意目录中,这里我新建一个lvgl工作目录存储三个压缩包。输入:
```
ubuntu@ubuntu1804ubuntu@ubuntu1804:~$ mkdir lvgl-work
ubuntu@ubuntu1804:~$ cd lvgl-work
```
将`allwinner-tinasdk_lvgl8_demo_V1.0.tar.gz`文件传入`lvgl-work`目录中,如下所示:
```
ubuntu@ubuntu1804:~/lvgl-works$ ls
allwinner-tinasdk_lvgl8_demo_V1.0.tar.gz
```
新建`toolchain`文件夹用于存储`sysroot`和`gcc`文件夹
```
ubuntu@ubuntu1804ubuntu@ubuntu1804:~$ mkdir toolchain
ubuntu@ubuntu1804:~$ cd toolchain
```
传入压缩包后,如下所示:
```
ubuntu@ubuntu1804:~/lvgl_work/toolchain$ ls
100ask_t113-pro_arm-openwrt-linux-eabi-glibc_sysroot_v1.0.tar.gz
gcc-6.4-2017.11-x86_64_arm-openwrt-linux-eabi-musl.tar.gz
```
在toolchain目录中解压gcc工具链压缩包和sysroot依赖压缩包,输入:
```
tar -xzvf gcc-6.4-2017.11-x86_64_arm-openwrt-linux-eabi-musl.tar.gz
```
```
tar -xzvf 100ask_t113-pro_arm-openwrt-linux-eabi-glibc_sysroot_v1.0.tar.gz
```
解压完成后返回上一级lv_work目录中输入:
```
ubuntu@ubuntu1804:~/lvgl_work/toolchain$ cd ../
ubuntu@ubuntu1804:~/lvgl_work$
```
解压lvgl demo源码压缩包
```
tar -xzvf allwinner-tinasdk_lvgl8_demo_V1.0.tar.gz
```
解压完成后的目录如下所示:
```
ubuntu@ubuntu1804:~/lvgl_work$ tree -L 2
.
├── allwinner-tinasdk_lvgl8_demo_V1.0.tar.gz
├── lv_port_linux_frame_buffer
│ ├── CMakeLists.txt
│ ├── LICENSE
│ ├── lv_conf.h
│ ├── lv_drivers
│ ├── lv_drv_conf.h
│ ├── lvgl
│ ├── main.c
│ ├── Makefile
│ ├── mouse_cursor_icon.c
│ └── README.md
└── toolchain
├── 100ask_t113-pro_arm-openwrt-linux-eabi-glibc_sysroot_v1.0.tar.gz
├── arm-openwrt-linux-eabi-musl
├── gcc-6.4-2017.11-x86_64_arm-openwrt-linux-eabi-musl.tar.gz
├── sysroot
└── toolchain
7 directories, 11 files
```
其中`lv_port_linux_frame_buffer`为LVGL Demo示例源码;`toolchain`中包含gcc交叉编译工具链和sysroot依赖文件。
下面开始修改源码中的Makefile文件,使lvgl源码使用下载的工具链进行编译。
进入gcc工具链文件目录的bin目录中查看交叉编译工具链是否存在
```
ubuntu@ubuntu1804:~/lvgl_work/toolchain/arm-openwrt-linux-eabi-musl/bin$ ls arm-openwrt-linux-muslgnueabi-gcc
arm-openwrt-linux-muslgnueabi-gcc
ubuntu@ubuntu1804:~/lvgl_work/toolchain/arm-openwrt-linux-eabi-musl/bin$ pwd
/home/ubuntu/lvgl_work/toolchain/arm-openwrt-linux-eabi-musl/bin
```
`arm-openwrt-linux-muslgnueabi-gcc`交叉编译工具链绝对路径为:
```
/home/ubuntu/lvgl_work/toolchain/arm-openwrt-linux-eabi-musl/bin/arm-openwrt-linux-muslgnueabi-gcc
```
进入LVGL源码目录中,查看源码文件。
```
ubuntu@ubuntu1804:~/lvgl_work$ cd lv_port_linux_frame_buffer/
ubuntu@ubuntu1804:~/lvgl_work/lv_port_linux_frame_buffer$ ls
CMakeLists.txt LICENSE lv_conf.h lv_drivers lv_drv_conf.h lvgl main.c Makefile mouse_cursor_icon.c README.md
```
修改Makfiel文件
```
vi Makefile
```
修改Makefile文件中`CC`为刚刚前面确认的交叉编译工具链路径,例如我刚刚确认的gcc交叉编译工具链绝对路径为:
```
/home/ubuntu/lvgl_work/toolchain/arm-openwrt-linux-eabi-musl/bin/arm-openwrt-linux-muslgnueabi-gcc
```
那么修改Makfile文件中的`CC`修改为gcc交叉编译工具链绝对路径。
![image-20230708140533761](//file1.elecfans.com/web2/M00/00/C7/wKgaomaq7FuAH3_sAAAzynaOVYo599.png)
修改步骤如下所示:
![100ask-lvgl-modifyMakefile](http://photos.100ask.net/allwinner-docs/lvgl8-ui/100ask-lvgl-modifyMakefile.gif)
修改完成后,保存退出编辑界面。
### 编译LVGL源码
此时还需要指定存放交叉编译需要使用的工具链、库文件、头文件的文件夹。在终端输入
```
export ARCH=arm
export CROSS_COMPILE=arm-openwrt-linux-muslgnueabi-
export PATH=$PATH:/home/ubuntu/lvgl_work/toolchain/arm-openwrt-linux-eabi-musl/bin/
export SYSROOT_DIR=/home/ubuntu/lvgl_work/toolchain/sysroot/
export STAGING_DIR=/home/ubuntu/lvgl_work/toolchain/arm-openwrt-linux-eabi-musl/
```
注意:如果您是自己配置的虚拟机的请修改为对应的路径,,如果使用我们提供的方式二 直接 复制 粘贴到 ubuntu18.04终端执行即可。
配置完成后,输入`make`即可开始编译。编译过程如下所示:
![100ask-t113-lvgl-makeAndBuild](http://photos.100ask.net/allwinner-docs/lvgl8-ui/100ask-t113-lvgl-makeAndBuild.gif)
等待编译完成后,会在当前目录下生成名称为`demo`的应用程序。
```
book@100ask:~/lvgl-work/lv_port_linux_frame_buffer$ ls demo
demo
```
### 上传至开发板运行
注意: 默认情况下 上述的 ubuntu系统配置环境 以及我们制作的虚拟机镜像已经配置好 adb环境,大家只需要 参考 文章 [3-通过adb传输文件在新窗口打开](http://allwinner-docs.100ask.org/Basic/100ASK_V853-PRO/03-StartFirstExperience.html#_3-%E9%80%9A%E8%BF%87adb%E4%BC%A0%E8%BE%93%E6%96%87%E4%BB%B6) 讲您的开发板 挂载至 ubuntu系统上 即可操作如下步骤 开始进行上传操作。
在ubuntu系统下使用ADB功能将生成`demo`应用程序传输到开发板中运行,将ADB设备连接到虚拟机端中。查看ADB设备的设备号
```
abd devices
```
传输LVGL示例程序进开发板端的root目录下
```
adb push demo /mnt/UDISK
```
操作过程如下所示:
![100ask-lvgl-adbPush](http://photos.100ask.net/allwinner-docs/lvgl8-ui/100ask-lvgl-adbPush.gif)
传输完成后,切换到开发板串口终端软件,进入终端,输入 如下命令: 即可看到屏幕运行 自己编译新的demo程序。
```
root@TinaLinux:/# cd /mnt/UDISK
root@TinaLinux:/mnt/UDISK# ls
demo
root@TinaLinux:/mnt/UDISK# ./demo 0
wh=1024x600, vwh=1024x1200, bpp=32, rotated=0
```
输入完成后,即可实现镜像中内置的lvgl demo演示示例。
- 2024-07-29
-
发表了主题帖:
飞凌全志T527开发板实现局域网内文件传输功能
之前玩开发板的时候,如果需要实现主机与开发板之间的文件传输,通常是通过挂载NFS的方式,而飞凌的OKT527板载WIFI,并且官方提供的镜像中已经将其成功驱动,那我们就可以通过WIFI连接家中的路由器的方式,实现局域网内的数据传输。
根据用户手册中的说明,我们连接到家里的WIFI
命令如下:fltest_wifi.sh -i wlan0 -s H3C_708 -p 123456785. 将-s后面的字符换成自己WIFI的名字,-p后面为密码,当出现connect ok的字样时,说明已经连接成功了,并且途中可见分配了192.168.3.13的ip地址,如果不记得也不要紧,我们可以通过在开发板中使用ipconfig命令进行查询,wlan0网卡对应的IP就是开发板的IP。
![460945fe-139f-4110-9258-4782f31c1c8f-image.png](https://bbs.aw-ol.com/assets/uploads/files/1721665840617-460945fe-139f-4110-9258-4782f31c1c8f-image.png)
![71f93b35-e0ae-4a12-8a8c-1e80757c3042-image.png](https://bbs.aw-ol.com/assets/uploads/files/1721665845068-71f93b35-e0ae-4a12-8a8c-1e80757c3042-image.png)
进一步,我们看一下我们主机的IP地址为192.168.3.5,说明他们属于同一个网段,
![e8738e0d-34c5-4857-8cd2-f5135a8d7d4a-image.png](https://bbs.aw-ol.com/assets/uploads/files/1721665850276-e8738e0d-34c5-4857-8cd2-f5135a8d7d4a-image.png)
从开发板端ping一下主机,emm,竟然还有丢包,算了没关系,连接成功就好了。
![64590de9-8a7a-45f0-b6c3-83eb91b30d52-image.png](https://bbs.aw-ol.com/assets/uploads/files/1721665856339-64590de9-8a7a-45f0-b6c3-83eb91b30d52-image.png)
此时,理论上我们就可以实现文件传输与通信了,我们在主机端写一个简单的文件test.txt,包含一句”hello forlinx”,使用aarch64的交叉编译工具链进行编译。
![336a75d5-8dba-45ad-9a53-393347e8bef6-image.png](https://bbs.aw-ol.com/assets/uploads/files/1721665869806-336a75d5-8dba-45ad-9a53-393347e8bef6-image.png)
下一步,我们在开发板端使用ftp的方式命令将test.txt传输到开发板中。
刚才我们已经拿到开发板IP为192.168.3.13,我们使用ftp 192.168.3.13命令进行文件传输。(如果没有这个命令,先执行sudo apt-get install vsftpd),按照要求输入开发板的账号与密码。
执行put test.txt,执行成功会提示传输完成。
在开发板端的根目录下,就可以看到传输过来的文件。
后续通过这种方式就可以实现文件的快速传输。
- 2024-07-24
-
发表了主题帖:
AvaotaA1全志T527开发板AMP异构计算资源划分
### DSP 资源
| Module | cacheable属性 | Address | Size | 地址映射说明 |
| ------------ | ----------------- | --------------------------- | ------ | -------------------------------------------------- |
| DSP IRAM | non-cacheable | 0x0002_0000 - 0x0002_FFFF | 64KB | DSP通过外部总线访问 |
| DSP DRAM0 | non-cacheable | 0x0003_0000 - 0x0003_7FFF | 32KB | DSP通过外部总线访问 |
| DSP DRAM1 | non-cacheable | 0x0003_8000 - 0x0003_FFFF | 32KB | DSP通外部总线访问 |
| DSP IRAM | non-cacheable | 0x0040_0000 - 0x0040_FFFF | 64KB | DSP通过内部总线访问 |
| DSP DRAM0 | non-cacheable | 0x0042_0000 - 0x0042_7FFF | 32KB | DSP通过内部总线访问 |
| DSP DRAM1 | non-cacheable | 0x0044_0000 - 0x0044_7FFF | 32KB | DSP通过内部总线访问 |
| DRAM SPACE | non-cacheable | 0x1000_0000 - 0x1FFF_FFFF | 256M | 对应DDRR的前256M空间(需要DSP输出ahb做地址重映射) |
| DSP IRAM | cacheable | 0x2002_0000 - 0x2002_FFFF | 64KB | DSP通过外部总线访问 |
| DSP DRAM0 | cacheable | 0x2003_0000 - 0x2003_7FFF | 32KB | DSP通过外部总线访问 |
| DSP DRAM1 | cacheable | 0x2003_8000 - 0x2003_FFFF | 32KB | DSP通过外部总线访问 |
| DRAM SPACE | cacheable | 0x3000_0000 - 0x3FFF_FFFF | 256M | 对应DDR的前256M空间(需要DSP输出ahb做地址重映射) |
| DRAM SPACE | non-cacheable | 0x4000_0000 - 0x7FFF_FFFF | 1G | DRAM特殊映射 |
| DRAM SPACE | cacheable可配置 | 0x8000_0000 - 0xBFFF_FFFF | 1G | 预留空间 |
| DRAM SPACE | cacheable | 0xC000_0000 - 0xFFFF_FFFF | 1G | 直接映射到DDR对应空间 |
由于DSP的cacheable空间大小只能按照你512MB去划分,而且跳转指令不能超过1G空间,因此对于SRAM、以及DRAM的空间,DSP存在多套地址映射,根据不同的地址段区分cacheable和non-cacheable。
DSP的local sram包括IRAM和DRAM0/1,放在DSP内部,其他主机可以通过DSP的总线接口对该RAM进行访问,而DSP可以通过特定地址(0x0040_0000 - 0x0044_FFFF)对其直接访问,实现最高效率。
### RV资源
| Module | cacheable属性 | Address | Size | 地址映射说明 |
| ------------- | --------------- | --------------------------- | -------------------- | ------------------------------------------------------------------------------------------------------------- |
| DSP IRAM | non-cacheable | 0x0002_0000 - 0x0002_FFFF | 64KB | |
| DSP DRAM0 | non-cacheable | 0x0003_0000 - 0x0003_7FFF | 32KB | |
| DSP DRAM1 | non-cacheable | 0x0003_8000 - 0x0003_FFFF | 32KB | |
| SRAM A2 | non-cacheable | 0x0004_0000 - 0x0006_3FFF | 16+128KB | 系统外设 |
| 其他 | non-cacheable | 0x0800_0000 - 0x3FEF_FFFF | | 与CPUX memory mapping一致 |
| SRAM SPACE0 | | 0x3FF0_0000 - 0x3FFF_FFFF | 1MB(实际使用256KB) | 0x3FF0_0000 - 0x3FFB_FFFF在总线上被屏蔽,0x3FFC_0000 - 0x3FFF_FFFF映射到DSP SRAM0 0x0728_0000 - 0x072B_FFFF |
| SRAM SPACE1 | | 0x4000_0000 - 0x7FFF_FFFF | 1GB | 0x4000_0000 - 0x4003_FFFF映射到DSP SRAM1 0x072C_0000 - 0x072F_FFFF,其余区间无映射 |
### 设备树配置
```c
reserved-memory {
dsp0ddr_reserved: dsp0ddr@4a000000 {
reg =;
no-map;
};
riscvsram0_reserved: riscvsram0@7280000{
reg =;
no-map;
};
riscvsram1_reserved: riscvsram1@72c0000 {
reg =;
no-map;
};
/*
* The name should be "vdev%dbuffer".
* Its size should be not less than
* RPMSG_BUF_SIZE * (num of buffers in a vring) * 2
* = 512 * (num of buffers in a vring) * 2
*/
dsp_vdev0buffer: vdev0buffer@4ac00000 {
compatible ="shared-dma-pool";
reg =;
no-map;
};
/*
* The name should be "vdev%dvring%d".
* The size of each should be not less than
* PAGE_ALIGN(vring_size(num, align))
* = PAGE_ALIGN(16 * num + 6 + 2 * num + (pads for align) + 6 + 8 * num)
*
* (Please refer to the vring layout in include/uapi/linux/virtio_ring.h)
*/
dsp_vdev0vring0: vdev0vring0@4ac40000 {
reg =;
no-map;
};
dsp_vdev0vring1: vdev0vring1@4ac42000 {
reg =;
no-map;
};
/*
* The name should be "vdev%dbuffer".
* Its size should be not less than
* RPMSG_BUF_SIZE * (num of buffers in a vring) * 2
* = 512 * (num of buffers in a vring) * 2
*/
rv_vdev0buffer: vdev0buffer@4ae00000 {
compatible ="shared-dma-pool";
reg =;
no-map;
};
/*
* The name should be "vdev%dvring%d".
* The size of each should be not less than
* PAGE_ALIGN(vring_size(num, align))
* = PAGE_ALIGN(16 * num + 6 + 2 * num + (pads for align) + 6 + 8 * num)
*
* (Please refer to the vring layout in include/uapi/linux/virtio_ring.h)
*/
rv_vdev0vring0: vdev0vring0@4ae40000 {
reg =;
no-map;
};
rv_vdev0vring1: vdev0vring1@4ae42000 {
reg =;
no-map;
};
/*
* mcu ram addr
*/
mcu0iram_reserved: mcu0iram@20000{
reg =;
no-map;
};
mcu0dram0_reserved: mcu0dram0@30000{
reg =;
no-map;
};
mcu0dram1_reserved: mcu0dram1@38000{
reg =;
no-map;
};
dsp0_rpbuf_reserved: dsp0_rpbuf@4ae44000 {
compatible ="shared-dma-pool";
no-map;
reg =;
};
dsp_share_space@4ab00000 {
no-map;
reg =;
};
};
```
-
发表了主题帖:
AvaotaA1全志T527开发板AMP异构计算简介
Avaota SBC 的部分平台内具有小核心 CPU,与大核心一起组成了异构计算的功能。
在异构多处理系统中,主核心和辅助核心的存在旨在共同协作,以实现更高效的任务处理。这种协作需要系统采取一系列策略来确保各个核心能够充分发挥其性能优势,并实现有效的通信和协同工作。这就形成了一种称为异构多处理系统(AMP系统)的架构。
在AMP系统中,通常采用主-从结构。主核心作为系统的控制中心,负责启动和管理辅助核心。一旦辅助核心启动完成,主核心和辅助核心之间会建立通信通道,以便进行数据交换和协同计算。这种通信通常通过IPC(Inter Processor Communication,处理器间通信)方式进行,而RPMsg则是其中一种常用的通信协议之一。
一项关键的任务在于确保两个核心之间的数据共享和同步。为此,系统通常会采用共享内存的方式,使得两个核心能够访问相同的数据空间。此外,系统还需要设计合适的中断机制,以便在必要时触发核心间的通信和同步操作。
## 异构系统的通讯
异构系统通讯在硬件上使用的是 MSGBOX,在软件层面上使用的是 AMP 与 RPMsg 通讯协议。其中大核心上基于 Linux 标准的 RPMsg 驱动框架,小核心是基于 OpenAMP 的异构通信框架。
### AMP 与 RPMsg
主核心与辅助核心是完全不同的两个核心,为了最大限度的发挥他们的性能,协同完成某一任务,所以在不同的核心上面运行的系统也各不相同。这些不同架构的核心以及他们上面所运行的软件组合在一起,就成了 AMP 系统 (Asymmetric Multiprocessing System, 异构多处理系统)。
由于两个核心存在的目的是协同的处理,因此在异构多处理系统中往往会形成 Master - Remote 结构。主核心启动后启动从核心。当两个核心上的系统都启动完成后,他们之间就通过 IPC(Inter Processor Communication)方式进行通信,而 RPMsg 就是 IPC 中的一种。
在AMP系统中,两个核心通过共享内存的方式进行通信。两个核心通过 AMP 中断来传递讯息。内存的管理由主核负责。
异构多处理系统的设计需要充分考虑到主核心和辅助核心的异构性质,以及它们之间的通信和协作方式,从而实现任务的高效分配和处理。
![在这里插入图片描述](https://docs.avaota.fun/assets/images/image-20220704155816774-3b1f87eaec75897abc2ec68d8241b394.png)
AMP 系统在每个通信方向上都有两个缓冲区,分别是 `USED` 和 `AVAIL`,这个缓冲区可以按照 RPMsg 中消息的格式分成一块一块链接形成一个环。
![在这里插入图片描述](https://docs.avaota.fun/assets/images/image-20220704160952936-d935d39ac5331928866997e523ba653d.png)
当主核需要和从核进行通信的时候可以分为四步:
(1)主核先从USED中取得一块内存(Allocate)
(2)将消息按照消息协议填充
(3)将该内存链接到 AVAIL 缓冲区中(Send)
(4)触发中断,通知辅助核有消息处理
![在这里插入图片描述](https://docs.avaota.fun/assets/images/2958689-e0da20bb240ff26d-99bdcc4e062f081332514baa9cb7819f.png)
反之,从核需要和主核通信的时候也类似:
(1)从核先从AVAIL中取得一块内存(Allocate)
(2)将消息按照消息协议填充
(3)将该内存链接到 USED 缓冲区中(Send)
(4)触发中断,通知主核有消息处理。
![在这里插入图片描述](https://docs.avaota.fun/assets/images/2958689-9430112ac1bc82dd-756bb98ee2c2def8cbd55209c5ba045b.png)
### RPMsg 协议
既然 RPMsg 是一种信息交换的协议,与TCP/IP类似,RPMsg 协议也有分层,主要分为三层,分别是传输层、MAC层和物理层。
![在这里插入图片描述](https://docs.avaota.fun/assets/images/image-20220704161948895-f6b3d96fccdf2e952423544492bacd76.png)
其中 MAC层 的 VirtIO 是一种I/O 半虚拟化解决方案,是一套通用 I/O 设备虚拟化的程序,是对半虚拟化 Hypervisor 中的一组通用 I/O 设备的抽象。 提供了一套上层应用与各 Hypervisor 虚拟化设备之间的通信框架和编程接口,减少跨平台所带来的兼容性问题,大大提高驱动程序开发效率。
RPMsg 总线上的消息都具有以下结构,包含消息头和数据两个固定的部分,该消息格式的定义位于`drivers/rpmsg/virtio_rpmsg_bus.c`中,具体定义如下:
```c
structrpmsg_hdr{
u32 src;
u32 dst;
u32 reserved;
u16 len;
u16 flags;
u8 data[];
} __packed;
```
## 异构系统的控制
在异构系统中,不止需要消息的传输,还需要相关控制。例如主核对辅助核心的开启,加载固件,关闭等等。这就需要用到 remoteproc 框架。
remoteproc 框架支持对不同平台,不同架构的处理器进行控制,可以监控辅助核心的运行情况。
- 2024-07-22
-
发表了主题帖:
在AvaotaA1全志T527开发板上驱动WS2812 RGB LCD
在 Avaota SBC 的开发板中,通常会有几个 WS2812 RGB LED 灯。例如 Avaota A1 的如下位置:
![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://docs.avaota.fun/assets/images/image-20240531204921506-2afc83e6c2f78315dbb02eb0d414cd9d.png)
对于 AvaotaOS,提供了硬件的 LEDC(Light Emitting Diode Controller),发光二极管控制器作为WS2812 RGB LED 灯的控制器。每个 LED 的三基色均可实现 256 级亮度显示,因此整个 LED 可完成 256ˆ3(即 16777216)种颜色的全真色彩显示。模块支持最大1024颗外控 LED级联。
## WS2812 驱动介绍
LED 典型电路如图所示,其中 DI 表示控制数据输入脚,DO 表示控制数据输出脚。DI 端接收从控制器传过来的数据,每个 LED 内部的数据锁存器会存储 24bit 数据,剩余的数据经过内部整形处理电路整形放大后通过 DO 端口开始转发输出给下一个级联的 LED。因此,每经过一个LED,数据减少 24bit。
![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://docs.avaota.fun/assets/images/image-20230324173621026-ac0e3c03c865c1e554f379e90a768037-ac0e3c03c865c1e554f379e90a768037.png)
LED典型电路如上图所示,其中 DI 表示控制数据输入脚,DO 表示控制数据输出脚。DI 端接受从控制器传输过来的数据,每个 LED 内部的数据锁存器会存储 24bit (分别对应 R,G,B 三种颜色)数据,剩余的数据经过内部整形处理电路整形放大后通过 DO 端口开始转发输出给下一个级联的 LED 。因此,每经过一个 LED ,数据减少 24bit。
![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://docs.avaota.fun/assets/images/image-20240329003829327-de68a8ff0cbf28b5c9fd3237fa257dc5-de68a8ff0cbf28b5c9fd3237fa257dc5.png)
![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://docs.avaota.fun/assets/images/image-20230324173635697-4ea6c216b677d8916d33c59dd86e12eb-4ea6c216b677d8916d33c59dd86e12eb.png)
## WS2812 驱动配置说明
配置驱动,默认 Avaota OS 已经勾选该驱动。如果未勾选请配置
```
LED Drivers ->
LEDC Support for Allwinner SoCs
```
![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://docs.avaota.fun/assets/images/image-20240329004108251-62035080125c5c2a937e142cd4aaaed3-62035080125c5c2a937e142cd4aaaed3.png)
配置设备树,首先需要配置 PIO 节点,配置 LEDC 使用的 GPIO
```c
&pio {
ledc_pins_a: ledc@0{
pins ="PH19";
function ="ledc";
drive-strength =;
};
ledc_pins_b: ledc@1{
pins ="PH19";
function ="gpio_in";
};
};
```
然后配置 LEDC 模块的数值
```c
&ledc {
pinctrl-names ="default","sleep";
pinctrl-0=;
pinctrl-1=;
led_count =;
output_mode ="GRB";
reset_ns =;
t1h_ns =;
t1l_ns =;
t0h_ns =;
t0l_ns =;
wait_time0_ns =;
wait_time1_ns =;
wait_data_time_ns =;
status ="okay";
};
```
* `pinctrl-names`: 用于表示 0 和 1 的 pinctrl 哪个是默认和休眠状态。
* `pinctrl-0`: 引脚配置,这里是默认使用的时候配置。
* `pinctrl-1`: 同上,这里是休眠时的配置。
* `led_count`: LED 灯的数目,根据硬件配置。
* `output_mode`: LED 灯输出模式,根据 LED 灯的 datasheet 进行配置。
* `reset_ns`: LED 灯 reset 时间控制。
* `t1h_ns`: 1 码高电平时间,根据 LED 灯的 datasheet 进行配置。
* `t1l_ns`: 1 码低电平时间,根据 LED 灯的 datasheet 进行配置。
* `t0h_ns`: 0 码高电平时间,根据 LED 灯的 datasheet 进行配置。
* `t0l_ns`: 0 码低电平时间,根据 LED 灯的 datasheet 进行配置。
* `wait_time0_ns`: 两个 LED 数据之间的等待时间,根据 LED 灯的 datasheet 进行配置。
* `wait_time1_ns`: 帧数据之间的等待时间,根据 LED 灯的 datasheet 进行配置。
* `wait_data_time_ns`: 内部 FIFO 等待数据时间,超过时间触发异常中断。
* `status`: 设备状态。
### WS2812 使用说明
驱动会在 `/sys/class/leds` 注册每个LED对应的设备目录
```
/sys/class/leds/sunxi_led0r // 红色
/sys/class/leds/sunxi_led0g // 绿色
/sys/class/leds/sunxi_led0b // 蓝色
```
其中 `0` 表示LED的编号,如果是 1 号 LED 则是
```
/sys/class/leds/sunxi_led1r
/sys/class/leds/sunxi_led1g
/sys/class/leds/sunxi_led1b
```
需要调节第 0 个LED的颜色为白光且最亮,操作如下:
```
echo 255 > /sys/class/leds/sunxi_led0r/brightness
echo 255 > /sys/class/leds/sunxi_led0g/brightness
echo 255 > /sys/class/leds/sunxi_led0b/brightness
```
### 实现七彩流水灯
#### C 语言实现
```c
#include
#include
#include
#include
#include
#include
#include
#include
// 使用RGB 分量合成颜色值
#defineMERAGECOLOR(G, R, B)(((uint32_t)G = b)
h =((g - b)*60.0f/ cdes)+0;
elseif(cmax == r && g < b)
h =((g - b)*60.0f/ cdes)+360;
elseif(cmax == g)
h =((b - r)*60.0f/ cdes)+120;
else
h =((r - g)*60.0f/ cdes)+240;
v *= k;
float f, p, q, t;
float rf, gf, bf;
int i =((int)(h /60)%6);
f =(h /60)- i;
p = v *(1- s);
q = v *(1- f * s);
t = v *(1-(1- f)* s);
switch(i){
case0:
rf = v;
gf = t;
bf = p;
break;
case1:
rf = q;
gf = v;
bf = p;
break;
case2:
rf = p;
gf = v;
bf = t;
break;
case3:
rf = p;
gf = q;
bf = v;
break;
case4:
rf = t;
gf = p;
bf = v;
break;
case5:
rf = v;
gf = p;
bf = q;
break;
default:
break;
}
r =(uint8_t)(rf *255.0);
g =(uint8_t)(gf *255.0);
b =(uint8_t)(bf *255.0);
sunxi_set_led_brightness(id, r, g, b);
}
// 测试 LEDC
intmain(){
int i =0, j =0, err;
int mode =0;
uint8_t R =0, G =0, B =0;
init_leds();
while(1){
for(j =0; j