【record】

文章目录


前言

本篇博客仅作为本人平时工作中遇到的一些项目或者问题的记录或者笔记。主要用于记录自己的成长历程,不用于商业用途和任何盈利活动。

笔记

【定制安装ubuntu的rootfs】:

链接

【设置虚拟机网络来ping通板子】

链接

【如何进入loader模式】

关于按法:先两个一起按下去,然后再松开reset键
手动进入loader模式的方式很简单,先上电,同时按住板子的reset按键(靠近电源接口)和recovery按键,然后松开reset按键并等待几秒,等到烧录工具显示“发现一个LOADER设备”后松开即可

【建立软链接并更新】

验证完自己的rootfs正确无误之后,需要建立软链接

ln -sf (实体) (快捷方式)

之后还要更新build的【软链接】。

./build.sh -h
./build.sh ubuntu
cd rockdev/
ls -l
ln -sf ../ubuntu_rootfs/rk3399-rootfs-20220630.img rootfs.img
ls -l
cd ..
./build.sh -h

在服务器里面的SDK里面,把rootfs的img打包到整个系统镜像

./build.sh [uboot/kernet/rootfs]  (单独编译)
./build.sh updateimg   (打包成整个系统固件)

【备份rootfs】

板子上挂在自己的rootfs源文件,先查看自己的rootfs处在那个mmc分区
(查看分区)

df -h

(查看每个mmc分区是什么内容)

/sys/block/mmcblk${id}/mmcblk${id}p*/uevent

(板子挂载自己的rootfs)

mount /dev/mmcblk1p4 /mnt

(确保板子自己的ip是192.168.64.20,网关是192.168.64.10)
修改/etc/network/interfaces,添加,然后reboot即可,也可手动配置。

(尝试windows是否可以ping192.168.64.20)
网线连接板子和电脑,断掉网络,修改网络适配器的ipv4参数,ip:192.168.64.10,网关:192.168.64.20,然后去ping192.168.64.20。

(虚拟机设置网络设置成使用桥接模式,并勾选复制物理网络)

(进入虚拟机后,只有一个有线链接,设置linux的网络ipv4设置和windows相通,ping)

(备份rootfs)

mkdir temp
sudo rsync -av root@192.168.64.20:/mnt/ temp

(如果报主机身份被改变,是因为连接过不同的设备,直接复制报错里面的指令修改即可)
(如果需要root的密码,就去板子上用passwd root来设置密码)

​(temp内为rootfs)

mkdir rootfs
dd if=/dev/zero of=linuxroot.img bs=1M count=1200
mkfs.ext4 linuxroot.img
sudo mount linuxroot.img rootfs/
sudo cp -rfp temp/* rootfs/
sudo umount rootfs/
e2fsck -p -f linuxroot.img
resize2fs  -M linuxroot.img

今天只是单纯的把wugt给的rk3399-rootfs-20220630烧录到板子里面,然后测试发现所有的工具都已经安装了

如果想要修改img,直接mount就可以看到了


在dd创建新的img镜像文件是,需要进入temp文件夹下,执行du -sh查看当前目录大小
扩容可以利用/usr/local/bin/firstboot来扩容

【时间同步相关指令】

时间同步相关指令文件

date
dmesg |grep rtc
cd /etc/c
cat /etc/crontab

时间同步的意思是编写脚本把系统时间变成和硬件时间相同,开机自动校准ntp服务器上的网络时间

设置系统和硬件时间为一个过去的时间用来测试是否会自动校准。

hwclock --set --date "20000427 20:23:00"

显示硬件时钟

hwclock --show

以硬件时间为基准,修改系统时间

hwclock --hctosys
hwclock -s

以系统时间为基准,修改硬件时间

hwclock -w

【RK3399时间同步改动操作步骤—2022/9/5更新】

开机自动执行脚本,选择后台服务,脚本自行新建

vim /etc/rc.local

增加一行

/usr/local/bin/time-Synchronization.sh &&表示后台执行)

time-Synchronization.sh脚本内容

#!/bin/bash
#This is a simple script.

ntpdate cn.pool.ntp.org >/dev/null 2>&1 &
ntpdate cn.pool.ntp.org >/dev/null 2>&1 &
ntpdate cn.pool.ntp.org >/dev/null 2>&1 &
hwclock -w

(ntpdate … >/dev/null 2>&1 & (取消输出))



2022/9/5 更新,配合ui板启动,每隔3秒自动访问ntpserver同步时间

修改 time-Synchronization.sh

#!/bin/bash
#This is a simple script.

#ntpdate cn.pool.ntp.org >/dev/null 2>&1 &
#ntpdate cn.pool.ntp.org >/dev/null 2>&1 &
#ntpdate cn.pool.ntp.org >/dev/null 2>&1 &

#echo "testing"
count=0

ntpdate cn.pool.ntp.org >/dev/null 2>&1 

while [ $? -ne 0 ];
do
  sleep 3
  count=$((count+1))
  if [ $count -gt 20 ];
  then
    echo "ntpserver update time is too long!"
    break
  fi


  ntpdate cn.pool.ntp.org >/dev/null 2>&1 
done


hwclock -w

【串口通信】

windows与板子上的ubuntu系统进行串口通信
板子上的ubuntu需要 minicom来充当他的串口调试工具,同时使用网线ssh连接ubuntu终端,串口线连接到板子的串口(非左下角的调试串口)

在ssh终端中
cat /proc/tty/driver/serial (查看每个串口的收发数据的状态,注意到有两个tx,rx都是0)

windows中的串口调试工具选择定时发送,观察到有一个rx在不断增加,他的MMIO 是 oxff1c0000
然后

cd /proc/tty/driver/
dmesg | grep ttyS*

可以查看到同样的MMIO的是ttyS4. (3号和4号串口都是ttyS4)

配置minicom:

sudo minicom -s

选择Serial port setup

指令使用minicom
sudo minicom -D /dev/ttyS4 -b 115200 -w & (之后就可以接收到windows发送过来的数据)

sudo minicom -D /dev/ttyS3 -b 115200 -w
printk(KERN_EMERG   "GetIot: KERN_DEBUG\n");
dmesg

cd ~/../../media/hdd2/liangji/rk3288-linux-v4.4-sdk/kernel/drivers/tty/serial/
~/../../media/hdd1/liangji/
/var/log/serial_kern.log


dmesg |grep in32

dmesg |grep GetIot


dev_err(dev, "DMA mapping error for RX.\n");

https://blog.csdn.net/weixin_40407893/article/details/117956968
https://www.cnblogs.com/liushuhe1990/articles/11287338.html

------------------------------------------------------------------------------------------2022/7/12

grep -rn 'rotate' *

 578	        uart4: serial@ff1c0000 {
 579                 compatible = "rockchip,rk3288-uart", "snps,dw-apb-uart";
 580                 reg = <0x0 0xff1c0000 0x0 0x100>;
 581                 interrupts = <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>;
 582                 reg-shift = <2>;
 583                 reg-io-width = <4>;
 584                 clocks = <&cru SCLK_UART4>, <&cru PCLK_UART4>;
 585                 clock-names = "baudclk", "apb_pclk";
 586                 pinctrl-names = "default";
 587                 pinctrl-0 = <&uart4_xfer>;
 588                 status = "disabled";


printk(KERN_EMERG   "GetIot2: KERN_DEBUG\n");

dev_err(p->dev, "Couldn't set LCR to %d\n", value);

printk(KERN_SOH    "GetIot2: KERN_DEBUG\n");

------------------------------------------------------------------------------------------2022/7/14
修改n_tty.c里面的n_tty_read()里面的copy_from_read_buf()

可以在终端打印出数据。

修改/etc/rsyslog.d/50-default.conf,
将里面的kern输出重定向,kern.emerg /var/log/serial_kern.log

重启rsyslog服务

service rsyslog restart

【RK3288 串口驱动数据导出总结】

修改n_tty.c中,从read_buf中导出数据到自己的缓冲区中,经过字符串转16进制,转换成16进制序列输出

输出使用printk,优先级KERN_EMERG

修改/etc/rsyslog.d/50-default.conf
将printk的内核log输出重定向到自己的serial_kern.log文件

查看log文件

cat /var/log/serial_kern.log

关闭时间戳

echo N > /sys/module/printk/parameters/time

禁止终端打印输出信息

echo 0 >/proc/sys/kernel/printk
sudo minicom -D /dev/ttyS4 -b 115200 -w &
sudo minicom -D /dev/ttyS3 -b 115200 -w -H &

echo " " > /var/log/serial_kern.log
echo " " > /var/log/syslog

/etc/logrotate.d/rsyslog

dmesg |grep GetIot

修改配置文件

vim /etc/logrotate.d/rsyslog

/usr/sbin/logrotate -d -f /etc/logrotate.d/rsyslog
chmod g-w /var/log
/usr/sbin/logrotate -v -f /etc/logrotate.d/rsyslog

显示syslog大小

ls -hl /var/log/syslog*
du -sh /var/log/syslog

清空syslog

echo " " > /var/log/syslog	

logrotate -v -f rsyslog

修改权限

chmod g-w /etc/logrotate.d

强制执行

logrotate -f /etc/logrotate.conf

【限定syslog容量大小的办法】

https://askubuntu.com/questions/184949/how-do-i-limit-the-size-of-my-syslog/1083570#1083570]

https://github.com/rsyslog/rsyslog/issues/4924

修改配置文件

vim /etc/rsyslog.d/50-default.conf

增加一行

$outchannel mysyslog,/var/log/syslog,1048576,/etc/rsyslog.d/my_action.sh

my_action.sh文件内容:

#! /bin/bash

echo " " > /var/log/syslog	

脚本权限

chmod 777 -R /etc/rsyslog.d/my_action.sh

*.*一行注释并添加

*.*;auth,authpriv.none  :omfile:$mysyslog

重启rsyslog服务

sudo service rsyslog restart

轮询脚本:

#! /bin/bash

cp /var/log/syslog /var/log/syslog.1



rm syslog.7.gz
mv syslog.6.gz syslog.7.gz
mv syslog.5.gz syslog.6.gz
mv syslog.4.gz syslog.5.gz
mv syslog.3.gz syslog.4.gz
mv syslog.2.gz syslog.3.gz
mv syslog.1.gz syslog.2.gz

gzip /var/log/syslog.1

echo " " > /var/log/syslog

修改解压后命名一样的问题

#! /bin/bash

NUM=8

#syslog.*.gz is exist or not

for ((i=1; i<=$NUM; i++))
do
  FILE=/var/log/syslog.$i.gz
  if [ -f "$FILE" ]; then
    cp /var/log/syslog /var/log/syslog.exist
  else
    cp /var/log/syslog /var/log/syslog.$i
    echo " " > /var/log/syslog.$i
    gzip /var/log/syslog.$i
  fi
done

for ((j=1; j<=$NUM; j++))
do
  gzip -d /var/log/syslog.$j.gz
done

cp /var/log/syslog /var/log/syslog.1.temp

rm /var/log/syslog.$NUM

for ((k=$NUM; k>=2; k--))
do
  PRO=$(($k-1))
  mv /var/log/syslog.$PRO /var/log/syslog.$k
done

mv /var/log/syslog.1.temp /var/log/syslog.1

for ((m=1; m<=$NUM; m++))
do
  gzip /var/log/syslog.$m
done

echo " " > /var/log/syslog

【git使用】

git status

用git把代码提交到本地

git add n_tty.c
git commit -sv			(sv,使用vim添加标签)

可以使用vim

git config --global core.editor vim

在文件头部添加前缀描述词

feat: support log serial log

查看提交到本地的代码记录

tig

git format-patch -1 HEAD

git commit --amend

查看当前分支

git branch

查看当前状态

git status

建立新的develop分支

git checkout -b develop origin/develop

一个commit中如果amend了一个不想要的改动,可以用git reflog查找commit的版本,然后

git reset ad22jas

【gitlab使用】

整个project(废了重新拉,包含多个仓库的整个项目)

repo init -u ssh://git@172.16.13.15/common/manifest.git -b android6.0 -m android6.0.xml --repo-url=ssh://git@172.16.13.15/common/git-repo.git  --no-repo-verify
repo sync -f -j16

从远程拉下来(单个仓库)(repo 是对git 的封装)

git pull origin develop
或者
repo sync kernel

可以用tig查看是否拉下来

修改代码之后
由于这个版本的代码在远程已经merge了
所以这次的改动要新commit一次

提交到远程

git push origin HEAD:fix-custom     (HEAD表示)

到这里只是提交到gitlab上作为草稿,还无法审核
提交新的merge 请求,这样才能够提交审核

【借用其他文件夹的makefile编译内核文件】

编译多个文件

gcc -o test process_api.c c_vector.c transportcrc.c

把多个文件放在有其他文件的文件夹下,借用他们的配置文件进行编译

修改/arch/arm/configs/rockchip_linux_defconfig

添加+CONFIG_TRANSPORTCRC=y

修改/drivers/tty/Makefile
添加 obj-y += transportcrc.o

【RK3399 通过系统实现USB端口自动检测并建立软链接】

由于usb3.0可能会有gpio口供电问题,所以用2.0的usb口单独测试 lora

查看导出到文件中的log信息

cat /var/log/usb-test.log

查看tty设备的软链接

ls -l /dev/tty*

修改自动执行脚本

vim /etc/rc.local
/usr/local/bin/usb_scan.sh

手动执行
usb_scan/usb_scan

echo “”>/var/log/usb-test.log

ssh://liangji@review.keenonrobot.com:29418/linux/tools/usb-device-detect

上传代码

git push ssh://liangji@review.keenonrobot.com:29418/linux/tools/usb-device-detect HEAD:refs/for/develop

【RK3288 UI板LED灯闪烁控制】

板子上一共3个LED灯,但是红灯不能控制,能够控制的是左边的蓝色和绿色的灯。

修改板子的设备树文件

vim kernel/arch/arm/boot/dts/rk3288-evb-act8846.dts

找到leds的设备树,里面有2个led设备的子节点

修改led默认状态为打开

default-status = "on"

修改trigger的模式为heartbeat (选择heartbeat的触发方式,触发方式的具体定义在kernel/drivers/leds/trigger/ledtrig-heartbeat.c)

linux,default-trigger = "heartbeat"

确保ledtrig-heartbeat.c被编入内核

vim /arch/arm/configs/rockchip_linux_defconfig

CONFIG_LEDS_TRIGGERS=y 
CONFIG_LEDS_TRIGGER_TIMER=y 
CONFIG_LEDS_TRIGGER_ONESHOT=y 
CONFIG_LEDS_TRIGGER_HEARTBEAT=y 
CONFIG_LEDS_TRIGGER_BACKLIGHT=y 

参考文献: https://blog.csdn.net/WANGYONGZIXUE/article/details/116449460
https://blog.csdn.net/u013443294/article/details/115178057

【RK3288串口数据解析transportcrc】

移植好相关代码

transportcrc.c,transportcrc.h,type.h,n_tty.c

修改Makefile文件
增加一行

obj-y    += transportcrc.o

修改/arch/arm/configs/rockchip_linux_defconfig
增加一行

CONFIG_TRANSPORTCRC=y

以上是把自己的文件编入内核,这样就可以使用了

【RK3288安卓系统内置app】

使用现成的apk进行

安卓系统内的软件分为可卸载和不可卸载(内置)两类,

可卸载目录:
/device/rockchip/rk3288/preinstall_del 百度输入法

不可卸载目录:
/packages/apps

操作:
在/packages/apps中新建一个文件夹 My_Calculator

将现成的.apk文件拷贝到该文件夹下

新建Android.mk文件
写入内容如下(修改包名为My_Calculator):

LOCAL_PATH:= $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := My_Calculator
LOCAL_MODULE_TAGS := optional
LOCAL_SRC_FILES := $(LOCAL_MODULE).apk
LOCAL_MODULE_CLASS := APPS
LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX)
LOCAL_CERTIFICATE := PRESIGNED


# priv-app
LOCAL_PRIVILEGED_MODULE := true

include $(BUILD_PREBUILT)

在device/制造商/项目名/项目名.mk文件中增加一行

PRODUCT_PACKAGES += My_Calculator

编译有源码app

mmm packages/apps/My_Calculator/

整体编译

./build_keenon.sh W3


内核中用代码实现软链接
位于文件/kernel/include/linux/syscalls.

https://zhuanlan.zhihu.com/p/43505308#:~:text=1%20%E4%BB%A3%E7%A0%81%E4%B8%AD%E4%BC%9A%E4%B8%BA%E9%93%BE%E6%8E%A5%E6%96%87%E4%BB%B6%E5%88%9B%E5%BB%BA%E4%B8%80%E4%B8%AAinode%E7%BB%93%E6%9E%84%EF%BC%8C%E8%BF%99%E5%9C%A8%E5%87%BD%E6%95%B0%20ext3_new_inode%20%28%29%E4%B8%AD%E5%AE%9E%E7%8E%B0%EF%BC%8C%E8%BF%99%E4%B9%9F%E6%98%AF%E7%A1%AC%E9%93%BE%E6%8E%A5%E5%92%8C%E8%BD%AF%E9%93%BE%E6%8E%A5%E7%9A%84%E6%9C%80%E5%A4%A7%E4%B8%8D%E5%90%8C%EF%BC%9B%202,%E9%93%BE%E6%8E%A5%E6%96%87%E4%BB%B6%E7%9A%84%E6%96%87%E4%BB%B6%E5%86%85%E5%AE%B9%E6%98%AF%E6%BA%90%E6%96%87%E4%BB%B6%E7%9A%84%E6%96%87%E4%BB%B6%E5%90%8D%EF%BC%8C%E8%80%8C%E4%B8%94%EF%BC%8C%E5%A6%82%E6%9E%9C%E6%96%87%E4%BB%B6%E5%90%8D%E4%B8%8D%E6%98%AF%E5%BE%88%E9%95%BF%EF%BC%88%E5%B0%8F%E4%BA%8E60%E5%AD%97%E8%8A%82%EF%BC%89%EF%BC%8C%E4%BC%9A%E5%B0%86%E6%96%87%E4%BB%B6%E5%90%8D%E7%9B%B4%E6%8E%A5%E4%BF%9D%E5%AD%98%E5%9C%A8inode%E4%B8%AD%EF%BC%8C%E6%97%A0%E9%9C%80%E4%B8%BA%E5%85%B6%E5%88%86%E9%85%8D%E6%95%B0%E6%8D%AE%E5%9D%97%EF%BC%9B%203%20%E6%9C%80%E5%90%8E%E4%BC%9A%E5%B0%86%E9%93%BE%E6%8E%A5%E6%96%87%E4%BB%B6%E7%9A%84inode%E4%B8%8Edentry%E5%BB%BA%E7%AB%8B%E5%85%B3%E8%81%94%EF%BC%8C%E5%B9%B6%E5%B0%86%E9%93%BE%E6%8E%A5%E6%96%87%E4%BB%B6%E7%9A%84dentry%E5%86%99%E5%85%A5%E5%88%B0%E7%88%B6%E7%9B%AE%E5%BD%95%E7%9A%84%E6%95%B0%E6%8D%AE%E5%9D%97%E4%B8%AD%EF%BC%8C%E8%B0%83%E7%94%A8%E7%9A%84%E6%98%AF%E5%87%BD%E6%95%B0%20ext3_add_nondir%20%28%29%E3%80%82

SYSCALL_DEFINE2(symlink,…)

https://blog.csdn.net/hxmhyp/article/details/22699669



【ttyACM乱跳问题解决】

检测和注册ttyACM设备文件usb/class/cdc-acm.c 通过grep -rn 'ttyACM' *找到的

解决方案:在kernel/drivers/usb/class/cdc-acm.c中将所有ttyACM创建软链接ttyACM0,然后通过在系统的检测usb设备发出的广播,告诉上位机app需要close重新open

frameworks/base/services/usb/java/com/android/server/usb/UsbHostManager
加入mContext.Broadcast(i)来使用广播

【如何在内核中增加自己的驱动文件夹hello,并进行编译】

https://zhuanlan.zhihu.com/p/28461589

在kernel/drivers/下建立一个文件夹hello

mkdir hello
touch hello.c
touch Kconfig
touch Makefile

加入hello.c的内容

修改kernel/drivers/hello/Kconfig (这个是为了生成 make menuconfig的目录选项)

config HELLO
	tristate "Hello Worldfor fengyuwuzu"
	help
	Hello forfengyuwuzu

修改kernel/drivers/hello/Makefile (指明要编译出的.o文件)

obj-$(CONFIG_HELLO) += hello.o

退回上级目录 ,进入目录kernel/drivers/

修改kernel/drivers/Makefile 加入

obj-y += hello/

修改kernel/drivers/Kconfig 加入 (告诉上级目录hello的目录)

source "drivers/hello/Kconfig"

回到kernel/
make menuconfig 勾选相关选项

修改/arch/arm/configs/rockchip_linux_defconfig
增加CONFIG_HELLO=y
(如果有多文件,需要注意也要加上上级目录,比如gpio的上级custom)

修改.config文件内容
增加CONFIG_HELLO=y

之后编译即可

【RK3399 USB在内核阶段上电】

根据光韬的代码原理,他的代码已经实现了对单个usb的GPIO的申请设置

关于gpio号的计算方法, &gpio0~7 每一个都对应了32个号:A0~7 B0~7 C0~7 D0~7。借此来计算dts里面的号码

关于数组的使用方法,参考的是rk3288-android6.0-sdk里面的dts里面的pinctrl
然后找到对应的调用该设备节点的驱动文件,通过设备树节点里面的init-gpios来查找到pinctrl-rockchip.c文件,仿照里面的用法,获得gpio口数组的每一行

【vim操作】

加入插件以后
:T tab后可以打开该文件的大纲
:N tab后可以打开文件目录索引

ctrl w 切换窗口

搜索并全部替换:
ctrl v ,选择操作区域

s/要替换掉的内容/使用替换的东西/g

【压缩解压指令】

压缩目录

tar -czvf myetc.tar.gz etc

解压目录

tar -xzvf myetc.tar.gz

【查询立体视觉等usb设备对应的usb的gpio】

每一个设备,立体视觉有对应的idVendoridProduct
前者表示厂商号码,通过lsusb指令查询得到立体视觉的idVendor2207

由于idVendoridProduct存放在/sys/bus/usb/devices/3-1.4/

grep -rn "2207" /sys/bus/usb/devices/*/idVendor 

