Remote Wake Up from Deep Sleep with USB

|

PM Code have support keeping power for USB.

You just need to apply below pacthes to avoid usb phy being disabled.

    From ba76095e25daa35220f681aaccbcd54f2940b222 Mon Sep 17 00:00:00 2001
    From: Jacob Chen <jacob-chen@iotwrt.com>
    Date: Thu, 7 Sep 2017 15:06:13 +0800
    Subject: [PATCH] USB: dwc2: Don't turn off the usbphy in suspend

    Change-Id: I0dc42678f44664dfc2bbbc67bbfdf851bb87369a
    Signed-off-by: Jacob Chen <jacob-chen@iotwrt.com>
    ---
    drivers/usb/dwc2/platform.c | 4 ++++
    1 file changed, 4 insertions(+)

    diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c
    index 60ffcb6..113bea0 100644
    --- a/drivers/usb/dwc2/platform.c
    +++ b/drivers/usb/dwc2/platform.c
    @@ -641,6 +641,8 @@ static int __maybe_unused dwc2_suspend(struct device *dev)
            if (dwc2_is_device_mode(dwc2))
                    dwc2_hsotg_suspend(dwc2);
    
    +	return 0;
    +
            if (dwc2->ll_hw_enabled)
                    ret = __dwc2_lowlevel_hw_disable(dwc2);
    
    @@ -652,6 +654,8 @@ static int __maybe_unused dwc2_resume(struct device *dev)
            struct dwc2_hsotg *dwc2 = dev_get_drvdata(dev);
            int ret = 0;
    
    +	return 0;
    +
            if (dwc2->ll_hw_enabled) {
                    ret = __dwc2_lowlevel_hw_enable(dwc2);
                    if (ret)
    -- 
    2.7.4

Use OpenCV with Gstreamer

|

最近在Rockchip Linux的平台尝试了一下OpenCV + Gstreamer的组合, 发现效果还蛮不错的. :)
过程中有些心得, 在这里记录一下…. 我想这些也不只适用RockChip平台,因为涉及的都是标准的概念, 比如DMABUF, DRM, OpenCL,G2D…放到像Intel, Nvdia这些平台也是成立的.

下面的内容会涉及一些Linux概念, 如果你不懂的话建议先查阅下相关文章, 当然最好是接触下对应的开发:

Code

一个简单的人脸识别应用:
使用了2D加速, 视频硬解加速
gstreamer-opencv

Changes

这几天尝试添加了一下异步处理, 这样来看拷贝的方式反而不重要了, 因为一秒里可能就处理了2,3张图片而已, 拷贝耗时不大, 而且拷贝后的buffer是cached的normal内存, 处理起来速度会更快. 所以拷贝是不是个问题, 得看相应的应用场景和算法需求.

Background

Gstreamer

首先,要先讨论下为什么需要在OpenCV上用上Gstreamer. 比如我直接一个摄像头 v4l2 图像传给 OpenCV 不行吗?

Gstreamer是嵌入式平台处理Media的首选组件, 像Nvdia/TI/NXP/Rockchip平台, 都是使用Gstreamer来整合Media应用. 在Rockchip平台上, 我们已经有为Gstreamer开发了像Decode/Encode/ISP-Camera/2D加速器/DRM-Display-sink这些的Plugin.

所以OpenCV如果链接上Gstreamer, 输入源就不仅仅是摄像头, 还可以是RTSP/本地视频;输出显示的代码可以不用写, 让Gstreamer来显示; 转换格式让Gstreamer来转, 利用硬件加速; 处理的图像送回Gstreamer编码.

ARM

在ARM系统上做Media的开发, 有一个原则要很重要, 就是 : 避免拷贝.
如果你手边正好有一块ARM板子和Linux PC, 可以尝试在上面跑一些memcpy的Test. 一般来说, 测试的性能会相差5,6倍. 即时是DDR同频的两个系统, 性能也会差到3-4倍(不过也可能是DDR其他参数有影响?). 内存操作速度的劣势是RISC天生的, ARM也不列外. (虽然也没有研究过对应微处理器结构,道听途说 :-P)

还有一个更影响速度的就是, 这些Buffer一般都是uncached的DMA Buffer, 为了保证cpu和其他ip的内存一致性, 所以CPU读写速度就更慢了..

在开发OpenCV + Gstreamer的过程中, 一定要尽量避免拷贝的发生, 如果一定要有, 也不能是由CPU来做. (替代可以是2D加速器, GPU)

OpenCV

我之前只在X86上使用过OpenCV, 其实不太了解OpenCV在ARM Device需要怎么开发. (怀疑其他ARM平台上到底能不能用OpenCV, 因为像TI/NXP这种, CPU/GPU太弱, 估计只能内部的DSP跑算法; 像全志, 基本没有Linux平台的组件支持; 唯一能搞的估计也就是Nvdia的terga了, cuda还是厉害. ;) )

