最近因工作忙起来了较少去整F1C100s了,趁今天较空闲,就跟大家分享一下我前段时间把玩的成果吧。可能有点啰嗦,各位看官将就着看吧
前段时间玩的“硬光标”+LVGL演示
因为我也是刚接触到F1C100s不久,之前玩的都是M3,M4,M7内核的单片机,也是靠在挖坑网上参考各位大神的经验才逐渐上手,目前也仅仅会在RTThread这种小实时系统内把玩一下,对RTThread了解的还不是很深,对于linux什么的更是没入门。。。因此我在玩F1C100s的时候,真的就把它当做一个单片机在玩了,大家看看就好。
我先大概说一下我已经实现的功能:
1.开发环境:Windows,基于RTThread v4.0.1官方源码包,使用RTT ENV工具开发。如果要入门的,可以参考燕大侠的RTT新手上路篇https://whycan.cn/t_943.html
2.通过修改链接文件和启动文件,将BootLoader集成到App中,无需额外烧录boot,启动速度快且可控。
这里参考了香酥肉饼的帖子https://whycan.cn/t_3645.html,谢谢这里的大神们的贡献。关于这个我走的弯路可参考我另一个贴关于无boot启动的求助帖。。。
3.将mksunxi和sunxi-fel工具整合到一个批处理,在ENV工具中,实现编译后,直接执行这个批处理就可完成程序下载(当然SOC还是得进入到FEL模式),无需繁琐的各种打包操作,开发速度更快。
3.支持硬件4图层,硬件游标,剥离了原达克罗德驱动中时序控制和图层结构体。
关于LCD驱动这一块参考了达克罗德的帖子https://whycan.cn/t_1457.html,同样谢谢这些大神的贡献
4.移植了LVGL v6.1.1,(目前准备将其配置写入menuconfig中)
5.使用了UART2接收虚拟鼠标数据
6.开启了SDIO(RTT BSP包自带)
RTThread自带的BSP包中已经包含了Clock、UART、GPIO、SDIO的驱动了,再加上FB的驱动,已经可以用作一般项目开发使用了。下面主要说一下我开发的的程序中一些说明和注意事项。
1.第一个是关于BootLoader部分。这部分主要完成的就是将App加载到DDR中运行。App不需要关心在Flash中的地址(App是紧跟着Bootloader代码的),也不需要关心其大小(当然,由于我对DDR的使用区域重新做了划分,我限定App大小是4MB,详细见第4点)。这个Bootloader含有魔术头(BROM通过识别到特定字符才认为Flash中存在可执行代码),在生成bin文件后,需通过mksunxi工具修改一下bootloader头一些校验信息,然后就可以将这个bin通过sunxi-fel直接烧录到Flash地址0的地方开始运行。为了开发方便,我将这两个工具操作写在了一个批处理中,沿用Keil裸机工程中使用的bat名字flashtospi.bat。在ENV中使用scons编译后,直接输入flashtospi.bat就可进行代码烧录(与CMD命令一样,首次输入后,下次可以用方向键调取之前的指令,更快开发)。这里有一个要注意的操作,就是如果flashtospi.bat烧录执行失败(比如忘了使Soc进入FEL模式),那么就不要再直接执行这个批处理了,因为这个批处理会先在此对bin再次进行校验修改,这样bin的校验就不对了。解决办法就是要么修改下代码重新编译(不能直接再次scons,因为代码未变化的话不会重新生成bin),要么就手动执行sunxi-fel,或者就把flashtospi.bat中魔术头修改和下载的两个操作分到两个bat文件,这样每次编译后,先执行魔术头修改,再执行烧录。我是贪方便就放一起了。
2.我重新修改和整理了原达克罗德大神的FB驱动,参考手册,剥离了TCON时序控制部分,和FB的图层管理部分。支持硬件4图层。关于硬件4图层,我想简单说一下我的理解。F1C100s的显示引擎FB支持4个图层的显示与混叠,同时,还可以指定4个图层之下的背景颜色。也就是说,就算这4个图层你一个都不用,还是可以显示纯色背景,而这背景是没有所谓的显存的,通过一个寄存器指定。所有的图层都显示在这个背景色之上。这个背景填充永远是填满整个屏幕的,但是图层不同。这些图层更像是“窗体”,是可以显示在屏幕的任意位置的,大小也任意,这就很灵活了。我剥离出的图层参数结构体如下:
typedef struct
{
uint32_t width;//图层宽度(像素)
uint32_t height;//图层高度(像素)
uint32_t posx;//图层显示相对屏幕左上角坐标X
uint32_t posy;//图层显示相对屏幕左上角坐标Y
uint32_t priority;//该图层显示优先级
uint32_t pipe;//该图层使用混叠管道
uint32_t alpha_value;//该图层透明度(整个图层)
uint32_t alpha_enable;//是否使用图层透明度
uint32_t vram_format;//图层像素数据格式,支持RGB565,RGB888,ARGB32
void * vram;
}lcd_layer_Struct;
前面的4个参数就不多说了,就是图层大小及图层在哪显示。这里说一下几个重点。
第一个就是图层显示优先级。因为支持4个图层,当显示图层多于2个后,必然涉及图层叠加问题,即谁在谁之上。这就是这个优先级控制的。优先级范围0-3,0为优先级最低,也就是显示在最下面,3为显示在最上面。当然优先级0的图层,也是在背景色之上的。这个优先级是可以随时更改的,就像激活窗体显示在最上面一样。参数修改后重新配置下层即可。根据手册说明,当图层数大于2个后,每个图层必须要用自己的唯一优先级,即不能有2个优先级相同,这点在设计时就要考虑好。
第二个就是pipe的使用。当图层透明度使能后,F1C100s有2个管道用于图层混叠,在多于2个图层时,必然至少有一个图层使用相同的管道。当使用相同管道的图层没有重合部分时,每个图层可以按显示优先级从上到下实现图层混叠。若相同通道的图层存在重合部分时,那么重叠部分只有优先级最高的图层能使用这个管道完成其它图层的颜色混叠。当然,如果图层透明度未开启,则图层显示不受这个通道的限制。
第三个就是前面提到的图层透明度。这里必须提一下这个透明度是全局的,由专门一个参数指定的(alpha_value)。每个图层的像素格式虽然可以是ARGB,但在硬件图层混叠时,并不是使用像素的A值,而是使用这个指定的alpha_value,像素的A值被忽略。因此想指望依靠这个硬件图层混叠功能实现类似PNG图片显示的功能就别想了。但这也并不是一无是处,比如做一些显示的淡入淡出、滑动显示等还是很好用的。
最后说一下图层像素数据格式和数据指针。在图层结构体中,可以直接指定数据使用的格式为RGB565、RGB888或ARGB8888,每个图层可以自由使用不同的像素数据格式,相互之间不影响。指针*vram直接指向图层像素数据区,这个数据区就是这个图层的显存,可直接读写操作。这个显存的格式必须和参数vram_format一一对应。也许看到这你就有想法了,每个图层的数据格式可以不同,那么就可以很方便的将这四个图层各司其职:比如层0用作GUI绘制层用RGB565格式,层1用作图片显示ARGB888,层2用作视频
播放RGB888...这样可以避免做更多的数据转换,实现快速显示的效果。
当然除了直接修改结构体参数重新配置各层参数可以实现参数设置外,我也额外提供了一些API接口,随时可以调用,比如控制层显示或不显示的Layer_SetEnable,设置层透明度的Layer_SetAlpha,设置层显示位置的Layer_SetPos等等,可以参考drv_fb.h文件。我在示例工程中也有层的使用范例。同时我默认把layer0放在LCD初始化过程中,作为默认的显示图层。
这里顺便提一下剥离出来的LCD时序控制结构体,这个是与硬件相关的,也很简单,主要填一下屏幕物理像素宽度和高度以及一些时序参数即可。
typedef struct
{
uint32_t pixel_clock_hz;
uint32_t width;
uint32_t height;
uint32_t h_front_porch;
uint32_t h_back_porch;
uint32_t h_sync_len;
uint32_t v_front_porch;
uint32_t v_back_porch;
uint32_t v_sync_len;
uint32_t h_sync_active;
uint32_t v_sync_active;
uint32_t den_active;
uint32_t clk_active;
uint32_t line_per_pixel;
uint32_t rstdefe;
uint32_t rstdebe;
uint32_t rsttcon;
uint32_t backcolor;
} lcd_cfg_Struct;
这里注意一下line_per_pixel这个参数,是指硬件上与LCD连接的数据线宽度,如果连接的是RGB565接口的屏就是16线,RGB666的接口就是18线,RGB888就是24线,这与上面提到的图层像素数据格式无关。rstdefe、rstdebe、rsttcon参考的就是达克罗德大神的值,也没去深究了。backcolor就是上面提到的,最底层的背景色。
3.关于硬件游标,参考我上一个帖子。硬件游标作为独立的一个部件,位于所有图层之上,具备ARGB像素混叠,不过一般不会有人使用它。我是因为没办法触摸操作,所以使用了这个硬件游标来代替,顺便把串口2给用上了。
4.最后再来谈谈一开始说到的程序4MB问题,这是我自己规划的。因为我把DDR前面4M划分为APP运行区(含Data和bss段),紧接着4MB专门用作所有图层的显存区,剩余的24M用于RTThread的堆用于动态内存分配。实际上这也没多大必要。在RTThread BSP源码包的/drivers/board.h中,原本是自动根据APP加载的大小自动把余下的DDR分配给内核进行内存动态分配的,这样就没有APP大小的限制,这样每个图层的显存也通过动态内存来分配即可。而我是直接在APP之后划分了4M作为显存而不经过动态内存分配,因为我考虑到显存一般是永久性分配且比较大,没必要占用内存分配表。当然这样也有风险了,因为万一APP超过4M,我也没检测,这样运行就会出错了。所以不想麻烦的,还是保持官方做法就好。
5.关于LVGL的移植,就很简单了,网上有很多参考,只需实现flush功能就基本可用了。这里遇到一个奇葩,直接从网上下载6.1.1的源码包,用ENV工具编译时在文件lv_draw_rect.c中报错,经过排查是在其中一个画矩形的函数中,有两个局部变量是在函数代码中间定义后再使用。很奇怪的是其它函数也这样做都没问题,然后我把那两个变量放到函数开始后再编译就没问题了。我在程序中开启了图层0,并在图层0上建立了LVGL,所有的LVGL都是在图层0上操作。
6.最后一个是SD卡的问题。RTT官方BSP包中已经写好SD的驱动了,在menuconfig中开启SD设备就行。使能SD卡后RTT会自动建立一个SD卡检测及初始化线程,由于荔枝派SD卡没做插拔检测,因此只上电执行一次SD卡初始化,或者手动调用mmcsd_change触发再次检测,具体可分析一下源码包。SD卡初始化后需要进行挂载操作,可以使用自动挂载或者手动挂载。这里就要注意同步问题了,必须等初始化结束后再进行挂载。使用时发现一个问题,在频繁读SD文件时,容易出现CMD17错误,但过会再读又正常。暂时不知道是卡的原因还是啥,反正我试过3个不同的卡都会这样,而且出错时间点不定,有时很快出现,有时1小时都不出现一次。另外,BSP中的sd driver中使用了软件延时,这个要注意一下如果提高了CPU运行时钟,可能这部分延时需作相应调整。
好了,啰里啰嗦说了一堆,都是个人在近期把玩的结果,可能还有一些地方是理解有误的,还请大家指正。
代码如下。请先在RTT官网下载源码包,然后将附件解压到BSP文件夹中。RTT源码BSP中有很多其他方案的代码,除allwinner_tina外可全部删除。。
希望有更多的人参与进来玩,分享各自成果。下面想入门Linux,希望还有大神带路啊,不胜感激!
allwinner_tina_prj_v1.rar
最近编辑记录 ntmusic (2020-03-26 15:43:30)
离线
对了,这里再上传一个“虚拟鼠标”的上位机软件,使用很简单,打开通信端口后(波特率115200),把鼠标移入触摸区域就行了。拉伸软件边框可以调整触摸区域大小,这个触摸区域就对应了屏幕的触摸区域。为了提高鼠标灵敏度可以将帧率调整为高。其实下发的数据非常简单,就每一帧就5个字节,因为仅仅做试验也不加什么帧头帧尾了,第一字节标识鼠标按压状态(按压或释放)。第二,第三字节作为当前光标位置X坐标,第四第五字节为Y坐标,就这么简单。。。
我使用荔枝派UART2做虚拟鼠标数据接收,引脚是PE7、PE8。
软件在此,感兴趣的可以试试。
NTVisualTouch.rar
离线
友情顶,希望更多的人一起玩RTT。
压缩包下不下来。。。
奇怪,我上传成功了啊,我试了下确实下不来,不知道咋回事?
离线
我下载了。我想将你的代码与我的
https://whycan.cn/t_3538.html
合并,然后发布到GITEE上。
我这里加了入I2C,GT911,看门狗驱动。将你的启动哪Bootloader合并放进去,是否OK。
没问题,欢迎探讨
离线
这个能提供源码么?
或者加上帧头帧尾吧,否则只要错一个字节,就永远回不来了。
放心不会的,接收数据是以数据帧为单位的,帧与帧有间隔的,即使串口受到扰动,只要串口连接恢复正常,通信就恢复正常。唯一问题可能就是错误数据会导致光标乱跳吧,但事实是只要串口连接稳定,是不会有这个问题的。我上面的F1C100s工程里含了这个串口鼠标的代码的,如果你要这个上位机的代码,如下:
NTVisualTouch源码.rar
离线
TKS,,水一贴。希望更多的人加入RTT+F1C100S。
其实我将声音驱动也搞好了,不过用了别人的代码,他不希望公开。
还是尊重他的要求,哪部份我只能去掉。
理解的,毕竟是他的劳动成果。我本来就是在这个论坛学到的知识,有很多大神在默默奉献自己的代码和踩坑经验,自己虽学艺不精,但能给其他人一些帮助是再好不过了。很多时候提供源码不是重点,重点是希望有人能指引一下方向
离线