可以查到

/sys/class/gpio下可以手动配置每个usb的gpio的电压值,通过这里来上电

/etc/init.d下可以查到开机自启动脚本上电操作

【串口数据量显示调试工具demo】

源码发给了 杜尚东
/serial_data_count

修改main.c里面,使用while循环,每次读取缓存区内的数据量并返回大小打印,同时sleep(1),即可实现定时输出,无需定时器

【git提交gerrit】

gerrit出现问题

重新拉一次项目的最初的源码,在外层目录

git clone ssh://liangji@review.keenonrobot.com:29418/linux/tools/usb-device-detect
cd
tig

切换到主分支

git checkout master

删除刚刚误创建的分支

git branch -D develop

创建远程的的分支到本地

git checkout -b develop origin/develop

查看是否拉到源码到本地

tig

到gerrit上找到需要修改的一页,找到右上角的downloads pull下来

git pull ssh://liangji@review.keenonrobot.com:29418/linux/tools/usb-device-detect refs/changes/48/30248/4

查看是否把要修改的commit拉下来

tig

修改该commit代码,并提交

vim main.c
git add main.c
git commit --amend
git push ssh://liangji@gerrit.ikeenon.com:29418/linux/tools/usb-device-detect HEAD:refs/for/develop
(第一个参数是远程仓库,第二个参数指的是把HEAD的commit提交到远程的分支)

【git操作解析】

git fetch origin 

会抓取克隆(或上一次抓取)后新推送的所有工作。 必须注意 git fetch 命令只会将数据下载到你的本地仓库——它并不会自动合并或修改你当前的工作。 当准备好时你必须手动将其合并入你的工作。


git clone 

命令会自动设置本地 master 分支跟踪克隆的远程仓库的 master 分支(或其它名字的默认分支)


git pull 

通常会从最初克隆的服务器上抓取数据并自动尝试合并到当前所在的分支,自动抓取后合并该远程分支到当前分支


git push <remote> <branch>

Git 的分支,其实本质上仅仅是指向提交对象的可变指针。
HEAD 也是个指针,指向当前所在的本地分支,来表示当前在那个分支上,将 HEAD 想象为当前分支的别名


git branch testing

创建分支


git log --oneline --decorate
git log --oneline --decorate --graph --all

查看当前分支关系,HEAD

git 提交的commit打包成patch

git format-patch -1 HEAD

【网络通信】

配置一台机器的网络:

公司网关172.16.9.1

自动获取ip地址:

sudo dhclient eth0
sudo ifconfig eth0

1、配置开发板ip

ifconfig eth0 192.168.137.2 

2、配置开发板网关(网关代表外部网络)

route add default gw 192.168.137.1

3、ping www.baidu.com

【RK3399版本管理】

将0830的那个rootfs挂载到台式机上,然后光韬有一个rootfs的配置文件的root目录,你每次有什么配置文件需要修改的,就直接修改root的配置文件管理目录,然后将他cp到台式机,用rsync进行同步。

【ubuntu台式机使用scp从服务器上下载文件到本地】

scp liangji@172.16.13.15:/media/hdd2/liangji/XXX /home/administrator/RK3399-rootfs-202208030/

1、从服务器上下载文件

scp username@servername:/path/filename /var/www/local_dir(本地目录)

例如scp root@192.168.0.101:/var/www/test.txt192.168.0.101上的/var/www/test.txt 的文件下载到/var/www/local_dir(本地目录)

2、上传本地文件到服务器

scp /path/filename username@servername:/path   

例如scp /var/www/test.php root@192.168.0.101:/var/www/ 把本机/var/www/目录下的test.php文件上传到192.168.0.101这台服务器上的/var/www/目录中

3、从服务器下载整个目录

scp -r username@servername:/var/www/remote_dir/(远程目录) /var/www/local_dir(本地目录)

例如:scp -r root@192.168.0.101:/var/www/test /var/www/

4、上传目录到服务器

scp  -r local_dir username@servername:remote_dir

例如:scp -r test root@192.168.0.101:/var/www/ 把当前目录下的test目录上传到服务器的/var/www/ 目录

【RK3399研究syslog和kmsg的区别】

通过对usb的gpio口上下电,进行开关,
syslog和kmsg都是通过从ringbuffer中读取log信息,关闭其中一个,另一个的调试信息可以完整输出

----------------------------------------------------------------------------16:42 2022/9/8

【iptables配置ubuntu主机网络共享】

iptables有多个参数可以进行配置四表五链

使用案例https://www.cnblogs.com/wanstack/p/8393282.html
参数详解https://www.jianshu.com/p/5a604b4ef342

需要将ubuntu台式机配置成路由器实现网络共享功能
ubuntu台式机与笔记本之间vnc连接 10.-
ubuntu台式机与开发板之间连接 192
Ubuntu台式机与公司网络连接 172

1.永久打开ubuntu的nat表功能

sudo gedit /etc/sysctl.conf

2.取消注释

net.ipv4.ip_forward=1

3.启动

sudo sysctl -p

这样在经过PREROUTING后经过路由选择后可以走FORWARD通道,之后走POSTROUTING
由于ubuntu默认FORWARD的默认策略是ACCEPT,所以filter里的FORWARD链不需要再进行设置

4.让每个网口都支持转发功能(加入规则,只要是往这个网口输出的,全部自动修改源地址MASQUERADE)

sudo iptables -t nat -N nat_board_computer

sudo iptables -t nat -I nat_board_computer 1 -o enp2s0 -j MASQUERADE
sudo iptables -t nat -I nat_board_computer 1 -o enx000ec6821555 -j MASQUERADE
sudo iptables -t nat -A nat_board_computer -o enx000ec670d129 -j MASQUERADE

sudo iptables -t nat -I POSTROUTING -j nat_board_computer

注意
Windows下ping baidu.com 找不到服务器名 原因是没有配置DNS 8.8.8.8 或者 114.114.114.114

DNS是和baidu.com同级的存在,用于帮忙查询翻译baidu.com的IP地址

【安卓网络诊断工具】

打算在显示里面加一个网络诊断工具按钮控件
package/目录下

diff --git a/apps/Settings/res/xml/display_settings.xml b/apps/Settings/res/xml/display_settings.xml
index b8b47c6..a817f61 100644
--- a/apps/Settings/res/xml/display_settings.xml
+++ b/apps/Settings/res/xml/display_settings.xml
@@ -37,6 +37,12 @@
                 android:key="systembar_hide"
                 android:title="@string/systembar_hide_title"/>
 
+        <PreferenceScreen
+                android:key="network_debug_tool"
+                android:title="@string/network_info_debug_title"/>
+
+
+
         <!-- Hide night mode for now
         <ListPreference
             android:key="night_mode"

定义按钮的标题文件

diff --git a/apps/Settings/res/values-zh-rCN/strings.xml b/apps/Settings/res/values-zh-rCN/strings.xml
index d9bdd5d..19063b1 100644
--- a/apps/Settings/res/values-zh-rCN/strings.xml
+++ b/apps/Settings/res/values-zh-rCN/strings.xml
@@ -3062,6 +3062,7 @@
     <string name="switch_success">切换成功</string>
     <string name="connect_to_pc">连接到 PC</string>
     <string name="systembar_hide_title">永久隐藏工具栏</string>
+    <string name="network_info_debug_title">网络信息诊断工具</string>
     <!--$_rbox_$_modify_$_end-->
 
 </resources>
diff --git a/apps/Settings/res/values/strings.xml b/apps/Settings/res/values/strings.xml
index c1c1fdc..f8d25f3 100644
--- a/apps/Settings/res/values/strings.xml
+++ b/apps/Settings/res/values/strings.xml
@@ -7205,6 +7205,7 @@
     <string name="connect_to_pc">Connect to PC</string>
     <string name="switch_success">switch success</string>
     <string name="systembar_hide_title">Always hide the status bar</string>
+    <string name="network_info_debug_title">Network debug tool</string>
     <!--$_rbox_$_modify_$_end-->
 
 </resources>

定义按钮控件的动作

diff --git a/apps/Settings/src/com/android/settings/DisplaySettings.java b/apps/Settings/src/com/android/settings/DisplaySettings.java
index b86de5a..3b52d7a 100644
--- a/apps/Settings/src/com/android/settings/DisplaySettings.java
+++ b/apps/Settings/src/com/android/settings/DisplaySettings.java
@@ -63,6 +63,7 @@ import android.preference.CheckBoxPreference;
 import java.util.ArrayList;
 import java.util.List;
 
+import java.io.IOException;
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.OutputStream;
@@ -74,8 +75,11 @@ public class DisplaySettings extends SettingsPreferenceFragment implements
 
     /** If there is no setting in the provider, use this. */
     private static final int FALLBACK_SCREEN_TIMEOUT_VALUE = 30000;
+    private static final int CLICK_DELAY_TIME = 500;
+    private static long lastClickTime;
 
     private static final String KEY_SYSTEMBAR_HIDE = "systembar_hide";
+    private static final String KEY_NETWORK_DEBUG_TOOL = "network_debug_tool";
     private static final String KEY_SCREEN_TIMEOUT = "screen_timeout";
     private static final String KEY_FONT_SIZE = "font_size";
     private static final String KEY_SCREEN_SAVER = "screensaver";
@@ -92,6 +96,7 @@ public class DisplaySettings extends SettingsPreferenceFragment implements
     private static final int DLG_GLOBAL_CHANGE_WARNING = 1;
 
     private CheckBoxPreference mSystemBarHide;
+    private Preference mNetworkDebugTool;
     private WarnedListPreference mFontSizePref;
 
     private final Configuration mCurConfig = new Configuration();
@@ -128,6 +133,7 @@ public class DisplaySettings extends SettingsPreferenceFragment implements
         }
 
         mSystemBarHide = (CheckBoxPreference) findPreference(KEY_SYSTEMBAR_HIDE);
+        mNetworkDebugTool = (Preference) findPreference(KEY_NETWORK_DEBUG_TOOL);
 
 
         mScreenTimeoutPreference = (ListPreference) findPreference(KEY_SCREEN_TIMEOUT);
@@ -237,6 +243,15 @@ public class DisplaySettings extends SettingsPreferenceFragment implements
             mNightModePreference.setOnPreferenceChangeListener(this);
         }
     }
+    public static boolean isNotFastClick() {
+        boolean flag = false;
+        long currentClickTime = System.currentTimeMillis();
+        if ((currentClickTime - lastClickTime) >= CLICK_DELAY_TIME) {
+            flag = true;
+        }
+        lastClickTime = currentClickTime;
+        return flag;
+    }
 
     private static boolean allowAllRotations(Context context) {
         return Resources.getSystem().getBoolean(
@@ -475,6 +490,18 @@ public class DisplaySettings extends SettingsPreferenceFragment implements
             Intent i = new Intent("com.keenon.changeBarHideStatus");
             getActivity().sendBroadcast(i);
         }
+        else if(preference == mNetworkDebugTool)
+        {
+            if (isNotFastClick()) {
+                Log.i(TAG, "network debug tool is running, please waiting");
+                try{
+                    Process process = Runtime.getRuntime().exec("/system/bin/network_debug_tool.sh");
+                } catch (IOException e){
+                    Log.e(TAG, "Fail: IOException");
+                }
+            }
+        }
+
         return super.onPreferenceTreeClick(preferenceScreen, preference);
     }
 
@@ -611,4 +638,4 @@ public class DisplaySettings extends SettingsPreferenceFragment implements
                     return result;
                 }
             };
-}
+        }

把运行脚本默认放到/system/bin/目录下/device/rockchip/rk3288/

diff --git a/rk3288.mk b/rk3288.mk
index 74c185d..30494a5 100644
--- a/rk3288.mk
+++ b/rk3288.mk
@@ -28,6 +28,7 @@ PRODUCT_MANUFACTURER := rockchip
 
 # Keenon Jimmy.Jin add
 PRODUCT_COPY_FILES += device/rockchip/rk3288/user_service.sh:system/bin/user_service.sh
+PRODUCT_COPY_FILES += device/rockchip/rk3288/network_debug_tool.sh:system/bin/network_debug_tool.sh
 PRODUCT_COPY_FILES += device/rockchip/rk3288/EC20/libreference-ril.so:system/lib/libreference-ril.so
 PRODUCT_COPY_FILES += device/rockchip/rk3288/EC20/ip-down:system/etc/ppp/ip-down
 PRODUCT_COPY_FILES += device/rockchip/rk3288/EC20/ip-up:system/etc/ppp/ip-up
@@ -43,7 +44,7 @@ PRODUCT_PROPERTY_OVERRIDES += \