根据上面ARM的原则, 开发的时候要避免调用到OpenCv的cvtcolor和clone这些函数, 因为每次拷贝都会消耗大量的CPU资源.

OpenCV也支持OpenCL加速, 当然..其实没什么卵用, 尤其你是在处理实时的图像的时候, 因为GPU处理数据的时候, 需要加载Texture到GPU内存上, 放OpenCL上, 就是你要处理的帧, 全部要拷一份到新的内存地址上….虽然在嵌入式设备上, GPU并没有和CPU使用分离的内存, 完全没必要这么做; 在图形应用的框架上, GPU处理dmabuf都是zero-copy的, 也就是要处理的帧, 只要让GPU MMAP一下就可以了, 而OpenCV, OpenCL, 我是没找到方法…(所以GPU通用计算还是要靠Vulkan了..)
当然在算法的处理耗时有好几秒的时候, 加载纹理消耗10毫秒也是可以忽视的 : 这种场合才建议使用OpenCL.

才发现这个好像是ARM上特有的问题, opencv已经是用了CL_MEM_USE_HOST_PTR, 理论上不应该有拷贝. 但是ARM上这个flag却会导致拷贝, ARM上需要使用特殊的api来做zero-copy.
嗯…这样你得去修改OpenCV才能用起来…

Desgin

Pipeline

Pipeline Prototype 1:

    video/rtsp/camera -> decoder -> opencv

这是我最先想到的, 通过gstreamer拿到decoder的buffer, 然后全部由opencv来处理. 但是前面说过, 要避免拷贝, 而opencv的显示 imshow , 是存在大量拷贝的, 所以不能这么做.

Pipeline Prototype 2:

    video/rtsp/camera -> decoder -> opencv -> display sink

为了优化显示, 需要把buffer送回给gstreamer, 这样就得到了Prototype 2. 但是是要注意, OpenCV的默认格式是bgr的, 所有的画图函数都是基于bgr; CV的大部分算法都是都需要预处理成灰度图, 而某些图像格式排列不适合转换灰度图.
在Rockchip平台上Decoder出来的颜色格式是NV12的, 必须要想办法转换成BGR格式.
所以decoder到opencv之间还需要有处理颜色格式的单元, 这个工作不可能由CPU来做, 一般可以使用专有硬件, 如果相应的平台没有这样的硬件, 也可以使用GPU用特定的Shader来转(OpenGL的设计目的里, 加速2D就是很重要的一块, 我们有时候看到QT/Wayland这些地方说使用到GPU加速, 就是用GPU做这样的事).

Pipeline Prototype 3:

    video/rtsp/camera -> decoder -> 2d convert -> opencv -> display sink

Implement

首先opencv在gstreamer是有plugin的, 但是从应用开发的角度, 这样不够flexible : plugin里的东西和外界是封闭的. 在实现上, 更建议使用Appsink和AppSrc, 这些模块, 在你的应用里, 是以Thread的形式存在的, 开发起来要更方便.
另外还有一点很重要, 就是什么gstreamer, gobject, 真的很恶心…还是C++舒服…

更多懒得解释了, 看代码吧.. :-P
涉及到的平台坑我都在代码里踩了给你了….
结构上大致如下: Gstreamer AppSink不停的送Buffer, 应用MMap出来给OpenCV处理, 完后AppSrc送会Gstreamer显示.

Gstreamer Pipeline:

    video/rtsp/camera ! decoder ! v4l2videoconvert ! appsink
    appsrc ! display

Rockchip Gstreamer Pipeline:

    "filesrc location=/usr/local/test.mp4 ! qtdemux ! h264parse ! mppvideodec \
    ! v4l2video0convert output-io-mode=dmabuf capture-io-mode=dmabuf ! \
    video/x-raw,format=BGR,width=(int)1920,height=(int)1080 ! \
    appsink caps=video/x-raw,format=BGR name=sink"

    "appsrc caps=video/x-raw,format=(string)BGR,width=(int)1920,height=(int)1080,framerate=(fraction)30/1 \
    block=true name=src ! rkximagesink sync=false";

MiPi CSI(Rockchip Linux)

|

RK平台上android使用的MIPI CSI驱动是userspace based的驱动, 需要基于android的hal层使用,因此并不适合linux平台.

按照linux standard, 需要是写成v4l2形式的驱动, 类似uvc, 从而可以兼容常见的应用, 比如opencv, gstreamer……

RK的v4l2驱动也分两套.

一套叫cif_isp10, 用于rv系列和sofia系列的linux系统. 我个人来说, 并不是很喜欢这套驱动, 因为他只是output的接口用了v4l2而已, 但内部的实现比较蛋疼. 一是sensor驱动的框架是自己实现了一套,并没有基于标准的subdev接口, 调试sensor的时候不能使用已有的在driver/media/i2c下的驱动. 二是模块分层并不清晰, 理解代码和定位流程都很麻烦.

