@l1878980638 暂时还没有哦,关于SDK有什么问题都可以在论坛里发帖提问的
q1215200171 发布的最佳帖子
-
男人至死都是孩子——大佬在D1开发板上移植魂斗罗游戏
小白通过buildroot搭建哪吒D1开发环境详细步骤,并且在HDMI显示器上玩上了魂斗罗(基于QT5).(感谢晕哥对我的指导)
所有的内容都通过buildroot搭建,包括uboot,内核,qt5等等。
我是通过UBUNTU18.4搭建的,如果在buildroot的下载过程中遇到了半天都下不下来,直接就强行终止,然后执行
sudo systemd-resolve --flush-caches (UBUNTU18.4,其他的版本需要自己查)这个是刷DNS,我有的时候下载不动就用此命令。1.apt-get update
2.sudo apt-get install -y sed make binutils build-essential gcc g++ bash patch gzip bzip2 perl tar cpio unzip rsync file bc wget python cvs git mercurial rsync scp subversion android-tools-mkbootimg libncurses5-dev
Bzr 注意:第2步骤是我自己摸索出来的,与韦东山老师要求安装的库的不同,请注意。
3.找一个文件夹 或者是home文件夹 mkdir -p ~/Neza-D1/ && cd ~/Neza-D1/ 这样就有Neza-D1文件夹了。
4.git clone https://gitee.com/weidongshan/neza-d1-buildroot.git buildroot-2021 这个是韦东山老师的buildroot,下载速度应该是比较快。
5.在buildroot-2021/configs/的文件夹下有neza-d1_defconfig,这个就是默认的配置文件。 通过make neza-d1_defconfig 生成默认文件。然后通过
make menuconfig 进入buildroot配置,Qt5的这三个库去掉。(我是下载不下来没有办法去掉的,如果可以下载下来,也不用去掉)
Qt5-coap需要去掉
Qt5-knx 需要去掉
Qt5-mqtt需要去掉6.make all,这个过程非常漫长。完成之后会在buildroot/image下生成sdcard.img,通过写SD卡的工具写入就可以了。
7.写入之后,可以通过串口启动,就成功了一半,这个时候插入HDMI是不能识别,好像是sink什么什么错误。然后执行
mount -t debugfs none /sys/kernel/debug; cd /sys/kernel/debug/dispdbg; echo disp0 > name; echo switch1 > command; echo 4 10 0 0 0x4 0x101 0 0 0 8 > param; echo 1 > start;
然后你的显示屏幕就只能显示左边一部分,然后你执行 cat /dev/urandom > /dev/fb0 应该可以看到左边一小半屏幕有雪花屏幕。
8.我的LCD是1024x600的,显示不全应该是设备树的问题,然后就修改uboot设备树和linux内核设备树。
uboot与linux内核都在 buildroot的output/build/目录下
uboot设备树在 uboot-origin_master文件夹下的 arch/boot/dts/uboot-board.dts
linux内核设备树在 linux-origin_master文件夹下的 arch/riscv/boot/dts/board.dts
两个设备树都要修改成下面这种,-就是要去掉,+就是要增加,其中dev0_output_mode是调分辨率- <10>就是1080p
- <5> 就是720p
- <2> 就是360p
具体可以查文档
disp_init_enable = <1>; disp_mode = <0>; - screen0_output_type = <1>; - screen0_output_mode = <4>; - - screen1_output_type = <3>; - screen1_output_mode = <10>; - - screen1_output_format = <0>; - screen1_output_bits = <0>; - screen1_output_eotf = <4>; - screen1_output_cs = <257>; - screen1_output_dvi_hdmi = <2>; - screen1_output_range = <2>; - screen1_output_scan = <0>; - screen1_output_aspect_ratio = <8>; - - dev0_output_type = <1>; - dev0_output_mode = <4>; + screen0_output_type = <3>; + screen0_output_mode = <10>; + + screen0_output_format = <0>; + screen0_output_bits = <0>; + screen0_output_eotf = <4>; + screen0_output_cs = <257>; + screen0_output_dvi_hdmi = <2>; + screen0_output_range = <2>; + screen0_output_scan = <0>; + screen0_output_aspect_ratio = <8>; + + screen1_output_type = <1>; + screen1_output_mode = <4>; + + dev0_output_type = <4>; + dev0_output_mode = <10>; dev0_screen_id = <0>; - dev0_do_hpd = <0>; - - dev1_output_type = <4>; - dev1_output_mode = <10>; - dev1_screen_id = <1>; - dev1_do_hpd = <1>; + dev0_do_hpd = <1>;
改完成之后,在uboot-origin_master文件夹下与 linux-origin_master文件夹下都需要执行
rm .stamp_built
然后 在buildroot目录下 make all
然后下载到sd卡,
cat /dev/urandom > /dev/fb0 应该是全屏幕的雪花9.这个时候插入鼠标键盘虽然有打印消息但是没有/dev/input/ 这个时候需要在内核加入Event interface,
修改完成还是需要 rm .stamp_built,烧入sd卡,这个时候就有/dev/input/eventx,这个时候鼠标与键盘还是不能用在qt5中。export QT_QPA_GENERIC_PLUGINS=tslib,evdevkeyboard:/dev/input/eventx,evdevmouse:/dev/input/eventx
这个eventx需要根据实际情况来 这个时候qt5就支持键盘了.
10.交叉编译QT5的NES模拟器,我在github下的,它那个需要很多的依赖,
例如需要继承OPENGL。我后面就改成了,只要有最基本的库就可以了。(文件会随后发出来)
qmake在 buildroot的output/host/bin目录下,有qmake就可以交叉编译。qt4-NES4_5_512_480_640_480.7z
这个是QT5源文件,,qt4-NES4_5_512_480_640_480/Qt/hdl.nes 拷贝到根目录可以直接一运行,接上键盘就可以直接玩。
1 2 A W S D L O通过这几个键就可以玩魂斗罗啦,嘻嘻。
这个是我的HDMI显示器图for (y = 0; y < NES_DISP_HEIGHT; y++ )//240
{
for (x = 0; x < NES_DISP_WIDTH; x++ )//256
{
p=(WorkFrame+(y*NES_DISP_WIDTH)+x);
((WorkFrameX+(y<<1))+(x<<1))=*p;
((WorkFrameX+(y<<1))+((x<<1)+1))=*p;
((WorkFrameX+((y<<1)+1))+(x<<1))=*p;
((WorkFrameX+((y<<1)+1))+((x<<1)+1))=*p;
}
}
这个是将图像放大两倍,mask一个标签
infones的linux版本 绘制点是一点一点计算,如果屏幕比较大,应该就比较慢(文章转载自:WhyCan Forum 哇酷开发者社区 )
(原文链接:https://whycan.com/t_7253.html ) -
【FAQ】全志D1芯片 如何解决Audiocodec使用S24_LE格式进行录音,软件分析波形异常的问题?
问题背景
硬件:R329
软件:Tina
内核:Linux-4.9问题描述
使用Audiocodec进行录音,格式S24_LE,录制的.wav波形在某些软件中异常
arecord -D hw:audiocodec -f S24_LE -r 16000 -c 2 -d10 /tmp/test3_S24_LE.wav
需要放大很多倍才能看到声音波形问题分析
1.R329的Audiocodec用于录音的ADC只支持16bit和20bit的采样精度。采样后的数字信号会存放到RX_FIFO中,RX_FIFO的大小为256*20-bit,其他平台可以在User Manual确认支持的采样精度,从而判断是否会有这个问题产生
2.RX_DATA是一个32位的寄存器,保存的是从RX_FIFO获取的一个channel的样本数据,当使用arecord进行录音时,RX_DATA中的值会经DMA搬至内存,最后保存到.wav中
其中RX_DATA有四种模式去获取RX_FIFO的数据,S24_LE和S32_LE均采用20-bit mode0
当设置了20bit采样精度时,对应的两种模式如下图所示:
3.先说明一下S24_LE和S32_LE这两种格式的区别
S24_LE指有符号整型,范围是-2^23 ~ ((2^23) - 1),有效数据在低24位
S32_LE指有符号整型,范围是-2^31 ~ ((2^31) - 1),有效数据在高24位LSB MSB 1st byte 2nd byte 3rd byte 4th byte alignment S32_LE: 00000000 xxxxxxxx xxxxxxxx xxxxxxxx 32 bits S24_LE: xxxxxxxx xxxxxxxx xxxxxxxx 00000000 32 bits S24_3LE: xxxxxxxx xxxxxxxx xxxxxxxx 24 bits
4.在驱动程序中,S24_LE和S32_LE虽然都支持,但他们两者都是使用20-bit的mode0,这导致这两种格式保存到文件中的数据排布是一致的,但生成的wav头信息中的采样位数则不一样,从下图可以看出两者的差异
S32_LE的wav文件信息:
若软件以S32_LE进行解析,以上红框的数据变为0x0f80f0,依然可以保留全部有效数据
S24_LE的wav文件信息:
若软件以S24_LE进行解析,以上红框的数据变为0x55f000,便会丢失一部分数据
解决方案
总结原因就是audiocodec的采样精度只支持16和20bit,因此PCM格式中S24_LE虽然也支持,但硬件的特性使驱动并不能做到很好的适配,若软件以标准S24_LE格式进行分析,则会丢失高位的有效数据,这取决于软件如何对数据进行分析,解决方法有以下三种
- 使用audiocodec时,使用-f S32_LE,修改wav头信息中的采样位数位32,这对大部分软件都有效
arecord -D hw:-f S32_LE -r 16000 -c 2 -d10 /tmp/test32.wav
- 如果必须使用S24_LE格式进行录音,可以选择其他支持24bit采样的音频接口,如I2S等
- 假如必须使用audiocodec声卡,S24_LE格式进行录音,可以自行调整RX_DATA寄存器的模式,结合RX_DATA寄存器中实际的有效数据分布,自己开发软件进行数据分析
如果有分析和处理音频数据的需求,可以参考以上思路,结合RX_DATA寄存器去调整
-
麻雀d1s编译修复adb和phoenixsuit连接问题
- 修复pc连接电脑掉电问题;
- 修复phoenixsuit连接问题;
修复pc连接电脑后掉电问题
官方的tina编译出来之后,连接电脑,如果使用了otg口,会导致这个开发板不断的断开和重连.
而且串口不断地打印断连重连的信息.有这个报错信息:
WARN: get power supply failed\n
看起来是和供电有关的问题,我在网上找到这个文章.
作者说这是因为开发板连接usb之后会把某个电流限制到500ma.我们可以改一下
在文件tina-d1-open/lichee/linux-5.4/drivers/usb/sunxi_usb/udc/sunxi_udc.c中,修改函数sunxi_set_cur_vol_work.
void sunxi_set_cur_vol_work(struct work_struct *work) { #if !defined(SUNXI_USB_FPGA) && defined(CONFIG_POWER_SUPPLY) struct power_supply *psy = NULL; union power_supply_propval temp; if (of_find_property(g_udc_pdev->dev.of_node, "det_vbus_supply", NULL)) psy = devm_power_supply_get_by_phandle(&g_udc_pdev->dev, "det_vbus_supply"); if (!psy || IS_ERR(psy)) { DMSG_PANIC("%s()%d WARN: get power supply failed\n", __func__, __LINE__); } else { temp.intval = 2500; //改为2500ma power_supply_set_property(psy, POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT, &temp); } #endif }
改完之后编译打包,这个现象不会出现了.
修复phoenixsuit连接问题
修改文件tina-d1-open/lichee/brandy-2.0/u-boot-2018/drivers/sunxi_flash/mmc/sdmmc.c中的sunxi_sprite_mmc_probe函数:
int sunxi_sprite_mmc_probe(void) { #ifndef CONFIG_MACH_SUN50IW11 return sdmmc_init_for_sprite(0, 0); //修改了这里. #else int workmode = uboot_spare_head.boot_data.work_mode; if (workmode == WORK_MODE_CARD_PRODUCT) return -1; else return sdmmc_init_for_sprite(0, 0); #endif }
改了之后就可以直接用phoenixsuit来刷机.而不需要使用读卡器.
文章作者: zzidun pavo
文章链接: https://zzidun.github.io/2022/02/08/ma-que-d1s-bian-yi-xiu-fu-adb-he-phoenixsuit-lian-jie-wen-ti/ -
【FAQ】全志XR806芯片 汇编代码调试技巧
1.问题背景
问题平台:XR806 + RTOS2.问题描述
XR806(M33内核)适配新的RTOS时,沿用M4F的启动代码后出现了系统奔溃,但是expection显示的PC地址和LR地址都被修改,无法准确判断哪条语句导致的错误。3.问题分析
- 通过log定位到是启动代码出现了问题。
- arm汇编中,可利用b .进入死循环。
- 在汇编中可以利用以下代码打印log:
//.c文件中插入 void AsmPrint(void) { printf("var = %#x\n",PrintMagic); } #汇编代码中插入以下代码查看R0的值 LDR R8,=PrintMagic str R0,[R8] LDR R8,=AsmPrint bx R8
- 最后发现汇编代码正常,但在运行第一个任务时系统奔溃。原因为M33内核新增了PSPlimit功能,任务栈超过了设定值时会直接触发usage Fault。同时RTOS在系统启动前修改了PC地址和LR地址,导致exception中无法正确显示PC地址和LR地址。
4.解决方法
使用__set_PSPLIM可以设置PSPlimit地址,在不确定PSP限制时,可以__set_PSPLIM(0)取消这个功能,MSP也是相同道理。 -
回复: H616的SDK可以在本论坛下载到吗
@shenhao618 市面上有很多Pi都是基于H616开发的哦,我们欢迎大家到全志在线讨论相关的内容,SDK的话可以联系你购买商家的客服或者代理获取
-
华清远见推出基于全志D1-H的嵌入式RISC-V实验箱
这是华清远见首次使用全志芯片推出实验箱走进高校实验室,D1-H使用的是阿里平头哥的RISC-V C906核心,同时集成了大量全志自研IP,这将极大地提升国内高校嵌入式教育的国产化程度,让课程和实验都在自主可控的科研环境下进行。
全志D1-H主板
主板采用全志的D1-H芯片为主控平台,D1-H是全球首颗量产的搭载平头哥玄铁906 RISC-V的应用处理器,支持RVV,1GHz+主频,可支持Linux系统。同时支持最高4K的H.265/H.264解码,最高可外接2GB DDR3,可以应用于智慧城市、智能汽车、智能商显、智能家电、智能办公和科研教育等多个领域。
主板采用底板+核心板结构、核心板采用6层板设计、底板和核心板采用BTB连接器,方便插拔,且比传统插针稳定可靠,同时也配备了一块7寸电容触控屏。
主板上留有2个2.54MM间距,双排插孔,50PIN标准Arduino插座,可以更换核心板运行不同的操作程序。
配套Linux系统编程实验Linux网络编程实验、Linux设备驱动实验、综合项目案例,更加方便学习,易上手。
嵌入式RISC-V实验箱
实验箱分为两层结构,上层实验层,下层储物层,储物层的存放各种接线、传感器、一件还原节点等;主板带管理锁,方便储物层的设备安全管理;针对实验功能,实验箱具有整体化、一体化设计,铝合金包边,承重抗压不易变形。
图片
D1-H可以独立直接访问3个标准的Arduino板载扩展接口及资源;也可以D1-H通过串口通信间接访问,再由串口通信直接访问控制3个标准的Arduino板载扩展接口及资源,形成微处理器+微控制器的复合应用。
除了主控板之外,实验箱内还有若干外接的拓展板。
- RISC-V核心板
- 4G/GPS二合一模块
- 无线传感网节点
- 传感器模块
- arduino键盘控制扩展板
- arduino电机控制扩展板
- arduino传感器扩展板
- RFID模块
*......
华清远见
在科研教育领域华清远见已深耕多年,科研中心推出的嵌入式、物联网、人工智能、AIoT虚拟仿真实验室已广泛应用于包括武汉大学、哈尔滨工业大学、北京邮电大学等知名高校,在业内拥有极高的知名度及认可度。
于武汉大学完成物联网、嵌入式ARM实验箱的验收培训
为山东大学搭建的高级自动驾驶飞行控制平台
为沈阳工业大学搭建的人工智能实验室全志科研教育领域发展
全志目前已经和中科院软件所、清华大学、同济大学、华侨大学、挪威科技大学等高校及科研机构达成了科研教育合作意向,未来全志将继续积极助力高校科研和教育行业,促进产学研合作。
同济大学分享现场 -
【FAQ】全志R系列在Tina下如何确认方案的optee版本信息
问题背景
Tina环境下当前支持两个版本的optee,一个是2.5.0,一个是3.7.0。由于Tina下平台众多,客户不是很清楚哪些平台支持哪个版本的optee。
问题分析
optee版本主要涉及三个部分optee-client,optee-os-dev-kit,optee.bin。由于2.5与3.7版本跨度太大,所以这三者必须版本匹配,系统才能正常工作,Tina release版本SDK是通过make menuconfig中的OPTEE_VERSION_2_5与OPTEE_VERSION_3_7来统一配置版本信息。可以参考《TinaLinux_安全使用指南》第1.2章节的适用范围来,确认平台的optee版本,旧芯片支持2.5版本,新芯片使用3.7版本。这里汇总如下:
optee-2.5.0: R18、MR133、R311、R328…
optee-3.7.0: R329、MR813、R818、R528…
理论上来说,所有平台都可以支持optee的3.7.0版本。有些客户希望对旧芯片,如R328,升级到3.7.0,此时,系统中就会存在两个版本optee,如果没有统一管理,就容易造成混乱。
问题解决
optee-client
查看tina/package/security/optee-client*/Makefile中的PKG_VERSION来确认版本信息。PKG_VERSION:=2.5.0
optee-os-dev-kit
查看tina/package/security/optee-os-dev-kit/dev_kit/arm-plat-xxx/export-ta_arm32/host_include/conf.mk中的CFG_OPTEE_REVISION_MAJOR与CFG_OPTEE_REVISION_MINOR CFG_OPTEE_REVISION_MAJOR=2 CFG_OPTEE_REVISION_MINOR=5
optee.bin
optee.bin头部包含版本信息,可以通过hexdump进行查看。$ hexdump -C optee_xxx.bin -n 64 00000000 fd 03 00 ea 6f 70 74 65 65 00 00 00 00 00 00 00 |....optee.......| 00000010 00 00 00 00 00 00 00 00 00 00 00 00 33 2e 37 00 |............3.7.|
-
大二学生DIY RISC-V开发板,获阿里批量采购订单
DIY D1s开发板
00后开源创客 @YuzukiTsuru 基于全志D1s芯片设计并制作了一款RISC-V开发板,目前该开发板已经获得了阿里等多家知名科技公司的批量采购订单,将会被用于嵌入式系统的研究和IoT产品的研发。
值得一提的是,本开发板部分小件如电容电阻等是嘉立创机贴的,但D1s主控、XR829等大件物料为心灵手巧的作者本人手贴。
大佬手贴D1s实录
免费开源全部设计资料
该开发板基于全志D1s芯片(阿里平头哥C906 RISC-V核)设计,可用于方案评估、方案预研和个人DIY,可应用于游戏机、智能商显、智能中控等产品形态。作者将开源开发板的全部设计资料。
开发板将提供的资料有:
- 硬件资料:原理图、PCB layout、BOM list
- 软件资料:适配的Tina Linux SDK(全志官方客户平台可下载)、基于官方SDK修改的适配补丁、测试用的固件。
- 技术支持:将提供力所能及的基础技术支持,请到【全志在线开发者论坛】提问,作者和社区的爱好者会回复。
以上所有资料获取:https://bbs.aw-ol.com/topic/1257/
贴片图
实物图规格介绍:
- 基于全志D1s芯片,阿里平头哥C906 RISC-V核心
- 支持全志官方Tina Linux系统,标准linux5.4内核
- 支持RGB显示接口;
- 支持DSI接口;
- 支持TP接口;
- 支持SD卡;
- 支持JATG/UART debug;
- 支持USB Host/device;
- 支持LINEIN接口,支持HPOUT接口;
- 集成全志XR829 WiFi/BT芯片,支持a2dp与hfp
D1s开发板拓展应用-桌面小电脑00后创客大佬
开发板作者 @YuzukiTsuru 是一位00后的大二学生,目前就国内某院校物联网专业。他高中时就搭建了自己的个人博客,上大学后开始玩嵌入式,恰逢全志在线成立并进行资料开源,就开始围绕全志芯片进行项目开发,目前已经基于全志的芯片做了十几个不同型号的开发板并开源到立创开源硬件平台等社区。
立创开源硬件平台个人主页
Github个人主页
全志在线个人主页:https://bbs.aw-ol.com/user/yuzukitsuru
购买途径
本开发板由原作者委托哇酷科技代售并开具发票,所有收益将由哇酷转交给原作者@YuzukiTsuru,有兴趣的可以扫码到淘宝店购买。
-
【FAQ】全志XR806芯片 低功耗蓝牙BLE断开连接错误码和分析?
1、问题背景
硬件:R系列芯片,XR806
软件:Tina2、问题简述
说明:该FAQ旨在列出和分析低功耗蓝牙BLE常见的断开连接原因,方便排查连接过程、连接之后和绑定过程中的断开连接问题。3、问题分析和解决办法
蓝牙低功耗BLE连接时和连接后和绑定过程中可能会有不同原因造成蓝牙断开,下面是比较常见的几种断开错误码和原因分析。
-
回复: 全志在线开源芯片 新 SDK 平台下载方法汇总
@shenhao618 市面上有很多Pi都是基于H616开发的哦,我们欢迎大家到全志在线讨论相关的内容,SDK的话可以联系你购买商家的客服或者代理获取
-
平头哥Sipeed LicheeRV 86 Panel GPIO管脚引出,RGB三色LED闪烁
作者@zhang1gong
原文链接:https://occ.t-head.cn/community/post/detail?spm=a2cl5.14300636.0.0.7f1f180fHnTGVq&id=40398097139641262081 核心板LED点亮
LicheeRV教程提供了核心板上的LED点亮教程。LED点亮或闪烁往往是广泛应用于自动控制的嵌入式系统运行的第一个试验程序,如同一般在桌面系统上学习编程语言运行的第一个程序:“Hello, world!”。我是第一次在Linux系统下运行点灯程序,感觉和在裸机上用c或汇编编程完全不同:基本上不用关心硬件,完全是对文件操作,充分提现了Linux系统“万物皆文件”的理念。核心板上驱动LED的GPIO口(PC1)与底板上的其他应用冲突,因此必须把核心板从底板上拆下,才能做这个点灯试验。但是,核心板上的USB口并不具备模拟串口功能,对此教程似乎并没有明确说明。几位已经做了这个试验的测试者都提到了:要用ADB。虽然大概早晚都会在我的桌面系统中装ADB以搭建交叉编译环境,我还是想先看看有没有其他办法。将核心板从底板拆下后,发现在USB口旁边有4个预留的焊盘,PCB板背面在焊盘旁边标出了“T R G 5V”,不禁使人想到:这难道是个串口?查了一下原理图,果然如此!正好我手头有不止一个串口转USB的小板(某宝上几块钱一个还包邮),为什么不用这个串口呢?忽然想到开发套件中有个小口袋装了4脚插针,应该就是干这个用的。顺利地将4脚插针焊上,但马上发现:如果将核心板插回底板,由于在串口插针下是底板上的复位按键,需要对焊上的插针修剪,否则插针的焊接端就会顶到复位按键上。焊接、修剪过程其实十分简单,但我差点儿在阴沟里翻船。经历了核心板不能工作、终于又恢复的过程(此处略去具体翻船现场和恢复过程200字),总算有惊无险!
通过核心板上的串口,经小板转换成USB连到桌面系统的模拟终端,按照教程给出的命令行指令逐条执行,点灯过程很顺利。(教程给出的命令行指令有一处小错:“cd /sys/class/gpio/export/gpio65”)
2 引脚扩展,RGB三色LED闪烁
底板上预留的扩展引脚区给人以无限遐想,总觉得如不把它们引出来,似乎对不起设计者的初衷。将引脚引出的主要障碍是需要把显示屏与底板分离。分离本身其实并不困难,难的是下决心去做这种带一点儿破坏性的事情(恳请厂家在出厂时就把双排插座焊上吧)。用刀片将显示屏和底板之间的连接分离,小心地在底板上焊上插座,可以方便地用杜邦线连接扩展引脚了。
根据底板上扩展引脚的标号,对照原理图,在感觉没有被占用的引脚中选择B2、B3、B4来用,分别用来驱动三色LEB中的R、G、B。参照教程,先用
“cat /sys/kernel/debug/pinctrl/2000000.pinctrl/pinmux-pins”
命令查询管脚标号对应的数字编号:
然后参照教程写了两个脚本,并放到“/mnt/SDCARD”目录下,这样掉电文件也不会丢失:
\
# rgb_config.sh echo 34 > /sys/class/gpio/export echo 35 > /sys/class/gpio/export echo 36 > /sys/class/gpio/export cd /sys/class/gpio/gpio34 echo out>direction cd /sys/class/gpio/gpio35 echo out>direction cd /sys/class/gpio/gpio36 echo out>direction
\
# rgb_blink.sh for a in $(seq 1 5) do cd /sys/class/gpio/gpio34 echo 1 > value sleep 0.5 cd /sys/class/gpio/gpio35 echo 1 > value sleep 0.5 cd /sys/class/gpio/gpio36 echo 1 > value sleep 1 cd /sys/class/gpio/gpio34 echo 0 > value sleep 0.5 cd /sys/class/gpio/gpio35 echo 0 > value sleep 0.5 cd /sys/class/gpio/gpio36 echo 0 > value sleep 1 done
脚本“rgb_config.sh”用来初始化管脚,“rgb_blink.sh”控制三色LED的闪烁。
Linux系统下万物皆文件,还要进一步好好体会。
-
【FAQ】全志XR806芯片 XR806如何添加本地音频到flash?
问题背景
XR806的文件管理系统是littlefs或spifs,不像fatfs可以直接进行文件传输,有客户放映不清楚如何通过文件管理系统调用音频文件。问题描述
XR806SDK中的audio_demo找不到本地mp3等音频文件。问题分析
- 因为XR806的文件管理系统是littlefs或者spifs,所以需要在PC本地把文件打包成littlefs文件系统格式,否则无法识别。打包工具是SDK下的tools/fs_img_tools/mklittlefs。
- 上一步打包好的文件,如果通过“section”的方式打包进img镜像会有64byte的偏移,所以需要用“raw_bin”的方式进行打包。
解决方法
打包音频文件
新建一个文件夹,如data(名称随意),并把目标音频文件存放仅该目录下,值得注意的是因为audio_demo中默认播放的的是music文件夹下的音频文件,所以音频文件也必须放在music文件夹下。. ├── data │ └── music │ └── 1.mp3 └── mklittlefs
打包该文件夹使用如下命令
./mklittlefs -c data/ -d 0 -b 4096 -p 256 -s 524288 lfs.bin
-c后接目标路径。
-d后接debug等级,默认为0,不用修改。
-b后接block的大小,littlefs默认为4096,一般情况下不用修改。
-p后接page大小,默认为256,不用修改。
-s后接littlefs镜像大小,和在make menuconfig中的配置必须一致。
lfs.bin是生成的镜像文件名。名称随意,但一般是.bin后缀。make menuconfig配置
进入图形化界面配置,并选中filesystem support后选项配置如下。推荐勾选上flash filesystem image pack support,编译代码后会自动把lfs.bin打包到镜像,否则只能在phoenixMC的调试界面中擦除flash地址1572864(0x18000)后的内容,并手动把lfs.bin写进flash。其中步骤1所说的镜像大小524288就是由2048*1024-1572864而来。--- filesystem support [*] flash filesystem image pack support FileSystem Type Select (LittleFS) ---> (1572864) little filesystem start address (4096) little filesystem block size (128) little filesystem block count
修改工程cfg文件配置
把前面打包好的lfs.bin复制到project/demo/audio_demo/image/xr806目录下,并修改目录下的image.cfg。{ "magic" : "AWIH", "version" : "0.5", "image" : {"max_size": "1532K"}, "section" :[ {"id": "0xa5ff5a00", "bin" :"boot_40M.bin", "cert": "null", "flash_offs": "0K", "sram_offs": "0x00230000", "ep": "0x00230101", "attr":"0x1"}, {"id": "0xa5fe5a01", "bin" :"app.bin", "cert": "null", "flash_offs": "71K", "sram_offs": "0x00201000", "ep": "0x00201101", "attr":"0x1"}, {"id": "0xa5fd5a02", "bin" :"app_xip.bin", "cert": "null", "flash_offs": "104K", "sram_offs": "0xffffffff", "ep": "0xffffffff", "attr":"0x2"}, {"id": "0xa5fa5a05", "bin" :"wlan_bl.bin", "cert": "null", "flash_offs": "1075K", "sram_offs": "0xffffffff", "ep": "0xffffffff", "attr":"0x1"}, {"id": "0xa5f95a06", "bin" :"wlan_fw.bin", "cert": "null", "flash_offs": "1078K", "sram_offs": "0xffffffff", "ep": "0xffffffff", "attr":"0x1"}, {"id": "0xa5f85a07", "bin" :"sys_sdd_40M.bin", "cert": "null", "flash_offs": "1103K", "sram_offs": "0xffffffff", "ep": "0xffffffff", "attr":"0x1"}, {} ], "raw_bin" :[ {"bin" :"lfs.bin", "flash_offs": "1536K"}, {} ] }
编译完成后编译烧录即可。
-
LVGL日历控件和显示天气
利用TCP封装HTTP包请求天气信息
Linux还真是逐步熟悉中,现在才了解到Linux即没有原生的GUI,也没有应用层协议栈,所以要实现HTTP应用,必须利用TCP然后自己封装HTTP数据包。本篇即记录封装HTTP数据包,到心知天气请求天气信息的案例实现过程。
1、心知天气API说明
心知天气应该是当下国内使用很普遍的一个天气数据站点。相关注册和使用过程,这里就不再啰嗦了,不清楚的朋友可以自己到官网上查看(https://www.seniverse.com/)。本例仅测试实时天气数据获取,天气相关数据只有“状态(晴朗之类)”和“气温”,请求接口地址如下:
可以看到请求地址给的是域名,TCP连接需要直接给IP地址,所以用ping来获取其IP为“116.62.81.138”,端口自然是80。
得到IP地址后,先不着急编程,通过网络助手实验一把,具体过程是:选择TCP Client,连接对方IP和端口(116.62.81.138:80),然后将请求地址前加上方法字串“GET”,结尾还要有两个回车换行“\r\n\r\n”。初次测试时,忘记了回车换行符没有成功,加上后就好了。
封装好的数据包是:“GET https://api.thinkpage.cn/v3/weather/now.json?key=yourkey&location=tianjin&language=en&unit=c\r\n\r\n”。
2、JSON分析
请求到的数据是JSON格式,贴到Json.cn(https://www.json.cn/)的在线工具里,可以更清晰的看到其结构。可以看到请求实时数据(now.json),得到一个JSON对象,包含一个“results”引导的JSON数组,且数组只有一个元素,元素中又包含“location”、“now”和“last_update”三个JSON对象,内部还有键值对。
既然是开发Linux API的C程序,当然利用cJSON库来帮助进行数据解析了。本人使用的库是从网上搜到的一个百度网盘分享。
链接:https://pan.baidu.com/s/1DQynsdlNyIvsVXmf4W5b8Q
提取码:ww4z3、请求天气案例
具体思路就是建立TCP Client连接心知天气的Server,然后发送请求包,得到响应包,解析并打印出结果,案例比较简单做成单次的——开启即运行到底,代码如下:#include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <string.h> #include <netinet/in.h> #include <arpa/inet.h> #include "cJSON.h" #define SERVER_IP "116.62.81.138" #define SERVER_PORT 80 #define NOW "now.json" #define DAILY "daily.json" #define API_KEY "SK0LJ8FI2TP0L-IsQ" #define CITY "tianjin" #define REQ_PACK "GET https://api.thinkpage.cn/v3/weather/%s?key=%s&location=%s&language=en&unit=c\r\n\r\n" #define N 1024 #define errlog(errmsg) do{ perror(errmsg);\ printf("----%s----%s----%d----\n", __FILE__, __func__, __LINE__);\ return -1;\ } while(0) //struct for weather data typedef struct { char id[16]; char name[32]; char country[16]; char path[64]; char timezone[32]; char tz_offset[16]; char text[16]; char code[4]; char temp[8]; char last_update[32]; } weather_t; //parse function & print weather_t data function void aita_ParseJsonNow(char *json, weather_t *w); void aita_PrintWeather(weather_t *w); int main(int argc, const char *argv[]) { int sockfd; struct sockaddr_in serveraddr; socklen_t addrlen = sizeof(serveraddr); char sendbuf[N] = ""; char recvbuf[N] = ""; weather_t weather = {0}; //create socket if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { errlog("socket error"); } //connect to server of seniverse.com serveraddr.sin_family = AF_INET; serveraddr.sin_addr.s_addr = inet_addr(SERVER_IP); serveraddr.sin_port = htons(SERVER_PORT); if((connect(sockfd, (struct sockaddr*)&serveraddr, addrlen)) < 0) { errlog("connect error"); } //build & send request package sprintf(sendbuf, REQ_PACK, NOW, API_KEY, CITY); if(send(sockfd, sendbuf, N, 0) < 0) { errlog("send error"); } //waiting server response if(recv(sockfd, recvbuf, N, 0) < 0) { errlog("recv error"); } printf("recv: %s\n", recvbuf); //parse & print data aita_ParseJsonNow(recvbuf, &weather); aita_PrintWeather(&weather); close(sockfd); return 0; } void aita_ParseJsonNow(char *msg, weather_t *w) { cJSON *json, *ja, *jo, *josub, *item; json = cJSON_Parse(msg); //parse string to cJSON type if(json == NULL) { printf("json type cast error: %s", cJSON_GetErrorPtr()); return; } else { printf("parse now pack\n"); if((ja=cJSON_GetObjectItem(json, "results")) != NULL) { //get results array if((jo=cJSON_GetArrayItem(ja, 0)) != NULL) { //get array[0](the only item) //get location object if((josub=cJSON_GetObjectItem(jo, "location")) != NULL) { if((item=cJSON_GetObjectItem(josub, "id")) != NULL) { memcpy(w->id, item->valuestring, strlen(item->valuestring)); } if((item=cJSON_GetObjectItem(josub, "name")) != NULL) { memcpy(w->name, item->valuestring, strlen(item->valuestring)); } if((item=cJSON_GetObjectItem(josub, "country")) != NULL) { memcpy(w->country, item->valuestring, strlen(item->valuestring)); } if((item=cJSON_GetObjectItem(josub, "path")) != NULL) { memcpy(w->path, item->valuestring, strlen(item->valuestring)); } if((item=cJSON_GetObjectItem(josub, "timezone")) != NULL) { memcpy(w->timezone, item->valuestring, strlen(item->valuestring)); } if((item=cJSON_GetObjectItem(josub, "timezone_offset")) != NULL) { memcpy(w->tz_offset, item->valuestring, strlen(item->valuestring)); } } //get now object if((josub=cJSON_GetObjectItem(jo, "now")) != NULL) { if((item=cJSON_GetObjectItem(josub, "text")) != NULL) { memcpy(w->text, item->valuestring, strlen(item->valuestring)); } if((item=cJSON_GetObjectItem(josub, "code")) != NULL) { memcpy(w->code, item->valuestring, strlen(item->valuestring)); } if((item=cJSON_GetObjectItem(josub, "temperature")) != NULL) { memcpy(w->temp, item->valuestring, strlen(item->valuestring)); } } //get last_update object if((josub=cJSON_GetObjectItem(jo, "last_update")) != NULL) { memcpy(w->last_update, josub->valuestring, strlen(josub->valuestring)); } } } } //delete original json pack free memory cJSON_Delete(json); return; } void aita_PrintWeather(weather_t *w) { printf("id: %s\n", w->id); printf("name: %s\n", w->name); printf("country: %s\n", w->country); printf("path: %s\n", w->path); printf("timezone: %s\n", w->timezone); printf("timezone_offset: %s\n", w->tz_offset); printf("text: %s\n", w->text); printf("code: %s\n", w->code); printf("temperature: %s\n", w->temp); printf("last_update: %s\n", w->last_update); }
项目路径中建立了源文件main.c,编写上述代码,并导入cJSON.c和cJSON.h,编译命令为:“riscv64-unknown-linux-gnu-gcc main.c cJSON.c -o weather -lm”。因为cJSON会用到math库,而它需要“-lm”来动态链接。
lvgl显示图片和本地时间
1、lvgl的图片显示
lvgl框架中图片可以是一个文件也可以是一个变量(数组形式的图片码),当然文件还需要初始化lvgl对文件系统的接口,本例暂以变量形式提供。应用要显示图片,则需要引入一个图片控件,然后设置它的数据源——使用“lv_img_set_src()”函数。示例如下:
lv_obj_t * icon = lv_img_create(lv_scr_act(), NULL); /*From variable*/ lv_img_set_src(icon, &my_icon_dsc);
上述代码中“icon”是一个lvgl对象指针,通过“lv_img_create()”实例化,则对应图片控件。设置数据源时传入参数“my_icon_dsc”是lvgl中的图片描述符数据结构“lv_img_dsc_t”——本身是一个结构体类型,其定义源码如下:
//in “../lvgl/src/draw/lv_img_buf.h” typedef struct { uint32_t cf : 5; /*Color format: See `lv_img_color_format_t`*/ uint32_t always_zero : 3; /*It the upper bits of the first byte. Always zero to look like a non-printable character*/ uint32_t reserved : 2; /*Reserved to be used later*/ uint32_t w : 11; /*Width of the image map*/ uint32_t h : 11; /*Height of the image map*/ } lv_img_header_t; typedef struct { lv_img_header_t header; /**< A header describing the basics of the image*/ uint32_t data_size; /**< Size of the image in bytes*/ const uint8_t * data; /**< Pointer to the data of the image*/ } lv_img_dsc_t;
示例代码中,图片描述符变量的定义过程如下代码:
uint8_t my_icon_data[] = {0x00, 0x01, 0x02, ...}; static lv_img_dsc_t my_icon_dsc = {![8.png](/assets/uploads/files/1653270047514-8.png) .header.always_zero = 0, .header.w = 80, .header.h = 60, .data_size = 80 * 60 * LV_COLOR_DEPTH / 8, .header.cf = LV_IMG_CF_TRUE_COLOR, /*Set the color format*/ .data = my_icon_data, };
其中,枚举“LV_IMG_CF_TRUE_COLOR”是色彩格式定义,表示RGB格式。
宏“LV_COLOR_DEPTH”则定义色彩深度,它位于“lv_conf.h”,用户可以自定义。本例中设置为32,即4字节的ARGB8888格式。
2、时间获取
86板的Tina Linux可以通过C time库轻松地获得本地时间等数据。本例使用的API有:time()、localtime()、strftime()以及time_t、struct tm。3、图片和时间显示案例
本例继续使用线程管理lvgl刷新,创建1s周期的lvgl定时器,在定时器回调中获取本地时间并格式化输出。另外,系统初始时显示一个“天津”的Logo,而且初始即做一次时间获取和输出(如果不做,初始刹那label会显示默认“text”字样)。图片码通过软件“Img2Lcd”获取,软件配置方式如下图所示。图片生成的数组有72008个字节,被放置到头文件“aita_logo.h”。
/* Includes ------------------------------------------------------- */ #include "lvgl/lvgl.h" #include "lv_drivers/display/fbdev.h" #include "lv_drivers/indev/evdev.h" #include <stdio.h> #include <string.h> #include <unistd.h> #include <pthread.h> #include <time.h> #include <sys/time.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include "aita_logo.h" /* Private macro -------------------------------------------------- */ #define AITA_DISP_BUF_SIZE (128 * 1024) #define AITA_SCREEN_WIDTH 480 #define AITA_SCREEN_HEIGHT 480 #define AITA_TITLE_STRING "AITA Weather for LicheeRV with LVGL" #define SEND_PERIOD 1000 #define errlog(errmsg) do{ perror(errmsg);\ printf("----%s----%s----%d----\n", __FILE__, __func__, __LINE__);\ return;\ } while(0) /* Global variables ----------------------------------------------- */ lv_indev_t *aita_indev; //pointer of indev lv_obj_t *sys_scr; //pointer of system screen instance lv_obj_t *head_label; //pointer of title label instance lv_obj_t *main_label; //pointer of main label instance char main_label_text[32]; //main label text string for datetime lv_obj_t *logo_img; //pointer of city logo image instance lv_timer_t *sec_timer; //pointer of timer instance for tcp polling pthread_t lvgl_tid; //lvgl thread id pthread_t tcprecv_tid; //tcp receive thread id pthread_mutex_t lvgl_mutex; //mutex for lvgl tick //image descriptor for logo_img //ARGB8888 image 180*100 which code array is 'tj_logo' lv_img_dsc_t img_dsc_city = { .header.always_zero = 0, .header.w = 180, .header.h = 100, .data_size = 18000 * LV_COLOR_SIZE / 8, .header.cf = LV_IMG_CF_TRUE_COLOR, .data = tj_logo, }; /* Private function prototypes ------------------------------------ */ void aita_InitLVGL(void); void aita_CreateMainUI(void); void *thread_lvgl(void *arg); void sec_timer_cb(lv_timer_t *timer); void aita_InitTimer(void); void aita_GetTime(void); /* Private functions ---------------------------------------------- */ int main(void) { void *retval; //by author. initialize lvgl including displaybuffer, device for disp & input aita_InitLVGL(); //by author. initialize and register event device //these code must be in main(), otherwise the touch will fail. static lv_indev_drv_t indev_drv; lv_indev_drv_init(&indev_drv); indev_drv.type = LV_INDEV_TYPE_POINTER; //by author. choice touchpad indev_drv.read_cb = evdev_read; //by author. input callback aita_indev = lv_indev_drv_register(&indev_drv); //by author. create the main view when the demo starts up aita_CreateMainUI(); //by author. create a timer aita_InitTimer(); //by author. create mutex for lvgl if(pthread_mutex_init(&lvgl_mutex, NULL) != 0) { errlog("initialize mutex error"); } //by author. create lvgl thread if(pthread_create(&lvgl_tid, NULL, thread_lvgl, (void *)0) != 0) { errlog("create lvgl thread error"); } //by author. wait for thread exit, this demo should never be here. pthread_join(lvgl_tid, &retval); printf("lvgl thread exit, return value: %s\n", (char *)retval); pthread_mutex_destroy(&lvgl_mutex); return 0; } /*Set in lv_conf.h as `LV_TICK_CUSTOM_SYS_TIME_EXPR`*/ uint32_t custom_tick_get(void) { static uint64_t start_ms = 0; if(start_ms == 0) { struct timeval tv_start; gettimeofday(&tv_start, NULL); start_ms = (tv_start.tv_sec * 1000000 + tv_start.tv_usec) / 1000; } struct timeval tv_now; gettimeofday(&tv_now, NULL); uint64_t now_ms; now_ms = (tv_now.tv_sec * 1000000 + tv_now.tv_usec) / 1000; uint32_t time_ms = now_ms - start_ms; return time_ms; } void aita_InitLVGL(void) { /*LittlevGL init*/ lv_init(); /*Linux frame buffer device init*/ fbdev_init(); //by author. initialize framebuffer device for display evdev_init(); //by author. initialize event device for touchpad /*A small buffer for LittlevGL to draw the screen's content*/ static lv_color_t buf[AITA_DISP_BUF_SIZE]; /*Initialize a descriptor for the buffer*/ static lv_disp_draw_buf_t disp_buf; lv_disp_draw_buf_init(&disp_buf, buf, NULL, AITA_DISP_BUF_SIZE); /*Initialize and register a display driver*/ static lv_disp_drv_t disp_drv; lv_disp_drv_init(&disp_drv); disp_drv.draw_buf = &disp_buf; disp_drv.flush_cb = fbdev_flush; disp_drv.hor_res = 480; disp_drv.ver_res = 480; lv_disp_drv_register(&disp_drv); } void aita_CreateMainUI(void) { //by author. create system screen which is basic graphic level sys_scr = lv_obj_create(lv_scr_act()); lv_obj_set_size(sys_scr, AITA_SCREEN_WIDTH, AITA_SCREEN_HEIGHT); //by author. create the main title which is just a label head_label = lv_label_create(sys_scr); lv_label_set_text(head_label, AITA_TITLE_STRING); lv_obj_align(head_label, LV_ALIGN_TOP_MID, 0, 10); //by author. create the city logo image logo_img = lv_img_create(sys_scr); lv_img_set_src(logo_img, &img_dsc_city); lv_obj_align(logo_img, LV_ALIGN_TOP_LEFT, 10, 40); //by author. get local time and show string aita_GetTime(); main_label = lv_label_create(sys_scr); lv_label_set_text(main_label, main_label_text); lv_obj_align(main_label, LV_ALIGN_TOP_LEFT, 200, 40); lv_obj_set_style_text_font(main_label, &lv_font_montserrat_20, 0); } //by author. lvgl core thread function void *thread_lvgl(void *arg) { while(1) { pthread_mutex_lock(&lvgl_mutex); lv_task_handler(); pthread_mutex_unlock(&lvgl_mutex); usleep(5000); /* sleep for 5 ms */ } } //by author. sec_timer callback which refresh date string void sec_timer_cb(lv_timer_t *timer) { aita_GetTime(); lv_label_set_text(main_label, main_label_text); } //by author. initialize timer for 1s timing void aita_InitTimer(void) { sec_timer = lv_timer_create(sec_timer_cb, 1000, NULL); lv_timer_set_repeat_count(sec_timer, -1); } //by author. get local time string void aita_GetTime(void) { time_t tsec; struct tm *tlocal; tsec = time(NULL); tlocal = localtime(&tsec); memset(main_label_text, 0, 32); strftime(main_label_text, 32, "%Y-%m-%d %a %H:%M:%S", tlocal); }
lvgl日历控件和显示天气
本篇结合本人前两篇的HTTP请求天气数据(通过“心知天气”网站)和lvgl显示图片及时间,在案例主界面上增加了日历显示和实时天气显示,先直接上图。
1、lvgl日历控件
calendar是lvgl提供的“Extra widgets”组件之一,需要注意的是8.0版本后有几个API的传参发生了变化,本例使用8.3版本,设置日期是需要同时传递“年、月、日”三个参数。本例使用的API有:lv_calendar_create()、lv_canlendar_set_today_date()、lv_calendar_set_showed_date()和lv_calendar_header_arrow_create()。
lv_calendar_create()函数用于实例化calendar控件,传参是控件的父容器指针,本例使用“lv_scr_act()”即系统屏幕。
lv_canlendar_set_today_date()函数用于设置当前日期,本人使用发现lvgl是附带万年历功能的,只要设置好当天的年月日,就可以自动生成正确的日历排布。函数传参分别是控件指针和年月日数据。
关于年月日参数有两点注意事项。一是v7版本中,传参通过lv_calendar_date_t结构体,其包含年月日三个成员。二是如果使用了C time库的struct tm,注意其中年份需要加上“1900”,而月份则需要加“1”。
lv_calendar_set_showed_date()函数用于设置日历当前显示页,也就是设置当前月份。本人实验的效果是当天日期框会自动高亮,如果想设置多个高亮日期,可以使用函数lv_calendar_set_highlighted_dates()。
lv_calendar_header_arrow_create()函数用于向日历控件顶部增加“左、右箭头”两个按钮用于日历翻页(一页是一月)。此外,还有函数lv_calendar_header_dropdown_create()则是设置两个下拉列表分别用于选择年份和月份。这两个函数都只用传递日历控件指针一个参数,且是8.1版本新增API。
2、日历和天气显示案例
本案例的思路是:1)在应用启动时,获取当前时间(上篇中已经实现),然后将时间保存在全局量“struct tm today”中,并利用变量“today”来初始化日历控件的日期数据。2)上篇实现的时间显示案例,通过lvgl定时器,每秒获取本地数据,此处在定时器回调中再增加一个每到正分钟发送“Linux条件变量”。3)同时,应用启动时建立两个线程——lvgl线程和请求天气线程,请求天气线程等待条件变量到来,开启一次天气数据请求过程。本例代码结合文章上半部分已经给出的案例,这里只给出改变部分。
/* Includes ------------------------------------------------------- */ // 增加头文件,cJSON用于解析JSON格式的天气数据 #include "cJSON.h" /* Private macro -------------------------------------------------- */ // 增加请求天气数据相关的宏定义 #define HTTP_IP "116.62.81.138" #define HTTP_PORT 80 #define NOW "now.json" #define API_KEY "SK0LJ8FI2TP0L-IsQ" #define CITY "tianjin" #define REQ_PACK "GET https://api.thinkpage.cn/v3/weather/%s?key=%s&location=%s&language=en&unit=c\r\n\r\n" #define N 1024 // struct for weather data 建立结构体存储解析后的天气数据 typedef struct { char id[16]; char name[32]; char country[16]; char path[64]; char timezone[32]; char tz_offset[16]; char text[16]; char code[4]; char temp[8]; char last_update[32]; } weather_t; /* Global variables ----------------------------------------------- */ // 增加显示天气的标签控件定义 lv_obj_t *weather_label; //pointer of weather label instance // 增加日历控件定义 lv_obj_t *calendar; //pointer of calendar instance // 定义today变量存储当前日期,用于设置日历 struct tm today; // // 请求天气的线程ID pthread_t reqweather_tid; //request weather thread id // 请求天气线程等待的条件变量(min_cond) // Linux中需要互斥量包含条件变量的使用,所以定义cond_mutex pthread_mutex_t cond_mutex; //mutex for 1-min cond pthread_cond_t min_cond; //1-min cond /* Private functions ---------------------------------------------- */ int main(void) { // other code from previous demo // main()函数中创建互斥量、条件变量、请求天气线程 //by author. create mutex for 1-min cond if(pthread_mutex_init(&cond_mutex, NULL) != 0) { errlog("initialize cond mutex error"); } //by author. create condition for 1-min if(pthread_cond_init(&min_cond, NULL) != 0) { errlog("initialize 1 minute condition error"); } //by author. create request weather thread if(pthread_create(&reqweather_tid, NULL, thread_reqweather, (void *)0) != 0) { errlog("create request weather thread error"); } //by author. wait for thread exit, this demo should never be here. pthread_join(lvgl_tid, &retval); printf("lvgl thread exit, return value: %s\n", (char *)retval); pthread_join(reqweather_tid, &retval); printf("request weather thread exit, return value: %s\n", (char *)retval); pthread_mutex_destroy(&lvgl_mutex); pthread_mutex_destroy(&cond_mutex); pthread_cond_destroy(&min_cond); return 0; } void aita_CreateMainUI(void) { // other code from previous demo // aita_CreateMainUI()被main()函数调用,初始化主界面。 //by author. create the weather label weather_label = lv_label_create(sys_scr); lv_label_set_text(weather_label, " "); lv_obj_align(weather_label, LV_ALIGN_TOP_LEFT, 200, 120); //by author. create the calendar calendar = lv_calendar_create(sys_scr); lv_obj_set_size(calendar, 235, 235); lv_obj_align(calendar, LV_ALIGN_BOTTOM_LEFT, 10, -50); lv_calendar_set_today_date(calendar, today.tm_year+1900, today.tm_mon+1, today.tm_mday); lv_calendar_set_showed_date(calendar, today.tm_year+1900, today.tm_mon+1); lv_calendar_header_arrow_create(calendar); } // 增加正分钟发送条件变量 void sec_timer_cb(lv_timer_t *timer) { aita_GetTime(); lv_label_set_text(main_label, main_label_text); if(today.tm_sec == 0) { //by author. send condition signal per whole minute pthread_cond_signal(&min_cond); } } // 增加对today的赋值 void aita_GetTime(void) { time_t tsec; struct tm *tlocal; tsec = time(NULL); tlocal = localtime(&tsec); today = *tlocal; memset(main_label_text, 0, 32); strftime(main_label_text, 32, "%Y-%m-%d %a %H:%M:%S", tlocal); } // 请求天气线程业务逻辑 void *thread_reqweather(void *arg) { int sockfd; struct sockaddr_in serveraddr; socklen_t addrlen = sizeof(serveraddr); char sendbuf[N] = ""; char recvbuf[N] = ""; weather_t weather = {0}; char w_string[64] = ""; while(1) { pthread_mutex_lock(&cond_mutex); pthread_cond_wait(&min_cond, &cond_mutex); pthread_mutex_unlock(&cond_mutex); //create socket if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { errlog("socket error"); } //connect to server of seniverse.com serveraddr.sin_family = AF_INET; serveraddr.sin_addr.s_addr = inet_addr(HTTP_IP); serveraddr.sin_port = htons(HTTP_PORT); if((connect(sockfd, (struct sockaddr*)&serveraddr, addrlen)) < 0) { errlog("connect error"); } //build & send request package memset(sendbuf, 0, N); sprintf(sendbuf, REQ_PACK, NOW, API_KEY, CITY); if(send(sockfd, sendbuf, N, 0) < 0) { errlog("send error"); } //waiting server response if(recv(sockfd, recvbuf, N, 0) < 0) { errlog("recv error"); } printf("recv: %s\n", recvbuf); //parse & print data,下面两个函数来自于“十三”案例 aita_ParseJsonNow(recvbuf, &weather); aita_PrintWeather(&weather); close(sockfd); memset(recvbuf, 0, N); //show weather string memset(w_string, 0, 64); sprintf(w_string, "weather:%s temperatur:%s", weather.text, weather.temp); pthread_mutex_lock(&lvgl_mutex); lv_label_set_text(weather_label, w_string); pthread_mutex_unlock(&lvgl_mutex); } }
另外,本例在lvgl工程中增加了cJSON.c和cJSON.h文件,Makefile也做出了调整,具体如下所示。
原文链接:https://occ.t-head.cn/community/post/detail?spm=a2cl5.25411629.0.0.6597180fVP7giT&id=4039525135236603904
作者 @ firr -
【FAQ】全志R329如何使用audiocodec如何减少snd_pcm_open的耗时
问题背景
客户在使用audiocodec进行声音播放时,发现调用snd_pcm_open所用的时间达400多ms,客户希望能减少耗时开发环境
硬件:R328
软件:Tina
内核: Linux-4.9问题分析
客户调用snd_pcm_open时,传入的PCM NAME是使用了dmix插件的,dmix插件的功能是可以让多个应用同时访问音频通道,实现声音同时输出的效果。当不使用任何插件时(-D hw:audiocodec,0),调用snd_pcm_open会马上获取对应的pcm句柄,获取成功后再配置音频通路和寄存器,而当使用dmix插件时,调用snd_pcm_open会先解析插件中的参数,再根据参数配置音频通路和寄存器,通过dapm打开功放和操作DAC寄存器,之后再获取对应的pcm句柄,执行的逻辑更多。
当打开功放和操作DAC寄存器时,为了防止pop音的产生,驱动中加上了160ms + 2*30ms的sleep(乘以2是因为有左右声道),这里的sleep就是耗时产生的地方
解决方案
- 保证没有pop音的前提下,可以在dts中减少pa_msleep的值,这个值是操作功放的使能位后产生的延迟,对应上图的spk_cfg->pa_msleep
- 调整内核printk打印级别
snd_pcm_open,2646,s:0.439500 Used Time:0.439527 ----> 调整前 snd_pcm_open,2646,s:0.258538 Used Time:0.258548 ----> 调整后
- 删去内核不必要的打印或者用ftrace代替,调试发现一条内核打印耗时约4ms,过多的打印会严重影响性能
- 列表保证没有pop音的前提下,可以在驱动程序中直接减少sunxi_codec_playback_event的msleep值,因为这个sleep是为了避免操作DAC后出现尖刺导致的pop音,因此此方式应为最低优先级
-
【FAQ】全志R328如何进入monitor模式
【问题背景】
硬件:R328+ Wi-Fi模组(XR829)
软件:Tina
说明:该FAQ旨在记录在Tina系统上XR829如何进入monitor模式【问题简述】
我们知道xradio的xconfig配网方式,会自动切到monitor模式,那么驱动如何手动设置进入monitor模式呢?【问题分析】
1.既然xconfig配网可以进入monitor模式,那么直接分析代码就可以找到对应的操作。
2.可以通过添加打印来跟踪xconfig的调用流程。echo 0xff > /sys/kernel/debug/xradio_host_dbg/dbg_common echo 0xff > /sys/kernel/debug/xradio_host_dbg/dbg_sta
【解决方法】
手动设置进入monitor模式:
insmod /system/vendor/modules/xradio_wlan.ko //加载xr829.ko ifconfig wlan0 down //可能系统起来会默认进入sta模式,所以先down掉 iw wlan0 set type monitor //最关键的,设置进入monitor模式 iw wlan0 info //获取wlan0网卡信息 ifconfig wlan0 up //up wlan0 iw wlan0 set channel 6 //设置信道 echo 0xffff,0xffff > /sys/kernel/debug/ieee80211/phy0/xradio/parse_flags //打开收发帧调试,可以分析monitor模式
-
将开发板设计拆解为10个部分,教你DIY一块F1C200S Linux开发板
本项目是基于全志F1C200S设计的开源屏幕开发板,设计的目标是提供一个低成本、超迷你且适合Linux开发的平台,特别是针对屏幕接口的支持。
项目简介
开发板板载16M nor flash,主控芯片采用F1C200S,内置64M DRAM。同时附带USB Host接口以及USB type-c口,以及CH340串口转USB芯片,用于开发调试使用。
硬件设计
由于芯片功能繁多,开发板设计也相对复杂,为了教会大家自己DIY开发板,作者将开发板设计的硬件部分按功能拆分为了10个不同的知识点,来对开发板整体设计进行全面介绍和详细讲解电路原理。
全志F1C200S主控
全志F1C200s是一款高度集成、低功耗的移动应用处理器,支持高清视频解码,包括H.264、H.263、MPEG 1/2/4等格式,同时还具备音频编解码器和I2S/PCM接口,适用于多媒体音视频设备。
芯片基于ARM 9架构,并SiP了DDR,这样的配置使其外围电路在设计时会非常简单,非常适合作为入门级的Linux开发板。该部分原理图如下图所示:
- SVREF用于给DRAM提供参考电压,该部分所需电压为VCC_DRAM/2
- 2VCC_DRAM为DRAM供电,电压为2.5V
- VCC_IO为GPIO供电,电压为3.3V
- VCC_CORE为核心供电,电压为1.2V
- AVCC为模拟供电,该部分非常重要,不接会导致USB Host无法枚举设备,同时需要注意该引脚供电范围为2.5V-3.1V,不可以使用3.3V供电,会导致内部电路损坏。
- X1为24M晶振,为芯片提供时钟信号,采用22pF负载电容。
SDMMC接口
SDMMC接口用于接入Micro SD卡,系统启动时,可以从SD卡中加载U-Boot,内核,RootFS,实现Linux启动。
如上图所示,相关线路说明如下所示:
- CLK: SDMMC时钟,每个时钟周期传输一个命令或数据位。频率可在0至25MHz之间变化。SD卡总线管理器可以自由产生0至25MHz的频率,没有任何限制
- CMD: 命令传输线,命令通过该CMD线串行传输
- D0~D3: 数据通过这些数据线传传输
- 按照SDMMC规范,SDMMC线路还需要增加10K上拉电阻,如果没有可以会影响数据传输,本原理图中R7-R11即上拉电阻。同时,为了保证电源质量,增加了C22滤波电容
- SHELL引脚为SDMMC连接器固定引脚,此处接地处理,CD引脚用于探测SD卡是否插入,这一块悬空未使用
CH340串口转USB
此电路用于用户连接系统调试中断使用,其功能为将TTL串口转换为USB接口,使得用户可以在电脑中连接该串口进行调试。
需要注意的是,由于F1C200S的UART0接口(PE0/PE1引脚)被触摸的I2C接口占用,所以本开发板将CH340的串口连接到了F1C200S的UART1(PA2/PA3引脚)上,后续编译U-Boot和内核时我们需要相应的修改代码。
如上图所示,该部分除了串口转USB外,还兼顾了系统的供电。
- 用户通过Type-C线缆连接该调试口后,将同时为开发板供电
- 板上的5.1K电阻用于双头Type-C线缆识别从机,为其供电
- 如果R12,R13不焊接会导致使用双头Type-C线时板子没有供电
- D2为TVS瞬态抑制二极管用于保护PCB板上元件,防止静电击穿原件
三路DC-DC接口
该部分主要为主控芯片提供供电,采用SY8089A1AAC,单路最大输出电流2A。
- SVREF用于给DRAM提供参考电压,该部分所需电压为VCC_DRAM/2
- 2VCC_DRAM为DRAM供电,电压为2.5V
- VCC_IO为GPIO供电,电压为3.3V
- VCC_CORE为核心供电,电压为1.2V
- AVCC为模拟供电,该部分非常重要,不接会导致USB Host无法枚举设备,同时需要注意该引脚供电范围为2.5V-3.1V,不可以使用3.3V供电,会导致内部电路损坏。
- X1为24M晶振,为芯片提供时钟信号,采用22pF负载电容。
在该模块中,我们使用了2520电感,与普通的电感相比,体积更小,但是2520电感在DCR(即直流电阻)参数上,会比普通的电感大一点,电感值的计算公式可以参考下方:
- L为计算出的电感容量
- Vout为降压芯片输出电压
- L为计算出的电感容量
- Vin为降压芯片输入电压
- Fsw为芯片开关频率,SY8089取1.5Mhz,也就是1500000Hz
- Iout,max为最大输出电流
如下图所示,本开发板电感值直接参考SY8089数据手册文档,折中后取1.5Uh:
芯片的反馈电阻控制着芯片的输出电压,可以参考下方公式计算:
- Rh为上端分压电阻阻值
- Rl为下端分压电阻阻值
- 0.6V指的是芯片的Vfb,也就是反馈电阻
- Vout即最终的电压输出值
- 在这里,我们需要确定Rl和Vout,然后将其代入公式,计算出Rh
- 为了最大限度地减少轻负载下的功耗,最好为 RH 和 RL 选择较大的电阻值。强烈建议 RL 使用 10k 到 200k 之间的值
AVCC 3V LDO
该部分用于AVCC 3V供电,使用XC6206 3V LDO,位号为U10,由于较为简单,此处不在详细说明。
SPI Nor Flash
Nor Flash为F1C200S芯片提供了第二种启动方式。
- 上电后,F1C200S首先从内部BROM (芯片内置,无法擦除)启动
- 首先检查 SD0 有没有插卡, 如果有插卡就读卡 8k偏移数据,是否是合法的启动数据, 如果是BROM 引导结束, 否则进入下一步
- 第二步:检测SPI0 NOR FLASH是否存在, 是否有合法的启动数据, 如果是BROM 引导结束, 否则进入下一步
- 第三步:检测SPI0 NAND FLASH 是否存在, 是否有合法的启动数据, 如果是BROM 引导结束, 否则进入下一步
- 最后,因为找不到任何可以引导的介质,系统会进入usb fel模式,此时可以使用USB烧录
此处SPI Nor Flash可以同时兼容Nand Flash,不过目前裸机资料基本上都是以SPI Nor Flash为基础,所以此处焊接了W25Q128JVEIQ 128Mbit(16Mbyte)SPI Nor Flash。
- R4为上拉电阻(F1C200S内部也存在上拉电阻,可以不焊),防止未供电时芯片错误写入数据
- C16为滤波电容
- SW2为FEL模式开关,将SPI_MISO短路到地后,F1C200S将无法检测到SPI Nor Flash,从而进入USB Fel模式,此时可以松开按键,烧录内容至SPI Nor Flash
- /WP为SPI Nor Flash保护引脚,低电平有效,有效时无法写入数据
- /HOLDor/RESET为SPI Nor Flash保持或者复位输入引脚。
- 最后,因为找不到任何可以引导的介质,系统会进入usb fel模式,此时可以使用USB烧录
外部IO接口
此处引出了未使用的IO,用户可连接其他设备,C35为滤波电容,用于保证电源质量,该部分引脚功能可以参考下图(来源:芯片数据手册14/15页):
USB OTG/USB TYPE-C
该部分连接到了芯片的DP/DM引脚,为芯片的USB接口。
USB Type-C用于USB Fel模式烧录系统,无供电输入/输出能力。
USB OTG处可用于连接其他USB设备,带5V输出,当然也可以接双头USB Type-A线缆用于USB Fel模式。
需要注意的是,开发板中没有连接ID线(ID线用于识别USB模式),所以在编写设备树时,我们需要强制指定USB模式为主机或从机。
背光驱动
该部分用于驱动RGB屏幕背光,标准40Pin RGB屏幕基本采用串联背光,由于本身开发板供电只有5V,所以我们需要使用背光驱动芯片升压到合适的电压,来驱动屏幕背光。
同时,背光驱动芯片采用恒流控制,可以避免电流过大导致背光LED烧毁,该部分原理图如下所示:
- C19 C20为滤波电容,C19电容的耐压需要特别考虑,一般的RGB屏背光电压基本在18V以上(白光LED压降3V*6串),过低的电容耐压会导致电容损坏
- BL_CTR为芯片背光控制引脚,此处直接接入了上拉,再开发时可以将BL_CTR引脚接入F1C200S的PWM引脚上,这样可以灵活控制屏幕亮度,同时,有恒流驱动的存在,控制亮度时,背光也不存在明显的频闪
- L1 为升压电路的电感,按照要求一般取10uh或22uh即可,不需要使用公式详细计算,但是需要注意电流不能超过电感额定电流
R5为芯片的反馈电阻,用于调节输出的电流,计算公式可参考下方:
此处我们选择20ma,所以R1=0.25/0.020(Ω) = 12.5Ω,就近取12Ω。
如上图,下方说明了LED为2并5串,额定电流为40ma,我们为了保险,选择了20ma,亮度会有所损失。
40Pin RGB/触摸接口
此处参考屏幕数据手册即可,由于F1C200S只支持RGB565,RGB666,此处使用RGB666,屏蔽了RGB三色的低2位,这样最终色彩影响比较小,同时,F1C200S内置色彩抖动,可以更加接近RGB888效果。
其中需要注意的是,CTP_SDA/CTP_SCL最好加上拉电阻,此处选用了内部上拉,所以并没有加电阻,该部分原理图如下所示:
开发环境搭建
使用VSCode的DeviceTree插件,我们可以实现设备树文件的代码高亮,编辑c语言代码。
安装VSCode后,我们开始安装设备树插件,再商店中搜索DeviceTree插件,点击安装安装即可:
同理,推荐读者同时安装中文汉化,搜索CN,参考下图安装即可,安装后按照要求重启VSCode即可使用。
打开安装好的Ubuntu 18.04虚拟机,将需要分区的SD卡插入电脑USB口,并右键点击VMware右下角的USB存储器图标,点击连接,将SD卡连入虚拟机。具体操作过程如下图所示:
点击桌面左下角图标,进入所有应用,然后搜索GPartd,可参考下图:
此时需要输入密码,输入用户密码,提权到root用户,如下图所示:
接着在右上角选择我们需要格式化的SD卡,默认为/dev/sda,这个是我们虚拟机的系统盘,我们需要切换到SD卡,此处一定要小心,sdb不一定是我们的sd卡。
完成切换后,右键点击如图所示位置,点击“卸载”,接着点击“删除”按钮删除SD卡中原有分区,最后点击确定,确认删除,具体过程可以参考下图。
接着开始创建分区,首先创建boot分区,用于u-boot读取设备树、内核等文件,我们需要在分区前方空出一定的空间,用于u-boot以及SPL程序存放,如下图所示,首先点击左上角按钮,创建新分区,然后按照下图创建boot分区。
此处为U-Boot以及SPL预留了1Mib的空间,完全足够存放这些程序。
接着创建rootfs分区,我们将剩下的空间全部作为rootfs,文件系统选择ext4,如下图所示:
最后点击保存,确认后生效,拔出SD卡备用,操作可参考下图:
开源资料获取
作者适配的U-Boot目前使用了master分支的U-Boot并给出了移植指南。由于后续master分支代码可能会存在更新,所以移植指南使用了最近的一个U-Boot版本来指导复刻打开发者进行修改和配置,编译出自己的U-Boot。
本项目所有资料均已开源,软硬件都开源了,其中软件开源了:UBoot、Kernel、Buildroot:测试镜像下载地址等……想获取资料自己DIY学习的伙伴可以前往获取
-
Ubuntu官方发布适配全志D1-H哪吒开发板的镜像
Ubuntu发行商Canonical近日官方发布了适配全志D1-H哪吒开发板的Ubuntu镜像,旨在为开发者提供稳定的底层框架,让开发者可以专注于核心应用程序的开发。
官方原文:https://canonical.com/blog/canonical-enables-ubuntu-on-allwinners-nezha-risc-v-boards
开发者可以直接到Ubuntu官方网站获取镜像文件及安装指南。
下载链接:https://ubuntu.com/download/risc-v
此次发布的镜像是Ubuntu Severt 22.04.1版本,该版本的移植适配工作由 Canonical、阿里平头哥以及全志共同完成。
D1-H哪吒运行Ubuntu ServerUbuntu是最受欢迎的开源操作系统之一,其稳定且可靠的特性吸引大部分开发者选用其作为开发时的首选OS。RISC-V架构在近些年的时间里飞速发展,从低端微控制器到高端服务器级处理器皆可发现用RISC-V架构进行部署的应用。开源软件搭配上开源硬件,让免费且可扩展软硬件的自由度迈上新的台阶。
D1-H哪吒开发板距发布至今已有超过一年的时间,全志以“开放BSP,融入OS”为核心,建立起了丰富的Linux开发生态,目前开发板已经成功适配了全志自研Tina Linux、Ubuntu、RT-Thread Smart、Debian、Fedora......等数款系统,全志也将携手各厂商、社区、工程师、开源创客等业内伙伴,在开源软硬件适配方向持续深耕,完善开发生态,为开发者提供多元化的选择。
-
【FAQ】全志R329如何利用wpa_cli设置地区代码?
问题背景
硬件:R328+ Wi-Fi模组(XRADIO)
软件:Tina3.0及以上
说明:该FAQ旨在记录XRADIO驱动常见的调试Tips。与具体驱动相关,具有一般性。问题简述
客户需求,如何获取和设置地区代码?
问题分析
地区码:表示现有的国家、独立机构或特殊地理政治区域的名称代码。
区别于
移动网络代码:是与移动设备国家代码(Mobile Country Code,MCC)(也称为“MCC / MNC”)相结合,以用来表示唯一一个的移动设备的网络运营商。这些运营商可以是使用的GSM/LTE、CDMA、iDEN、TETRA和通用移动通讯系统的公共陆基移动网亦或是卫星网络。
当前xr829驱动并没有透出接口用来获取和设置地区代码。
解决方法
借用wpa_cli工具来获取和设置:
root@TinaLinux:/# wpa_cli -i wlan0 -p /etc/wifi/sockets set country US OK root@TinaLinux:/# wpa_cli -i wlan0 -p /etc/wifi/sockets get country US
-
【FAQ】全志系列芯片 如何在Tina Linux中使用脚本完成定制化升级?
1.主题
在Tina Linux中,如何使用脚本完成定制化升级
2.问题背景
硬件:全平台
软件:Tina
其他:支持OTA升级的平台,可实现脚本定制化升级3.具体表现
在OTA升级过程中,添加定制化需求,实现控制变量升级。
4.问题分析
利用swupdate升级满足定制化脚本需求
5.解决办法
因为swupdate支持脚本,所以在升级过程中,添加能够实现定制升级的脚本即可,将带有定制升级的脚本编入策略描述文件(sw-descrition)OTA升级配置文件中(sw-subimgs),在打包ota升级包时,将脚本一起打包进ota包中。在进行下面的配置后,输入升级命令时,首先开始执行脚本中的内容,满足升级条件后,再进行升级流程。下面进行详细的步骤介绍:
1.swupdate支持shellscript脚本,需要以下功能配置(默认选中)
执行:make menuconfig/make ota_menuconfig Allwinner ---> <*> swupdate............................. software update for embedded system Swupdate Settings ---> General Configuration ---> [*] enable pre and postinstall scripts Image Handlers ---> [*] shellscript
2.在swupdate文件夹下创建脚本,名字随意,在脚本中写入要实现的功能。例如:目前有一个方案需要升级,但是分为A,B两种产品,对应做了不同的功能,为了防止升级混淆,可以利用脚本去控制变量升级,比如A产品方案中的env,可以添加一个变量project=a,B产品方案中的env添加一个变量project=b,那么脚本中的内容就可以判断project=a或b时,继续完成升级。env中添加内容和脚本内容举例如下:
env中:
脚本内容如下:
3.在描述文件中添加脚本功能,在sw-description中添加以下代码:
4.将脚本打包进ota包中,脚本名字可以任意起,我这里是preinstall_checkAB.sh。
5.重新编译主系统和recovery系统,烧录固件,打包ota包,再进行验证。
6.验证:当校验失败时,返回值为1,会看到如下打印,不能升级。
校验成功时,返回值为0,看到如下打印,升级成功。
-
【FAQ】全志V853芯片 Tina获取各个分区编译好后的分区镜像文件[脚本]
[需求描述]
做SDK对接过程作,应用开发有可能需要自己制作升级固件(OTA,烧录)。这就需要从SDK中找出编译好的各个分区镜像文件。本FAQ提供一个脚本,将各个分区已经编译好的镜像分区给拷贝到一个固定地方。
[脚本安装方法]
将附件中内容按照目录替换到sdk的相应目录当中。
目录:scripts/.hooks (如.hooks 目录不存在,在需要创建)scripts/.hooks |_post-pack |_pack_script |_aw_pack.sh
[使用方法]
安装完成后,直接按正常使用那样,执行pack 脚本进行打包,打包成功后回有打印:
/home/v833-sdk/out/v831_pro_ipc/image/…/aw_pack_src
[工具生成的目录介绍]
├── aw_pack.sh #执行该脚本即可再进行打包,并输出在当前目录的out目录 ├── config #打包的配置文件 ├── image #各种分区镜像文件,可以替换,请勿改名 │ ├── boot0_nand.fex #boot0 的nand镜像 │ ├── boot0_sdcard.fex #boot0 的SD卡镜像 │ ├── boot0_spinor.fex #boot0 的spinor镜像 │ ├── boot.fex #内核镜像 │ ├── boot_package.fex # uboot打包镜像 │ ├── boot_package_nor.fe # uboot 在spinor方案上的打包镜像 │ ├── env_nor.fex #env环境变量镜像 │ ├── rootfs.fex #rootfs 镜像 │ ├── sunxi.fex #GTP分区表 │ └── other.fex #其他分区镜像 ├── other #打包所需的其他文件 ├── out #执行aw_pack.sh脚本后输出的目录 ├── tmp #临时目录,用于打包时使用 └── tools #打包时需要的linux 工具
脚本文件:aw_pack_src.tar.gz
-
【FAQ】全志V853芯片 VE debugfs调试节点信息说明
VE debugfs调试节点信息说明
【调试信息】
cat /sys/kernel/debug/mpp/ve ********Channal[0]: H265Enc Ver.07388090580d7ad94c897633057ff0806abf4340 F119******** MainProfile, Level:186, BitRate:1048576, FrameRate:20 Input:1920x1080, Output:2304x1296, RotAng:0 Crop: Left:0, Top:0, Width:0, Height:0 IDRPeriod:40, GopSize:2, NormalP, VBR, IpcCase, Colour InitQp:30, IQp[10~50], PQp[10~50] CurPQp:29, TargetBits:23424, RealBits:25920, BitRatio:110.66% Scene:1, Move:0, MovingLevel:0, BinImgRatio:0.32%, MovingTh:20 AvgBitRate:3, RealBitRate:763, AvgFrmRate:0, RealFrmRate:21 LBC:1, Lossy2X, y&yc_stride:1152,1728 VbvSize:622592, Unused:619328, Valid:3264, ValidFrmNum:1 Intra4x4:1, IntraInP:1, 3DNR:1 Quality:10, IBitsCoef:10, PBitsCoef:10 Mad[][10]:96.21 1.55 0.42 0.23 0.17 0.10 0.07 0.03 0.00 0.00 0.00 0.00 Mad[0][]:3.83 4.90 39.77 30.91 10.06 3.28 1.81 0.83 0.45 0.36 ClassifyTh[]:0 0 0 0 0 0 0 0 0 0 0 0 Lambda:0.00, LambdaC:0.00, LambdaSqrt:0.00 Intra: Coef{31 31 31}, Th{0 0 0} PredTend: Inter:16, Skip:16, Merge:20 ********End Channal[0] H265Enc******** ********Channal[1]: H264Enc Ver.07388090580d7ad94c897633057ff0806abf4340 F119******** MainProfile, Level:51, BitRate:512000, FrameRate:20 Input:640x360, Output:640x360, RotAng:0 Crop: Left:0, Top:0, Width:0, Height:0 IDRPeriod:60, NormalP, VBR, IpcCase, Colour InitQp:30, IQp[10~45], PQp[10~45] CurPQp:20, TargetBits:20894, RealBits:25648, BitRatio:122.75% Scene:0, Move:1, MovingLevel:1, BinImgRatio:1.55%, MovingTh:20 AvgBitRate:585, RealBitRate:374, AvgFrmRate:21, RealFrmRate:21 LBC:1, Lossy2X, y&yc_stride:384,576 VbvSize:304128, Unused:300864, Valid:3264, ValidFrmNum:1 Intra4x4:1, IntraInP:1, 3DNR:1 Quality:10, IBitsCoef:10, PBitsCoef:10 Mad[][10]:46.81 7.12 1.50 0.44 0.38 0.56 0.19 0.19 0.25 0.06 0.00 0.00 Mad[0][]:1.31 5.94 7.38 3.81 4.75 5.50 7.31 4.81 3.62 2.38 ClassifyTh[]:0 0 0 0 0 0 0 0 0 0 0 0 ********End Channal[1] H264Enc********
【参数说明】
参数 描述 Channal VE通道号,0/1/2/3 EncType 编码类型,H264:H264Enc;H265:H265Enc Ver 编码库版本,对应的commit ID FrameCnt 编码帧的帧数,例如F119表示第119帧 Profile 编码输出视频的档次,档次越高,允许使用的编码技术越丰富。H264低于High不能使用8x8转换,质量变差,如客户没具体要求,默认H264使用Hihg,H265使用Main。H264:Base/ Main/ High,H265:Main/ Main10/ MainStill Level 编码输出视频的等级,按照标准规定的分辨率和帧率而定。过往有些客户的机器出现解码高Level码流性能不足的情况,所以建议由编码库内部自适应配置。H264:定义在enum H264_LEVEL_E,H265:定义在enum H265_LEVEL_E BitRate 码率,单位bps FrameRate 帧率,单位fps Input 编码输入分辨率 Output 编码输出分辨率 RotAng 旋转角度 Crop 裁剪坐标 IDRPeriod I帧周期 GopSize 编码参考集大小,该参数不影响码率控制,H265的该参数会影响某些解码器的参考帧内存预分配,建议统一配置成2。 FixQp 固定I/P帧Qp,仅在RcMode选择FixQp时生效 InitQp RcMode为非FixQp下,首个I帧Qp IQp I帧Qp取值范围 PQp P帧Qp取值范围 TargetBits 当前帧目标bit数 RealBits 当前帧实际bit数 BitRatio bit数比例 = 100 * RealBits / TargetBits Scene 纹理复杂程度的等级,[0,2] Move 运动复杂程度的等级,[0,4] MovingLevel 场景变化剧烈程度等级,[0,3] BinImgRatio SAD超过MovingTh的8x8块数量比例,[0%,100%] MovingTh 8x8块SAD阈值,[10,31] AvrBitRate 到目前为止的平均码率,按编码器拿到的VIBuffer的时间戳每隔一秒更新一次 RealBitRate 实际最近一秒内的瞬时码率,按编码器拿到的VIBuffer的时间戳每隔一秒更新一次 AvgFrmRate 到目前为止的平均帧率,按编码器拿到的VIBuffer的时间戳每隔一秒更新一次 RealFrmRate 实际最近一秒内的瞬时帧率,按编码器拿到的VIBuffer的时间戳每隔一秒更新一次 AFBC VI使用LBC的开关,[0,1] LBC VI使用LBC的开关,[0,1] VbvSize 编码器输出Buffer长度 Unused VbvBuffer剩余可用空间 Valid VbvBuffer已占用空间 ValidFrmNum 占用VbvBuffer未归还的帧数量 Intra4x4 帧内4x4块预测开关,[0,1] IntraInP P帧使用帧内预测开关,[0,1] 3DNR 编码器3D滤波开关,[0,1] Quality 静止场景下的P帧bit数比重,按10为100%计算,[0,20] IBitsCoef I帧bit数比重,按10为100%计算,[1,20] PBitsCoef 运动场景下P帧bit数比重,按10为100%计算,[1,50] Mad[][10] 纹理MAD直方图比例分布,以10为步长 Mad[0][] 纹理MAD在10以内的直方图比例分布,以1为步长 ClassifyTh MB级码控分类阈值 Lambda H265编码器Lambda值,H264:无效,V853的H265无效 LambdaC H265编码器LambdaC值,H264:无效,V853的H265无效 LambdaSqrt H265编码器LambdaSqrt值,H264:无效,V853的H265无效 IntraCoef 帧内分块决策系数,三个系数分别对应32x32、16x16、8x8块,系数越大,越倾向于分小块,H264:无效,H265:[0,31] IntraTh 帧内分块决策MAD阈值,三个阈值分别对应32x32、16x16、8x8块,阈值越小,越倾向于分小块,H264:无效,H265:[0,127] PredTendInter Inter预测模式倾向系数,系数越小,越倾向于Inter预测,H264:无效,H265:[0,63] PredTendSkip Skip预测模式倾向系数,系数越小,越倾向于Skip预测,H264:无效,H265:[0,63] PredTendMerge Merge预测模式倾向系数,系数越小,越倾向于Merge预测,H264:无效,H265:[0,36] 【调试方法】
app运行结束后,支持查看VE debugfs调试信息功能的开启方法。
默认情况下,app运行结束后,通过 cat /sys/kernel/debug/mpp/ve 无法继续查看ve的debugfs调试信息。
在app运行前执行命令 echo 1 > /sys/kernel/debug/mpp/ve 可开启该功能。
平台重启后,修改会自动失效,需要重新打开。执行命令 echo 0 > /sys/kernel/debug/mpp/ve 可恢复默认情况。
-
【全志&OpenHarmony】全志两款支持OpenHarmony开发板在开放原子开源基金会OpenHarmony见面会实况分享
2021年12月28日,OpenAtom OpenHarmony开源见面会首站在江苏南京圆满举行。本次活动为OpenHarmony城市和高校全年巡回活动的首发站,以“融合行业需求,夯实关键技术”为主题,精彩呈现OpenHarmony 2021年度的共建成果及未来发展规划。
本次会议特别设立了Dev-Board-SIG分论坛,各家共建单位详尽阐述了OpenHarmony开发板目前的开发概况和未来规划。目前,在众家共建单位的努力下,小组已经有40余块开发板完成或计划完成基于OpenHarmony 3.0 LTS版本的移植适配工作,给OpenHarmony主线代码演进提供了源源不断的硬件基础。
全志也在本次见面会的Dev-Board-SIG分论坛上展出了两款支持OpenHarmony的开发板,分别为哪吒D1开发板、XR806开源鸿蒙开发板,除了本次大会上展出的开发板,全志T507等多个芯片平台的开发版也在适配OpenHarmony系统。
哪吒D1开发板
目前,主干代码里已经支持部分友商的芯片,计划在2022年支持ARM、MIPS、RISC-V等构架及多数主流芯片,全志D1也在即将支持的RISC-V框架芯片范围之内。因为它的CPU是RISC-V架构的,使用的是阿里平头哥的C906核心。中科院软件所于佳耕团队和全志一同进行OpenHarmony系统的移植,并已经完成适配工作。作为全志在线基于全志D1芯片定制的AIoT开发板,是全球首款支持64bit RISC-V指令集并支持Linux系统的可量产开发板。可以应用于科研教学、产品项目预研、开发爱好者DIY等。
XR806开源鸿蒙开发板
XR806开源鸿蒙开发板是在Dev-Board-SIG开发板展区展出的第二块全志的板子,也是全志首款适配OpenHarmony系统的开发板,XR806开发板使用的是全志自研的XR806芯片,支持wifi和ble,可以应用于智能家居、工业控制等场景的无线互联,同时也使用的是Arm-Star ARMv8-M MCU,sip了ddr和flash。高集成度的特点,可以帮助我们的客户和开发者最大化地降低硬件设计的复杂度,降低bom成本。同时支持efuse和security,留给了开发者更大的软件开发和设计空间。目前,XR806开发板代码已经通过XTS认证合入主仓。
仓库地址:https://gitee.com/moldy-potato-chips/devboard_device_allwinner_xr806千行百业加速数字化转型的当下,OpenHarmony将坚持”融合行业需求 夯实关键技术”的重要信念,全志也会持续输出优质产品,并进行OpenHarmony的适配工作,与开放原子开源基金会和众友商共建OpenHarmony繁荣生态,共享共赢新未来。
-
4月全志芯片开源项目分享合辑
FunnyPi-全志T113-S3卡片电脑
作者:flose
开源项目地址:https://oshwhub.com/flose/funnypi-quanzhi-t113-s3-card-computer
FunnyPi-T113是一款基于全志T113-S3/D1S处理器的完全开源多功能开发板,设计FunnyPi最初的目的是想满足日常学习,结合T113高效能和低功耗的特点,来满足做语音助手,智能家居屏幕、桌面摆件屏、博客服务器等嵌入式应用的开发需求。
FunnyPi开发板内置了丰富的外设接口,包括USB、GPIO、I2C、SPI、UART等,方便用户连接各种传感器、执行器和其他外围设备,同时板载了标准RGB接口、WiFi模组、PMIC芯片、串口转USB芯片等,方便开发者进行DIY开发。
此外,这款开发板适配全志Tina-Linux,支持快启,最重要的一点是,本开发板所有阻容使用0603封装且将绝大部分元件放在了正面,非常方便手焊!
基于全志T113的串口助手
作者:huerli
开源项目地址:https://oshwhub.com/huerli/chuan-kou-zhu-shou
本项目是基于全志T113-S3制作的无线串口调试器,上位机由Qt制作的串口助手客户端、下位机数据采集转发装置组成,配有无线WiFi蓝牙模组,可以对下位机采集到的数据显示以及对于数据绘制波形。
上位机信号的转换使用的是CH343P,对串口3输出TTL信号的调试信息转换成USB差分信号,当然也可以不焊CH343P,用TTL转USB工具直接于电脑连接。电源管理方面使用的是IP5306来进行锂电池充放电管理,并由单节4.2V锂电池进行供电。屏幕则是使用比较常见的十寸RGB565,同样支持RGB666,触摸IC使用GT911。
上位机由Awboot+Linux+Buildroot组成,作者本人开源了交叉编译器、Awboot源码、串口助手qt界面源码等内容,并详细介绍了开发环境搭建及qt界面配置等教程。
T113智能家居86盒(圆屏版)
作者:萨纳兰的黄昏
开源项目地址:https://oshwhub.com/planevina/t11386-box-revision
如上,你所见到的这款圆滚滚的小玩意,就是魔改了一款在前几期的文章中我们所介绍过的,一款方形的T113-S3智能家居86盒,原项目因其验证过的原理图和PCB(√),可初始化的屏幕(√),详尽的SDK和保姆级的部署教程(√),从而受到了不少开发者的关注,其中也包括一些爱整活的小伙伴。
萨纳兰的黄昏在86盒的原作者FanHuaCloud大佬加持下,又给86盒挖了个新坑,为了解决之前所驱动的圆屏只能播放MJPEG并且帧率较低的尴尬问题,集圆屏加一体化驱动板+外壳+炫酷LVGL UI于一身的圆形86盒横空出世,并命名其为——T113太极派。
目前的版本是插电使用的超薄版本 ,后续可能会增加带扩展版的支持电池的充电版本,其最主要的特点是作者为这款圆形的太极派专门给它建模做了一个极其轻薄的CNC外壳,触摸屏直径是71.8mm,外壳直径为74mm。树脂版外壳厚度为13mm,CNC版外壳厚度为10mm。
T113 MIPI触摸屏核心板
作者:搞事情团队
开源项目地址:https://oshwhub.com/gao-shi-qing-tuan-dui/t113_mipi
此核心板尺寸小巧,板载资源极其丰富,元件均在一面,背面可直接与大显3寸MIPI液晶屏通过FPC排线相连。板载CH340,MPU6050,HUB,NANDFlash,麦克风,XR829-WIFI。仅用一根Typc线便可调试此核心板,非常方便。调试串口,ADB接口,音频接口及USB,GPIO均已用引出。扩展性极强。板载资源均已调试通过。
-
【FAQ】全志V853芯片 编码P帧帧内如何刷新功能检查?
编码P帧帧内刷新功能检查方法
H264
使用Elescard StreamEye 4.6 工具(只支持H264),按如下截图配置后,开启P帧帧内刷新后,图像看到一个橙色的竖状矩形条,同时逐帧往后查看时矩形条会从左往右移动;关闭P帧帧内刷新后,则无此矩形条。
H265
使用YUView 工具(需要配置ffmpeg动态库)可分析H265文件,勾选Pred Mode后,可显示一个蓝色的竖状矩形条,同时逐帧往后查看时矩形条会从左往右移动;关闭P帧帧内刷新后,则无此矩形条。
注:
YUView 工具配置ffmpeg动态库
为使YUView 工具分析能力更强,需要配置ffmpeg动态库。配置方法如下:
-
成本400元,DIY一个高刷新率热成像相机
在市面上开源的热成像作品中,有一部分颜值高,但分辨率太低;也有一部分把分辨率提高了,但使用起来却不太流畅。
基于此,作者本人结合二者的优势,设计了一款热成像相机——LiThermal,成本算下来只要400出头,还具备了万全的功能。
- 拍照
- 录像
- 查看相册
- 查看温度最大值、最小值、中心值
- 温度统计图
- 修改调色板
- 重定向后台管理页面,电脑访问
这款热成像相机不仅拥有高分辨率及丝滑流畅的拍摄,在主控全志T113的加持下,UI界面的几乎所有动画都能达到90Hz刷新率,并支持随意的动画打断,最重要的是,作者将热成像相机的软硬件全部开源了出来!
热成像相机开机动画演示
PCB温度检测演示
远距相机检测演示热成像相机功能
相机不仅支持高清拍照功能,而且在拍照的同时能够即时捕捉并显示全屏范围内的温度数据,为用户提供直观的温度分布视图,拍摄后的照片和视频都可以在相册中查看。
此外,该设备还提供了温度数据的最大值、最小值以及中心值的查看功能,帮助快速识别温度异常区域,为了更直观地展示温度变化趋势,设备还贴心配备了温度统计图功能。
为了满足不同用户的需求,设备还支持自定义调色板,根据个人偏好或特定应用场景调整色彩显示方案,重定向后台管理页面的功能,可以通过电脑访问后台管理系统,实现更高级的设置和数据管理操作。
系统配置
作者直接为相机在全志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://oshwhub.com/lxu0423/lithermal-thermal-imaging-camera
Github开源链接:https://github.com/diylxy/LiThermal
视频版介绍:https://www.bilibili.com/video/BV1e4xeeCEGL以上链接中包含硬件设计文件,程序源代码和编译工具链,可以根据这些资料完整复刻本作品,达到视频中的效果。
复刻注意事项:本作品难度较大,想要完整复刻需要能够焊接0402元件和0.3毫米间距的QFP引脚,并且需要有一定Linux系统使用经验和计算机网络基础,请做好心理准备。
-
【FAQ】全志V853芯片 如何查看NPU时钟电源配置以及信息?
[KERNEL_DIR]/arch/arm/boot/dts/sun8iw21p1.dtsi
npu: npu@03050000 { compatible = "allwinner,npu"; reg = <0x0 0x03050000 0x0 0x1000>; device_type = "npu"; dev_name = "npu"; interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>; clocks = <&clk_npu>, <&clk_pll_npux4>; clock-frequency = <504000000>; interrupt-names = "npu"; iommus = <&mmu_aw 6 1>; status = "okay"; power-domains = <&pd V853_PD_NPU>; };
一:如何使能电源控制以及电源状态确认
在dts确认配置power-domains后,电源默认打开,如果NPU模块电源需要关闭,需要内核支持CONFIG_SUNXI_POWER_DOMAINS=y;不用的时候应用层软件会默认将其关闭;root@TinaLinux:/# echo 0x070010a0,0x070010ac > /sys/class/sunxi_dump/dump && cat /sys/class/sunxi_dump/dump 0x070010a0: 0x00000002 0x00020000 0x00000000 0x00000000
如上为电源处理关闭状态
echo 0x070010a0,0x070010ac > /sys/class/sunxi_dump/dump && cat /sys/class/sunxi_dump/dump 0x070010a0: 0x00000001 0x00010000 0x00000000 0x00000000
如上电源处于开启状态
二:如何配置支持的频率
clock-frequency = <504000000>;代表现在设置的频率为504M;客户请严格按照原厂建议配置,或直接默认配置,勿随意更改其频点;
clocks = <&clk_npu>,<&clk_pll_npux4>;前面为模块时钟,后面为父时钟;
在[KERNEL_DIR]/drivers/clk/sunxi/clk-sun8iw21_tbl.c中有如下table代表目前所支持的频点;
/* PLL_NPU(n, d1, freq) F_N8X8_D1V1X1 */ struct sunxi_clk_factor_freq factor_pllnpux4_tbl[] = { PLLNPU(24, 1, 300000000U), PLLNPU(40, 1, 492000000U), PLLNPU(20, 0, 504000000U), PLLNPU(25, 0, 624000000U), PLLNPU(28, 0, 696000000U), PLLNPU(41, 0, 1008000000U), PLLNPU(57, 0, 1392000000U), }; 配置规则为: npu4x的计算公式为:24M * (N+1) / (M+1)N:0-254M:0-1 在clk-sun8iw21_tbl.c中截图部分添加新的频率组即可 如:492PLLNPU(40, 1, 492000000U),24*(40+1)/(1+1)= 492
通过clk_summary我们可以看到配置是否生效
root@TinaLinux:/# cat /sys/kernel/debug/clk/clk_summary pll_npux4 0 2 504000000 0 0 npu 0 1 504000000 0 0
当然我们也可以从probe的打印看到时钟的相关配置
[ 843.717406] Want set pclk rate(504000000) support(504000000) real(504000000) [ 843.725445] Want set mclk rate(504000000) support(504000000) real(504000000)
三:怎么用命令修改时钟的频率
reboot uboot #等待其处于uboot中后: fdt list /soc/npu fdt set /soc/npu clock-frequency <696000000> fdt list /soc/npu save boot
-
【FAQ】全志V853芯片 烧录spinor烧录器固件方法
1.主题
v85x/v83x 烧录spinor烧录器固件方法
2.问题背景
产品:spinor 烧录
硬件:v83x / v85x-
什么是spinor烧录器固件?
烧录器固件就是就是在spinor flash上从地址start(0x00) ~ end 的二进制数据文件。 -
哪些场景会使用烧录器固件?
①工厂会使用烧录器工具多一点,在贴片前,使用烧录器固件批量给多个spinor烧录固件。烧录完成后再贴片;
②开发的同学有些也喜欢烧录自己制作的烧录器固件,而非使用全志Tina SDK 编译出来的固件。 -
如何制作烧录器固件?
①从一个已经烧录好的机器读取flash的全部二进制数据出来,形成一个烧录器固件;
②只要按照划分好各个分区的起始点,把需要pack后的分区文件按偏移拼接起来。如:
|boot0|boot_package|mbr|boot|rootfs|env|…
- 如何使用工具烧录spinor “烧录器固件” ?
请看下面的解决方法:
3.解决办法
-
如果制作好了烧录器固件: factory_flash.bin 16M烧录到16M 的spinor 里面。
-
插入usb到pc,板子进入efex 模式,进入efex 方式有:
①系统下输入reboot efex (进入后,打印会输出CCCC)
②在uboot输入 efex (进入后,打印会输出CCCC)
③按住2,上电开机 (进入后,打印会输出CCCC)
④短路flash,让flash读取失败 (进入后,打印会输出CCCC) -
下载附件工具sunxi-tester.exe(附件上) ,Pc(windows)上烧录工厂flash固件:
sunxi-tester-v853-0704.zip
- 使用帮助
Usage: D:\我的文档\桌面\sunxi-tester.exe [options] command arguments… [command…] -h, --help Print this usage summary and exit -v, --verbose Verbose logging -p, --progress “write” transfers show a progress bar -l, --list Enumerate all (USB) FEL devices and exit spiflash-read addr length file Write SPI flash contents into file spiflash-write addr file Store file contents into SPI flash
注意: 此工具sunxi-tester.exe 只能操作spinor flash 前面16M空间。 超过16M无法进行读写。
-
-
第二届RISC-V中国峰会议程公布
第二届 RISC-V中国峰会将于2022年8月24日至26日举办,持续三天,峰会将分成两个线上分会场同时进行。
本届峰会将会包含产业界最新技术及产品发布、学术界前沿成果展示等,共收录技术报告、成果展示、短演讲80余个。
全志科技产品研发中心总经理黄少锐也将以“RISC-V音视频计算芯片的应用与探索”为题,在8月24日周三的下午,于分会场A进行线上主题演讲,欢迎感兴趣的朋友前来交流探讨。
以下为峰会的完整议程时间表:
-
【FAQ】全志V853芯片 如何动态打开蓝牙kernel部分的log?
1.主题
如何动态打开蓝牙kernel部分的log2.问题背景
产品:扫描笔等Tina产品
硬件:V853 + XR829
软件:Tina linux4.9目的是为了分析问题,抓取kerne里面/net/bluetooth/、driver/bluetooth/目录下的BT_DBG打印。
3.解决办法
- 环境配置
menuconfig选上CONFIG_DEBUG_FS、CONFIG_DYNAMIC_DEBUG
- 小机端
1. echo 8 > /proc/sys/kernel/printk 调整printk打印等级为7以上 2. cat /sys/kernel/debug/dynamic_debug/control | grep bluetooth 查看目前能控制的打印 3. echo 'file hci_core.c +p' > /sys/kernel/debug/dynamic_debug/control 指将hci_core.c文件的打印打开 4. echo 'file hci_core.c -p' > /sys/kernel/debug/dynamic_debug/control 指将hci_core.c文件的打印关闭 5. echo "file net/bluetooth/rfcomm/core.c line 1603 +p" > /sys/kernel/debug/dynamic_debug/control 指将文件net/bluetooth/rfcomm/core.c的第1603行的打印打开 6. echo 'module $mod_name +p' > /sys/kernel/debug/dynaminc_debug/control 指将某个模块的打印打开。
按照上面的方法配置好后,打开蓝牙调试就可以了,默认会输出到终端上或dmesg方式查看。
-
回复: 第二届RISC-V中国峰会议程公布
下午两点全志科技线上分享地址:
B站:https://live.bilibili.com/10339607
电子发烧友:https://t.elecfans.com/live/2096.html -
【FAQ】全志R329如何解决在Audiocodec使用S24_LE格式进行录音时产生的软件分析波形异常问题?
问题背景
硬件:R329
软件:Tina
内核:Linux-4.9问题描述
使用Audiocodec进行录音,格式S24_LE,录制的.wav波形在某些软件中异常
arecord -D hw:audiocodec -f S24_LE -r 16000 -c 2 -d10 /tmp/test3_S24_LE.wav
需要放大很多倍才能看到声音波形问题分析
1.R329的Audiocodec用于录音的ADC只支持16bit和20bit的采样精度。采样后的数字信号会存放到RX_FIFO中,RX_FIFO的大小为256*20-bit,其他平台可以在User Manual确认支持的采样精度,从而判断是否会有这个问题产生
2.RX_DATA是一个32位的寄存器,保存的是从RX_FIFO获取的一个channel的样本数据,当使用arecord进行录音时,RX_DATA中的值会经DMA搬至内存,最后保存到.wav中
其中RX_DATA有四种模式去获取RX_FIFO的数据,S24_LE和S32_LE均采用20-bit mode0
当设置了20bit采样精度时,对应的两种模式如下图所示:
3.先说明一下S24_LE和S32_LE这两种格式的区别
S24_LE指有符号整型,范围是-2^23 ~ ((2^23) - 1),有效数据在低24位
S32_LE指有符号整型,范围是-2^31 ~ ((2^31) - 1),有效数据在高24位LSB MSB 1st byte 2nd byte 3rd byte 4th byte alignment S32_LE: 00000000 xxxxxxxx xxxxxxxx xxxxxxxx 32 bits S24_LE: xxxxxxxx xxxxxxxx xxxxxxxx 00000000 32 bits S24_3LE: xxxxxxxx xxxxxxxx xxxxxxxx 24 bits
4.在驱动程序中,S24_LE和S32_LE虽然都支持,但他们两者都是使用20-bit的mode0,这导致这两种格式保存到文件中的数据排布是一致的,但生成的wav头信息中的采样位数则不一样,从下图可以看出两者的差异
S32_LE的wav文件信息:
若软件以S32_LE进行解析,以上红框的数据变为0x0f80f0,依然可以保留全部有效数据
S24_LE的wav文件信息:
若软件以S24_LE进行解析,以上红框的数据变为0x55f000,便会丢失一部分数据
解决方案
总结原因就是audiocodec的采样精度只支持16和20bit,因此PCM格式中S24_LE虽然也支持,但硬件的特性使驱动并不能做到很好的适配,若软件以标准S24_LE格式进行分析,则会丢失高位的有效数据,这取决于软件如何对数据进行分析,解决方法有以下三种
- 使用audiocodec时,使用-f S32_LE,修改wav头信息中的采样位数位32,这对大部分软件都有效
arecord -D hw:-f S32_LE -r 16000 -c 2 -d10 /tmp/test32.wav
- 如果必须使用S24_LE格式进行录音,可以选择其他支持24bit采样的音频接口,如I2S等
- 假如必须使用audiocodec声卡,S24_LE格式进行录音,可以自行调整RX_DATA寄存器的模式,结合RX_DATA寄存器中实际的有效数据分布,自己开发软件进行数据分析
如果有分析和处理音频数据的需求,可以参考以上思路,结合RX_DATA寄存器去调整
-
【FAQ】全志R329如何在Linux Device Tree中配置预留内存?
前言
有时我们需要在 Linux 内核中预留一部分内存空间用作特殊用途(给安全模块使用,给其它处理器使用,或是给特定的驱动程序使用等),在 Device Tree 中有提供两种方法对预留内存进行配置:memreserve 和 reserved-memory。
memreserve
memreserve 的使用方法比较简单,如下所示,会将从地址 0x40000000 开始共 1MB 的内存空间预留出来:
/memreserve/ 0x40000000 0x00100000;
使用 memreserve 预留出来的内存一般无法再被 Linux 系统使用(当然,也可以通过特殊方法让代码固定访问该地址,但这种并非标准用法,在此不展开描述)。
reserved-memory
reserved-memory 框架提供了更多样的使用方法,并且与内核的 DMA API 和 CMA 框架紧密联系。
推荐先阅读一下内核自带的文档 Documentation/devicetree/bindings/reserved-memory/reserved-memory.txt,里面有其详细的语法说明和注意事项(例如 reserved-memory 节点中的 #address-cells 和 #size-cells 的值需要与根节点的保持一致)。
下面对几种常见的使用方法进行举例说明:
通过 memremap/ioremap 来使用
在 Device Tree 配置如下,然后通过“memory-region”参数可将该预留内存分配给特定的设备驱动使用:reserved-memory { #address-cells = <2>; #size-cells = <2>; ranges; foobar_reserved: foobar@70000000 { no-map; reg = <0x0 0x70000000 0x0 0x10000000>; }; }; foobar_driver: foobar_driver@0 { memory-region = <&foobar_reserved>; };
在设备驱动程序中,可解析 Device Tree 节点获得预留内存的物理地址和大小,然后通过 memremap/ioremap 映射这片内存空间来使用:
/* Get reserved memory region from Device-tree */ np = of_parse_phandle(dev->of_node, "memory-region", 0); if (!np) { dev_err(dev, "No %s specified\n", "memory-region"); goto error1; } rc = of_address_to_resource(np, 0, &r); if (rc) { dev_err(dev, "No memory address assigned to the region\n"); goto error1; } lp->paddr = r.start; lp->vaddr = memremap(r.start, resource_size(&r), MEMREMAP_WB); dev_info(dev, "Allocated reserved memory, vaddr: 0x%0llX, paddr: 0x%0llX\n", (u64)lp->vaddr, lp->paddr);
通过 DMA API 来使用
设置“shared-dma-pool”属性后,可让设备驱动通过 DMA API 来使用预留内存:
reserved-memory { #address-cells = <2>; #size-cells = <2>; ranges; foobar_reserved: foobar@70000000 { compatible = "shared-dma-pool"; no-map; reg = <0x0 0x70000000 0x0 0x10000000>; }; }; foobar_driver: foobar_driver@0 { memory-region = <&foobar_reserved>; };
设备驱动程序中可类似常规地使用 DMA API,它申请的内存不是来源于默认的 CMA 内存池,而是来源于该预留内存:
/* Initialize reserved memory resources */ rc = of_reserved_mem_device_init(dev); if(rc) { dev_err(dev, "Could not get reserved memory\n"); goto error1; } /* Allocate memory */ dma_set_coherent_mask(dev, 0xFFFFFFFF); lp->vaddr = dma_alloc_coherent(dev, ALLOC_SIZE, &lp->paddr, GFP_KERNEL); dev_info(dev, "Allocated coherent memory, vaddr: 0x%0llX, paddr: 0x%0llX\n", (u64)lp->vaddr, lp->paddr);
给 CMA 预留内存
有时我们不需要将预留内存分配给特定的设备驱动,而只是想给默认 CMA 内存池分配一片固定的内存区域,这时我们可配置上“reusable”和“linux,cma-default”:
reserved-memory { #address-cells = <2>; #size-cells = <2>; ranges; linux,cma { compatible = "shared-dma-pool"; reusable; reg = <0x0 0x70000000 0x0 0x10000000>; linux,cma-default; }; };
由此可见,不同于 memreserve,通过 reserved-memory 预留的内存有可能进入系统 CMA,这需要满足以下几个条件:
- compatible 需要为“shared-dma-pool”
- 没有定义“no-map”属性
- 定义了“reusable”属性
-
到立创开源平台DIY 赢取万元奖金
- 星火计划报名页面:
https://oshwhub.com/activities/spark2023/fp#P1
- 全志H616电脑DIY报名页面:
https://oshwhub.com/activities/spark2023/fp/detail?demand_uuid=6bdf5f66bf064607b3fb371299c9bd22
什么是「星火计划」?
嘉立创旗下的开源硬件平台,特推【星火计划】活动,给想干一个大项目的电子人提供弹药,也提供展示的平台。
星火计划,是立创开源硬件平台面向全球电子爱好者发出的硬件开源助力活动。专门陪跑那种比较费钱的开源设计!
星火计划项目在2022年正式开启,每年举办一次,每次举办一年。
目前,星火计划分为两个赛道,分别是自由赛道和外包赛道。
自由赛道项目不限主题,不限参与人群,只要你有想法都可以来报名,该赛道下单个项目最高可提供一万元的耗材经费支持!
外包赛道为星火计划二期的全新赛道,有不同类型的外包项目需求,每个外包项目均提供定额项目奖金,外包项目仅对接一人,成功结项百分百获奖!
外包计划
纠结症患者在参赛时一般会想:我要做什么项目?我能做什么项目?我的项目要实现什么功能才能脱颖而出?做好了能不能评上奖?.......
这也是嘉立创通过对2022期参赛者的调研发现的普遍问题,大家把前因后果全都考虑了一遍才发现自己还是连一点项目头绪都没有,但又不想错过这个千载难逢的好机会!毕竟,这种史诗级羊毛不薅?这说不过去!
基于此类“通病”,星火计划外包赛道就为专门治愈这类“纠结症患者”而生!不同应用领域的需求让你应接不暇,总有一个适合你!
一套流程行云流水,每个外包项目均提供定额的项目奖金,且只对接一位参赛者,成功结项将百分百获奖!
贡献创意
如果 这里面没有你想要参加的项目,你也可以“贡献创意”,把你觉得还不错的项目创意提给我们,为星火计划推波助澜,成就更多开源好项目。
【贡献创意】的需求一经采纳,贡献者奖100元无门槛元器件券,无上限!
活动奖励
活动流程
Vlog记录奖励
全志方案赛道
在外包赛道中有全志H616电脑的悬赏项目,当然,有更好想法的开发者也可以选择自由赛道,无限发挥自己的脑洞,你的每一个创意都可以在星火计划中获得全力的支持。
H616电脑设计需求
外设接口
1、HDMI接口1(4k显示);
2、USB2.03
3、USB2.0_OTG1;
4、3.5mm音频接口1;
5、USB-Type-C供电*1;
6、TF卡槽;内置:
1、板载WiFi、蓝牙5.0;
2、运行存储:2GB;
3、内存:32GB;
4、电池充放电电路;
5、10.1寸触摸屏;设计说明
1、使用嘉立创EDA设计;
2、整体项目需设计合适的3D外壳,材料不限(公版模型也可以);
3、外壳模型必须有着对应的接口说明;
4、支持加载Android镜像载入;验收说明
1、电路部分需完全使用嘉立创EDA专业版进行设计,设计前需与工作人员确认方案的可行性后再进行;
2、原理图电路正确,PCB布局走线要求整理美观,无明显缺陷,设计合理,整体外形协调美观;
3、要求录制完整的演示视频,提供项目硬件、软件源文件、器件清单,填写完善开源项目描述。
4、中标后即可进行设计,设计过程中所需耗材与器件需自行准备,项目完成后发放奖金,规定时间内未完成将重新启动项目招标,原项目作废,且不报销已购买物料。
5、嘉立创EDA拥有完整的项目解释权,但会保留作者的著作权。 -
【FAQ】全志R系列如何在Tina下使用bootchartd来分析rootfs启动时间?
问题背景
硬件: R818
软件: Tina2.5及以上
操作: bootchart工具打开后无法开机。
说明: 客户程序较复杂,系统应用起来时间有25秒,需要优化。bootchart无使用说明。问题简述
Tina整体启动时间中rootfs占用的比重很大,但是rootfs启动过程中log很多,在自启动脚本中也添加不了打印,造成启动时间统计非常不便。
Tina SDK有集成busybox bootchart工具,可使用该工具分析rootfs启动过程各个进程的启动时刻以及耗费时间等信息,可以让用户分析启动过程并进行针对性优化。
解决办法
该方法支持Tina所有方案。
Tina上开启bootchartd方法:
① make menuconfig,打开CONFIG_BUSYBOX_CONFIG_BOOTCHARTD
② 修改文件env-x.x.cfg,将“init=/sbin/init”修改为“init=/sbin/bootchartd”
③ 编译,烧写固件,设备启动后,等待一段时间(1min左右),直到出现/var/log/bootlog.tgz,使用adb pull将该文件拉到PC端。
④ 在PC端解压附件工具bootchart.tar.xz,运行命令“./bootchart/pybootchartgui.py bootlog.tgz”,生成bootchart.png图片,打开可得系统各进程的启动时间。bootchart.png图片分析
bootchart.png效果如下图所示,图中横坐标是时间,纵坐标是各进程信息。图上方两条是CPU和I/O的使用情况;下方是各个进程的运行状态,包含各个进程开始执行时间与结束时间,进程条上有颜色信息,表示对CPU、I/O的占用情况。
优化思路:
- 将主应用程序一起主应用依赖的程序提前执行,其他程序延后执行。
- 调整进程启动顺序,使CPU、I/O不要太高,避免竞争产生等待。
-
(送开发板~)看!是芒果派,他好像在玩一种很新的开发板
小巧的板型,精致的设计,芒果派 - MangoPi,坚持“艺术品”PCB设计,目前全系开发板皆选用全志方案
(文末有芒果派准备的福利哦)
MangoPi - Nezha MQ
芒果派-哪吒MQ(MangoPi-Nezha MQ)是芒果派(MangoPi)针对全志D1s设计的小型RISCV-Linux原型板,一体化极简设计,可以应用于屏显类AIoT产品。D1s芯片DSI接口的强大功能,赋予了哪吒MQ点屏神器的头衔,板载WiFi以及双Type-C的接口也显示出哪吒MQ紧跟潮流的设计理念,独立BOOT按键、超高集成度......都是哪吒MQ虽小,五脏俱全的最佳佐证。
MangoPi - MQ R
MQ-R是将MQ/MQ-Dual与较早时期的Mango Pi R3混合后的产物,在保证极简设计的同时,让开发板更适合量产开发。这款开发板提供了Arm核的T113以及RISC-V核的D1s两个版本,T113版本内置128MB DDR,D1s版本则内置64MB DDR,开发者可根据实际开发需求选择不同版本的开发板使用。
MangoPi - MQ Pro
芒果派MQ Pro延续了芒果派开发板一贯小而美的作风,板子虽小,但却具备了所有重要的功能,MQ Pro以全志D1-H为主控,内置最高1G DDR,板载WiFi/BT/,并提提供了多种常用的外设接口,完整的功能也使得开发板可以很好地运行Tina/Debian之类的嵌入式软件系统。
MangoPi - MQ Quad
MQ-Quad与MQ-Pro具有极其相似的外形设计,他们都有着与RaspberrPi Zero W拥有一样的外形尺寸,两者之间不同的是,MQ-Pro的主控是全志D1-H,而MQ-Quad则是选用全志H616作为主控。芒果派 MQ-Quad 配备 1GB RAM、一个 mini HDMI 输出、两个 USB Type-C 端口、WiFI和蓝牙连接、TF卡槽,以及常用的外设接口, 开发板同时适配了Tina Linux(OpenWrt)、Ubuntu 和 Android 等系统。
MangoPi - MCore
MCore H616是基于全志H616设计的超迷你模组,大小与普通的SD卡不相上下,板子虽然设计得小,但也板载了1GB内存和AXP313电源管理芯片。MCore四周设计了邮票孔的连接方式,方便开发者直接进行手焊,以满足开发者DIY各种小电视/Linux/Android盒子的需求。
MangoPi - Coming soon
继MCore-H616核心板之后,芒果派即将推出新的R818核心板。R818更侧重于本地显示和CSI,可直接驱动 DSI/LVDS/RGB 这种接口的屏幕,其他资源和H616相当,但R818是达到工规级的芯片。另外芯片本体更小,所以这次将R818+EMMC+LPDDR4+PMU(带锂电池管理)整体做到了3x3cm的大小。并且预留屏蔽罩安装接口。系统方面除了本身提供的Android10以外,还有Tina-Linux,芒果派会在开发板发布时搭配上Tina,ArmBian,Android三套系统。
为回馈开发者对芒果派长期的喜爱与支持,芒果派准备了全系列开发板作为礼物送给大家。
- 一等奖:芒果派MQ-Pro * 2
- 二等奖:芒果派MQ-Quad * 2
- 三等奖:芒果派MQ-R * 1
- 四等奖:芒果派MQ系列开发板全家桶 * 1
开奖时间 2022/11/24 10:00
参与方式:点击下方文章公众号文章链接,关注全志在线微信公众号,发送消息“真的好想要芒果派呀”,参与抽奖
-
回复: 【素材汇总】V853素材汇总
产品包装清单
包括:
V853主板 *1
7寸屏幕及转接板 *1
双摄像头模组 *1
亚克力支架 *1
Type-C USB数据线 *1
串口线 *1
电源适配器 *1
小喇叭 *1
包装盒 *1
-
回复: 【素材汇总】V853素材汇总
- Arm Cortex-A7 + RISC-V E907 + 1T NPU 高性能算力组合
- 512MB DDR3 + 8G eMMC
- 高清双目摄像头 + 高清屏幕
- WiFi + 蓝牙 + 以太网
- USB/UART/SD CARD/MIC/Line-in/SPEAKER/ISP/MIPI/TP/BAT等丰富接口