执行脚本 network_debug_tool.sh

#!/system/bin/sh

FLAG=/mnt/network_debug_tool_process_flag.pid

if [ -f "$FLAG"  ]
then
    exit
fi


touch $FLAG
[ ! -d /sdcard/network_log ] && mkdir /sdcard/network_log

FILE=/sdcard/network_log/networkk_debug_info_$(date +%Y%m%d_%H%M%S).log

route -n >> $FILE
ifconfig >> $FILE
iwconfig >> $FILE 2>&1

ip rule >> $FILE
ip route show table 1 >> $FILE

iptables -nvL >> $FILE
iptables -nvL -t nat >> $FILE
iptables -nvL -t raw >> $FILE
iptables -nvL -t mangle >> $FILE

ping -c 4 -W 1 192.168.64.20 >> $FILE
ping -c 4 -W 1 baidu.com >> $FILE

rm $FLAG


【ubuntu创建自定义指令工具】

vi ~/.bashrc

加入一行
alias diagnosis='/usr/local/bin/diagnosis/diagnosis'

source ~/.bashrc

【c语言实现全局变量】

main.c

#include <stdio.h>

#define EXPORT_GLOBALS
#include "define_variable_in_header.h"

#include "fun.h"


int main(int argc, char* argv[])
{
    g_flag = 5;
    g_flag++;
    printf("%d\r\n", g_flag);

    usb_scan();
    return 0;
}


define_variable_in_header.h

#pragma once
#ifndef __DEFINE_VARIABLE_IN_HEADER_H
#define __DEFINE_VARIABLE_IN_HEADER_H

#ifdef EXPORT_GLOBALS
#define EXTERN
#else
#define EXTERN extern
#endif

EXTERN unsigned int g_flag;

#endif/*__DEFINE_VARIABLE_IN_HEADER_H*/

fun.h

#pragma once
#include <stdio.h>

#define EXPORT_GLOBALS
#include "define_variable_in_header.h"

int usb_scan();

fun.c

#include "fun.h"
int usb_scan()
{
	printf("usb_scan: %d\n", g_flag);
	return 0;

}

在这里插入图片描述

【usb_scan支持-v-t-f-s,且作为后台服务】

usb_scan

【RK3308 dmesg不停打印init: /dev/tty1 termined status 1 】

未找到解决方法,原因是dev/ttyN 没有自动创建,导致init在执行tty1.conf时循环执行/sbin/getty,无法打开文件。
为了解决该问题打印大量日志的问题,将/etc/init/tty*.conf改名未/etc/init/tty*.conf.no

【RK3288 android6.0 支持同时显示多个摄像头源码解析】

https://www.litreily.top/2021/07/12/dual-camera/

光韬博客
https://www.litreily.top/

int camera_get_number_of_cameras(void)
{
    char cam_sys[40];
    char cam_path[20];
    char cam_num[3],i;
    int cam_cnt=0,fd=-1,rk29_cam[CAMERAS_SUPPORT_MAX];
    struct v4l2_capability capability;
    rk_cam_info_t camInfoTmp[CAMERAS_SUPPORT_MAX];
    char *ptr,**ptrr;
    char version[PROPERTY_VALUE_MAX];
    char property[PROPERTY_VALUE_MAX];
    int hwrotation = 0;
	camera_board_profiles * profiles = NULL;
    size_t nCamDev = 0;
    char trace_level[PROPERTY_VALUE_MAX];
	struct timeval t0, t1;
    ::gettimeofday(&t0, NULL);
	
    if (gCamerasNumber > 0)
        goto camera_get_number_of_cameras_end;

    {
		property_set(CAMERAHAL_CAM_OTP_PROPERTY_KEY, "true");
        memset(version,0x00,sizeof(version));
        sprintf(version,"%d.%d.%d",((CONFIG_CAMERAHAL_VERSION&0xff0000)>>16),
            ((CONFIG_CAMERAHAL_VERSION&0xff00)>>8),CONFIG_CAMERAHAL_VERSION&0xff);
        property_set(CAMERAHAL_VERSION_PROPERTY_KEY,version);

        property_get(CAMERAHAL_TRACE_LEVEL_PROPERTY_KEY, trace_level, "-1");
        if (strcmp(trace_level,"-1")==0) {
            property_set(CAMERAHAL_TRACE_LEVEL_PROPERTY_KEY, "0");
        }

        memset(version,0x00,sizeof(version));
        sprintf(version,"%d.%d.%d",((ConfigBoardXmlVersion&0xff0000)>>16),
            ((ConfigBoardXmlVersion&0xff00)>>8),ConfigBoardXmlVersion&0xff);
        property_set(CAMERAHAL_CAMBOARDXML_PARSER_PROPERTY_KEY,version);


        CamEngineVersionItf *camEngVerItf;
        CamEngVer_t camEngVer;

        camEngVerItf = new CamEngineVersionItf();

        camEngVerItf->getVersion(&camEngVer);
        
        memset(version,0x00,sizeof(version));
        sprintf(version,"%d.%d.%d",((camEngVer.libisp_ver&0xff0000)>>16),
            ((camEngVer.libisp_ver&0xff00)>>8),camEngVer.libisp_ver&0xff);
        property_set(CAMERAHAL_LIBISP_PROPERTY_KEY,version);

        memset(version,0x00,sizeof(version));
        sprintf(version,"%d.%d.%d",((camEngVer.isi_ver&0xff0000)>>16),
            ((camEngVer.isi_ver&0xff00)>>8),camEngVer.isi_ver&0xff);
        property_set(CAMERAHAL_ISI_PROPERTY_KEY,version);

        delete camEngVerItf;

    }
    
    for(int i=0;i<CAMERAS_SUPPORT_MAX;i++){
        memset(&camInfoTmp[i],0x00,sizeof(rk_cam_info_t));
    }
    //memset(&camInfoTmp[0],0x00,sizeof(rk_cam_info_t));
    //memset(&camInfoTmp[1],0x00,sizeof(rk_cam_info_t));

    profiles = camera_board_profiles::getInstance();
    nCamDev = profiles->mDevieVector.size();
	LOGE("board profiles cam num %d\n", nCamDev);
    if (nCamDev>0) {
        camera_board_profiles::LoadSensor(profiles);
        char sensor_ver[32];
		
        for (i=0; (i<nCamDev); i++) 
        {  
        	LOGE("load sensor name(%s) connect %d\n", profiles->mDevieVector[i]->mHardInfo.mSensorInfo.mSensorName, profiles->mDevieVector[i]->mIsConnect);
        	if(profiles->mDevieVector[i]->mIsConnect==1){
    	        rk_sensor_info *pSensorInfo = &(profiles->mDevieVector[i]->mHardInfo.mSensorInfo);
    	        
    	        camInfoTmp[cam_cnt].pcam_total_info = profiles->mDevieVector[i];
    	        strncpy(camInfoTmp[cam_cnt].device_path, pSensorInfo->mCamsysDevPath, sizeof(camInfoTmp[cam_cnt].device_path));
    	        strncpy(camInfoTmp[cam_cnt].driver, pSensorInfo->mSensorDriver, sizeof(camInfoTmp[cam_cnt].driver));
				unsigned int SensorDrvVersion = profiles->mDevieVector[i]->mLoadSensorInfo.mpI2cInfo->sensor_drv_version;
				memset(version,0x00,sizeof(version));
    	        sprintf(version,"%d.%d.%d",((SensorDrvVersion&0xff0000)>>16),
	    	            ((SensorDrvVersion&0xff00)>>8),SensorDrvVersion&0xff);
						 
    	        if(pSensorInfo->mFacing == RK_CAM_FACING_FRONT){     
    	            camInfoTmp[cam_cnt].facing_info.facing = CAMERA_FACING_FRONT;
    	        } else {
    	            camInfoTmp[cam_cnt].facing_info.facing = CAMERA_FACING_BACK;
    	        } 

                memset(sensor_ver,0x00,sizeof(sensor_ver));
                if (strlen(pSensorInfo->mSensorName) < (sizeof(sensor_ver)-16))
                    sprintf(sensor_ver,"%s%s%s","sys_graphic.",pSensorInfo->mSensorName,".ver");
                else 
                    sprintf(sensor_ver,"%s",pSensorInfo->mSensorName);                
                property_set(sensor_ver, version);	
                
    	        camInfoTmp[cam_cnt].facing_info.orientation = pSensorInfo->mOrientation;
    	        cam_cnt++;

    			unsigned int CamsysDrvVersion = profiles->mDevieVector[i]->mCamsysVersion.drv_ver;
    	        memset(version,0x00,sizeof(version));
    	        sprintf(version,"%d.%d.%d",((CamsysDrvVersion&0xff0000)>>16),
    	            ((CamsysDrvVersion&0xff00)>>8),CamsysDrvVersion&0xff);
    	        property_set(CAMERAHAL_CAMSYS_VERSION_PROPERTY_KEY,version);
    		}
        }
    }

   	if(cam_cnt<CAMERAS_SUPPORT_MAX){
		int i=0;
		int element_count=0;
		while(MediaProfile_Resolution[i][0]>0 && MediaProfile_Resolution[i][1]>0){
			element_count++;
			i++;
		}
		
        for (i=0; i<20; i++) {
            cam_path[0] = 0x00;
			//unsigned int pix_format_tmp = V4L2_PIX_FMT_NV12;
            //strcat(cam_path, CAMERA_DEVICE_NAME);
            cam_sys[0] = 0x00;
            strcat(cam_sys, CAM_SYS_NAME);
            sprintf(cam_num, "%d", i);
            strcat(cam_sys,cam_num);
            strcat(cam_sys,"/index");
            FILE* ifp;
            ifp = fopen(cam_sys, "r");
            if (ifp == NULL){
                LOGD("fail to open sys file:%s",cam_sys);
                continue;
            }
            unsigned char index;
            fread(&index, sizeof(char),1, ifp);
            fclose(ifp);
            LOGD("open %s index %x",cam_sys,index);
            if(index == 0x31){
                LOGD("%s wrong index continue",cam_sys);
                continue;
            }
            strcat(cam_path, CAMERA_DEVICE_NAME);

            strcat(cam_path,cam_num);
            fd = open(cam_path, O_RDONLY);
            unsigned int pix_format_tmp = V4L2_PIX_FMT_NV12;
            if (fd < 0) {
                LOGE("Open %s failed! strr: %s",cam_path,strerror(errno));
                break;
            } 
            LOGD("Open %s success!",cam_path);

            memset(&capability, 0, sizeof(struct v4l2_capability));
            if (ioctl(fd, VIDIOC_QUERYCAP, &capability) < 0) {
            	LOGE("Video device(%s): query capability not supported.\n",cam_path);
                goto loop_continue;
            }
            
            if ((capability.capabilities & (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING)) != (V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING)) {
        	    LOGD("Video device(%s): video capture not supported.\n",cam_path);
            } else {
            	rk_cam_total_info* pNewCamInfo = new rk_cam_total_info();
                memset(camInfoTmp[cam_cnt].device_path,0x00, sizeof(camInfoTmp[cam_cnt].device_path));
                strcat(camInfoTmp[cam_cnt].device_path,cam_path);
                memset(camInfoTmp[cam_cnt].fival_list,0x00, sizeof(camInfoTmp[cam_cnt].fival_list));
                memcpy(camInfoTmp[cam_cnt].driver,capability.driver, sizeof(camInfoTmp[cam_cnt].driver));
                camInfoTmp[cam_cnt].version = capability.version;
                if (strstr((char*)&capability.card[0], "front") != NULL) {
                    camInfoTmp[cam_cnt].facing_info.facing = CAMERA_FACING_FRONT;
                } else {
                    camInfoTmp[cam_cnt].facing_info.facing = CAMERA_FACING_BACK;
                }  
                ptr = strstr((char*)&capability.card[0],"-");
                if (ptr != NULL) {
                    ptr++;
                    camInfoTmp[cam_cnt].facing_info.orientation = atoi(ptr);
                } else {
                    camInfoTmp[cam_cnt].facing_info.orientation = 0;
                }

                memset(version,0x00,sizeof(version));
                sprintf(version,"%d.%d.%d",((capability.version&0xff0000)>>16),
                    ((capability.version&0xff00)>>8),capability.version&0xff);
                property_set(CAMERAHAL_V4L2_VERSION_PROPERTY_KEY,version);
				
				if(strcmp((char*)&capability.driver[0],"uvcvideo") == 0)//uvc
				{
					int ret,i=0,j=0;					 
					struct v4l2_frmivalenum fival;
					struct v4l2_frmsizeenum fsize;
					struct v4l2_fmtdesc fmtdesc;
					unsigned int width, height;
					unsigned int sensor_resolution_w=0,sensor_resolution_h=0;
					unsigned int CameraHal_SupportFmt[6];
					unsigned int mCamDriverSupportFmt[CAMERA_DRIVER_SUPPORT_FORMAT_MAX];
					unsigned int mCamDriverPreviewFmt=0;
					unsigned int maxfps;

					//add usb camera to board_profiles 
					rk_DV_info *pDVResolution = new rk_DV_info();
					memset(pNewCamInfo->mHardInfo.mSensorInfo.mSensorName, 0x00, sizeof(pNewCamInfo->mHardInfo.mSensorInfo.mSensorName));
					strcpy(pNewCamInfo->mHardInfo.mSensorInfo.mSensorName, UVC_CAM_NAME);
					pNewCamInfo->mIsIommuEnabled = capability.reserved[0];
					#if 0
					//DV
					strcpy(pDVResolution->mName, "480p");
		    	    pDVResolution->mWidth = 640;
		    	    pDVResolution->mHeight = 480;
		    	    pDVResolution->mFps = 10;
		    	    pDVResolution->mIsSupport =  1;
		            pDVResolution->mResolution = ISI_RES_VGAP15;
		            pNewCamInfo->mSoftInfo.mDV_vector.add(pDVResolution);
					#endif
					//paremeters
					pNewCamInfo->mSoftInfo.mAntiBandingConfig.mAntiBandingSupport = 0;
					pNewCamInfo->mSoftInfo.mAntiBandingConfig.mDefault = 0;
					pNewCamInfo->mSoftInfo.mAwbConfig.mAwbSupport = 0;
					pNewCamInfo->mSoftInfo.mAwbConfig.mDefault = 0;
					pNewCamInfo->mSoftInfo.mContinue_snapshot_config= 0;
					pNewCamInfo->mSoftInfo.mEffectConfig.mEffectSupport = 0;
					pNewCamInfo->mSoftInfo.mEffectConfig.mDefault = 0;
					pNewCamInfo->mSoftInfo.mFlashConfig.mFlashSupport= 0;
					pNewCamInfo->mSoftInfo.mFlashConfig.mDefault = 0;
					pNewCamInfo->mSoftInfo.mFocusConfig.mFocusSupport= 0;
					pNewCamInfo->mSoftInfo.mFocusConfig.mDefault = 0;
					pNewCamInfo->mSoftInfo.mHDRConfig= 0;
					pNewCamInfo->mSoftInfo.mSenceConfig.mSenceSupport= 0;
					pNewCamInfo->mSoftInfo.mSenceConfig.mDefault = 0;
					pNewCamInfo->mSoftInfo.mZSLConfig = 0;
					pNewCamInfo->mSoftInfo.mInterpolationRes = 0;
					//profiles->AddConnectUVCSensorToVector(pNewCamInfo, profiles);

					CameraHal_SupportFmt[0] = V4L2_PIX_FMT_NV12;
				    CameraHal_SupportFmt[1] = V4L2_PIX_FMT_NV16;
				    #if CONFIG_CAMERA_UVC_MJPEG_SUPPORT
				    CameraHal_SupportFmt[2] = V4L2_PIX_FMT_MJPEG;
				    CameraHal_SupportFmt[3] = V4L2_PIX_FMT_YUYV;
				    CameraHal_SupportFmt[4] = V4L2_PIX_FMT_RGB565;
				    #else
				    CameraHal_SupportFmt[2] = V4L2_PIX_FMT_YUYV;
				    CameraHal_SupportFmt[3] = V4L2_PIX_FMT_RGB565;
				    CameraHal_SupportFmt[4] = 0x00;
				    #endif
				    CameraHal_SupportFmt[5] = 0x00;

					memset(&fmtdesc, 0, sizeof(fmtdesc));	 
					fmtdesc.index = 0;
					fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;    
					while (ioctl(fd, VIDIOC_ENUM_FMT, &fmtdesc) == 0) {
						mCamDriverSupportFmt[fmtdesc.index] = fmtdesc.pixelformat;
						LOG1("mCamDriverSupportFmt:(%c%c%c%c),index = %d",fmtdesc.pixelformat&0xFF,(fmtdesc.pixelformat>>8)&0xFF,
							(fmtdesc.pixelformat>>16)&0xFF,(fmtdesc.pixelformat>>24)&0xFF,fmtdesc.index);
						fmtdesc.index++;
					}
										
					i = 0;	  
					while (CameraHal_SupportFmt[i]) {
						LOG1("CameraHal_SupportFmt:fmt = %d,index = %d",CameraHal_SupportFmt[i],i);
						j = 0;
						while (mCamDriverSupportFmt[j]) {
							if (mCamDriverSupportFmt[j] == CameraHal_SupportFmt[i]) {
								break;
							}
							j++;
						}
						if (mCamDriverSupportFmt[j] == CameraHal_SupportFmt[i]) {
							break;
						}
						i++;
					}
					
					if (CameraHal_SupportFmt[i] == 0x00) {
						mCamDriverPreviewFmt = 0;
					} else {  
						mCamDriverPreviewFmt = CameraHal_SupportFmt[i];
					}

					fsize.index = 0;
					fsize.pixel_format = mCamDriverPreviewFmt;

					while ((ret = ioctl(fd, VIDIOC_ENUM_FRAMESIZES, &fsize)) == 0) {
						if (fsize.type == V4L2_FRMSIZE_TYPE_DISCRETE) {  
							//if(fsize.discrete.width%16 || fsize.discrete.height%16)
							//{
							//	fsize.index++;
							//	continue;
							//}
					
							if (fsize.discrete.width > sensor_resolution_w) {
								sensor_resolution_w = fsize.discrete.width;
								sensor_resolution_h = fsize.discrete.height;
							}
						}
						fsize.index++;
					}
					if(sensor_resolution_w == 0){
						sensor_resolution_w = 640;
						sensor_resolution_h = 480;
						pDVResolution->mResolution = ISI_RES_VGAP15;
					}
					for(i=0; i<element_count; i++){
						width = MediaProfile_Resolution[i][0];
			            height = MediaProfile_Resolution[i][1];				
			            memset(&fival, 0, sizeof(fival));
			            fival.index = 0;
			            fival.pixel_format = fsize.pixel_format;
			            fival.width = width;
			            fival.height = height;
			            fival.reserved[1] = 0x00;	
						maxfps = 0;
						
						rk_DV_info *pDVResolution = new rk_DV_info();
						pDVResolution->mWidth = width;
		    	    	pDVResolution->mHeight = height;
		    	    	pDVResolution->mFps = 0;
		    	    	pDVResolution->mIsSupport =  0;

						if ((width>sensor_resolution_w) || (height>sensor_resolution_h)) {
							pNewCamInfo->mSoftInfo.mDV_vector.add(pDVResolution);
	                		continue;
	            		}
	            		//LOGE("index = %d, pixel_format = %d, width = %d, height = %d", 
	            		//    fival.index, fival.pixel_format, fival.width,  fival.height);
						while ((ret = ioctl(fd, VIDIOC_ENUM_FRAMEINTERVALS, &fival)) == 0) {
							if (fival.type == V4L2_FRMIVAL_TYPE_DISCRETE) {
								pDVResolution->mFps = fival.discrete.denominator/fival.discrete.numerator;
								pDVResolution->mIsSupport = 1;
								if (pDVResolution->mFps > maxfps)
									maxfps = pDVResolution->mFps;
								LOG1("%dx%d : %d	%d/%d",fival.width,fival.height, pDVResolution->mFps,fival.discrete.denominator,fival.discrete.numerator);
							}else if (fival.type == V4L2_FRMIVAL_TYPE_CONTINUOUS) {
			                    break;
			                } else if (fival.type == V4L2_FRMIVAL_TYPE_STEPWISE) {
			                    break;
			                }
							fival.index++;
						}
						if(ret){
							pDVResolution->mIsSupport = 1;
							if(maxfps > 0)
								pDVResolution->mFps = maxfps;
							else
								pDVResolution->mFps = 10;
				 		}
						pNewCamInfo->mSoftInfo.mDV_vector.add(pDVResolution);	        
					}
				}
				else//cif soc camera
				{
					int i=0;					 
					int fps;
					int crop_w, crop_h;
					int width, height;
					struct v4l2_format fmt;
					struct v4l2_format format;
					struct v4l2_frmivalenum fival;
					int sensor_resolution_w=0,sensor_resolution_h=0;
					int resolution_index = -1;
					
					fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
			        fmt.fmt.pix.pixelformat= V4L2_PIX_FMT_NV12;
			        fmt.fmt.pix.field = V4L2_FIELD_NONE;
			        fmt.fmt.pix.width = 10000;
			        fmt.fmt.pix.height = 10000;
			        int ret = ioctl(fd, VIDIOC_TRY_FMT, &fmt);
			        sensor_resolution_w = fmt.fmt.pix.width;
			        sensor_resolution_h = fmt.fmt.pix.height;  /* ddl@rock-chips.com: v0.4.e */				
					for(i=0; i<element_count; i++){
						width = MediaProfile_Resolution[i][0];
			            height = MediaProfile_Resolution[i][1];				
			            memset(&fival, 0, sizeof(fival));
			            fival.index = 0;
			            fival.pixel_format = pix_format_tmp;
			            fival.width = width;
			            fival.height = height;
			            fival.reserved[1] = 0x00;	

						rk_DV_info *pDVResolution = new rk_DV_info();
						pDVResolution->mWidth = width;
		    	    	pDVResolution->mHeight = height;
		    	    	pDVResolution->mFps = 0;
		    	    	pDVResolution->mIsSupport =  0;

						if ((width>sensor_resolution_w) || (height>sensor_resolution_h)) {
							pNewCamInfo->mSoftInfo.mDV_vector.add(pDVResolution);
	                		continue;
	            		}
										
						if ((ret = ioctl(fd, VIDIOC_ENUM_FRAMEINTERVALS, &fival)) == 0) {
							if (fival.type == V4L2_FRMIVAL_TYPE_DISCRETE) {	
								fps = (fival.discrete.denominator/fival.discrete.numerator);
	                    		crop_w = (fival.reserved[1]&0xffff0000)>>16;
	                    		crop_h = (fival.reserved[1]&0xffff);
                                pDVResolution->mFps = 30;//fps;//for passing cts,should be ok for now.
								pDVResolution->mIsSupport = 1;
								
								if ((crop_w != width) || (crop_h != height)) {
			                        if((width==1280 && height==720 ) || (width==1920 && height==1080 )) {
			                            pDVResolution->mIsSupport = 0;
			                        }
			                    }

								if(width==720 && height==480){
			                        if ((crop_w>800) || (crop_h>600)) {    /* ddl@rock-chips.com: v0.4.e */
			                             pDVResolution->mIsSupport =  0;    
			                        } else {                       
			                            resolution_index = find_DV_resolution_index(640,480);
										if(resolution_index>0)
			                 				pNewCamInfo->mSoftInfo.mDV_vector[resolution_index]->mIsSupport = 0;
			                        }
			                    }

                                /* needn't support dv 800x600 ,just support vga*/
								if((width == 800) && (height == 600)){
									pDVResolution->mIsSupport = 0;
								}
								
							}else{
								pDVResolution->mIsSupport = 0;
								LOGE("find frame intervals failed ret(%d)\n", ret);
							}
						}else{
							pDVResolution->mIsSupport = 0;
							LOGE("find frame intervals failed ret(%d)\n", ret);
						}
						
						pNewCamInfo->mSoftInfo.mDV_vector.add(pDVResolution);	        
					}
					
					strcpy(pNewCamInfo->mHardInfo.mSensorInfo.mSensorName, SOC_CAM_NAME);
					pNewCamInfo->mIsIommuEnabled = capability.reserved[0];
					if (strstr((char*)&capability.card[0], "front") != NULL) {
                    	pNewCamInfo->mHardInfo.mSensorInfo.mFacing = 1;
                	} else {
                    	pNewCamInfo->mHardInfo.mSensorInfo.mFacing = 0;
                	}
				}
                pNewCamInfo->mHardInfo.mSensorInfo.mPhy.type = CamSys_Phy_end;

				//pNewCamInfo->mDeviceIndex = (profiles->mDevieVector.size()) - 1;
				pNewCamInfo->mIsConnect = 1;
				profiles->mCurDevice= pNewCamInfo;
            	profiles->mDevieVector.add(pNewCamInfo);
				pNewCamInfo->mDeviceIndex = (profiles->mDevieVector.size()) - 1;
                camInfoTmp[cam_cnt].pcam_total_info = pNewCamInfo;
                cam_cnt++;
                if (cam_cnt >= CAMERAS_SUPPORT_MAX)
                    i = 20;
            }
    loop_continue:
            if (fd > 0) {
                close(fd);
                fd = -1;
            }
            continue;    
        }
   	}

   
	camera_board_profiles::ProduceNewXml(profiles);
	
    gCamerasNumber = cam_cnt;

#if CONFIG_AUTO_DETECT_FRAMERATE
    rk29_cam[0] = 0xff;
    rk29_cam[1] = 0xff;
    for (i=0; i<cam_cnt; i++) {
        if (strcmp((char*)&camInfoTmp[i].driver[0],"rk29xx-camera") == 0) {
            if (strcmp((char*)&camInfoTmp[i].driver[0],(char*)&gCamInfos[i].driver[0]) != 0) {
                rk29_cam[i] = i; 
            }
        } else {
            rk29_cam[i] = 0xff;
        }
    }

    if ((rk29_cam[0] != 0xff) || (rk29_cam[1] != 0xff)) {
        if (gCameraFpsDetectThread == NULL) {
            gCameraFpsDetectThread = new CameraFpsDetectThread();
            LOGD("%s create CameraFpsDetectThread for enum camera framerate!!",__FUNCTION__);
            gCameraFpsDetectThread->run("CameraFpsDetectThread", ANDROID_PRIORITY_AUDIO);
        }
    }
#endif    

    #if CONFIG_CAMERA_SINGLE_SENSOR_FORCE_BACK_FOR_CTS
    if ((gCamerasNumber==1) && (camInfoTmp[0].facing_info.facing==CAMERA_FACING_FRONT)) {
        gCamerasNumber = 2;
        memcpy(&camInfoTmp[1],&camInfoTmp[0], sizeof(rk_cam_info_t));
        camInfoTmp[1].facing_info.facing = CAMERA_FACING_BACK;
    }
    #endif
    
    //memcpy(&gCamInfos[0], &camInfoTmp[0], sizeof(rk_cam_info_t));
    //memcpy(&gCamInfos[1], &camInfoTmp[1], sizeof(rk_cam_info_t));
    for(int i=0;i<CAMERAS_SUPPORT_MAX;i++){
        memcpy(&gCamInfos[i], &camInfoTmp[i], sizeof(rk_cam_info_t));
    }


    property_get("ro.sf.hwrotation", property, "0");
    hwrotation = strtol(property,0,0);

#if 0
    if (hwrotation == 0) {
        gCamInfos[0].facing_info.orientation = 0;    /* ddl@rock-chips.com: v0.4.17 */ 
        gCamInfos[1].facing_info.orientation = 0;
    }
#endif
//for test isp,zyc
//  gCamerasNumber =1;
//  gCamInfos[0].facing_info.orientation = 180;
    
camera_get_number_of_cameras_end:
    LOGD("%s(%d): Current board have %d cameras attached.",__FUNCTION__, __LINE__, gCamerasNumber);

	::gettimeofday(&t1, NULL);
	LOGD("meida_profiles_xml_control time (%ld)us\n", (t1.tv_sec*1000000 + t1.tv_usec) - (t0.tv_sec*1000000 + t0.tv_usec));
    return gCamerasNumber;
}