另一套叫rockchip-isp1, 是后来在chromeos项目上基于cif_isp10改出来的, 符合linux standard的驱动, 也是我们现在给3288使用的驱动.
这个驱动有了比较多的review, 结构比较清晰.

拓扑接口:
sensor->mipiphy->isp subdev->sp/mp vdev

如下的硬件框图:
3的输出对应mp vdev(/dev/videox+2), 可以输出raw格式和yuv格式的数据.
4的输出对应sp vdev(/dev/videox), 可以输出yuv格式和rgb格式的数据.
1-crop, 2-resize, 3和4全部都在capture.c里, 对外stream vdev的形式, 就是你看到的/dev/videox, 对这个节点s_fmt调用resize, s_selesction调用crop.
isp, ie, si是用于3a, 图像处理的部分, 被隐藏在isp subdev里, 默认下输出的是未处理的图像, 只有使用isp gstreamer plugin或者我们提供的linux hal时, 会操作这个subdev, 传入tuning的数据.

Tips

sensor

调试sensor的技巧:

第一步是在rkisp1_mipi_isr里加中断, 确认mipi phy的信号有出来. mipi phy有信号, 可以验证以下事情: mipi phy/controler可以接收输入, sensor信号有了输出. 反之如果没有, 原因也就是这个两个, 可以用下面的命令来验证.

io -4 -l 0x100 0xff911c00(rk3288)

出来的数据, 第2个部分代表mipi status, 多输入几次, 看看有没有变化, bit 8:11代表data lane0-3的stop state, bit12代表clock lane stop state. 如果有所的stop bit没变, 需要检查sensor是不是正确输出了, 如果只是clock lane, 需要看下sensor的clock lane是不是在s_stream前没在lp11模式.

第二步, 如果mipi_isr有中断了, 但是有sync_error的错误, 表示mipi接收的图像和isp配置的信息不一致, 可以有以下原因: mipi接收的图形大小和isp配置的不一致, mipi接收的信号有问题.
第一个原因,检查下是不是sensor配置了1080p输出, 但是设置的软件size确是720p.
第二个原因,检查下是不是bitrate设置的有问题, lane num设置的有问题, 硬件信号有问题.

Burn Mac Address(Rockchip Linux)

|

Unlike rockchip android, we don’t limit you how to get mac address. You can write/read it in any places.

Usually, it could be stored in reserved1.
http://opensource.rock-chips.com/wiki_Partitions

Bellow is how to burn mac address to reserved1 and read it.

First, enter maskrom and issue fllowing command to burn mac adress.

printf '\xde\xad\xbe\xef\xef\xee' > mac.bin
build/flash_tool.sh -p reserved1 -c rk3288 -i mac.bin

Then, add ethadder-set fucntion to u-boot board file, it will read mac address from reserved1.

#include <mmc.h>

int rk_board_late_init(void)
{
  u8 ethaddr[1024];

  // 1 for sd-card
  struct mmc *mmc = find_mmc_device(0);
  struct blk_desc *desc = mmc_get_blk_desc(mmc);
  unsigned long blk_start = 8064;
  unsigned long blk_cnt = 1;

  int d = blk_dread(desc, blk_start, blk_cnt, ethaddr);

  eth_setenv_enetaddr("ethaddr", ethaddr);

  return 0;
}

Show Boot Logo(Rockchip Linux)

|

Unlik rockchip android, we don’t have a complete method for boot logo on linux.

It means you can only show logo by generic way, and there are three parts.

U-boot

First, you need enable video driver in u-boot and make it show console in screen. and then, apply below patches.(Don’t forget to remove console in screen)

https://github.com/wzyy2/Scripts/blob/master/tmp/U-Boot-v1-1-2-board-rockchip-common-Add-bmp-logo-support.patch
https://github.com/wzyy2/Scripts/blob/master/tmp/U-Boot-v1-2-2-rockchip-include-Enable-logo-display-for-evb-rk3399.patch

Since rockchip rom code have litmit the uboot size to 1Mb, so you can’t display with big size bmp. If you want to display big size bmp, you might need use gzipped bmp.

https://github.com/rockchip-linux/u-boot/blob/release/cmd/bmp.c#L40

Kernel

http://blog.csdn.net/wang_zheng_kai/article/details/41847687

set logos_freed to false
http://elixir.free-electrons.com/linux/latest/source/drivers/video/logo/logo.c#L32

System

You can use ‘plymouth’ to show logo before desktop launched.

If you are using debian, there are some bug need fix.

  1. Change ExecStartPost in /lib/systemd/system/plymouth-start.service to ExecStartPost=-/usr/bin/udevadm settle –timeout=30 –exit-if-exists=/sys/class/drm/card0/dev ; /usr/bin/udevadm settle –timeout=30 –exit-if-exists=/sys/class/graphics/fb0/dev ;

  2. Add plymouth-quit.service to After in /lib/systemd/system/lightdm.service

Comments