结构解析

存好通用配置版本信息
OTP true
VERSION version1
TRACE_LEVEL --> trace_level[VALUE_MAX]
CAMBOARDXML_PARSER version2
LIBISP version3
ISI version4

由camera_board_profiles空间的getinstance 获得具体的摄像头数量nCamDev
设备向量

for(i)
{
针对每个摄像头
把向量中的每个摄像头的信息保存到本地数组中
}

for(i)
{
针对每一个虚拟的/dev/videon
获得系统文件名/sys和设备文件名/dev
系统文件检查index
设备文件检查设备功能是否支持

}

【安卓6.0 rtl8821cu 蓝牙适配】

【device/common/】
	device/common/bluetooth/libbt-rtk/uart/Android.mk(.bk)
				      .../usb/Android.mk(.bk)

【build】
	core/product.mk
	 	加了一个BOARD_HAVE_BLUETOOTH_RTK 变量
【device/rockchip/common/】
	audio_policy_rk30board.conf
	 	加入了指定采样频率,频道掩膜,格式等
	overlay/packages/apps/Bluetooth/res/values/config.xml
	  	关掉原来的蓝牙的配置文件,使用sink的配置文件
【device/rockchip/rk3288/】
	init.rc
	  	insmod 加入指定芯片编译好的ko文件(system/lib/modules/8188eu(8821cu).ko)									到内核中
【kernel】
   [8723bu代替8188eu]
	arch/arm/boot/dts/rk3288-tb_8846.dts
		向上层指定wifi芯片类型(可兼容)
	arch/arm/configs/rockchip_defconfig			
		增加CONFIG_RTL8723BU = y

   [支持8821cu]
	drivers/bluetooth/rtk_btusb.c(h)
		指定蓝牙需要的固件名称(fw_patch)
   [换回8818eu]
		8723->8818
   [支持8821cuwifi驱动]
		一系列wifi驱动源码 driver/net/wireless/....
   [RK3288支持8821]
	drivers/net/wireless/Kconfig
	drivers/net/wireless/Makefile
	drivers/net/wireless/rockchip_wlan/rtl8821cu/Makefile
		修改编译配置文件,加入wifi驱动
 
   [编译8821和兼容8188wifi驱动为.ko文件]
	arch/arm/configs/rockchip_defconfig
		设置CONFIG_RTL8188EU, CONFIG_RTL8821CU = m
	drivers/net/wireless/Kconfig
	drivers/net/wireless/rockchip_wlan/rtl8821cu/Makefile
		编译出来的模块名叫做 MODULE_NAME := 8821cu

   [支持rlt8821 wifi芯片]
	drivers/net/wireless/rockchip_wlan/wifi_sys/rkwifi_sys_iface.c
		common接口加入8821
	include/linux/rfkill-wlan.h
		加入8821 WiFi选项
	net/rfkill/rfkill-wlan.c
		common接口加入8821


【packages】
   [支持bluetooth a2dp sink mode]
	apps/Bluetooth/AndroidManifest.xml
	  	给用户权限 RECORD_AUDIO
	apps/Bluetooth/src/com/android/bluetooth/a2dp/A2dpSinkStateMachine.java
	  	对蓝牙sink模式的实现
【system】
   [支持bluetooth a2dp sink mode]
	bt/btif/src/btif_media_task.c
	  	换了一个宏函数(APPL_TRACE_EVENT --> APPL_TRACE_ERROR)
	  	取消 如果没有一个设备在监听就忽略数据的功能
	bt/include/bt_target.h
		#define BTA_AV_SINK_INCLUDED TRUE
	bt/udrv/ulinux/uipc.c
		换了一个宏函数(APPL_TRACE_EVENT --> APPL_TRACE_ERROR)
		UIPC_Send
【vendor】
   [为新的wifi蓝牙8821支持固件]
	rockchip/common/bluetooth/bluetooth.mk
		加入rtl8821c的固件编译文件索引
	rockchip/common/bluetooth/realtek/firmware/usb/rtl8821c/device-rtl.mk(编译文件)
		编译文件指明配置config文件和固件fw
							......./rtl8821c_config
							......./rtl8821c_fw
   [支持8188和8821 wifi]
	rockchip/common/wifi/modules/8188eu(8821cu).ko
		把编译好的ko文件放入该文件夹

   [加入hci 蓝牙]
	rockchip/common/rftesttool/broadcom/broadcom.mk
	rockchip/common/rftesttool/rftesttool.mk
		和rk3288相关配置

根据报错信息发现,蓝牙无法打开的原因是缺少文件libbt-vendor_usb.so

在 device/common/ 下找到编译出该so文件的源码usb/和uart/,但是由tig发现被禁用了。
原因是:光韬当时认为rtl8821cu自己会带有usb/,会和原来的device/common/下的系统默认的冲突。

我将光韬原来的那个好的系统里面的两个.so文件拷贝到这个坏的系统中就好了。说明就是缺少so文件。在源码中搜索。并没有找到so文件,说明没有编译出来,思考是被禁用了。应当查看对应的mk等编译文件,看看是不是被禁用了


主要问题有两个,一个是缺少libbt-vendor_usb.so库文件,一个是驱动编译出来有问题
1.缺少libbt-vendor_usb.so库文件
这里由两个来源方法,

一个是从/device/common/bluetooth/libbt-rtk/usb中获得。
这个是系统自带的,原先光韬为了防止和其他地方冲突,选择禁用默认的这个libbt-vendor_usb.so,想要选择8821cu自带的。但是那个8821的文件会导致乱码问题。所以换回这个默认。只要把原来加了后缀的Android.mk文件改回来就行了。

另一个是从/device/rockchip/rk3288里面。
根据8821cu的移植手册,在将rtkbt目录移过来之后,要修改执行rtkbt/system/etc/的文件里面指定usb而不是uart。然后在rk3288目录下的device.mk文件中加入编译选项。但是由于有问题,所以选择取消编译选项

2.驱动编译有两种,一个是内嵌到内核中(y),另一个是以模块形式编译(m)成ko文件,然后自己insmod进入内核。

内嵌到内核:
kernel/arch/arm/configs/rockchip_defconfig中找到CONFIG_BT_RTKBTUSB= y .(这个是Kconfig里指定的名字)
make rockchip_defconfig 更新编译配置文件
然后修改好drivers/bluetooth里面的rtk_btusb.c.h文件,
./mk.sh编译好后可以看到刚刚的文件里面生成了.o文件

以模块形式编译驱动:
kernelarch/arm/configs/rockchip_defconfig中找到CONFIG_BT_RTKBTUSB= m
make rockchip_defconfig
然后修改好驱动文件。
kernel目录下: make modules
可以看到刚刚的文件下多出了.ko文件。
然后将这些ko文件需要放到系统默认的/system/lib/modules目录下。
根据当时vendor下当时的wifi实现,放在和wifi模块驱动的同级目录即可,在rk3288目录下有个init.rc里面有insmod
当编译完整体镜像之后,可以在out目录下找到ko文件
也可以自己在烧录完镜像后手动insmod,都可以。

【安卓目录结构简记】

art:Android Runtime,一种App运行模式,区别于传统的Dalvik虚拟机,旨在提高Android系统的流畅性
bionic:基础C库源代码,Android改造的C/C++库
bootable:Android程序启动导引,适合各种bootloader的通用代码,包括一个recovery目录
build:存放系统编译规则及generic等基础开发包配置
compatibility:Android兼容性计划
cts: Android兼容性测试套件标准
dalvik:Android Dalvik虚拟机相关内容
developers:Android开发者参考文档
development: Android应用开发基础设施相关
device:Android支持的各种设备及相关配置
external:Android中使用的外部开源库
frameworks:应用程序框架,Android系统核心部分,由Java和C++编写
hardware:硬件适配接口
kernel:Linux Kernel,不过Android默认不提供,需要单独下载,只有一个tests目录
libcore:Android Java核心类库
libnativehelper:Android动态库,实现JNI库的基础
packages:应用程序包
pdk:Plug Development Kit 的缩写,本地开发套件
platform_testing:Android平台测试程序
prebuilts:x86和arm架构下预编译的一些资源
sdk:Android的Java层sdk
system:Android底层文件系统库、应用和组件
test:Android Vendor测试框架
toolchain:Android工具链文件
tools:Android工具文件
Android.bp:Android7.0开始代替Android.mk文件,它是告诉ndk将jni代码编译成动态库的一个脚本
Makefile:全局Makefile文件,用来定义编译规则

【Android 6 状态栏隐藏】

diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 8eaf6a8..ea6efde 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -1024,6 +1024,10 @@ public class StatusBar extends SystemUI implements DemoMode,
         filter.addAction("com.keenon.changeBarHideStatus");
         filter.addAction("com.keenon.usbModeSet");
         // Keenon wugt add end
+        // Keenon liangji add start
+        filter.addAction("com.keenon.changeBarHideStatus_enable");
+        filter.addAction("com.keenon.changeBarHideStatus_disable");
+        // Keenon liangji add end
         context.registerReceiverAsUser(mBroadcastReceiver, UserHandle.ALL, filter, null, null);
 
         IntentFilter demoFilter = new IntentFilter();
@@ -1409,6 +1413,28 @@ public class StatusBar extends SystemUI implements DemoMode,
         }
     }
 
+    private void changeBarHideStatus_enable()
+    {
+        Log.d("liangji: Keenon","changeBarHideStatus_enable");
+        Settings.System.putInt(mContext.getContentResolver(),Settings.System.SYSTEMBAR_HIDE,1);
+        int get_int = 3;
+        get_int = Settings.System.getInt(mContext.getContentResolver(),Settings.System.SYSTEMBAR_HIDE,0); 
+        String text = String.valueOf(get_int);
+        Log.i("liangji:Settings.System.SYSTEMBAR_HIDE = ", text);
+        removeBar();
+    }
+
+    private void changeBarHideStatus_disable()
+    {
+        Log.d("liangji: Keenon","changeBarHideStatus_disable");
+        Settings.System.putInt(mContext.getContentResolver(),Settings.System.SYSTEMBAR_HIDE,0);
+        int get_int = 3;
+        get_int = Settings.System.getInt(mContext.getContentResolver(),Settings.System.SYSTEMBAR_HIDE,0); 
+        String text = String.valueOf(get_int);
+        Log.i("liangji:Settings.System.SYSTEMBAR_HIDE = ", text);
+        restoreBar();
+    }
+
     private void usbModeSet()
     {
         int usbmode = Settings.System.getInt(mContext.getContentResolver(),Settings.System.USB_OTG_MODE, 1);
@@ -2753,6 +2779,16 @@ public class StatusBar extends SystemUI implements DemoMode,
                 usbModeSet();
             }
             // Keenon wugt add end
+            // Keenon liangji add start
+            else if("com.keenon.changeBarHideStatus_enable".equals(action))
+            {
+                changeBarHideStatus_enable();
+            }
+            else if("com.keenon.changeBarHideStatus_disable".equals(action))
+            {
+                changeBarHideStatus_disable();
+            }
+            // Keenon liangji add end
         }
     };
 

自己发广播测试,用am指令

发送
am broadcast -a com.keenon.changeBarHideStatus_global

接受
logcat |grep liangji
liangji:Settings.system.SYSTEMBAR_HIDE

【python ssh 免密连接,dd更新内核】

项目文件链接

ssh传输文件和执行执行的python脚本: repair.py

# -*- coding: UTF-8 -*-

import os
import re
import sys
import paramiko
from scp import SCPClient
import time
import tkinter
import tkinter.messagebox

PWD = os.path.abspath(".")   
IP = "192.168.64.20"
PORT = "22"
USER = "peanut"
PSWD = "keenonrobot"
REMOTE_PATH = "/home/peanut/boot_v1.0.3"
LOCAL_PATH = ""

def show_info(msg):
    top = tkinter.Tk()
    top.geometry("0x0+999999+0")
    tkinter.messagebox.showinfo("Info", msg)
    top.destroy

def show_warn(msg):
    top = tkinter.Tk()
    top.geometry("0x0+999999+0")
    tkinter.messagebox.showwarning("Warn", msg)
    top.destroy

def upload_file():
    try:
        #创建SSHClient 实例对象
        ssh = paramiko.SSHClient()
        # 调用方法,表示没有存储远程机器的公钥,允许访问
        ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        # 连接远程机器,地址,端口,用户名密码
        print("ssh connect")
        ssh.connect(IP, PORT, USER, PSWD, timeout=20)
        print("ssh connect over")
    except Exception as e:
        show_warn("unable to connect to port 22 on 192.168.64.20")
        ssh.close()
        sys.exit(1)

    #创建存放升级文件目录
    cmd = 'mkdir /home/peanut/boot_v1.0.3;cd /home/peanut/boot_v1.0.3;'
    print("ssh exec cmd start")
    ssh.exec_command(cmd)
    print("ssh exec cmd over")
    #上传升级文件
    scp = SCPClient(ssh.get_transport(), socket_timeout=20)
    if os.path.exists(PWD):
        for root, dirs, files in os.walk(PWD):
            for file in files:
                LOCAL_PATH = ""
                if re.search("boot", file): #用boot进行正则匹配
                    LOCAL_PATH = os.path.join(PWD, file) #加入拥有boot关键字的file文件名
                    scp.put(LOCAL_PATH, REMOTE_PATH) #scp 发送
                    print("liangji_send: ",file)
                    time.sleep(3)
                    ssh.exec_command('chmod 777 -R /home/peanut/boot_v1.0.3/*')
                elif re.search("update",file):
                    LOCAL_PATH = os.path.join(PWD, file) #加入拥有update关键字的file文件名
                    scp.put(LOCAL_PATH, REMOTE_PATH) #scp 发送
                    print("liangji_send: ",file)
                    time.sleep(3)
                    ssh.exec_command('chmod 777 -R /home/peanut/boot_v1.0.3/*')

    cmd = 'sudo /home/peanut/boot_v1.0.3/update.sh;sleep 3;rm -rf /home/peanut/boot_v1.0.3;sudo reboot;'
    print("ssh exec update_cmd start")
    ssh.exec_command(cmd)
    print("ssh exec update_cmd over")

    scp.close()
    ssh.close()

def update_ros():
    try:
        ssh_sec = paramiko.SSHClient()
        ssh_sec.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        ssh_sec.connect(IP, PORT, USER, PSWD, timeout=20)
    except Exception as e:
        show_warn("unable to connect to port 22 on 192.168.64.20")
        ssh_sec.close()
        sys.exit(1)

    session = ssh_sec.get_transport().open_session()
    session.set_combine_stderr(True)
    session.get_pty()
    #session.exec_command("sudo /home/peanut/keenon_update_ros/robotInstall.sh >> /home/peanut/keenon_update_ros/robot_install_sh.log 2>&1")
    session.exec_command("sudo /home/peanut/keenon_update_ros/robotInstall.sh")
    stdin = session.makefile('wb', -1)
    stdout = session.makefile('rb', -1)
    stdin.write(PSWD + '\n')
    stdin.flush()
    
    print(stdout.readlines())

    session.close()
    ssh_sec.close()

def query_ros():
    try:
        ssh_thi = paramiko.SSHClient()
        ssh_thi.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        ssh_thi.connect(IP, PORT, USER, PSWD, timeout=20)
    except Exception as e:
        show_warn("unable to connect to port 22 on 192.168.64.20")
        ssh_thi.close()
        sys.exit(1)

    cmd_thi = 'cat /home/peanut/keenon_update_ros/updated_ros'
    stdin, stdout, stderr = ssh_thi.exec_command(cmd_thi)
    list_thi = stdout.readlines()

    ssh_thi.close()
    return list_thi

if __name__ == '__main__':
    upload_file()
    # update_ros()

    # time.sleep(60)
    # flag = 0
    # list = query_ros()
    # list_size = len(list)
    # while True:
    #     if list_size == 1:
    #         if re.search("succeeded", list[0].strip()):
    #             show_info("ros upgrade succeeded!")
    #             break
    #     elif list_size < 1:
    #         time.sleep(60)
    #         list = query_ros()
    #         list_size = len(list)
    #         flag = flag +1
        
    #     if flag >= 4:
    #         show_warn("ros upgrade failed!")
    #         break

更新内核脚本 update.sh

#! /bin/bash

dd if=/home/peanut/boot_v1.0.3/boot.img of=/dev/mmcblk1p3 bs=4k

内核文件 boot.img

【诊断工具(底盘+蓝海雷达+lora+调度模块+科力雷达+立体视觉+乐动雷达)】

诊断工具v1.0.0文件链接

支持自动关闭ros和robot
支持蓝海雷达诊断
支持底盘诊断

【串口 自收自发 测试demo】

serial_test

【多线程 测试demo】

pthread_test

【蓝海雷达 测试demo】

lidar_test

【计时器 测试demo】

time_test

【文件修改时间 测试demo】

file_time_test

【udp client请求server发送 测试demo】
【乐动雷达 测试demo】

【镜像解包afptool】

在这里插入图片描述

或者使用RK3399 SDK的tools里面的解压工具解包

【android12 永久隐藏状态栏】

package/

From d1321e17d776c56830f0df232e2ec20132814ead Mon Sep 17 00:00:00 2001
From: liangji <liangji@keenon.com>
Date: Fri, 18 Nov 2022 16:11:30 +0800
Subject: [PATCH] feat: add checkbox to hide status bar

Signed-off-by: liangji <liangji@keenon.com>
---
 res/values-zh-rCN/strings.xml                 |  1 +
 res/values/strings.xml                        |  3 +++
 res/xml/display_settings.xml                  |  6 +++++
 src/com/android/settings/DisplaySettings.java | 39 +++++++++++++++++++++++++++
 4 files changed, 49 insertions(+)

diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml
index fe72d85..e5e5ec9 100644
--- a/res/values-zh-rCN/strings.xml
+++ b/res/values-zh-rCN/strings.xml
@@ -5599,6 +5599,7 @@
     <string name="dialog_getting_screen_info">"正在获取屏幕信息..."</string>
     <string name="dialog_update_resolution">"切换分辨率..."</string>
     <string name="dialog_wait_screen_connect">"更新信息到设备,请稍等..."</string>
+    <string name="systembar_hide_title">永久隐藏工具栏</string>
 
     <!--screenshot settings-->
     <string name="screenshot">截屏</string>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index a8f6864..e9a9e40 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -13714,4 +13714,7 @@
     <string name="dialog_getting_screen_info">getting screen info...</string>
     <string name="dialog_update_resolution">Updating resolution...</string>
     <string name="dialog_wait_screen_connect">please wait while updating info to the device...</string>
+    
+    <!--keenon liangji add for hide systembar-->
+    <string name="systembar_hide_title">Always_hide_the_status_bar</string>
 </resources>
diff --git a/res/xml/display_settings.xml b/res/xml/display_settings.xml
index 1d17f59..7a32317 100644
--- a/res/xml/display_settings.xml
+++ b/res/xml/display_settings.xml
@@ -160,5 +160,11 @@
             android:title="@string/hdmi_settings"
             settings:keywords="@string/hdmi_settings"
             android:fragment="com.android.settings.display.HdmiSettings" />
+
     </PreferenceCategory>
+
+    <CheckBoxPreference
+        android:key="systembar_hide"
+        android:title="@string/systembar_hide_title"/>
+
 </PreferenceScreen>
diff --git a/src/com/android/settings/DisplaySettings.java b/src/com/android/settings/DisplaySettings.java
index 6ce9ff5..d59c7ca 100644
--- a/src/com/android/settings/DisplaySettings.java
+++ b/src/com/android/settings/DisplaySettings.java
@@ -35,6 +35,13 @@ import com.android.settingslib.core.AbstractPreferenceController;
 import com.android.settingslib.core.lifecycle.Lifecycle;
 import com.android.settingslib.search.SearchIndexable;
 
+//keenon liangji add start
+import androidx.preference.Preference;
+import androidx.preference.CheckBoxPreference;
+import android.content.Intent;
+import android.provider.Settings;
+//keenon liangji add end
+
 import java.util.ArrayList;
 import java.util.List;
 
@@ -43,6 +50,12 @@ public class DisplaySettings extends DashboardFragment {
     private static final String TAG = "DisplaySettings";
     private static final String KET_HDMI_SETTINGS = "hdmi_settings";
 
+    //keenon liangji add start
+    private static final String KEY_SYSTEMBAR_HIDE = "systembar_hide";
+
+    private CheckBoxPreference mSystemBarHide;
+    //keenon liangji add end
+
     @Override
     public int getMetricsCategory() {
         return SettingsEnums.DISPLAY;
@@ -61,6 +74,14 @@ public class DisplaySettings extends DashboardFragment {
     @Override
     public void onCreate(Bundle icicle) {
         super.onCreate(icicle);
+        
+        //keenon liangji add start
+        mSystemBarHide = (CheckBoxPreference) findPreference(KEY_SYSTEMBAR_HIDE);
+        mSystemBarHide.setChecked(Settings.System.getInt(getContentResolver(),Settings.System.SYSTEMBAR_HIDE,
+                    0)==1);
+        //keenon liangji add end
+
+
     }
 
     @Override
@@ -97,4 +118,22 @@ public class DisplaySettings extends DashboardFragment {
                     return buildPreferenceControllers(context, null);
                 }
             };
+
+    //keenon liangji add start
+    @Override
+    public boolean onPreferenceTreeClick(Preference preference){
+        if(preference == mSystemBarHide)
+        {
+            Settings.System.putInt(getContentResolver(), Settings.System.SYSTEMBAR_HIDE,
+                    mSystemBarHide.isChecked() ? 1 : 0);
+            Intent i = new Intent("com.keenon.changeBarHideStatus");
+            getActivity().sendBroadcast(i);
+        }
+        return super.onPreferenceTreeClick(preference);
+    }
+    //keenon liangji add end
+
+
+
+
 }
-- 
2.7.4

framework/base/

https://blog.csdn.net/ljt2724960661/article/details/82779519
https://blog.csdn.net/Bill_xiao/article/details/108244267

From e546af745cc5f189594294fb32e802709378d776 Mon Sep 17 00:00:00 2001
From: liangji <liangji@keenon.com>
Date: Mon, 21 Nov 2022 17:53:47 +0800
Subject: [PATCH] feat: support always hide status bar

Signed-off-by: liangji <liangji@keenon.com>
---
 core/java/android/provider/Settings.java           |  8 ++++
 packages/SettingsProvider/res/values/defaults.xml  |  3 ++
 .../android/providers/settings/DatabaseHelper.java |  4 ++
 .../systemui/statusbar/phone/StatusBar.java        | 55 ++++++++++++++++++++++
 .../window/StatusBarWindowController.java          | 12 +++++
 5 files changed, 82 insertions(+)

diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 695e407..1d9e0a4 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -4900,6 +4900,14 @@ public final class Settings {
         public static final String SCREENSHOT_BUTTON_SHOW = "screenshot_button_show";
 
         /**
+         * keenon liangji: hide system bar
+         *
+         * @hide
+         */
+        public static final String SYSTEMBAR_HIDE="systembar_hide";
+
+
+        /**
          * Whether the phone vibrates when it is ringing due to an incoming call. This will
          * be used by Phone and Setting apps; it shouldn't affect other apps.
          * The value is boolean (1 or 0).
diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index aba8038..e2e7d8d 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -265,4 +265,7 @@
     <!-- should show the screenshot button default -->
     <integer name="def_screenshot_button_show">0</integer>
 
+    <!-- keenon liangji hide systembar -->
+    <bool name="def_systembar_hide">false</bool>
+
 </resources>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index 26d8b0d..2ba2445 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -2280,6 +2280,10 @@ class DatabaseHelper extends SQLiteOpenHelper {
             loadIntegerSetting(stmt, Settings.System.SCREENSHOT_BUTTON_SHOW,
                     R.integer.def_screenshot_button_show);
 
+            //keenon liangji add start
+            loadIntegerSetting(stmt, Settings.System.SYSTEMBAR_HIDE,
+                    R.bool.def_systembar_hide);
+            //keenon liangji add end
             /*
              * IMPORTANT: Do not add any more upgrade steps here as the global,
              * secure, and system settings are no longer stored in a database
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index a6fb317..b471d07 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -1025,6 +1025,10 @@ public class StatusBar extends SystemUI implements
 
         // end old BaseStatusBar.start().
 
+        //keenon liangji add start
+        changeBarHideStatus();
+        //keenon liangji add end
+
         // Lastly, call to the icon policy to install/update all the icons.
         mIconPolicy.init();
 
@@ -1406,6 +1410,9 @@ public class StatusBar extends SystemUI implements
         filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
         filter.addAction(Intent.ACTION_SCREEN_OFF);
         filter.addAction(DevicePolicyManager.ACTION_SHOW_DEVICE_MONITORING_DIALOG);
+        //keenon liangji add start
+        filter.addAction("com.keenon.changeBarHideStatus");
+        //keenon liangji add end
         mBroadcastDispatcher.registerReceiver(mBroadcastReceiver, filter, null, UserHandle.ALL);
     }
 
@@ -2140,6 +2147,7 @@ public class StatusBar extends SystemUI implements
                     event.getAction() == MotionEvent.ACTION_CANCEL;
             setInteracting(StatusBarManager.WINDOW_STATUS_BAR, !upOrCancel || mExpandedVisible);
         }
+
     }
 
     boolean isSameStatusBarState(int state) {
@@ -2667,6 +2675,10 @@ public class StatusBar extends SystemUI implements
             else if (DevicePolicyManager.ACTION_SHOW_DEVICE_MONITORING_DIALOG.equals(action)) {
                 mQSPanelController.showDeviceMonitoringDialog();
             }
+            else if("com.keenon.changeBarHideStatus".equals(action))
+            {
+                changeBarHideStatus();
+            }
             Trace.endSection();
         }
     };
@@ -3898,6 +3910,49 @@ public class StatusBar extends SystemUI implements
         KeyboardShortcuts.dismiss();
     }
 
+    //keenon liangji add start
+    private boolean mBarIsAdd = true;
+
+    private void removeBar(){
+        Log.d("Keenon_liangji","removeBar");
+
+        mStatusBarWindowController.hideStatusBar();
+        mNavigationBarController.onDisplayRemoved(mDisplayId);
+
+        mBarIsAdd = false;
+    }
+
+    private void restoreBar(){
+        Log.d("Keenon_liangji","restoreBar");
+        if (mBarIsAdd==true)
+            return;
+
+        ViewGroup tempStatusBar = mStatusBarWindowController.getStatusBarWindowView();
+        if(tempStatusBar != null){
+            tempStatusBar.setVisibility(View.VISIBLE);
+            requestNotificationUpdate("StatusBar state changed");
+            checkBarModes();
+        }
+
+        createNavigationBar(null);
+        mBarIsAdd = true;
+    }
+
+    private void changeBarHideStatus()
+    {
+        Log.d("Keenon_liangji","changeBarHideStatus");
+        boolean hide_systembar = Settings.System.getInt(mContext.getContentResolver(),Settings.System.SYSTEMBAR_HIDE,0)==1;
+        if(hide_systembar){
+            removeBar();
+            //Settings.System.putInt(mContext.getContentResolver(),Settings.System.SYSTEMBAR_HIDE,1);
+        }
+        else {
+            restoreBar();
+        }
+    }
+
+    //keenon liangji add end
+
     /**
      * Dismiss the keyguard then execute an action.
      *
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowController.java
index 85a6cd2..e5af7e4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowController.java
@@ -119,6 +119,18 @@ public class StatusBarWindowController {
         if (DEBUG) Log.v(TAG, "defineSlots");
     }
 
+    //keenon liangji add start
+    public void hideStatusBar() {
+        mStatusBarWindowView.setVisibility(View.GONE);
+        if (DEBUG) Log.v(TAG, "defineSlots");
+    }
+
+    public ViewGroup getStatusBarWindowView(){
+        return mStatusBarWindowView;
+    }
+
+    //keenon liangji add end
+
     /**
      * Adds the status bar view to the window manager.
      */
-- 
2.7.4


总结:
java中每个package表示一个命名空间。
import后面的一长串,只有最后一个表示类名,前面的表示包名。

【Android6 system.img定制化修改开机动画】

  1. 获取整机镜像文件
  2. 利用RKTools里面的解包工具,将其解包(不能打包,因为会出错)
  3. 将解包后的system.img传到ubuntu主机,挂载
  4. 新建一个文件夹,将system.img挂载后的目录里面的所有的内容cp -a 到新的文件夹(因为原挂载文件夹无法修改)
  5. 将新的文件夹里面的media/bootanimation.zip替换成我们自己的bootanimation.zip。
  6. 将该新的文件夹压缩传回来,这个是我们新的system.img
  7. 使用从mkupdateimg.sh脚本中抠出来的打包新的安卓system.img方法进行打包(liangji_mksystem.sh),会在liangji_system/下生成新的system.img。
  8. kernel/中可以将logo.bmp(8位),logo_kernel.bmp(24位)替换为自己的图片。bmp图片转位数可以用
https://online-converting.com/image/convert2bmp/#
  1. 将新的resource.img和新的system.img 替换rockdev里面, 同时将RKTools解包工具里面的其他需要的部分替换到rockdev/里面。
  2. ./build_keenon -u 直接打包生成新的整机镜像。

liangji_mksystem.sh

#! /bin/bash

source build/envsetup.sh
lunch 13

IMAGE_PATH=liangji_system

system_size=`ls -l $OUT/system.img | awk '{print $5;}'`
[ $system_size -gt "0" ] || { echo "Please make first!!!" && exit 1; }
MAKE_EXT4FS_ARGS=" -L system -S $OUT/root/file_contexts -a system $IMAGE_PATH/system.img liangji_system/system_new"
ok=0
while [ "$ok" = "0" ]; do
	make_ext4fs -l $system_size $MAKE_EXT4FS_ARGS >/dev/null 2>&1 &&
	tune2fs -c -1 -i 0 $IMAGE_PATH/system.img >/dev/null 2>&1 &&
	ok=1 || system_size=$(($system_size + 5242880))
done
e2fsck -fyD $IMAGE_PATH/system.img >/dev/null 2>&1 || true


【iperf 测试工控机和ui板网络传输】

iperf工具下载(x86ubuntu + android6)

  1. 丢包延时测试,ping
  2. iperf 测试 tcp 吞吐量(iperf默认选择tcp测试)
#客户端
iperf -c 192.168.64.10 -t 300 -i 1 -P 4

#服务器
iperf -s -i 1
  1. iperf 测试udp 抖动测试
#客户端
iperf -c 192.168.64.10 -u -t 100 -b 100m

#服务器
iperf -s -i 1 -u

【tcpdump 抓包测试】

tcpdump -i br0 -w save.pcap

【RK3288 android6 lvds+edp双屏异显解析】

https://www.litreily.top/2021/06/18/dual-lcd/

【RK3288 android10 lvds+edp 双屏异显】

  1. 修改dts配置,(先能够实现单个屏幕点亮,然后是两个屏幕)
  2. 修改mk.sh
  3. 增加build.prop配置

dts修改
rk3288-evb-android-act8846-dual-screen-keenon.dtsi修改

/*
 * Copyright (c) 2018 Fuzhou Rockchip Electronics Co., Ltd
 *
 * SPDX-License-Identifier: (GPL-2.0+ OR MIT)
 */

/dts-v1/;
#include "rk3288-evb-android-act8846-keenon.dtsi"

/ {
	lvds_panel {
		status = "okay";
		compatible = "simple-panel";
		backlight = <&backlight>;
		//enable-gpios = <&gpio7 RK_PA4 GPIO_ACTIVE_HIGH>;
		pinctrl-0 = <&lcd_cs>;
		power-supply = <&vcc_lcd>;
		//prepare-delay-ms = <20>;
		//enable-delay-ms = <20>;
		/*
		 * MEDIA_BUS_FMT_RGB666_1X7X3_SPWG  - "jeida-18"
		 * MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA - "jeida-24"
		 * MEDIA_BUS_FMT_RGB888_1X7X4_SPWG  - "vesa-24"
		 */
		bus-format = <MEDIA_BUS_FMT_RGB888_1X7X4_SPWG>;

		display_timings:display-timings {
			native-mode = <&timing0>;

			timing0: timing0 {
			clock-frequency = <52000000>;
			hactive = <1024>;
			vactive = <600>;
			hfront-porch = <160>;
			hsync-len = <10>;
			hback-porch = <150>;
			vfront-porch = <12>;
			vsync-len = <1>;
			vback-porch = <22>;
			hsync-active = <0>;
			vsync-active = <0>;
			de-active = <0>;
			pixelclk-active = <1>;
			};
			// 10.1" 1280x800 LVDS panel
			timing4: timing4 {
			//screen-type = <SCREEN_LVDS>;
			//lvds-format = <LVDS_8BIT_1>;
			//out-face    = <OUT_D888_P666>;
			//color-mode = <COLOR_RGB>;
			clock-frequency = <65000000>;
			hactive = <1280>;
			vactive = <800>;
			hback-porch = <100>;
			hfront-porch = <120>;
			vback-porch = <10>;
			vfront-porch = <10>;
			hsync-len = <3>;
			vsync-len = <3>;
			hsync-active = <0>;
			vsync-active = <0>;
			de-active = <0>;
			pixelclk-active = <1>;
			swap-rb = <0>;
			swap-rg = <0>;
			swap-gb = <0>;
			};
		};
		port {
			panel_in_lvds: endpoint {
				remote-endpoint = <&lvds_out_panel>;
			};
		};
	};

edp_panel {
	status = "okay";
	compatible ="simple-panel";
	backlight = <&backlight>;
	enable-gpios = <&gpio7 RK_PA4 GPIO_ACTIVE_HIGH>;
	//prepare-delay-ms = <120>;
    power-supply = <&vcc_lcd>;
	pinctrl-0 = <&lcd_cs>;
        //delay,prepare = <120>;
        disp_timings: display-timings {
                native-mode = <&timing1>;
                //liangji add 1
			    timing2: timing2 {
			    clock-frequency = <138700000>;
			    hactive = <1920>;
			    vactive = <1080>;
			    hfront-porch = <120>;
			    hsync-len = <5>;
			    hback-porch = <35>;
			    vfront-porch = <20>;
			    vsync-len = <2>;
			    vback-porch = <10>;
			    hsync-active = <0>;
			    vsync-active = <0>;
			    de-active = <0>;
			    pixelclk-active = <1>;
			    };

                //11.6 1920x1080 edp panel W3
                timing1: timing1 {
			    clock-frequency = <152600000>;
			    hactive = <1920>;
			    vactive = <1080>;
			    hfront-porch = <120>;
			    hsync-len = <160>;
			    hback-porch = <30>;
			    vfront-porch = <28>;
			    vsync-len = <24>;
			    vback-porch = <8>;
			    hsync-active = <0>;
			    vsync-active = <0>;
			    de-active = <0>;
			    pixelclk-active = <1>;
			    };
        };
		port {
			panel_in_edp: endpoint {
				remote-endpoint = <&edp_out_panel>;
			};
		};
};


};

&lvds {
	status = "okay";
	ports {
		port@1 {
			reg = <1>;

			lvds_out_panel: endpoint {
				remote-endpoint = <&panel_in_lvds>;
			};
		};
	};
};

&video_phy {
	status = "okay";
};

&lvds_in_vopb {
	status = "disabled";
};

&lvds_in_vopl {
	status = "okay";
};

&vopl_out_lvds {
    status = "okay";
};

&vopb_out_lvds {
    status = "disabled";
};

&route_lvds {
	connect = <&vopl_out_lvds>;
	status = "okay";
};

&goodix_ts {
	status = "okay";
};
///
&edp {
	force-hpd;
	status = "okay";
	ports {
		port@1 {
			reg = <1>;

			edp_out_panel: endpoint {
				remote-endpoint = <&panel_in_edp>;
			};
		};
	};
};

&edp_phy {
	status = "okay";
};

&edp_in_vopb {
	//status = "disabled";
    status = "okay";
};

&edp_in_vopl {
	//status = "okay";
	status = "disabled";
};

&vopl_out_edp {
    status = "disabled";
};

&vopb_out_edp {
    status = "okay";
};

&route_edp {
	//connect = <&vopl_out_edp>;
	connect = <&vopb_out_edp>;
	status = "disabled";
};

&ilitek {
	status = "okay";
};

修改mk.sh
指定自己的dts文件

#!/bin/bash

echo "Start build kernel"

source ../build/envsetup.sh
KERNEL_ARCH=arm
KERNEL_DEFCONFIG="rockchip_defconfig android-10.config"
KERNEL_DTS="rk3288-evb-android-act8846-dual-screen-keenon"
#KERNEL_DTS="rk3288-evb-android-act8846-edp-keenon"

[ $# -eq 1 ] && {
    if [ $1 = "lvds7" ] || [ $1 = "lvds" ]; then
        KERNEL_DTS="rk3288-evb-android-act8846-lvds7-keenon"
    elif [ $1 = "lvds101" ]; then
        KERNEL_DTS="rk3288-evb-android-act8846-lvds101-keenon"
    fi
}

echo "KERNEL_DTS:"${KERNEL_DTS}

BUILD_JOBS=16
make ARCH=$KERNEL_ARCH $KERNEL_DEFCONFIG
make ARCH=$KERNEL_ARCH BOOT_IMG=../rockdev/Image-rk3288_Android10/boot.img  $KERNEL_DTS.img -j$BUILD_JOBS

if [ $? -eq 0 ]; then
    echo "Build kernel ok!"
else
    echo "Build kernel failed!"
    exit 1
fi

(临时)修改build.prop配置

https://blog.csdn.net/feiz3020/article/details/108767984?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522167098089716800186557478%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=167098089716800186557478&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2allfirst_rank_ecpm_v1~rank_v31_ecpm-2-108767984-null-null.142v68control,201v4add_ask,213v2t3_esquery_v2&utm_term=%E4%BF%AE%E6%94%B9build.prop%E9%87%8D%E5%90%AF&spm=1018.2226.3001.4187

增加两条
vendor.hwc.device.primary=LVDS
vendor.hwc.device.extend=eDP

(永久)修改build.prop配置

From eb72b8bba0e41fcf4426c31292da40365e9c6340 Mon Sep 17 00:00:00 2001
From: liangji <liangji@keenon.com>
Date: Wed, 14 Dec 2022 17:28:02 +0800
Subject: [PATCH] feat: enable t5pro dual-screen

Change-Id: I2ec93d7e119cf720942f75f36847667f8b6ffe44
Signed-off-by: liangji <liangji@keenon.com>
---
 device.mk | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/device.mk b/device.mk
index f4a8e28..48e3ae0 100755
--- a/device.mk
+++ b/device.mk
@@ -170,4 +170,6 @@ PRODUCT_PROPERTY_OVERRIDES += \
                 ro.com.android.mobiledata=true \
                 ro.telephony.default_network=9 \
                 persist.logd.size=4194304 \
-                ro.rk.displayd.enable=false
+                ro.rk.displayd.enable=false \
+                vendor.hwc.device.primary=LVDS \
+                vendor.hwc.device.extend=eDP \
-- 
2.7.4

【RK3399 android10 新增分区(nanopc)】

  1. 了解安卓各个分区,镜像的关系,文件夹
  • 分区是指的磁盘上的分区,由parameter.txt中的地址指出。

  • 分区所在的磁盘空间上烧录镜像文件。
    在这里插入图片描述

  • 每个分区上的镜像文件,都有其文件系统,就是格式。由他来确定如何从磁盘的存储块来映射操作具体的文件。

  • 开机后,镜像所在的分区被挂载到根文件系统,让用户通过访问文件夹的方式访问分区。

  • system.img,包括了sdk中的frameworks/,hardware/,device/等文件夹。

  • 根目录下的/system,是sdk中out/目录下的/system,并不是system.img

  1. 了解安卓启动加载分区流程
  • bootloader分区—>boot分区—>init(system分区)
  • boot分区加载分为加载kernel,准备挂载文件系统
  • init(system分区)加载init.rc,完成系统加载,包括system_service进程
  1. 新增分区oem

system/core/rootdir/init.rc开机创建文件夹oem,并给权限。用于挂载

diff --git a/system/core/rootdir/init.rc b/system/core/rootdir/init.rc
index 0fa9feb..c125971 100644
--- a/system/core/rootdir/init.rc
+++ b/system/core/rootdir/init.rc
@@ -215,6 +215,13 @@ on init
     chown system system /dev/cpuset/top-app/tasks
     chown system system /dev/cpuset/restricted/tasks

+    #keenon liangji add
+
+    chown system system /oem
+    chmod 0777 /oem
+
+    #keenon liangji add end
+
     # set system-background to 0775 so SurfaceFlinger can touch it
     chmod 0775 /dev/cpuset/system-background

device/rockchip/rk3399/nanopc-t4/fstab.in
device/rockchip/rk3399/fstab.rk30board
增加挂载信息,把块设备中的oem分区挂载到/oem目录

diff --git a/device/rockchip/rk3399/nanopc-t4/fstab.in b/device/rockchip/rk3399/nanopc-t4/fstab.in
index 866c23a..f03797f 100644
--- a/device/rockchip/rk3399/nanopc-t4/fstab.in
+++ b/device/rockchip/rk3399/nanopc-t4/fstab.in
@@ -12,6 +12,10 @@ ${_block_prefix}product         /product        ext4      ro,barrier=1 ${_flags}
 /dev/block/by-name/cache        /cache          ext4      noatime,nodiratime,nosuid,nodev,noauto_da_alloc,discard wait,check
 /dev/block/by-name/misc         /misc           emmc      defaults     defaults

+#keenon liangji add
+/dev/block/by-name/oem        /oem          ext4      rw,noatime,nodiratime,nosuid,nodev,noauto_da_alloc,discard wait,check
+#keenon liangji add end
+
 /dev/block/zram0                none            swap      defaults     zramsize=40%

 /devices/platform/*usb*         auto            vfat      defaults     voldmanaged=usb:auto




diff --git a/device/rockchip/rk3399/fstab.rk30board b/device/rockchip/rk3399/fstab.rk30board
index 30409ed..b11510a 100644
--- a/device/rockchip/rk3399/fstab.rk30board
+++ b/device/rockchip/rk3399/fstab.rk30board
@@ -4,7 +4,7 @@
 # specify MF_CHECK, and must come before any filesystems that do specify MF_CHECK

 /dev/block/by-name/system         /                   ext4      ro,barrier=1               wait,avb
-/dev/block/by-name/oem            /oem                ext4      ro,noatime,nodiratime,noauto_da_alloc                                  wait,check
+/dev/block/by-name/oem            /oem                ext4      rw,noatime,nodiratime,nosuid,nodev,noauto_da_alloc,discard                                  wait,check
 /dev/block/by-name/cache          /cache              ext4      noatime,nodiratime,nosuid,nodev,noauto_da_alloc,discard                wait,check
 /dev/block/by-name/metadata       /mnt/vendor/metadata           ext4      noatime,nodiratime,nosuid,nodev,noauto_da_alloc,discard                wait
 /dev/block/by-name/misc         /misc               emmc      defaults     defaults

device/rockchip/rk3399/nanopc-t4/parameter.txt修改oem分区的物理地址和大小

diff --git a/device/rockchip/rk3399/nanopc-t4/parameter.txt b/device/rockchip/rk3399/nanopc-t4/parameter.txt
index a43a62f..406c238 100644
--- a/device/rockchip/rk3399/nanopc-t4/parameter.txt
+++ b/device/rockchip/rk3399/nanopc-t4/parameter.txt
@@ -8,4 +8,4 @@ MACHINE: 3399
 CHECK_MASK: 0x80
 PWR_HLD: 0,0,A,0,1
 TYPE: GPT
-CMDLINE: mtdparts=rk29xxnand:0x00002000@0x00004000(uboot),0x00002000@0x00006000(trust),0x00002000@0x00008000(misc),0x00002000@0x0000a000(dtb),0x00002000@0x0000c000(dtbo),0x00002000@0x0000e000(vbmeta),0x00010000@0x00010000(boot),0x00030000@0x00020000(recovery),0x00038000@0x00050000(backup),0x00002000@0x00088000(security),0x000c0000@0x0008a000(cache),0x00008000@0x0014a000(metadata),0x00002000@0x00152000(frp),0x00614000@0x00154000(super),-@0x00768000(userdata:grow)
+CMDLINE: mtdparts=rk29xxnand:0x00002000@0x00004000(uboot),0x00002000@0x00006000(trust),0x00002000@0x00008000(misc),0x00002000@0x0000a000(dtb),0x00002000@0x0000c000(dtbo),0x00002000@0x0000e000(vbmeta),0x00010000@0x00010000(boot),0x00030000@0x00020000(recovery),0x00038000@0x00050000(backup),0x00002000@0x00088000(security),0x000c0000@0x0008a000(cache),0x00008000@0x0014a000(metadata),0x00002000@0x00152000(frp),0x00614000@0x00154000(super),0x01000000@0x00768000(oem),-@0x01768000(userdata:grow)

device/rockchip/rk3399/nanopc-t4/BoardConfig.mk ,增加oem分区大小,并关闭AB分区选项

diff --git a/device/rockchip/rk3399/nanopc-t4/BoardConfig.mk b/device/rockchip/rk3399/nanopc-t4/BoardConfig.mk
index a0f1420..f253159 100644
--- a/device/rockchip/rk3399/nanopc-t4/BoardConfig.mk
+++ b/device/rockchip/rk3399/nanopc-t4/BoardConfig.mk
@@ -24,7 +24,7 @@ BOARD_INCLUDE_DTB_IN_BOOTIMG :=
 endif

 # AB image definition
-BOARD_USES_AB_IMAGE := true
+BOARD_USES_AB_IMAGE := false

 ifeq ($(strip $(BOARD_USES_AB_IMAGE)), true)
     AB_OTA_UPDATER := true
@@ -42,3 +42,7 @@ endif
 ifeq ($(BOARD_HAS_GPS),true)
 DEVICE_MANIFEST_FILE += device/rockchip/rk3399/nanopc-t4/mgnss.xml
 endif
+
+#keenon liangji add
+BOARD_OEM_SIZE := 8589934592
+#keenon liangji add end

device/rockchip/common/BoardConfig.mk 增加自动读取分区大小

diff --git a/device/rockchip/common/BoardConfig.mk b/device/rockchip/common/BoardConfig.mk
index b5dc59d..acf2e40 100644
--- a/device/rockchip/common/BoardConfig.mk
+++ b/device/rockchip/common/BoardConfig.mk
@@ -123,6 +123,7 @@ ifeq ($(strip $(USE_DEFAULT_PARAMETER)), true)
   BOARD_BOOTIMAGE_PARTITION_SIZE := $(shell python device/rockchip/common/get_partition_size.py $(RK_PARAMETER) boot)
   BOARD_DTBOIMG_PARTITION_SIZE := $(shell python device/rockchip/common/get_partition_size.py $(RK_PARAMETER) dtbo)
   BOARD_RECOVERYIMAGE_PARTITION_SIZE := $(shell python device/rockchip/common/get_partition_size.py $(RK_PARAMETER) recovery)
+  BOARD_OEM_SIZE := $(shell python device/rockchip/common/get_partition_size.py $(RK_PARAMETER) oem)

   #$(info Calculated BOARD_SYSTEMIMAGE_PARTITION_SIZE=$(BOARD_SYSTEMIMAGE_PARTITION_SIZE) use $(RK_PARAMETER))
 else

device/rockchip/common/build/rockchip/RebuildFstab.mk 将分区大小加入分区大小队列

diff --git a/device/rockchip/common/build/rockchip/RebuildFstab.mk b/device/rockchip/common/build/rockchip/RebuildFstab.mk
index bda43d9..e1207b9 100644
--- a/device/rockchip/common/build/rockchip/RebuildFstab.mk
+++ b/device/rockchip/common/build/rockchip/RebuildFstab.mk
@@ -55,4 +55,10 @@ else
 ALL_DEFAULT_INSTALLED_MODULES += $(INSTALLED_RK_VENDOR_FSTAB) $(INSTALLED_RK_RAMDISK_FSTAB)
 endif

+#keenon liangji add
+ifeq ($(strip $(BOARD_OEM_SIZE)), )
+       partition_list := $(partition_list),$(BOARD_OEM_SIZE)
+endif
+#keenon liangji add end
+
 endif

RKTools/linux/Linux_Pack_Firmware/rockdev/package-file,打包update.img的时候将oem也打包

diff --git a/RKTools/linux/Linux_Pack_Firmware/rockdev/package-file b/RKTools/linux/Linux_Pack_Firmware/rockdev/package-file
index eebcac0..3ff1786 100755
--- a/RKTools/linux/Linux_Pack_Firmware/rockdev/package-file
+++ b/RKTools/linux/Linux_Pack_Firmware/rockdev/package-file
@@ -11,6 +11,7 @@ boot        Image/boot.img
 dtbo        Image/dtbo.img
 vbmeta      Image/vbmeta.img
 recovery    Image/recovery.img
+oem      Image/oem.img
 super      Image/super.img
 # Ҫд<C8><EB>backup<B7><D6><C7><F8><B5><C4><CE>ļ<FE><BE><CD><CA><C7><D7><D4><C9>▒update.img<A3><A9>

build/make/core/definitions.mk,取消无ab分区的报错

diff --git a/build/make/core/definitions.mk b/build/make/core/definitions.mk
index 59aeb16..ada2a6c 100644
--- a/build/make/core/definitions.mk
+++ b/build/make/core/definitions.mk
@@ -2768,10 +2768,10 @@ $(if $(2), \
   total=$$(( $$( echo "$$size" ) )); \
   printname=$$(echo -n "$(1)" | tr " " +); \
   maxsize=$$(($(2))); \
-  if [ "$$total" -gt "$$maxsize" ]; then \
-    echo "error: $$printname too large ($$total > $$maxsize)"; \
-    false; \
-  elif [ "$$total" -gt $$((maxsize - 32768)) ]; then \
+#  if [ "$$total" -gt "$$maxsize" ]; then \
+#    echo "error: $$printname too large ($$total > $$maxsize)"; \
+#    false; \
+  if [ "$$total" -gt $$((maxsize - 32768)) ]; then \
     echo "WARNING: $$printname approaching size limit ($$total now; limit $$maxsize)"; \
   fi \
  , \

build-nanopc-t4.sh 修改09无法参与运算的报错

diff --git a/device/rockchip/rk3399/build-nanopc-t4.sh b/device/rockchip/rk3399/build-nanopc-t4.sh
index 71f44c7..2574b95 100755
--- a/device/rockchip/rk3399/build-nanopc-t4.sh
+++ b/device/rockchip/rk3399/build-nanopc-t4.sh
@@ -142,7 +142,7 @@ function build_kernel() {
 }

 function build_android() {
-       true ${BUILD_NUMBER:=$(date +"6%y%m%d")$(($(date +"%H")/4))}
+       true ${BUILD_NUMBER:=$(date +"6%y%m%d")$(($(date +"%-H")/4))}
        export BUILD_NUMBER

        source build/envsetup.sh

mkimage.sh 增加编译oem.img

#增加
#keenon liangji add
 101 function make_oem_img() {
 102     echo "create oem.img..."
 103     [ -d $OUT/oem ] && \
 104         python build/make/tools/releasetools/build_image.py \
 105             $OUT/oem \
 106             $OUT/obj/PACKAGING/odm_intermediates/odm_image_info.txt \
 107             $OUT/odm.img \
 108             $OUT/system
 109     python device/rockchip/common/sparse_tool.py $OUT/odm.img
 110     mv $OUT/odm.img.out $OUT/oem.img
 111     cp -f $OUT/oem.img $IMAGE_PATH/oem.img
 112     echo "done."
 113 }
 114 #keenon liangji add end



 345 make_dtbo_img
 346 make_boot_img
 347 make_recovery_img
 348 make_vbmeta_img
 349 + make_oem_img
 350 + make_system_img
 351 + make_vendor_img
 352 + make_odm_img
 353
 354
 355 if [ "$PRODUCT_USE_DYNAMIC_PARTITIONS" = "true" ]; then
 356     copy_super_img
 357 else
 358     make_system_img
 359     make_vendor_img
 360     make_odm_img
 361 fi
 362

/out/target/product/nanopc-t4/下新建oem目录,里面是oem空间要有的东西

烧录后

df -h 查看/oem分区的具体的块设备名称,此时的oem分区大小还是镜像的大小

然后用 resize2fs来扩容/oem分区

【RK3399 android10 支持spi功能 (nanopc t4)】

https://www.bilibili.com/read/cv9360756?spm_id_from=333.999.0.0
https://www.bilibili.com/read/cv9360813?spm_id_from=333.999.0.0

1.内核设备树,由于uart4和spi1复用,要先关闭uart4,然后使能spi1
rk3399-nanopc-common.dtsi
编译后在/dev下能够找到spidev1.0的虚拟设备映射

2.从android6里拿来的spi自测程序,移植过来

From 25b862671036bd4cb9194bff9aba952b88073473 Mon Sep 17 00:00:00 2001
From: liangji <liangji@keenon.com>
Date: Tue, 3 Jan 2023 17:22:54 +0800
Subject: [PATCH] feat: disabled uart4 and enable spi1

Signed-off-by: liangji <liangji@keenon.com>
---
 kernel/Documentation/spi/Android.mk                |  16 ++
 kernel/Documentation/spi/Makefile                  |   9 +
 kernel/Documentation/spi/spidev_test.c             | 210 +++++++++++++++++++++
 .../boot/dts/rockchip/rk3399-nanopi4-common.dtsi   |   4 +-
 4 files changed, 237 insertions(+), 2 deletions(-)
 create mode 100644 kernel/Documentation/spi/Android.mk
 create mode 100644 kernel/Documentation/spi/Makefile
 create mode 100644 kernel/Documentation/spi/spidev_test.c

diff --git a/kernel/Documentation/spi/Android.mk b/kernel/Documentation/spi/Android.mk
new file mode 100644
index 0000000..293c2ec
--- /dev/null
+++ b/kernel/Documentation/spi/Android.mk
@@ -0,0 +1,16 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES += spidev_test.c
+
+LOCAL_MODULE := spidev_test
+
+LOCAL_CFLAGS += -Wno-unused-parameter
+
+LOCAL_LDFLAGS += -L$(LOCAL_PATH)
+
+LOCAL_LDLIBS := -llog
+
+include $(BUILD_EXECUTABLE)
+
diff --git a/kernel/Documentation/spi/Makefile b/kernel/Documentation/spi/Makefile
new file mode 100644
index 0000000..26e2e65
--- /dev/null
+++ b/kernel/Documentation/spi/Makefile
@@ -0,0 +1,9 @@
+# kbuild trick to avoid linker error. Can be omitted if a module is built.
+
+# List of programs to build
+hostprogs-y := spidev_test
+
+# Tell kbuild to always build the programs
+always := $(hostprogs-y)
+
+HOSTCFLAGS_spidev_test.o += -I$(objtree)/usr/include
diff --git a/kernel/Documentation/spi/spidev_test.c b/kernel/Documentation/spi/spidev_test.c
new file mode 100644
index 0000000..16feda9
--- /dev/null
+++ b/kernel/Documentation/spi/spidev_test.c
@@ -0,0 +1,210 @@
+/*
+ * SPI testing utility (using spidev driver)
+ *
+ * Copyright (c) 2007  MontaVista Software, Inc.
+ * Copyright (c) 2007  Anton Vorontsov <avorontsov@ru.mvista.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License.
+ *
+ * Cross-compile with cross-gcc -I/path/to/cross-kernel/include
+ */
+
+#include <stdint.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <linux/types.h>
+#include <linux/spi/spidev.h>
+
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
+
+static void pabort(const char *s)
+{
+	perror(s);
+	abort();
+}
+
+static const char *device = "/dev/spidev1.1";
+static uint8_t mode;
+static uint8_t bits = 8;
+static uint32_t speed = 500000;
+static uint16_t delay;
+
+static void transfer(int fd)
+{
+	int ret;
+	uint8_t tx[] = {
+		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+		0x40, 0x00, 0x00, 0x00, 0x00, 0x95,
+		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+		0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+		0xDE, 0xAD, 0xBE, 0xEF, 0xBA, 0xAD,
+		0xF0, 0x0D,
+	};
+	uint8_t rx[ARRAY_SIZE(tx)] = {0, };
+	struct spi_ioc_transfer tr = {
+		.tx_buf = (unsigned long)tx,
+		.rx_buf = (unsigned long)rx,
+		.len = ARRAY_SIZE(tx),
+		.delay_usecs = delay,
+		.speed_hz = speed,
+		.bits_per_word = bits,
+	};
+
+	ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
+	if (ret < 1)
+		pabort("can't send spi message");
+
+	for (ret = 0; ret < ARRAY_SIZE(tx); ret++) {
+		if (!(ret % 6))
+			puts("");
+		printf("%.2X ", rx[ret]);
+	}
+	puts("");
+}
+
+static void print_usage(const char *prog)
+{
+	printf("Usage: %s [-DsbdlHOLC3]\n", prog);
+	puts("  -D --device   device to use (default /dev/spidev1.1)\n"
+	     "  -s --speed    max speed (Hz)\n"
+	     "  -d --delay    delay (usec)\n"
+	     "  -b --bpw      bits per word \n"
+	     "  -l --loop     loopback\n"
+	     "  -H --cpha     clock phase\n"
+	     "  -O --cpol     clock polarity\n"
+	     "  -L --lsb      least significant bit first\n"
+	     "  -C --cs-high  chip select active high\n"
+	     "  -3 --3wire    SI/SO signals shared\n");
+	exit(1);
+}
+
+static void parse_opts(int argc, char *argv[])
+{
+	while (1) {
+		static const struct option lopts[] = {
+			{ "device",  1, 0, 'D' },
+			{ "speed",   1, 0, 's' },
+			{ "delay",   1, 0, 'd' },
+			{ "bpw",     1, 0, 'b' },
+			{ "loop",    0, 0, 'l' },
+			{ "cpha",    0, 0, 'H' },
+			{ "cpol",    0, 0, 'O' },
+			{ "lsb",     0, 0, 'L' },
+			{ "cs-high", 0, 0, 'C' },
+			{ "3wire",   0, 0, '3' },
+			{ "no-cs",   0, 0, 'N' },
+			{ "ready",   0, 0, 'R' },
+			{ NULL, 0, 0, 0 },
+		};
+		int c;
+
+		c = getopt_long(argc, argv, "D:s:d:b:lHOLC3NR", lopts, NULL);
+
+		if (c == -1)
+			break;
+
+		switch (c) {
+		case 'D':
+			device = optarg;
+			break;
+		case 's':
+			speed = atoi(optarg);
+			break;
+		case 'd':
+			delay = atoi(optarg);
+			break;
+		case 'b':
+			bits = atoi(optarg);
+			break;
+		case 'l':
+			mode |= SPI_LOOP;
+			break;
+		case 'H':
+			mode |= SPI_CPHA;
+			break;
+		case 'O':
+			mode |= SPI_CPOL;
+			break;
+		case 'L':
+			mode |= SPI_LSB_FIRST;
+			break;
+		case 'C':
+			mode |= SPI_CS_HIGH;
+			break;
+		case '3':
+			mode |= SPI_3WIRE;
+			break;
+		case 'N':
+			mode |= SPI_NO_CS;
+			break;
+		case 'R':
+			mode |= SPI_READY;
+			break;
+		default:
+			print_usage(argv[0]);
+			break;
+		}
+	}
+}
+
+int main(int argc, char *argv[])
+{
+	int ret = 0;
+	int fd;
+
+	parse_opts(argc, argv);
+
+	fd = open(device, O_RDWR);
+	if (fd < 0)
+		pabort("can't open device");
+
+	/*
+	 * spi mode
+	 */
+	ret = ioctl(fd, SPI_IOC_WR_MODE, &mode);
+	if (ret == -1)
+		pabort("can't set spi mode");
+
+	ret = ioctl(fd, SPI_IOC_RD_MODE, &mode);
+	if (ret == -1)
+		pabort("can't get spi mode");
+
+	/*
+	 * bits per word
+	 */
+	ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits);
+	if (ret == -1)
+		pabort("can't set bits per word");
+
+	ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits);
+	if (ret == -1)
+		pabort("can't get bits per word");
+
+	/*
+	 * max speed hz
+	 */
+	ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
+	if (ret == -1)
+		pabort("can't set max speed hz");
+
+	ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed);
+	if (ret == -1)
+		pabort("can't get max speed hz");
+
+	printf("spi mode: %d\n", mode);
+	printf("bits per word: %d\n", bits);
+	printf("max speed: %d Hz (%d KHz)\n", speed, speed/1000);
+
+	transfer(fd);
+
+	close(fd);
+
+	return ret;
+}
diff --git a/kernel/arch/arm64/boot/dts/rockchip/rk3399-nanopi4-common.dtsi b/kernel/arch/arm64/boot/dts/rockchip/rk3399-nanopi4-common.dtsi
index 60d087f..aa011e7 100644
--- a/kernel/arch/arm64/boot/dts/rockchip/rk3399-nanopi4-common.dtsi
+++ b/kernel/arch/arm64/boot/dts/rockchip/rk3399-nanopi4-common.dtsi
@@ -395,7 +395,7 @@
 };
 
 &spi1 {
-	status = "disabled";
+	status = "okay";
 	pinctrl-names = "default", "sleep";
 	pinctrl-1 = <&spi1_gpio>;
 
@@ -418,7 +418,7 @@
 };
 
 &uart4 {
-	status = "okay";
+	status = "disabled";
 };
 
 &vopb {
-- 
2.7.4


【RK3399 Android10 立体视觉ip配置(手动)(nanopc t4)】

ifconfig usb0 up 
ifconfig usb1 up

busybox udhcpc -i usb1  #自动获取动态ip
busybox udhcpc -i usb0

ifconfig usb1 10.11.12.11
ifconfig usb0 10.11.11.11

ip rule add from all pref 9999 table main  #策略路由
ip rule 
ip route show table local

ip route
ip route del 10.0.0.0/8 dev usb0  #默认网关
ip route del 10.0.0.0/8 dev usb1
ip route add 10.11.12.0/24 dev usb1
ip route add 10.11.11.0/24 dev usb0


【RK3399 Android10 dropbear移植,ssh功能支持】

项目目的
打算在android10上移植dropbear来实现ssh功能

结果
dropbear工具能用,但是没有实现账户密码登录(android里面没有user的概念),只能使用密钥登录

目前在网上找的dropbear源码放到rk3399-android10的sdk的external/下编译,会报eng 被废弃的错误,改成optional后会有大量语法警告报错,屏蔽之后还是有错误。都不能用。

之后打算移植openssh,网上找的代码在Android10中编译会报不是git仓库的问题

Android6的external/下自带有openssh,也可以编译的过,但是编译出的执行文件无法在Android10中使用。把openssh源码拿到rk3399-android10的external/下编译,依然报不是git仓库。

最后在网上找到了已经编译好的Android9的arm版本的dropbear。放到/system/bin下,竟然可以执行。
测试下来,发现可以通过密钥进行登录,但是无法设置账号密码登录。

使用
dropbear工具链接

目前只成功验证了使用秘钥的无密码登录方式,密码登录的方式没有验证成功
Android端的操作:
  1.将dropbear dropbearkey scp文件push到Android系统内,并给予执行权限 
  2.dropbearkey 生成一个自己的rsa文件 dropbearkey -t rsa -f /mnt/sdcard/dropbear/dropbear_rsa_host_key
  3.拉起dropbear服务   
    export HOME=/mnt/sdcard/dropbear/
    dropbear  -F -r $HOME/dropbear_rsa_host_key -T $HOME/id_rsa.pub -D  $HOME -p 2022 -A
    参数说明: -F前台运行  ,-r指定一个自己的秘钥, -T指定linux端登录访问的公钥, -p指定端口 
    
Linux端的操作:
   使用ssh-keygen -t rsa 指令生成秘钥和公钥,公钥push到Android系统里面,即dropbear启动参数里面的-T $HOME/id_rsa.pub  ,秘钥用ssh-add 添加到Linux的ssh list中

文件传输操作:
   将两个嵌入式设备连接到同一个局域网内,然后用ifconfig取得Android的ip地址(192.168.1.101),在Linux端使用以下指令
   登录服务: ssh 192.168.1.101
   Linux发送文件到Android端:scp -P 2022  /home/test/1.text  192.168.0.101:/mnt/sdcard/dropbear/
   Linux下载Android端的文件:scp -P 2022  192.168.0.101:/mnt/sdcard/dropbear/2.txt  /home/test

【RK3399 Android10 usb_scan重新适配,同时支持立体视觉自动适配】

未整理代码规范版本

【RK3399 Android10 wifi sta和ap模式 mac地址保持一致】

将sta模式的mac地址作为ap热点模式的mac地址

From 1c13bd69306a02be0be4186ae6e6bc43fe8e54d1 Mon Sep 17 00:00:00 2001
From: liangji <liangji@keenon.com>
Date: Wed, 18 Jan 2023 11:25:20 +0800
Subject: [PATCH] feat: use wifi sta mac as ap mac always

Signed-off-by: liangji <liangji@keenon.com>
---
 .../net/wireless/rockchip_wlan/rkwifi/bcmdhd_wifi6/dhd_linux.c     | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/kernel/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd_wifi6/dhd_linux.c b/kernel/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd_wifi6/dhd_linux.c
index 90616c2..51185d0 100644
--- a/kernel/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd_wifi6/dhd_linux.c
+++ b/kernel/drivers/net/wireless/rockchip_wlan/rkwifi/bcmdhd_wifi6/dhd_linux.c
@@ -198,6 +198,8 @@ static u32 vendor_oui = CONFIG_DHD_SET_RANDOM_MAC_VAL;
 
 #include <wl_android.h>
 
+
+uint8 fixed_dev_mac[ETHER_ADDR_LEN];
 /* Maximum STA per radio */
 #define DHD_MAX_STA     32
 
@@ -3143,7 +3145,9 @@ dhd_set_mac_address(struct net_device *dev, void *addr)
 	dhdif = dhd->iflist[ifidx];
 
 	dhd_net_if_lock_local(dhd);
-	memcpy(dhdif->mac_addr, sa->sa_data, ETHER_ADDR_LEN);
+	//memcpy(dhdif->mac_addr, sa->sa_data, ETHER_ADDR_LEN);
+	memcpy(dhdif->mac_addr, fixed_dev_mac, ETHER_ADDR_LEN);
+
 	dhdif->set_macaddress = TRUE;
 	dhd_net_if_unlock_local(dhd);
 	WL_MSG(dev->name, "iftype = %d macaddr = %pM\n",
@@ -12063,6 +12067,7 @@ dhd_register_if(dhd_pub_t *dhdp, int ifidx, bool need_rtnl_lock)
 
 	printf("Register interface [%s]  MAC: "MACDBG"\n\n", net->name,
 		MAC2STRDBG(net->dev_addr));
+    memcpy(fixed_dev_mac, net->dev_addr, ETHER_ADDR_LEN);
 
 #if defined(SOFTAP) && defined(WL_WIRELESS_EXT) && !defined(WL_CFG80211)
 //		wl_iw_iscan_set_scan_broadcast_prep(net, 1);
-- 
2.7.4


【(学习)Android10 屏幕显示】

fb设备,gralloc设备
framebuffer

Gralloc模块是一个HAL模块,为libui提供服务,管理framebuffer

gralloc被FramebufferNativeWindow.cpp构造函数开始调用

FramebufferNativeWindow实现FrameBuffer的管理,它主要被SurfaceFlinger使用。也能够被OpenGL Native程序使用。

gralloc模块—>FramebufferNativeWindow类—>surfaceFlinger
—>openGLNative

【gralloc (HAL层)】
抽象全部hal模块:struct hw_module_t
向上层提供的抽象接口:
struct hw_module_methods_t
{
*open()(回调函数指定)
}

在需要用到gralloc模块的时候,把*open,指向到gralloc_device_open()

gralloc模块支持打开两种设备:fb0(主屏幕),gpu0(Framebuffer分配和释放)

这两种设备在调用gralloc模块的FramebufferNativeWindow中以fbDev和grDev变量存在,
FramebufferNativeWindow中打开fbDev和grDev这两种设备的操作是
framebuffer_open()和gralloc_open()实质上都是调用的HAL的open—>gralloc_device_open()

【gralloc_device_open:gralloc设备打开】
给这个设备gralloc_context_t* dev变量指定grallop_alloc()和gralloc_free()接口函数

【gralloc_device_open:fb设备打开】

struct fb_context_t的设置配置
mapFrameBuffer(m)内存映射配置(在这里面开始真正调用内核接口,打开kernel内核设备)
成员变量有
framebuffer_device_t(需要如下接口)(这个是对framebuffer设备的统一描述)

post(将buffer数据post到显示屏,要求buffer必须和屏幕尺寸一致,且没有被locked,这样buffer内容将在下一次Vsync中被显示)
setSwapInterval(设置两个缓冲区的交换时间间隔)
setUpdateRect(设置刷新区域,也就是说,在此之外的区域很可以无效而不被刷新)

【EGL】

native window 本地窗口

native window 将openGL中渲染好的适配到具体的Android平台
针对android的GUI,需要两种native window:
面向管理者(surfaceFlinger)的本地窗口 == FramebufferNativeWindow (消费者)
面向应用程序 的本地窗口 == surface (生产者)

图形渲染都基于OpenGL ES的情况:
不同应用(surface)绘制---->memory Buffer---->OpenGl ES渲染---->FramebufferNativeWindow----->Framebuffer显示到屏幕

EGL是openGL渲染和本地窗口之间的接口

【android10 时间同步禁用,修改默认时区】

【网络工具ip 学习】

https://blog.csdn.net/A08118139/article/details/129980030

【RK3399 android10 nanopc wifi和eth网络连接优先级问题】

https://blog.csdn.net/A08118139/article/details/129980002?spm=1001.2014.3001.5502
原因出在framework中以太网eth和wifi在源码中的默认优先级,将wifi的默认优先级设置成高于eth就可以了

【RK3399 android10 nanopc typec接口驱动模式,adb模式和usb模式】

https://blog.csdn.net/A08118139/article/details/129979982
typec接口在驱动层面有两种工作模式,一个是adb调试模式,另一个是usb数据接口模式(u盘)

【RK3399 android10 nanopc 删除某些apk应用】

https://blog.csdn.net/A08118139/article/details/129979972?spm=1001.2014.3001.5501
删除com.android.quicksearchbox

  1. 在device/下 grep -rn quicksearchbox 发现有
  2. 在package/apps/下 grep -rn quicksearchbox 找到这个app,然后查看Android.bp 看看app 的name
  3. 在build/ 下grep -rn app的name,删掉

【RK3288 android6 4个摄像头固定映射】

https://blog.csdn.net/A08118139/article/details/129979963?csdn_share_tail=%7B%22type%22%3A%22blog%22%2C%22rType%22%3A%22article%22%2C%22rId%22%3A%22129979963%22%2C%22source%22%3A%22A08118139%22%7D

【RK3288 android6 快捷按键gpio 时间上报】

https://blog.csdn.net/A08118139/article/details/129979951?spm=1001.2014.3001.5502

【RK3399 android10 nanopc 自定义第三方apk安装,权限弹窗解决】

https://blog.csdn.net/A08118139/article/details/129724894?spm=1001.2014.3001.5502

【ESP32 通知铃 boost_en引脚发送脉冲】

https://blog.csdn.net/A08118139/article/details/129725729?spm=1001.2014.3001.5502

【RK3288 Android10 内核移植】

https://blog.csdn.net/A08118139/article/details/129725743?spm=1001.2014.3001.5502

【RK3399 android10 nanopc 时间24小时制显示】

http://t.csdn.cn/1fVTC

【RK3399 android10 nanopc 设置gboard为默认输入法】

【ESP32 通知铃 指令进入休眠模式】

【RK3288 android6 neoway 4G模块适配】

【485 IO板 支持modbus】

链接

【RK3288 hdmi副屏旋转】

【x86 工控机 配置桥接口+默认dns+ssh登录】

【可编程电源脚本使用】

链接

【RK3288 android6 UNIK 新板卡支持】

链接

【RK3288 Android6 S100 设置默认旋屏后概率性恢复】

链接

【RK3399 Android10 二合一 W3s 支持GM8775C mipi转lvds 10.1寸屏幕适配】

链接

【RK3399 Android10 二合一 W3S 支持ilitek触摸驱动】

【RK3399 Android10 二合一 支持ov4689 mipi摄像头】

链接

【ESP32 调度模块问题排查】

链接

【RK3288 Android10 UNIK 声音忽大忽小问题排查】

链接

【RK3399 ubuntu 工控机外设管理usb_scan v1】

链接

【RK3288 Android6 T2pro 支持移远和有方4G模块切换】

链接

【RK3288 Android10 C30 支持sim卡拔掉不弹窗,及热插拔】

链接

【RK3399 Android10 二合一,外设管理服务】

链接

【RK3288 Android6 网络转发,工控机反向访问PC机】

链接

【RK3399 Android10 二合一, 外设管理服务及嗅探工具, 串口读写 select】

【RK3288 Android6 “算法板系统中断,正在重启,请稍等”问题排查】

链接

【RK3288 Android6 T8, 突然无声音问题排查】

链接

【RK3399 Android10, 支持温控风扇】

链接

【RK3399 ubuntu, 研究mali T860 gpu使用】

【RK3288 android6, T8PRO 双屏显示】

【RK3399 android10 W3S 二合一 typeC OTG切换HOST和DEVICE 】

链接

【RK3288 Android6, T8PRO 快捷按键 gpio 配置上拉输入】

链接

【RK3288 Android10, UNIK 声音过小 问题解决】

链接

【RK32388 Android10, UNIK 4G模块导致usb hub出现 EMI 】

链接

【RK3288 Android6, apn 放开mnc号段限制研究】

【RK3288 Android6, T8 餐盘相机掉线现场问题排查】

【RK3288 Android10 T8pro usb hid-multitouch idc配置】

链接

【写在最后的话】

目前博主已经打算5月份辞职,回去考研,之后想要好好将内核驱动开发,安卓系统的相关模块的结构梳理相关的理论书看完。同时也想要有时间去完成博主的成为插画师的梦想。所以,擎朗篇章到这里,就要结束了,这里所有的项目均是博主在这两年间所做的认为有记录的价值的项目。

在这里,要特别感谢我的前辈光韬,以及嵌入式部门的老大蒋工,非常感谢两位前辈在我这短暂的两年嵌入式生涯中,给予我很多的帮助,不嫌麻烦的在我需要帮助的时候,帮助我把关,给我方向和提示。同时也非常感谢运哥,文斌,杰哥在解决疑难杂症和开发新功能的时候,给我硬件相关的支持。以及感谢小许,严新杨,润哥每天中午一起吃牛肉面。

上面的项目,如果还有为完成记录的,后续会慢慢补全,以上所有项目博客,均是为了记录学习所需,记录自己从一个新手,一点点成长的历程。也希望这些博客可以帮助同样使用RK平台的开发者们解决一些问题。请勿用作商业用途。

之后由于长时间会去复习备考,可能会对现在掌握的嵌入式的相关知识有所遗忘,所以现在简要记录一下之后需要复习和熟练掌握的知识。

  1. 代码规范
  2. git 工具的使用
  3. 计算机网络,四表五链,网络转发
  4. 系统开发
    4.1 bsp,支持板卡上已有的硬件资源
    4.2 以太网相关,显示相关,相机相关, 音频相关
    4.3 系统定制化(定制服务,app等)
  5. 安卓系统的重要模块的设计框架
    5.1 相机camera
    5.2 显示drm
    5.3 音频audio
    5.4 usb框架协议
    5.5(拓展)蓝牙协议了解
    5.6 gpu相关库和实现了解
    5.7 以太网内核相关部分(千兆网,百兆网)
    5.8 系统启动uboot相关
  6. esp32
  7. 嵌入式常用工具的掌握(vim, tmux,shell,Makefile,交叉编译,串口c编程select, autosar框架了解)
  8. linux驱动开发框架学习
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值