SSD202 Linux开发日志记录

记录一些开发过程中的基本操作,为什么要记录,Linux的存在很多版本兼容的问题,一下忘记了要花很多时间才恢复出来

一、挂载U盘

SDK默认自动加载USB存储模块,但没有自动挂载,插上U盘后识别sda

mount /dev/sda /mnt/

即可在/mnt查看U盘文件

二、make & make menuconfig 环境变量错误

在这里插入图片描述

kernel
make & make menuconfig 提示错误
打开新终端后输入

declare -x ARCH="arm"
declare -x CROSS_COMPILE="arm-linux-gnueabihf-"

三、CH340 USB转串口

→ Device Drivers → USB support → USB Serial Converter support
在这里插入图片描述
可找到对应的驱动模块加载编译即可

四、芯片引脚编号

SSD201 HW Checklist V10(1).xlsx
文件可找到芯片引脚编号与驱动序号对照表
在这里插入图片描述
用于用户空间操作GPIO

五、SDK默认只有/customer目录可读写,修改为根目录可以读写

在project/configs/current.configs文件中找到IMAGE_CONFIG对应的分区文件
在这里插入图片描述
修改ro为rw

六、GPIO复用模式

在这里插入图片描述
在有些文档中能找到GPIO复用功能说明,例如I2C的GPIO

七、生成disp_init程序,如需视频显示,在disp_init程序中加入

stDispPubAttr.eIntfType = E_MI_DISP_INTF_LCD;
stDispPubAttr.eIntfSync = E_MI_DISP_OUTPUT_USER;

八、用户空间读写寄存器

/config/riu_w bank reg value
/config/riu_r band reg

九、MIPI屏修改

在这里插入图片描述
DSC的标准协定,命令的参数:
[命令1],[参数长度n],[参数1],[参数2]…,[参数n-1],[参数n-1]
[命令2],[参数长度n],[参数1],[参数2]…,[参数n-1],[参数n-1]

[命令X],[参数长度n],[参数1],[参数2]…,[参数n-1],[参数n-1]

在这里插入图片描述
屏厂家提供的屏参文件为右边,需转换为左边的数组格式
DCS_Short_Write_1P 写一个字节
DCS_Short_Write_1P 写两个字节
DCS_Long_Write_FIFO 写一串命令字节流

左边格式,一行为一条指令,第一个为地址,第二个为长度,第三个为需写入数据
延时FLAG_DELAY,FLAG_DELAY,200,
在这里插入图片描述

在屏初始化命令最后需要结束符
FLAG_END_OF_TABLE, FLAG_END_OF_TABLE,

屏参数主要修改以下几个,可在屏数据手册找到
在这里插入图片描述
dts中panel 没配置为MIPI或者模式不对
这个一般log会打印 TTL!=MIPI
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
修改屏参时序数据
在这里插入图片描述
MIPI

十、修改各分区大小

我的板子使用spinand.ubifs.p2.partition.config这个文件
/project/image/configs/i2m/spniand.ubifs.p2.partition.config
在这里插入图片描述

十一、烧写不成,查看是否支持当前FLASH

project/image/output/images/boot/SPINANDINFO.sni
使用工具打开,查看是否支持当前Flash,没有需添加
在这里插入图片描述

十二、添加HY4635触屏驱动

→ System Type → SStar ARM SoCs
找到使用设备树文件
在这里插入图片描述
修改设备树,在I2C0下添加的触摸屏节点
在这里插入图片描述
修改touchscreen目录下kconfig文件添加配置项

config TOUCHSCREEN_HYCON
	tristate "HYCON HY46XX Dual touch support capacitive touchscreens"
	depends on I2C
	help
	  Say Y here if you have a touchscreen using HYCON HY46XX.

	  If unsure, say N.

	  To compile this driver as a module, choose M here: the
	  module will be called hy46xx_ts.

修改makefile文件

obj-$(CONFIG_TOUCHSCREEN_HYCON)	+= hy46xx_ts.o

在这里插入图片描述

十三、虽然内核带CH340的驱动,但不是最新,可以从git或者官网下载最新

git clone https://github.com/juliagoda/CH341SER

替换掉Makefile文件

ARCH := arm
CROSS_COMPILE := arm-linux-gnueabihf-
KERNELDIR := /home/dm/ssd201/kernel
CURRENT_PATH := $(shell pwd)

obj-m := ch34x.o

build: kernel_modules

kernel_modules:
	$(MAKE) ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) -C $(KERNELDIR) M=$(CURRENT_PATH) modules
	rm *.mod*
clean:
	$(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) clean

生成驱动模块

make modules

十四、RTL8723 STA及AP驱动编译及调试

参考链接:https://www.cnblogs.com/rain-blog/p/rtl8723bs-driver-test.html
驱动模块放kernel/driver/net/wireless/RT8723目录下,修改父目录的Kconfig及Makefile

修改模块下Makefle添加一个当前平台编译选项,如下

ifeq ($(CONFIG_PLATFORM_SSD20X_ARM), y)
EXTRA_CFLAGS += -DCONFIG_LITTLE_ENDIAN
EXTRA_CFLAGS += -DCONFIG_CONCURRENT_MODE
EXTRA_CFLAGS += -DCONFIG_IOCTL_CFG80211 -DRTW_USE_CFG80211_STA_EVENT
SUBARCH := $(shell uname -m )
ARCH := $(SUBARCH)
CROSS_COMPILE := arm-linux-gnueabihf-
KSRC := /home/dm/ssd201/kernel
MODULE_NAME :=wlan
endif

编译成功生成wlan.ko文件

添加WIFI驱动库

export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib:/lib:/config/wifi
//WIFI STA需要建立目录
mkdir -p /tmp/wifi/run
chmod 777 /tmp/wifi/run
//WIFI AP需建立目录
mkdir -p /var/run/hostapd
mkdir -p /var/wifi/misc
mkdir -p /var/lib/misc

十五、RTL8723蓝牙调试

蓝牙menuconfig配置说明
在这里插入图片描述

[ 3499.413323] rtk_btusb: Unknown symbol hci_free_dev (err 0)
[ 3499.416122] rtk_btusb: Unknown symbol hci_alloc_dev (err 0)
[ 3499.421573] rtk_btusb: Unknown symbol hci_unregister_dev (err 0)
[ 3499.427601] rtk_btusb: Unknown symbol hci_recv_frame (err 0)
[ 3499.433313] rtk_btusb: Unknown symbol hci_register_dev (err 0)
蓝牙部分以模块编译,insmod bluetooth.ko 可解决
[ 20.092472] rtk_btusb: config filename rtl8723b_config
[ 20.099007] usb 1-1: Direct firmware load for rtl8723b_config failed with error -2
[ 20.105226] rtk_btusb: fw name is rtl8723b_fw
[ 20.109662] usb 1-1: Direct firmware load for rtl8723b_fw failed with error -2
[ 20.116856] rtk_btusb: load firmware failed!
[ 20.121108] rtk_btusb: Rtk patch end -1
[ 20.124973] rtk_btusb: btusb_open failed
将固件文件拷贝到/lib/firmeare目录

可以使用buildroot直接生成以下工具
编译hciattach、hciconfig、hcidump、hcitool蓝牙调试工具

#pragma GCC diagnostic ignored “-Wformat-nonliteral”
就在包含头文件的地方加就行了

编译zlib
./configure --prefix=/home/dm/ssd201/arm-bluez/bluez
修改Makefile
CC=arm-linux-gnueabihf-gcc
LDSHARED=arm-linux-gnueabihf-gcc -shared -Wl,-soname,libz.so.1,–version-script,zlib.map
CPP=arm-linux-gnueabihf-gcc -E
AR=arm-linux-gnueabihf-ar
RANLIB=arm-linux-gnueabihf-ranlib
make
make install

编译libffi
./configure --host=arm-linux-gnueabihf --prefix=/home/dm/ssd201/arm_bluez/bluez
make
make install

编译glib
./configure --host=arm-linux-gnueabihf --prefix=/home/dm/ssd201/arm_bluez/bluez/ PKG_CONFIG_PATH=/home/dm/ssd201/arm-bluez/bluez/lib/pkgconfig glib_cv_stack_grows=no glib_cv_uscore=yes ac_cv_func_posix_getpwuid_r=yes ac_cv_func_posix_getgrgid_r=yes
make
make install
编译glib2.40出错
gdate.c:2497:7: error: format not a string literal, format string not checked [-Werror=format-nonlit

编译expat
./configure --host=arm-linux-gnueabihf --prefix=/home/dm/ssd201/arm_bluez/bluez/
make
make install

编译dbus
export CPPFLAGS=“-I/home/dm/ssd201/arm_bluez/bluez/include/”
export CFLAGS=“-I/home/dm/ssd201/arm_bluez/bluez/include/”
export LDFLAGS=“-L/home/dm/ssd201/arm_bluez/bluez/lib/”
./configure --host=arm-linux-gnueabihf --prefix=/home/dm/ssd201/arm_bluez/bluez/ GLIB_CFLAGS=“-I/home/dm/ssd201/arm-bluez/bluez/include/glib-2.0 -pthread -I/home/dm/ssd201/arm-bluez/bluez/lib/glib-2.0/include/” -disable-tests
make
make install

编译libical
export CC=arm-linux-gnueabihf-gcc
export CXX=arm-linux-gnueabihf-g++
ll /home/dm/ssd201/arm_bluez/bluez
cmake -DCMAKE INSTALL PREFIX=/home/dm/ssd201/arm_bluez/bluez
make
make install

编译ncurses.
wget http://ftp.gnu.org/pub/gnu/ncurses/ncurses-6.2.tar.gz
sudo ln -s /opt/gcc-arm-8.2-2018.08-x86_64-arm-linux-gnueabihf/bin/arm-linux-gnueabihf-strip /usr/bin/strip
./configure --host=arm-linux-gnueabihf --prefix=/home/dm/ssd201/arm_bluez/bluez CXX=“arm-linux-gnueabihf-g++” CC=“arm-linux-gnueabihf-gcc” --with-shared
make
make install

编译readline
./configure --host=arm-linux-gnueabihf --prefix=/home/dm/ssd201/arm_bluez/bluez bash_cv_wcwidth_broken=yes LDFLAGS=-L/home/dm/ssd201/arm_bluez/bluez/lib
make SHLIB_LIBS=-Incurses
make install

编译bluez-5.18
./configure --host=arm-linux-gnueabihf --prefix=/home/dm/ssd201/arm_bluez/bluez PKG_CONFIG_PATH=/home/dm/ssd201/arm_bluez/bluez/lib/pkgconfig --disable-systemd --disable-udev --disable-cups --disable-obex -enable-library LDFLAGS=“-L/home/dm/ssd201/arm_bluez/bluez/lib -lncurses” CFLAGS=-I/home/dm/ssd201/arm_bluez/bluez/include CPPFLAGS=-I/home/dm/ssd201/arm_bluez/bluez/include
make
make install

将bluez与dbus的bin与lib复制到目标板
将bluez与dbus的share、etc、var复制到目标板
建立运行环境
在这里插入图片描述
修改内核打开NFKILL
在这里插入图片描述
打开蓝牙
在这里插入图片描述
手机连接

第一次添加用户adduser messagebus
insmod rtk_btusb.ko
mkdir /var/run
mount tmpfs /var/run -t tmpfs
ln -s /customer/bluetooth/bluez_build/dbus/var/run/dbus /var/run/dbus
dbus-daemon --system &
bluetoothd -n -C &
bluealsa -p a2dp-source &
hciconifg hci0 up
hciconfig hci0 piscan
hciconfig hci0 leadv

在这里插入图片描述
使用nfr connect软件
连接到蓝牙设备
在这里插入图片描述
连接蓝牙耳机
bluetoothctl
scan on 扫描设备打开
scan off 找到设备关闭扫描
pair 地址 配对设备
connect 地址 连接设备

十六、更新根文件系统解压与压缩

tar -xvf ./rootfs.tar -C ./rootfs
tar -zcvf rootfs.tar.gz rootfs

定制/customer/demo.sh,/etc/profile,/etc/mdev.conf
修改project\image\configs\i2m\rootfs.mk

	echo 'mmcblk[0-9]p[0-9] 0:0 666 @ /etc/sd_card_inserting' >> ${OUTPUTDIR}/rootfs/etc/mdev.conf
	echo 'mmcblk[0-9] 0:0 666 $ /etc/sd_card_removing' >> ${OUTPUTDIR}/rootfs/etc/mdev.conf

	echo "export LD_LIBRARY_PATH=/lib:/customer/nfs/lib:/customer/lib:\$$LD_LIBRARY_PATH" >> $(OUTPUTDIR)/rootfs/etc/profile
	echo "busybox telnetd&" >> $(OUTPUTDIR)/rootfs/etc/profile
	echo "cd /sys/class/pwm/pwmchip0" >> $(OUTPUTDIR)/rootfs/etc/profile
	echo "echo 3 > export" >> $(OUTPUTDIR)/rootfs/etc/profile
	echo "cd pwm3" >> $(OUTPUTDIR)/rootfs/etc/profile
	echo "echo normal > polarity" >> $(OUTPUTDIR)/rootfs/etc/profile
	echo "echo 10000 > period" >> $(OUTPUTDIR)/rootfs/etc/profile
	echo "echo 10000 > duty_cycle" >> $(OUTPUTDIR)/rootfs/etc/profile
	echo "echo 1 > enable" >> $(OUTPUTDIR)/rootfs/etc/profile
	echo "mkdir -p /var/spool/cron/crontabs" >> $(OUTPUTDIR)/rootfs/etc/profile
	echo "mkdir /lib/firmware" >> $(OUTPUTDIR)/rootfs/etc/profile
	echo "mkdir -p /var/lib/dbus" >> $(OUTPUTDIR)/rootfs/etc/profile
	echo "mkdir -p /mnt/sd" >> $(OUTPUTDIR)/rootfs/etc/profile
	echo "cd /customer" >> $(OUTPUTDIR)/rootfs/etc/profile
	echo "deyeess" >> $(OUTPUTDIR)/rootfs/etc/profile

	echo "insmod /customer/modules/goodix.ko" >> $(OUTPUTDIR)/customer/demo.sh
	echo "ifconfig eth0 192.168.1.148 netmask 255.255.255.0" >> $(OUTPUTDIR)/customer/demo.sh
	echo "mkdir customer/nfs" >> $(OUTPUTDIR)/customer/demo.sh
	echo "mount -t nfs -o nolock 192.168.1.168:/home/dm/ssd201/nfs /customer/nfs/" >> $(OUTPUTDIR)/customer/demo.sh

	cp -r $(PROJ_ROOT)/../nfs/modules $(OUTPUTDIR)/customer/
	cp -r $(PROJ_ROOT)/../nfs/lib $(OUTPUTDIR)/customer
	cp $(PROJ_ROOT)/../nfs/deyeess $(OUTPUTDIR)/rootfs/bin
	cp  -r $(PROJ_ROOT)/../nfs/etc $(OUTPUTDIR)/rootfs

打包后文件更新project/image/rootfs/rootfs.tar.gz
make image

十七、添加合宙700E 4G网卡

https://e3zt58hesn.feishu.cn/docx/MGHWdYIg5oWpTox0qaecg483nKn
https://doc.openluat.com/article/419/0
修改内核
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

修改驱动
1.Add VID add PID
File: [KERNEL]/drivers/usb/serial/option.c

	//+add by airm2m for Air72x
	{ USB_DEVICE(0x19d1, 0x0001) },
	//-add by airm2m for Air72x
  1. Add the Zero Packet Mechanism
    File: [KERNEL]/drivers/usb/serial/usb_wwan.c
static struct urb *usb_wwan_setup_urb(struct usb_serial_port *port,
                      int endpoint,                                                              
                      int dir, void *ctx, char *buf, int len,
                      void (*callback) (struct urb *))
{
    struct usb_serial *serial = port->serial;
    struct urb *urb;
    urb = usb_alloc_urb(0, GFP_KERNEL); /* No ISO */
    if (!urb)
        return NULL;
    usb_fill_bulk_urb(urb, serial->dev,
              usb_sndbulkpipe(serial->dev, endpoint) | dir,
              buf, len, callback, ctx);
    //+add by airm2m for Air72x
    if(dir == USB_DIR_OUT){
        struct usb_device_descriptor *desc = &serial->dev->descriptor;
        if(desc->idVendor == cpu_to_le16(0x19d1) && desc->idProduct == cpu_to_le16(0x0001))
        {
            urb->transfer_flags |= URB_ZERO_PACKET;
        }
    }
    //-add by airm2m for Air72x
    return urb;
}
  1. Add Reset Resume
    ⦁For linux Kernel Version newer than 3.4:
    File: [KERNEL]/drivers/usb/serial/option.c
static struct usb_serial_driver option_1port_device = {
    .driver = {                                                                                                  
        .owner =    THIS_MODULE,
        .name =     "option1",
    },   
    ....
#ifdef CONFIG_PM
    .suspend           = usb_wwan_suspend,
    .resume            = usb_wwan_resume,
    //+add by airm2m for Air720
    .reset_resume      = usb_wwan_resume,
    //-add by airm2m for Air720
#endif

};

生成4个驱动模块
在这里插入图片描述
按顺序加载
insmod usbnet.ko
insmod cdc_ether.ko
insmod rndis_host.ko
insmod rndis_wlan.ko
在这里插入图片描述
识别出4G网卡
udhcpc -i eth2
在这里插入图片描述
网络连通
在这里插入图片描述

十八、编译minicom2.8

ncurses-6.2.tar.gz 试过5.7-6.0版本编译出错,这个版本可以编译通过
minicom-2.8.tar.bz2

先编译ncurse6.2

./configure --host=arm-linux-gnueabihf --prefix=/home/dm/ssd201/debug-toos/install/ncurses-6.2 CXX="arm-linux-gnueabihf-g++" CC="arm-linux-gnueabihf-gcc" --with-shared

编译minicom2.8

./configure CC=arm-linux-gnueabihf-gcc --prefix=/home/dm/ssd201/debug-toos/install/minicom --host=arm --enable-cfg-dir="/tmp"  CPPFLAGS="-I/home/dm/ssd201/debug-toos/install/ncurses-6.2/include" LDFLAGS="-L/home/dm/ssd201/debug-toos/install/ncurses-6.2/lib"

CPPFLAGS 和 LDFLAGS是刚刚编译的ncurses的头文件和库目录
enable-cfg-dir是minicom运行时配置保存的指定路径

移植

export TERMINFO=/tmp
export TERM=vt100

将程序minicom和配置vt100拷贝到开发板/tmp/v 目录。(此目录取决于TERMINFO=/tmp)
最后运行: ./minicom

十九、编译libmodbus库

下载连接:https://github.com/stephane/libmodbus/releases/download/v3.1.10/libmodbus-3.1.10.tar.gz

./configure --host=arm-linux-gnueabihf --prefix=/home/dm/ssd201/LIB/install/libmodbus --enable-shared --enable-static

make & make install

二十、PM_LED0、PM_LED1作普通IO

修改UBOOT
修改boot/drivers/mstar/emac/infinity2m/mhal_emac.c文件中的MHal_EMAC_ClkGen函数注释如下内容:

#if 0
//enable LED //16'0x0e_28[5:4]=01
uRegVal = MHal_EMAC_ReadReg8(REG_BANK_PMSLEEP, 0x50);
uRegVal = (uRegVal&~0x30)|0x10;
MHal_EMAC_WritReg8(REG_BANK_PMSLEEP, 0x50, uRegVal);
#endif

EMAC内核驱动修改\kernel\drivers\sstar\emac\hal\infinity2m\mhal_emac.c,需要注释多个地方
在这里插入图片描述
设备树文件中关于PAD_PM_LED0与PAD_PM_LED1的需要注释

二十一、修改为RGB屏

IDO板LCD不亮,可能为负压未产生
可通过修改/project/image/output/images/scripts/set_config
添加gpio out 18 1;

RGB点屏步骤:修改设备树为TTL->修改屏参->修改fbdev.ini->修改JPEGplayer代码
1、修改project/board/i2m/SSC011A-S01A/config/fbdev.ini
2、RGB屏为888,修改设备树文件
3、修改屏参文件
查看riu_r 0x101e 0xd是否有切对TTL mode(value:0x100)/MIPImode(vacdlue:0x1000)
按照步骤操作:
跑点屏的demo,初始化disp和panel;
如果跑的是显示UI的demo,先下cmd:echo GUI_SHOW 0 off >/proc/mi_modules/fb/mi_fb0 关闭UI;
通过reg关闭csc:riu_w 1129 30 bit0写0,riu_w 1129 3c bit0写0;
通过reg打纯色pattern:
SSD20X寄存器如下:
4、测试纯色的pattern:
riu_w 1129 1b 8000
bule:riu_w 1129 1b 801f
green:riu_w 1129 1b 83e0
red: riu_w 1129 1b fc00

pattern指令:
1、echo GUI_SHOW 0 off >/proc/mi_modules/fb/mi_fb0
2、riu_w 1129 30 0
3、riu_w 1129 3c 0
4、riu_w 1129 1b 8000
bule:riu_w 1129 1b 801f
green:riu_w 1129 1b 83e0
red: riu_w 1129 1b fc00
在这里插入图片描述
在这里插入图片描述
显示与实图,有点反色,调整VCOM电压
查看屏参
cat /proc/mi_modules/mi_panel/mi_panel0
修改project/board/i2m/SSC011A-S01A/config/fbdev.ini的分辨率
在这里插入图片描述
修改sstardisp.c分辨率
在这里插入图片描述
在这里插入图片描述
显示颜色与实际颜色反色,可调整LCD参数文件RGB颜色通道的顺序

在这里插入图片描述
类似这样的RGB屏显示花屏,基本都是HSYNC,VSYNC,PCLK,DE这几个信号反相,但SSD202是没有将这几个信号反相的能力,可通一个HC04进行信号反相
在这里插入图片描述
在这里插入图片描述
riu_r 0x101e 0xd读出来值非设定值需要通过命令强制设置
riu_w 0x101e 0x0d 100

二十二、启动LOGO

修改UBOOT

CONFIG_CMD_BOOTLOGO
CONFIG_SSTAR_DISP
CONFIG_SSTAR_PNL
CONFIG_SSTAR_JPD

修改project/configs/current.configs
在这里插入图片描述
复制jpeg到project/board/ini/misc
添加UBOOT屏参文件project/image/makefiletools/src/rawgenerator/pnl
修改添加屏参文件到disp_data_main.c
在这里插入图片描述
屏参名称要与DISP_OUT_NAME相同,名称长度最大20字符
在这里插入图片描述
project/configs/current.configs
在这里插入图片描述

make image
启动到uboot修改bootcmd设置背光引脚打开

setenv bootcmd 'bootlogo 0 0 0 0 0; mw 1f001cc0 11; gpio out 12 0; nand read.e 0x22000000 KERNEL 0x26e6d4; gpio out 12 1; bootm 0x22000000;nand read.e 0x22000000 RECOVERY 0x26e6d4; bootm 0x22000000'

上电启动到UI有其它颜色显示,修改背景颜色为黑色
1、指定YUV黑色
#define MAKE_YUYV_VALUE(y,u,v) ((y) << 24) | ((u) << 16) | ((y) << 8) | (v)
#define YUYV_BLACK MAKE_YUYV_VALUE(0,128,128)
2、设定u32BgColor
if (pstDispPubAttr->eIntfType == E_MI_DISP_INTF_LCD)
{
log_debug(“sstar_disp_init 3”);
init_panel_ST7701S();
log_debug(“sstar_disp_init 4”);
pstDispPubAttr->u32BgColor = YUYV_BLACK; // 设置背景色
pstDispPubAttr->stSyncInfo.u16Vact = stPanelParam.u16Height;
pstDispPubAttr->stSyncInfo.u16Vbb = stPanelParam.u16VSyncBackPorch;

}

二十三、工程管理

使用Cmake作工程管理,添加第三方modbus与lvgl库

cmake_minimum_required(VERSION 3.0.0)
project(energy_storage VERSION 0.1.0 LANGUAGES C)

include(CTest)
enable_testing()

link_directories(/home/dm/ssd201/LIB/install/libmodbus/lib)
link_directories(/home/dm/ssd201/project/release/nvr/i2m/common/glibc/8.2.1/mi_libs/dynamic)

add_compile_options(-DLV_CONF_INCLUDE_SIMPLE )

add_executable(energy_storage main.c)

set(CPACK_PROJECT_NAME ${PROJECT_NAME})
set(CPACK_PROJECT_VERSION ${PROJECT_VERSION})
SET(CMAKE_SYSTEM_NAME Linux)
SET(CMAKE_C_COMPILER   arm-linux-gnueabihf-gcc)
SET(CMAKE_CXX_COMPILER arm-linux-gnueabihf-g++)
SET(CMAKE_BUILD_TYPE “Debug”)
include(CPack)
include_directories(inc)
include_directories(/home/dm/ssd201/LIB/install/libmodbus/include)
include_directories(/home/dm/ssd201/LIB/install/lvgl8.3/include)
include_directories(/home/dm/ssd201/project/release/include)
include_directories(/home/dm/ssd201/project/kbuild/4.9.84/i2m/include/uapi/mstar)
add_subdirectory(src)
add_subdirectory(ui)

add_library(lvgl_demos STATIC IMPORTED)
set_property(TARGET lvgl_demos PROPERTY IMPORTED_LOCATION /home/dm/ssd201/LVGL8.30-SSD202/linux_frame_buffer/lvgl/liblvgl_demos.a)

add_library(lvgl_examples STATIC IMPORTED)
set_property(TARGET lvgl_examples PROPERTY IMPORTED_LOCATION /home/dm/ssd201/LVGL8.30-SSD202/linux_frame_buffer/lvgl/liblvgl_examples.a)

add_library(lvgl STATIC IMPORTED)
set_property(TARGET lvgl PROPERTY IMPORTED_LOCATION /home/dm/ssd201/LIB/install/lvgl8.3/lib/liblvgl.a)

target_link_libraries(energy_storage src libcjson.so  libmi_common.so  libmi_gfx.so    libmi_vdec.so
libmi_ai.so  libmi_disp.so    libmi_panel.so  libmi_venc.so libmi_ao.so  libmi_divp.so    libmi_sys.so    
libmi_wlan.so libmodbus.so lvgl lvgl_demos lvgl_examples ui)

set(CMAKE_EXE_LINKER_FLAGS    "-lpthread -ldl -Wincompatible-pointer-types")

二十四、编译LVGL库

针对8.3版本
添加编译器选项
在这里插入图片描述
/env_support/cmake,选择编译为静态库或动态库
在这里插入图片描述
cmake CMakeList.txt
make
make install

lvgl demo

二十五、linux查看设备树

针对SPNAND ssd202芯片的设备树文件
RGB屏设备树文件infinity2m-spinand-ssc011a-s01a-display.dts
MIPI屏设备树文件infinity2m-spinand-ssc011a-s01a-display_for_mipi.dts

ls /sys/firmware/devicetree/base
或者
ls /proc/device-tree

二十六、添加GT911触摸驱动

4.9内核已经有GT911驱动,在内核配置打开GT911
原理图查找相应的芯片使用触摸引脚
在这里插入图片描述
在这里插入图片描述
在设备树文件infinity2m-ssc011a-s01a-display中i2c0节点添加911设备

			goodix_gt911@5D{ //EVB i2c-padmux=2 SSD201_SZ_DEMO_BOARD i2c-padmux=1
                compatible = "goodix,gt911";
                reg = <0x5D>;
                goodix_rst = <PAD_SAR_GPIO2>; //SSD201_SZ_DEMO_BOARD PAD_GPIO1  EVB PAD_GPIO0
                goodix_int = <PAD_GPIO5>; //SSD201_SZ_DEMO_BOARD PAD_GPIO13  EVB PAD_GPIO1
                interrupts-extended = <&ms_gpi_intc INT_GPI_FIQ_GPIO5>;
                interrupt-names = "goodix_int";
            };

在设备树文件infinity2m-ssc011a-s01a-padmux-display修改GPIO6与GPIO7为I2C
在这里插入图片描述
驱动加载成功后建立/dev/input/event0设备,cat /dev/input/evnet0可打印触摸屏数据
GT911 800480 1024600参数

	//800*480
0x41,0x20,0x03,0xE0,0x01,0x0a,0x0c,0x20,0x01,0x08,
0x28,0x05,0x50,0x3c,0x03,0x05,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x89,0x2a,0x0b,
0x2d,0x2b,0x0f,0x0a,0x00,0x00,0x01,0xa9,0x03,0x2d,
0x00,0x01,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,
0x00,0x21,0x59,0x94,0xc5,0x02,0x07,0x00,0x00,0x04,
0x93,0x24,0x00,0x7d,0x2c,0x00,0x6b,0x36,0x00,0x5d,
0x42,0x00,0x53,0x50,0x00,0x53,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x02,0x04,0x06,0x08,0x0a,0x0c,0x0e,0x10,
0x12,0x14,0x16,0xff,0xff,0xff,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x02,0x04,0x06,0x08,0x0a,0x0f,0x10,
0x12,0x16,0x18,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,
0x24,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0xea,0x00

	//1024*600
//0x41,0x00,0x04,0x58,0x02,0x0a,0x0c,0x20,0x01,0x08,
//0x28,0x05,0x50,0x3c,0x03,0x05,0x00,0x00,0x00,0x00,
//0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x89,0x2a,0x0b,
//0x2d,0x2b,0x0f,0x0a,0x00,0x00,0x01,0xa9,0x03,0x2d,
//0x00,0x01,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,
//0x00,0x21,0x59,0x94,0xc5,0x02,0x07,0x00,0x00,0x04,
//0x93,0x24,0x00,0x7d,0x2c,0x00,0x6b,0x36,0x00,0x5d,
//0x42,0x00,0x53,0x50,0x00,0x53,0x00,0x00,0x00,0x00,
//0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
//0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
//0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
//0x00,0x00,0x02,0x04,0x06,0x08,0x0a,0x0c,0x0e,0x10,
//0x12,0x14,0x16,0xff,0xff,0xff,0x00,0x00,0x00,0x00,
//0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
//0x00,0x00,0x00,0x02,0x04,0x06,0x08,0x0a,0x0f,0x10,
//0x12,0x16,0x18,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,
//0x24,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x00,
//0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
//0x00,0x00,0x00,0x00,0xea,0x00

二十七、更换芯片为SSD201

修改project/configs/current.configs文件
在这里插入图片描述

./setup_config.sh ./configs/nvr/i2m/8.2.1/spinand.glibc.011a.64
make image

二十八、新增Nand Flash芯片

根据芯片手册修改参数
在这里插入图片描述
替换project目录下的SPINANDINFO.sni
在这里插入图片描述

二十九、添加PWM驱动

配置设备树
在这里插入图片描述

配置引脚,如需要背光控制,启动不闪显,不需配置GPIO
在这里插入图片描述

注释掉其它使用的引脚
在这里插入图片描述
使能内核PWM驱动
在这里插入图片描述

cd /sys/class/pwm/pwmchip0
echo 3 > export		//3对应PWM3
cd pwm3
echo normal > polarity
echo 10000 > period
echo 10000 > duty_cycle
echo 1 > enable

三十、vscode+GDB调试应用

GDB版本7.12.1

cd gdb-7.12.1
./configure --target=arm-linux --prefix=$PWD/installed -v
make
make install

进入gdb-7.12.1/gdb/gdbserver

./configure --target=arm-linux --host=arm-linux-gnueabihf
make

复制gdbserver到目标板

修改Makefile,添加调试信息选项
在这里插入图片描述

在这里插入图片描述
对下面的参数进行修改:
“program”:表示可执行文件的路径;
“miDebuggerPath”:表示gdb的路径;
“miDebuggerServerAddress”:表示连接目标机gdbserver的网络参数。
在这里插入图片描述
目标板执行
在这里插入图片描述
程序会停在main函数入口处。现在就可以进行DEBUG调试了。
在这里插入图片描述

三十一、自动挂载卸载SD卡

修改/etc/mdev.conf配置文件、添加
mmcblk[0-9]p[0-9] 0:0 666 @ /etc/sd_card_inserting
mmcblk[0-9] 0:0 666 $ /etc/sd_card_removing
/etc/sd_card_inserting内容如下:
#!/bin/sh
mount -t vfat /dev/mmcblk0p1 /mnt/sd

同时对应的/etc/sd_card_removing内容如下:
#!/bin/sh
sync
umount /mnt/sd

三十二、MPlayer 后台播放

mplayer 1.mp3 -loop 0 < /dev/null > /dev/null 2>1 &

mplaye播放没声音

  1. mplayer test.mp4 播放test.mp4视频
    结果报错:[AO OSS] audio_setup: Can’t open audio device /dev/dsp: No such file or directory” ,网上查了一下,需要配置内核添加 OSS PCM (digital audio) API模块,

  2. make muenconfig 进入linux内核配置,打开界面后:
    进入 Deivce Drivers——>Sound card support ——>Advanced Linux Sound Architecture 选中 OSS PCM(digital audiop) API 和 OSS PCM (Digital audio) API – Include plugin system 保存退出
    在这里插入图片描述
    3、查看设备列表,产生dsp设备,内核配置主要不能选择生成模块,要选择编译入内核才会产生dsp
    在这里插入图片描述

initd

三十三、触摸按键linux驱动接入input框架

#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/uaccess.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/ide.h>
#include <linux/errno.h>
#include <linux/gpio.h>
#include <asm/mach/map.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_gpio.h>
#include <asm/io.h>
#include <linux/device.h>
#include <linux/timer.h>
#include <linux/jiffies.h>
#include <linux/platform_device.h>
#include <linux/of_irq.h>
#include <linux/wait.h>
//#include <linux/sched/signal.h>
#include <linux/poll.h>
#include <linux/atomic.h>
#include <linux/i2c.h>
#include <linux/input.h>
#include <linux/input/mt.h>

#define XW09A_GPIO_INT_NAME		"xw09a_int"

/* AT42QT1070 support up to 7 keys */
static const unsigned short xw09a_key2code[] = {
	KEY_ENTER, KEY_DOWN, KEY_SPACE, KEY_ESC,
	KEY_4, KEY_5, KEY_6, KEY_7, KEY_8,
};

struct xw09a_data {
	struct i2c_client *client;
	struct input_dev *input;
	unsigned int irq;
	unsigned short keycodes[ARRAY_SIZE(xw09a_key2code)];
	u8 last_keys;
};

static int xw09a_read(struct i2c_client *client, u8 reg)
{
	struct i2c_msg msgs[2];
	int ret;
	u8 buf[2]={0};
	u16 key;

	msgs[0].flags = I2C_M_RD;
	msgs[0].addr  = client->addr;
	msgs[0].len   = 2;
	msgs[0].buf   = buf;

	ret = i2c_transfer(client->adapter, msgs, 1);

	key = (buf[0]<<8) | buf[1];

	return key;
}

static irqreturn_t xw09a_interrupt(int irq, void *dev_id)
{
	struct xw09a_data *data = dev_id;
	struct i2c_client *client = data->client;
	struct input_dev *input = data->input;
	int i;
	u32 new_keys, keyval;
	u16 mask = 0x1000;

	/* Read which key changed */
	new_keys = xw09a_read(client, 0x40);

	for (i = 0; i < ARRAY_SIZE(xw09a_key2code); i++) {
		keyval = new_keys & mask;
		if ( keyval == 0 ){
			input_report_key(input, data->keycodes[i], 1);
			input_report_key(input, data->keycodes[i], 0);
			// printk("key code %d\n",data->keycodes[i]);
			break;
		}
		mask >>= 1;
	}	
	input_sync(input);

	data->last_keys = new_keys;
	return IRQ_HANDLED;
}

static int xw09a_probe(struct i2c_client *client,
				const struct i2c_device_id *id)
{
	struct xw09a_data *data;
	struct input_dev *input;
	int i;
	int err;
	//int irq_gpio;

	err = i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE);
	if (!err) {
		dev_err(&client->dev, "%s adapter not supported\n",
			dev_driver_string(&client->adapter->dev));
		return -ENODEV;
	}

	client->irq = of_irq_get_byname(client->dev.of_node, XW09A_GPIO_INT_NAME);
	// printk(" irq %d \n",client->irq);

	if (!client->irq) {
		dev_err(&client->dev, "please assign the irq to this device\n");
		return -EINVAL;
	}

	data = kzalloc(sizeof(struct xw09a_data), GFP_KERNEL);
	input = input_allocate_device();
	if (!data || !input) {
		dev_err(&client->dev, "insufficient memory\n");
		err = -ENOMEM;
		goto err_free_mem;
	}

	data->client = client;
	data->input = input;
	data->irq = client->irq;

	input->name = "xw09a QTouch Sensor";
	input->dev.parent = &client->dev;
	input->id.bustype = BUS_I2C;

	/* Add the keycode */
	input->keycode = data->keycodes;
	input->keycodesize = sizeof(data->keycodes[0]);
	input->keycodemax = ARRAY_SIZE(xw09a_key2code);

	__set_bit(EV_KEY, input->evbit);

	for (i = 0; i < ARRAY_SIZE(xw09a_key2code); i++) {
		data->keycodes[i] = xw09a_key2code[i];
		// printk("code %d\n",data->keycodes[i]);
		__set_bit(data->keycodes[i], input->keybit);
	}

	msleep(400);

	err = request_threaded_irq(client->irq, NULL, xw09a_interrupt,
				   IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
				   client->dev.driver->name, data);

	if (err) {
		dev_err(&client->dev, "fail to request irq\n");
		goto err_free_mem;
	}

	/* Register the input device */
	err = input_register_device(data->input);
	if (err) {
		dev_err(&client->dev, "Failed to register input device\n");
		goto err_free_irq;
	}

	i2c_set_clientdata(client, data);

	return 0;

err_free_irq:
	free_irq(client->irq, data);
err_free_mem:
	input_free_device(input);
	kfree(data);
	return err;
}

static int xw09a_remove(struct i2c_client *client)
{
	struct xw09a_data *data = i2c_get_clientdata(client);

	/* Release IRQ */
	free_irq(client->irq, data);

	input_unregister_device(data->input);
	kfree(data);

	return 0;
}

#ifdef CONFIG_PM_SLEEP
static int xw09a_suspend(struct device *dev)
{
	struct i2c_client *client = to_i2c_client(dev);
	struct xw09a_data *data = i2c_get_clientdata(client);

	if (device_may_wakeup(dev))
		enable_irq_wake(data->irq);

	return 0;
}

static int xw09a_resume(struct device *dev)
{
	struct i2c_client *client = to_i2c_client(dev);
	struct xw09a_data *data = i2c_get_clientdata(client);

	if (device_may_wakeup(dev))
		disable_irq_wake(data->irq);

	return 0;
}
#endif

static SIMPLE_DEV_PM_OPS(xw09a_pm_ops, xw09a_suspend, xw09a_resume);

static const struct i2c_device_id xw09a_id[] = {
	{ "wmxwdz,xw09a", 0 },
	{ },
};
// MODULE_DEVICE_TABLE(i2c, xw09a_id);

// #ifdef CONFIG_ACPI
// static const struct acpi_device_id xw09a_acpi_match[] = {
// 	{ "wmxwdz,xw09a", 0 },
// 	{ }
// };
// MODULE_DEVICE_TABLE(acpi, xw09a_acpi_match);
// #endif

// #ifdef CONFIG_OF
// static const struct of_device_id xw09a_of_match[] = {
// 	{ .compatible = "xmxwdz,xw09a" },
// 	{ }
// };
// MODULE_DEVICE_TABLE(of, xw09a_of_match);
// #endif

/* 设备树的匹配列表 */
static struct of_device_id dts_match_table[] = {
    {.compatible = "wmxwdz,xw09a"}, /* 通过设备树来匹配 */
    {},
};

static struct i2c_driver xw09a_driver = {
	.driver	= {
		.name	= "xw09a QTouch sensor",
//		.acpi_match_table = ACPI_PTR(xw09a_acpi_match),
//		.of_match_table = of_match_ptr(xw09a_of_match),
		.pm	= &xw09a_pm_ops,
		.of_match_table = dts_match_table, /* 通过设备树匹配 */
	},
	.id_table	= xw09a_id,
	.probe		= xw09a_probe,
	.remove		= xw09a_remove,
};

module_i2c_driver(xw09a_driver);

MODULE_AUTHOR("KenDeng <448091454@qq.com>");
MODULE_DESCRIPTION("Driver for xw09a QTouch sensor");
MODULE_LICENSE("GPL");

三十四、生成fastboot固件

cd ${your path}/kernel
      make infinity2m_spinand_ssc011a_s01a_minigui_fastboot_defconfig 
      make clean; make
cd ${your path}/project/kbuild/4.9.84  
     ./release.sh -k ../../../kernel -b 011A-fastboot -p nvr -f spinand -c i2m -l glibc -v 8.2.1
cd ${your path}/project
     ./setup_config.sh ./configs/nvr/i2m/8.2.1/spinand.ram-glibc-squashfs.011a.64
	make clean; make image

三十五、buildroot复制一个libstdc++.so.6.0.25-gdb.py到project/image/output/rootfs/lib产生一个文件格式报错

/rootfs/lib/libstdc++.so.6.0.25-gdb.py: File format not recognized
搜索strip,添加! -name “*.py”
在这里插入图片描述

三十六、osip2(eXosip2)-5.1.0交叉编译(SSD202平台)

1、下载源码5.1.0
https://ftp.gnu.org/gnu/osip/
http://download.savannah.nongnu.org/releases/exosip/
openssl下载1.1.0f
https://ftp.openssl.org/source/old/1.1.0/

2、 编译osip2-5.1.0

# 在osip2-5.0.0目录下创建build编译目录
mkdir build
./configure --host=arm-linux-gnueabihf CC=arm-linux-gnueabihf-gcc --prefix=/home/dm/ssd201/exosip/libosip2-5.1.0/build --enable-shared --disable-static
# 编译,安装
make && make install

3、openssl-1.1.0f编译

# 进入openssl-1.1.0f目录,创建bulid编译目录
mkdir build
./Configure linux-elf no-asm --cross-compile-prefix=arm-linux-gnueabihf- --prefix=/home/dm/ssd201/exosip/openssl-1.1.0f/build
# 编译,安装
make && make install

4、编译eXosip2-5.1.0

# 在eXosip2-5.0.0目录下创建build编译目录
mkdir build
./configure --host=arm-linux-gnueabihf --prefix=/home/dm/ssd201/exosip/libexosip2-5.1.0/build --enable-shared --disable-static CC=arm-linux-gnueabihf-gcc PKG_CONFIG_PATH=/home/dm/ssd201/exosip/libosip2-5.1.0/build/lib/pkgconfig/:/home/dm/ssd201/exosip/openssl-1.1.0f/build/lib/pkgconfig
# 编译,安装
make && make install

在这里插入图片描述

三十七、交叉编译PJSIP

1、下载 pjproject-2.13.1.tar.gz
2、生成makfile

./configure CC=arm-linux-gnueabihf-gcc --host=arm-linux-gnueabihf  --disable-libwebrtc --disable-ssl --disable-openh264 --disable-libyuv --enable-static --prefix=/home/dm/ssd201/exosip/pjproject-2.13.1/build

3、make & make install
4、交叉编译asound
mkdir build

./configure CC=arm-linux-gnueabihf-gcc --host=arm-linux-gnueabihf --prefix=/home/dm/ssd201/exosip/alsa-lib-1.2.1.2/build

make
make install
5、在include/pj/config.h添加

#define	PJ_IS_BIG_ENDIAN	0
#define	PJ_IS_LITTLE_ENDIAN	1

在这里插入图片描述
6、demo
makefile

OBJ=	main

CC=	arm-linux-gnueabihf-gcc

CFLAGS=	-Wall -O -O2 -DPJ_IS_BIG_ENDIAN=0 -DPJ_IS_LITTLE_ENDIAN=1
VPATH=	/home/dm/ssd201/exosip/pjproject-2.13.1/build
#LIBS= -lpthread -lm

INCLUDE=	-I/home/dm/ssd201/exosip/pjproject-2.13.1/build/include
LIB_DIR=	-L/home/dm/ssd201/exosip/pjproject-2.13.1/build/lib -L/home/dm/ssd201/exosip/alsa-lib-1.2.1.2/build/lib

LIB=	-lpjsua2-arm-unknown-linux-gnueabihf -lstdc++ -lpjsua-arm-unknown-linux-gnueabihf -lpjsip-ua-arm-unknown-linux-gnueabihf -lpjsip-simple-arm-unknown-linux-gnueabihf -lpjsip-arm-unknown-linux-gnueabihf -lpjmedia-codec-arm-unknown-linux-gnueabihf -lpjmedia-arm-unknown-linux-gnueabihf -lpjmedia-videodev-arm-unknown-linux-gnueabihf -lpjmedia-audiodev-arm-unknown-linux-gnueabihf -lpjmedia-arm-unknown-linux-gnueabihf -lpjnath-arm-unknown-linux-gnueabihf -lpjlib-util-arm-unknown-linux-gnueabihf  -lsrtp-arm-unknown-linux-gnueabihf -lresample-arm-unknown-linux-gnueabihf -lgsmcodec-arm-unknown-linux-gnueabihf -lspeex-arm-unknown-linux-gnueabihf -lilbccodec-arm-unknown-linux-gnueabihf -lg7221codec-arm-unknown-linux-gnueabihf  -lpj-arm-unknown-linux-gnueabihf -lrt -lpthread  -lasound -ldl -lm

$(OBJ):
	$(CC) -o main.o main.c -Wall $(INCLUDE) $(LIB_DIR) $(LIB) -static

clean:
	rm	-f	main
#include "pj/log.h"
#include "pjlib.h"
#include "pjlib-util.h"
#include "pjnath.h"
#include "pjmedia.h"
#include "pjsip.h"
#include "pjsip_simple.h"
#include "pjsip_ua.h"
#include "pjsua-lib/pjsua.h"
#include "pjmedia-codec.h"
 
#define THIS_FILE "#### windaka_log"
#define SIP_DOMAIN "10.10.5.250"
#define SIP_USER   "01010011"
#define SIP_PASSWD "0000"
 
#define current_acc	pjsua_acc_get_default()
 
/*####获取所有声卡设备的结构####*/
typedef struct pjmedia_aud_sount_cnt{
    int devcnt;
    char name[32][32];
    unsigned devid[32];
}pjmedia_aud_sound_cnt;
 
/*####收到呼叫后的回调函数####*/
static void on_incoming_call(pjsua_acc_id acc_id, pjsua_call_id call_id,
			     pjsip_rx_data *rdata)
{
    pjsua_call_info ci;
 
    PJ_UNUSED_ARG(acc_id);
    PJ_UNUSED_ARG(rdata);
 
    /*####获取主叫信息####*/
    pjsua_call_get_info(call_id, &ci);
 
	/*####打印出主叫的URL####*/
    PJ_LOG(3,(THIS_FILE, "#### ---->Incoming call from %.*s!!",
			 (int)ci.remote_info.slen,
			 ci.remote_info.ptr));
 
    /*####收到呼叫后的应答函数接口####*/
    pjsua_call_answer(call_id, 200, NULL, NULL);
}
 
/* Callback called by the library when call's state has changed */
static void on_call_state(pjsua_call_id call_id, pjsip_event *e)
{
    pjsua_call_info ci;
    PJ_UNUSED_ARG(e);
    pjsua_call_get_info(call_id, &ci);
    PJ_LOG(3,(THIS_FILE, "Call %d state=%.*s,state=%d,last_status=%d", call_id,
			 (int)ci.state_text.slen,
			 ci.state_text.ptr,ci.state,ci.last_status));
}
/* Callback called by the library when call's media state has changed */
static void on_call_media_state(pjsua_call_id call_id)
{
    pjsua_call_info ci;
 
    pjsua_call_get_info(call_id, &ci);
 
    if (ci.media_status == PJSUA_CALL_MEDIA_ACTIVE) {
	// When media is active, connect call to sound device.
	pjsua_conf_connect(ci.conf_slot, 0);
	pjsua_conf_connect(0, ci.conf_slot);
    }
}
 
/*####程序异常退出接口####*/
static void error_exit(const char *title, pj_status_t status)
{
    pjsua_perror(THIS_FILE, title, status);
    pjsua_destroy();
    exit(1);
}
 
void get_device_sound_name(char *pathName,char *sound_name){
    FILE *fp;
    char tmp[32];
 
    if(pathName == NULL){
        return ;
    }
 
    fp = fopen(pathName,"r");
    if(fp == NULL){
        return ;
    }
 
    memset(tmp,0,sizeof(tmp));
    fread(tmp,1,32,fp);
    strcpy(sound_name,tmp);
    fclose(fp);
    return ;
}
 
void del_str_line(char *str){
    char *p = str;
 
    while('\n' != *p){
        p++;
	if(*p =='\0'){
            return ;
	}
    }
    *p = '\0';
    return ;
}
 
int main(int argc,char *argv[]){
    pjsua_acc_id acc_id;
    pj_status_t status;
 
    /*####创建pjsua####*/
    status = pjsua_create();
    if (status != PJ_SUCCESS){
		error_exit("Error in pjsua_create()", status);
	}
 
    /*####初始化pjsua####*/
    {
        pjsua_config cfg;
        pjsua_logging_config log_cfg;
 
        pjsua_config_default(&cfg);
        cfg.cb.on_incoming_call = &on_incoming_call;
	cfg.cb.on_call_media_state = &on_call_media_state;
	cfg.cb.on_call_state = &on_call_state;
 
	pjsua_logging_config_default(&log_cfg);
	log_cfg.console_level = 4;
 
	status = pjsua_init(&cfg, &log_cfg, NULL);
	if (status != PJ_SUCCESS){
	       	error_exit("Error in pjsua_init()", status);
        }
    }
 
    /*####设置pjsua使用的本地端口####*/
    {
        pjsua_transport_config cfg;
 
	pjsua_transport_config_default(&cfg);
	/*####本地使用5061端口####*/
	cfg.port = 5060;
	status = pjsua_transport_create(PJSIP_TRANSPORT_UDP, &cfg, NULL);
	if (status != PJ_SUCCESS){
	    error_exit("Error creating transport", status);
	}
    }
 
    /* Initialization is done, now start pjsua */
    status = pjsua_start();
    if (status != PJ_SUCCESS){
	error_exit("Error starting pjsua", status);
    }
 
    /* Register to SIP server by creating SIP account. */
    {
        pjsua_acc_config cfg;
 
        pjsua_acc_config_default(&cfg);
        int iloop = 0;
        char devName[32];
        unsigned devId = 0;
	static pjmedia_aud_sound_cnt *p = NULL;
 
	/*####获取系统指定声卡的name####*/
	memset(devName,0,sizeof(devName));
        //get_device_sound_name("/proc/asound/card0/id",devName); 
 
	/*####获取设备所有的声卡信息####*/
        //printf("#### ---->get_card_calc_dev() \n");
        //p = get_card_calc_dev();
        //printf("#### ---->p->devcnt=[%d]\n",p->devcnt);
 
#if 0
	char tmp[64];
	memset(tmp,0,sizeof(tmp));
	strcpy(tmp,"default:CARD=");
	strcat(tmp,devName);
        del_str_line(tmp);
 
	/*####根据指定声卡的name获取声卡的ID####*/
	printf("#### ---->p->devcnt = [%d]\n",p->devcnt);
	for(iloop = 0; iloop < p->devcnt;iloop++){
            printf("#### ---->tmp=[%s],p->name[iloop]=[%s]\n",tmp,p->name[iloop]);
   	    if(strcmp(tmp,p->name[iloop]) == 0){
                devId = p->devid[iloop];
                printf("#### ---->get device [%s],id = [%d]\n",p->name[iloop],devId);
		break;
	    }
	}
	/*####指定设备使用哪个声卡####*/
	pjsua_set_snd_dev(devId,devId);
#endif
        /*####设置SIP账号信息####*/
        cfg.vid_out_auto_transmit = PJ_TRUE;
        cfg.id = pj_str("sip:" SIP_USER "@" SIP_DOMAIN);
        cfg.reg_uri = pj_str("sip:" SIP_DOMAIN);
        cfg.cred_count = 1;
        cfg.cred_info[0].realm = pj_str("*");
        cfg.cred_info[0].scheme = pj_str("digest");
        cfg.cred_info[0].username = pj_str(SIP_USER);
        cfg.cred_info[0].data_type = PJSIP_CRED_DATA_PLAIN_PASSWD;
        cfg.cred_info[0].data = pj_str(SIP_PASSWD);
 
	/*####添加SIP账号####*/
        status = pjsua_acc_add(&cfg, PJ_TRUE, &acc_id);
        if (status != PJ_SUCCESS){
	    error_exit("Error adding account", status);
	}
    }
 
    /* Wait until user press "q" to quit. */
    for (;;) {
        char option[10];
 
        puts("\n'h' to hangup all calls\n'q' to quit\n'm' is call 17001010101\n'r' is register\n");
        if (fgets(option, sizeof(option), stdin) == NULL) {
            puts("EOF while reading stdin, will quit now..");
	    break;
	}
 
        if(option[0] == 'r'){
            pjsua_acc_set_registration(current_acc,PJ_TRUE);
        }
 
        if(option[0] == 'm'){
            pj_str_t uri=pj_str("sip:01010301@10.10.5.250");
            status = pjsua_call_make_call(acc_id,&uri,0,NULL,NULL,NULL);
            if(status != PJ_SUCCESS){
                printf("#### make call Error\n");
            }
        }
	if (option[0] == 'q'){
	    break;
	}
 
	if (option[0] == 'h'){
	    /*####挂断接口####*/
	    pjsua_call_hangup_all();
	}
    }
 
    /* Destroy pjsua */
    pjsua_destroy();
 
    return 0;
}

PJSIP DEMO 运行
在这里插入图片描述

三十八、屏参调试总结

1、闪屏
在这里插入图片描述
2、偏色
在这里插入图片描述

三十九、8800WIFI蓝牙驱动

1、MMC需要初始化成功
模块没有供电,初始化失败的信息
在这里插入图片描述
供电后初始化成功信息
在这里插入图片描述
加载驱动
insmod aic8800_bsp.ko
拷贝固件到板上指定目录
rwnx_load_firmware :firmware path = /vendor/etc/firmware/fw_patch_table_u03.bin
insmod aic8800_fdrv.ko

四十、project主要备份文件

/project/board/i2m/SSC011A-S01A/config/fbdev.ini
/project/configs/current.configs
/project/image/configs/i2m/rootfs.mk
/project/image/configs/i2m/spinand.ubifs.p2.partition.config
/kernel/.config

四十一、启动速度优化

关闭UBOOT网络启动

setenv autoestart 0
saveenv

四十二、USB或SD自动更新系统

1、修改UBOOT
在这里插入图片描述
2、修改cmd_bootlogo.c,打开背光开关,显示升级进度
在这里插入图片描述

setenv sdautoupgrade 1
setenv usbautoupgrade 1
setenv enable_version_chk 1
saveenv

四十三、sqlite3数据库移植测试

./configure --prefix=/home/dm/ssd201/sqlite-autoconf-3430000/build --host=arm-linux-gnueabihf
make
make install

arm-linux-gnueabihf-strip 去掉库文件或执行文件的调试信息,减少文件尺寸

#include <stdio.h>
#include <pthread.h>
#include <dlfcn.h>
#include <stdlib.h>
#include <string.h>
#include <sqlite3.h>

#define DATABASE_NAME                 "MyDBDemo.db"
#define DATABASE_TABLE_NAME           "table1"
#define DATABASE_TABLE_MEMBER         "name text, age int, note text, count int"
#define DATABASE_TABLE_LABEL          "name, age, note, count"
#define CREATE                        0
#define INSERT                        1
#define DELETE                        2
#define SELECT                        3
#define UPDATE                        4
#define DROP                          5
#define VACUUM                        6
#define PRAGMA                        7

struct sqlite_db_str {
 char *sql;
};

struct sqlite_db_str db_sqlstr[] = {
 [CREATE] = { .sql = "CREATE TABLE " },
 [INSERT] = { .sql = "INSERT INTO "  },
 [DELETE] = { .sql = "DELETE FROM "  },
 [SELECT] = { .sql = "SELECT "  },
 [UPDATE] = { .sql = "UPDATE "  },
 [DROP] =   { .sql = "DROP TABLE "  },
 [VACUUM] = { .sql = "VACUUM "  },
 [PRAGMA] = { .sql = "PRAGMA "  },
};

int main(int argc, char *argv[])
{
 int ret = -1;
 int k = 0;
 sqlite3 *db_ctx = NULL;
 char *zErrMsg = NULL;

 /*Step1: create database */
 ret = sqlite3_open_v2(DATABASE_NAME, &db_ctx, SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE | SQLITE_OPEN_NOMUTEX | SQLITE_OPEN_SHAREDCACHE, NULL);
 if(ret){
  printf("Open %s database errror!, ret: %d\n", DATABASE_NAME, ret);
  return -1;
 }

 /*Step2: create table */
 char sql_buf[256] = {'\0'};
 sprintf(sql_buf, "%s %s (%s);", db_sqlstr[CREATE].sql, DATABASE_TABLE_NAME, DATABASE_TABLE_LABEL);
 ret = sqlite3_exec(db_ctx, sql_buf, NULL, NULL, &zErrMsg);
 if( ret != SQLITE_OK ){
  if( ret == 1 ){
   /* table already exists */
   printf("database [%s]: %s\n", DATABASE_NAME, zErrMsg);
  } else {
   fprintf(stderr, "SQL error: %s, ret: %d\n", zErrMsg, ret);
   sqlite3_free(zErrMsg);
   return -1;
  }
 }

 /*Step3: insert*/
 for (k = 0; k < 10; k++) {
char insert_buf[128] = {0};
sprintf(insert_buf, "'%s%d', %d, 'note_%d', %d", "Vinson", k, k, k, k);
char sql_buf[1024] = {'\0'};

unsigned int sql_prefix_len = 0;
sprintf(sql_buf, "%s %s (%s) VALUES (", db_sqlstr[INSERT].sql, DATABASE_TABLE_NAME, DATABASE_TABLE_LABEL);
sql_prefix_len = strlen(sql_buf);
memcpy(sql_buf+sql_prefix_len, insert_buf, strlen(insert_buf));
memcpy(sql_buf+sql_prefix_len + strlen(insert_buf), ");", strlen(");"));

/* INSERT table1 (name age note count) VALUES (Vinson1,note1,1,1 )*/
ret = sqlite3_exec(db_ctx, sql_buf, NULL, NULL, &zErrMsg);
if( ret != SQLITE_OK ){
fprintf(stderr, "SQL error: %s\n", zErrMsg);
sqlite3_free(zErrMsg);
return -1;
}
if (ret < 0) {
   printf("insert table error! %d\n", ret);
   return -1;
  }
 }


 /*Step4: close*/
 sqlite3_close(db_ctx);

 return 0;
}

arm-linux-gnueabihf-gcc sqlite3_test.c -o sqlite3_demo -I./build/include  -L./build/lib/ -lsqlite3 -ldl -lpthread -lm

生成测试程序
sqlite3_demo mydemodb.db
在这里插入图片描述

四十四、ssw01b调试

1、配置内核生成wifi模块
在这里插入图片描述
在这里插入图片描述
2、加载模块

# insmod /config/wifi/llc.ko
# insmod /config/wifi/stp.ko
# insmod /config/wifi/bridge.ko
# /config/wifi/ssw01bInit.sh
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib:/lib:/config/wifi

3、修改SSID与PWD
修改/appconfigs/wpa_supplicant.conf
在这里插入图片描述
4、连接路由分配IP

./wpa_supplicant -Dnl80211 -i wlan0 -c /appconfigs/wpa_supplicant.conf -d &
sleep 2
udhcpc -q -i wlan0 -s /etc/init.d/udhcpc.script &

四十五、ST7701S点屏

ST7701S要驱动RGB前需通过SPI总线初始化,只需要执行一次,使用模拟SPI时序发送初始化指令,编译生成模块,显示前调用模块即可

#include <linux/types.h>

#include <linux/kernel.h>

#include <linux/delay.h>

#include <linux/ide.h>

#include <linux/init.h>

#include <linux/module.h>

#include <linux/errno.h>

#include <linux/gpio.h>

#include <asm/mach/map.h>

#include <asm/uaccess.h>

#include <asm/io.h>



#define LED_MAJOR        200        /* 主设备号 */

#define LED_NAME        "st7701"     /* 设备名字 */



//3线spi用到的三个IO口和一个RET管脚

#define SPI_DSIO            7//PAD_TTL21 

#define SPI_SCLK            6//PAD_TTL22

#define SPI_CS              5//PAD_TTL23

#define RST_PANEL           73

 

//单字节发送

static void spi_st7701s_SendData(unsigned char i)

{

    unsigned char n;

     for(n = 0; n < 8; n++) { 

     if(i & 0x80) {

   //      printf("this bit is 1 \r\n");

         gpio_set_value(SPI_DSIO, 1);

     } else {

  //        printf("this bit is 0 \r\n");

         gpio_set_value(SPI_DSIO, 0);

     }

       

     i<<= 1;



     gpio_set_value(SPI_SCLK, 0);

     udelay(1);

     gpio_set_value(SPI_SCLK, 1);

     udelay(1);

  }

}

/*

static unsigned char Spi_St7701s_ReadByte(unsigned char id)

{

    unsigned char i,tmp = 0;





    gpio_set_value(SPI_CS, 0);

    gpio_set_value(SPI_DSIO, 0);







    gpio_set_value(SPI_SCLK, 0);

    udelay(1);

    gpio_set_value(SPI_SCLK, 1);

    udelay(1);

    



    spi_st7701s_SendData(id);

    //先写寄存器地址0x04    

    gpio_set_value(SPI_SCLK, 0);

    gpio_set_value(SPI_DSIO, 1);//设为高阻态输入模式?

    

    udelay(1);



    gpio_direction_input(SPI_DSIO);

    for(i = 0;i < 8;i++)



    {

        gpio_set_value(SPI_SCLK, 1);



        tmp <<= 1; //移位

        

        

       // printf("value is %d \r\n",value);

        if(gpio_get_value(SPI_DSIO))

        {



            tmp |= 1; //读取一位数据

        }

        

        gpio_set_value(SPI_SCLK, 0);

        

    }

    gpio_direction_output(SPI_DSIO,1);





    gpio_set_value(SPI_SCLK, 1);

    udelay(1);

    gpio_set_value(SPI_SCLK, 0);



    gpio_set_value(SPI_DSIO, 1);

    

    gpio_set_value(SPI_CS, 1);



    return tmp; //返回数据

}

*/



//写指令

static void SPI_WriteComm( unsigned char i)

{



    gpio_set_value(SPI_CS, 0);



    gpio_set_value(SPI_DSIO, 0);



    gpio_set_value(SPI_SCLK, 0);



    udelay(1);

    gpio_set_value(SPI_SCLK, 1);

    udelay(1);



    spi_st7701s_SendData(i);



    gpio_set_value(SPI_CS, 1);

}



//写数据

static void SPI_WriteData( unsigned char i)

{



    gpio_set_value(SPI_CS, 0);





    gpio_set_value(SPI_DSIO, 1);



    gpio_set_value(SPI_SCLK, 0);

    udelay(1);

    gpio_set_value(SPI_SCLK, 1);

    udelay(1);



    spi_st7701s_SendData(i);



    gpio_set_value(SPI_CS, 1);

}



//初始化

void ST7701S_Init(void)

{

    gpio_request(SPI_DSIO,"SPI_DSIO");

    gpio_request(SPI_SCLK,"SPI_SCLK");

    gpio_request(SPI_CS,"SPI_CS");

    gpio_request(RST_PANEL,"RST_PANEL");

    

    gpio_direction_output(SPI_DSIO,1);

    gpio_direction_output(SPI_SCLK,1);

    gpio_direction_output(SPI_CS,1);

    gpio_direction_output(RST_PANEL,1);



    gpio_set_value(RST_PANEL,0);

    mdelay(200);

    gpio_set_value(RST_PANEL,1);

    mdelay(200);



    SPI_WriteComm(0xFF);

    SPI_WriteData(0x77);

    SPI_WriteData(0x01);

    SPI_WriteData(0x00);

    SPI_WriteData(0x00);

    SPI_WriteData(0x10);



    SPI_WriteComm(0xC3);  //配置工作模式为DE模式,供应商给的驱动源码并没有设置该 地址 。

    SPI_WriteData(0x8C);

    SPI_WriteData(0x02);    //VBP

    SPI_WriteData(0x00);    //HBP



    SPI_WriteComm(0xCD);    //RGB format

    SPI_WriteData(0x08);        //用565时屏蔽    666打开



    SPI_WriteComm(0x0C);

    SPI_WriteData(0x60); 



    SPI_WriteComm(0x3A);

    SPI_WriteData(0x77);  //55/50=16bit(RGB565);66=18bit(RGB666);77或默认不写3AH是=24bit(RGB888)  



    SPI_WriteComm(0xEF);

    SPI_WriteData(0x08);



    SPI_WriteComm(0xFF);

    SPI_WriteData(0x77);

    SPI_WriteData(0x01);

    SPI_WriteData(0x00);

    SPI_WriteData(0x00);

    SPI_WriteData(0x10);



    SPI_WriteComm(0xC0);    //Display Line Setting

    SPI_WriteData(0x63);

    SPI_WriteData(0x00);



    SPI_WriteComm(0xC1);    //Porch Control

    SPI_WriteData(0x07);

    SPI_WriteData(0x07);



    SPI_WriteComm(0xC2);    //Inversion selection & Frame Rate Control

    SPI_WriteData(0x01);

    SPI_WriteData(0x08);



    SPI_WriteComm(0xCC);

    SPI_WriteData(0x18);



    SPI_WriteComm(0xB0);    //Power pumping clk selection 2

    SPI_WriteData(0x00);

    SPI_WriteData(0x0F);

    SPI_WriteData(0x13);

    SPI_WriteData(0x0E);

    SPI_WriteData(0x12);

    SPI_WriteData(0x08);

    SPI_WriteData(0x00);

    SPI_WriteData(0x09);

    SPI_WriteData(0x08);

    SPI_WriteData(0x1A);

    SPI_WriteData(0x05);

    SPI_WriteData(0x14);

    SPI_WriteData(0x11);

    SPI_WriteData(0x21);

    SPI_WriteData(0x2B);

    SPI_WriteData(0x1F);



    SPI_WriteComm(0xB1);    //VCOM amplitude setting

    SPI_WriteData(0x0C);

    SPI_WriteData(0x11);

    SPI_WriteData(0x18);

    SPI_WriteData(0x0D);

    SPI_WriteData(0x10);

    SPI_WriteData(0x05);

    SPI_WriteData(0x02);

    SPI_WriteData(0x07);

    SPI_WriteData(0x07);

    SPI_WriteData(0x1C);

    SPI_WriteData(0x04);

    SPI_WriteData(0x12);

    SPI_WriteData(0x11);

    SPI_WriteData(0x22);

    SPI_WriteData(0x26);

    SPI_WriteData(0x1F);



    SPI_WriteComm(0xFF);

    SPI_WriteData(0x77);

    SPI_WriteData(0x01);

    SPI_WriteData(0x00);

    SPI_WriteData(0x00);

    SPI_WriteData(0x11);



    SPI_WriteComm(0xB0);    //Vop Amplitude setting

    SPI_WriteData(0x80);



    SPI_WriteComm(0xB1);    //VCOM amplitude setting

    SPI_WriteData(0x59);



    SPI_WriteComm(0xB2);    //VGH Voltage setting

    SPI_WriteData(0x87);



    SPI_WriteComm(0xB3);    //TEST Command Setting

    SPI_WriteData(0x80);



    SPI_WriteComm(0xB5);    //VGL Voltage setting

    SPI_WriteData(0x4D);



    SPI_WriteComm(0xB7);    //Power Control 1

    SPI_WriteData(0x85);



    SPI_WriteComm(0xB8);    //Power Control 2

    SPI_WriteData(0x21);



    SPI_WriteComm(0xB9);    //Power Control 2

    SPI_WriteData(0x10);



    SPI_WriteComm(0xBB);    //Power pumping clk selection 2

    SPI_WriteData(0x03);



    SPI_WriteComm(0xC1);    //Source pre_drive timing set1

    SPI_WriteData(0x78);



    SPI_WriteComm(0xC2);    //Source EQ2 Setting

    SPI_WriteData(0x78);



    SPI_WriteComm(0xD0);    //MIPI Setting 1

    SPI_WriteData(0x88);



    SPI_WriteComm(0xE0);    //Sunlight Readable Enhancement

    SPI_WriteData(0x80);

    SPI_WriteData(0x00);

    SPI_WriteData(0x02);



    SPI_WriteComm(0xE1);    //Noise Reduce Control

    SPI_WriteData(0x01);	

    SPI_WriteData(0xA0);	

    SPI_WriteData(0x00);	

    SPI_WriteData(0x00);	

    SPI_WriteData(0x02);	

    SPI_WriteData(0xA0);	

    SPI_WriteData(0x00);	

    SPI_WriteData(0x00);	

    SPI_WriteData(0x00);	

    SPI_WriteData(0x20);	

    SPI_WriteData(0x20);	



    SPI_WriteComm(0xE2);	//Sharpness Control

    SPI_WriteData(0x30);	

    SPI_WriteData(0x30);	

    SPI_WriteData(0x20);	

    SPI_WriteData(0x20);	

    SPI_WriteData(0x25);

    SPI_WriteData(0xA0);	

    SPI_WriteData(0x00);	

    SPI_WriteData(0x00);

    SPI_WriteData(0x26);

    SPI_WriteData(0xA0);	

    SPI_WriteData(0x00);	

    SPI_WriteData(0x00);

    SPI_WriteData(0x00);	



    SPI_WriteComm(0xE3);	   //Color Calibration Control

    SPI_WriteData(0x00);	

    SPI_WriteData(0x00);	

    SPI_WriteData(0x33);	

    SPI_WriteData(0x33);	



    SPI_WriteComm(0xE4);	    //Skin Tone Preservation Control

    SPI_WriteData(0x44);	

    SPI_WriteData(0x44);	



    SPI_WriteComm(0xE5);	

    SPI_WriteData(0x03);	

    SPI_WriteData(0x33);	

    SPI_WriteData(0xA0);	

    SPI_WriteData(0xA0);	

    SPI_WriteData(0x05);	

    SPI_WriteData(0x2D);	

    SPI_WriteData(0xA0);	

    SPI_WriteData(0xA0);	

    SPI_WriteData(0x07);	

    SPI_WriteData(0x2F);	

    SPI_WriteData(0xA0);	

    SPI_WriteData(0xA0);	

    SPI_WriteData(0x09);	

    SPI_WriteData(0x31);	

    SPI_WriteData(0xA0);	

    SPI_WriteData(0xA0);	



    SPI_WriteComm(0xE6);	

    SPI_WriteData(0x00);	

    SPI_WriteData(0x00);	

    SPI_WriteData(0x33);	

    SPI_WriteData(0x33);	



    SPI_WriteComm(0xE7);	

    SPI_WriteData(0x44);	

    SPI_WriteData(0x44);	



    SPI_WriteComm(0xE8);	

    SPI_WriteData(0x04);	

    SPI_WriteData(0x34);	

    SPI_WriteData(0xA0);	

    SPI_WriteData(0xA0);	

    SPI_WriteData(0x06);	

    SPI_WriteData(0x2E);	

    SPI_WriteData(0xA0);	

    SPI_WriteData(0xA0);	

    SPI_WriteData(0x08);	

    SPI_WriteData(0x30);	

    SPI_WriteData(0xA0);	

    SPI_WriteData(0xA0);	

    SPI_WriteData(0x0A);	

    SPI_WriteData(0x32);	

    SPI_WriteData(0xA0);	

    SPI_WriteData(0xA0);	



    SPI_WriteComm(0xE9);

    SPI_WriteData(0x36);

    SPI_WriteData(0x00);



    SPI_WriteComm(0xEB);

    SPI_WriteData(0x00);

    SPI_WriteData(0x02);

    SPI_WriteData(0x93);

    SPI_WriteData(0x93);

    SPI_WriteData(0x88);

    SPI_WriteData(0x00);

    SPI_WriteData(0x40);



    SPI_WriteComm(0xEC);

    SPI_WriteData(0xFF);

    SPI_WriteData(0x01);



    SPI_WriteComm(0xED);

    SPI_WriteData(0x2F);

    SPI_WriteData(0x0A);

    SPI_WriteData(0xB4);

    SPI_WriteData(0x56);

    SPI_WriteData(0x7F);

    SPI_WriteData(0xFF);

    SPI_WriteData(0xFF);

    SPI_WriteData(0xFF);

    SPI_WriteData(0xFF);

    SPI_WriteData(0xFF);

    SPI_WriteData(0xFF);

    SPI_WriteData(0xF7);

    SPI_WriteData(0x65);

    SPI_WriteData(0x4B);

    SPI_WriteData(0xA0);

    SPI_WriteData(0xF2);



    SPI_WriteComm(0xEF);

    SPI_WriteData(0x08);

    SPI_WriteData(0x08);

    SPI_WriteData(0x08);

    SPI_WriteData(0x45);

    SPI_WriteData(0x3F);

    SPI_WriteData(0x54);



    SPI_WriteComm(0xFF);

    SPI_WriteData(0x77);

    SPI_WriteData(0x01);

    SPI_WriteData(0x00);

    SPI_WriteData(0x00);

    SPI_WriteData(0x13);



    SPI_WriteComm(0xE8);

    SPI_WriteData(0x00);

    SPI_WriteData(0x0E);



    SPI_WriteComm(0xFF);

    SPI_WriteData(0x77);

    SPI_WriteData(0x01);

    SPI_WriteData(0x00);

    SPI_WriteData(0x00);

    SPI_WriteData(0x00);



    SPI_WriteComm(0x11);

    mdelay(120);



    SPI_WriteComm(0xFF);

    SPI_WriteData(0x77);

    SPI_WriteData(0x01);

    SPI_WriteData(0x00);

    SPI_WriteData(0x00);

    SPI_WriteData(0x13);



    SPI_WriteComm(0xE8);

    SPI_WriteData(0x00);

    SPI_WriteData(0x0C);



    mdelay(20);



    SPI_WriteComm(0xE8);

    SPI_WriteData(0x00);

    SPI_WriteData(0x00);



    SPI_WriteComm(0xFF);

    SPI_WriteData(0x77);

    SPI_WriteData(0x01);

    SPI_WriteData(0x00);

    SPI_WriteData(0x00);

    SPI_WriteData(0x00);



    SPI_WriteComm(0x36);    //Display data access control

    SPI_WriteData(0x48);



    SPI_WriteComm(0x29);

    

    printk("st7701s init finished!!!\n");

}





/*

 * @description        : 打开设备

 * @param - inode     : 传递给驱动的inode

 * @param - filp     : 设备文件,file结构体有个叫做private_data的成员变量

 *                       一般在open的时候将private_data指向设备结构体。

 * @return             : 0 成功;其他 失败

 */

static int st7701_open(struct inode *inode, struct file *filp)

{

    return 0;

}



/*

 * @description        : 从设备读取数据 

 * @param - filp     : 要打开的设备文件(文件描述符)

 * @param - buf     : 返回给用户空间的数据缓冲区

 * @param - cnt     : 要读取的数据长度

 * @param - offt     : 相对于文件首地址的偏移

 * @return             : 读取的字节数,如果为负值,表示读取失败

 */

static ssize_t st7701_read(struct file *filp, char __user *buf, size_t cnt, loff_t *offt)

{

    return 0;

}



/*

 * @description        : 向设备写数据 

 * @param - filp     : 设备文件,表示打开的文件描述符

 * @param - buf     : 要写给设备写入的数据

 * @param - cnt     : 要写入的数据长度

 * @param - offt     : 相对于文件首地址的偏移

 * @return             : 写入的字节数,如果为负值,表示写入失败

 */

static ssize_t st7701_write(struct file *filp, const char __user *buf, size_t cnt, loff_t *offt)

{



    return 0;

}



/*

 * @description        : 关闭/释放设备

 * @param - filp     : 要关闭的设备文件(文件描述符)

 * @return             : 0 成功;其他 失败

 */

static int st7701_release(struct inode *inode, struct file *filp)

{

    return 0;

}



/* 设备操作函数 */

static struct file_operations st7701_fops = {

    .owner = THIS_MODULE,

    .open = st7701_open,

    .read = st7701_read,

    .write = st7701_write,

    .release =     st7701_release,

};



/*

 * @description    : 驱动出口函数

 * @param         : 无

 * @return         : 无

 */

static int __init st7701_init(void)

{

    int retvalue = 0;

    

    ST7701S_Init();



    /* 6、注册字符设备驱动 */

    retvalue = register_chrdev(200, "st7701", &st7701_fops);

    if(retvalue < 0){

        printk("register chrdev failed!\r\n");

        return -EIO;

    }

    return 0;

}



/*

 * @description    : 驱动出口函数

 * @param         : 无

 * @return         : 无

 */

static void __exit st7701_exit(void)

{

    /* 注销字符设备驱动 */

    unregister_chrdev(200, "st7701");

}



module_init(st7701_init);

module_exit(st7701_exit);

MODULE_LICENSE("GPL");

MODULE_AUTHOR("kun");

ST7701S_Init函数的初始化命令序列向屏厂获取

四十六、bootlogo修改UBOOT RGB为第十二组

1、boot/drivers/mstar/panel/hal/infinity2m/src/hal_pnl.c
2、修改函数HalPnlSetTTLPadMux在这里插入图片描述

if(enFmt == E_HAL_PNL_OUTPUT_565BIT_MODE)
    {
        //W2BYTEMSK(REG_CHIPTOP_0D_L,0x0D00,0x0F00); // TTL Mode = 13
		W2BYTEMSK(REG_CHIPTOP_0F_L,0x0000,0xFFFF);
        W2BYTEMSK(REG_CHIPTOP_0E_L,0x0000,0xFFFF);
        W2BYTEMSK(REG_CHIPTOP_0D_L,0x0D00,0xFFFF); // TTL Mode = 13
    }
    else if(enFmt == E_HAL_PNL_OUTPUT_8BIT_MODE)
    {
        //W2BYTEMSK(REG_CHIPTOP_0D_L,0x0100,0x0F00); // TTL Mode = 1
		//W2BYTEMSK(REG_CHIPTOP_0D_L,0x0C00,0x0F00); // TTL Mode = 1
		W2BYTEMSK(REG_CHIPTOP_0F_L,0x0000,0xFFFF);
        W2BYTEMSK(REG_CHIPTOP_0E_L,0x0000,0xFFFF);
        W2BYTEMSK(REG_CHIPTOP_0D_L,0x0100,0xFFFF); // TTL Mode = 1
    }

3、make boot,刷boot,内核,bootlogo 0 0 0 0 0

四十七、建立基于mosquitto的MQTT服务器

1、openssl交叉编译
版本 openssl1.1.1g
下载:https://www.openssl.org/source/old/

mkdir build
./config no-asm -shared --prefix=/home/dm/ssd201/mosquitto/openssl-1.1.1g/build CC=arm-linux-gnueabihf-gcc CXX=arm-linux-gnueabihf-g++
make
make install

2、c-ares库交叉编译
https://c-ares.haxx.se/download/c-ares-1.14.0.tar.gz

mkdir build
./configure --host=arm-linux CC=arm-linux-gnueabihf-gcc --prefix=/home/dm/ssd201/mosquitto/c-ares-1.14.0/build
make && make install

3、e2fsprogs交叉编译
下载地址:https://sourceforge.net/projects/e2fsprogs/files/e2fsprogs/1.41.14/e2fsprogs-1.41.14.tar.gz/download

四十八、SDL

使用FFmpeg解码并播放视频,需要依赖SDL库进行渲染播放;
ffplay是以FFmpeg框架为基础,外加渲染音视频的库libSDL构建的媒体文件播放器

# wget http://www.libsdl.org/release/SDL2-2.0.12.tar.gz
# tar xvzf SDL2-2.0.12.tar.gz
# cd SDL2-2.0.12
# ./configure --prefix=/home/dm/ssd201/SDL/SDL2-2.0.12/build --host=arm-linux CC=arm-linux-gnueabihf-gcc --target=arm-linux --disable-pulseaudio
# make
# make install

避免这个错误提示,添加配置选项–disable-pulseaudio
在这里插入图片描述

四十九、FFMPGE与H264交叉编译

查看摄像头所有支持的格式

v4l2-ctl --list-formats-ext -d /dev/video0

下载地址 https://ffmpeg.org/releases/
tar -xvjf ffmpeg-4.1.3.tar.bz2

./configure --prefix=/usr/local/x264 --enable-shared --enable-static --host=arm-linux --cross-prefix=arm-linux-gnueabihf- --disable-opencl --enable-pic --disable-asm

export PKG_CONFIG_PATH=/home/dm/ssd201/rtsp/x264-master

./configure --pkg-config="pkg-config --static" --enable-libx264 --enable-shared --enable-gpl --target-os=linux --arch=arm32 --cross-prefix=arm-linux-gnueabihf- --prefix=/home/dm/ssd201/ffmpeg-6.1/build --extra-libs=-ldl --extra-cflags="-I/home/dm/ssd201/rtsp/x264-master" --extra-ldflags="-L/home/dm/ssd201/rtsp/x264-master"

make & make install

使用FFmpeg来播放视频并通过framebuffer显示

ffmpeg -i input.mp4 -vf scale=1280:720 -pix_fmt rgb565 -f rawvideo -r 30 - | sudo dd of=/dev/fb0 bs=720 count=1280

-i input.mp4:这是输入文件,你需要替换为你要播放的视频文件的路径。
-vf scale=1280:720:这是视频滤镜,用来调整视频的分辨率。你需要根据你的显示器的分辨率来调整这个值。
-pix_fmt rgb565:这是输出的像素格式。framebuffer通常使用rgb565的格式。
-f rawvideo:这是输出的格式,我们需要原始的未压缩的视频数据。
-r 30:这是输出的帧率,你可以根据需要调整。
| sudo dd of=/dev/fb0 bs=720 count=1280:这是将FFmpeg的输出重定向到framebuffer设备。你需要根据你的设备文件路径来修改。

将USB摄像头推流到RTSP,视频MP4编码,音频MP3编码

ffmpeg -f video4linux2 -s 640x480 -r 30 -i /dev/video0 -vcodec mjpeg/h264 -f alsa -thread_queue_size 1024 -ac 2 -ar 44100 -i plug:hw:1 -acodec mp3 -f rtsp rtsp://192.168.82.104:8554/camera_test

下载rtsp服务器: https://github.com/bluenviron/mediamtx/releases
运行rtsp可执行文件,把rtsp服务拉起来。
在这里插入图片描述
本地文件推流:
UDP:

ffmpeg -re -i input.mp4 -c copy -f rtsp rtsp://127.0.0.1:8554/stream
TCP:

ffmpeg -re -i input.mp4 -c copy -rtsp_transport tcp -f rtsp rtsp://127.0.0.1:8554/stream
循环推流:

ffmpeg -re -stream_loop -1 -i input.mp4 -c copy -f rtsp rtsp://127.0.0.1:8554/stream
参数:-re 以流的方式读取 -f 为格式化输出到哪里 -stream_loop循环输入

读取音视频设备推流:

ffmpeg -f dshow -i video=“name” -f rtsp rtsp://127.0.0.1:8554/stream
vlc/ffplay拉流
ffplay拉流:

ffplay rtsp://127.0.0.1:8554/stream

五十、转VGA输出

GM7123 模拟视频输出方式支持有以下几种:
1、模拟RGB+HSYNC+VHYNC。
2、模拟RGB+CSYNC(CSYNC和HSYNC为同一pin输出),这种方式的实现需要外部加一个门电路的IC,把分离同步变为复合同步 。
3、模拟RGB,同步信号附在G上面,这种方式需要跟BLANK和SYNC脚配合才能够实现,一般这种方式使用的不多。

关于7123的应用电路,有如下疑问:
1、数字RGB888和数字RGB565输出到7123的接法?(包括HSYNC VSYNC)
答:用户接过来的数字RGB888和数字RGB565信号直接到GM7123的数据RGB高位,GM7123没接的低位数字RGB线就通过零欧电阻接地或直接接地。

2、7123引脚Vref 、Psave 有没有固定接法?
答:这个Vref端口是输出参考电压,通常VREF脚外接0.1μF电容。Psave为芯片节能休眠脚,接低电平为芯片休眠,芯片无信号输出,与控制关掉打开 电源 的区别是,更快让芯片投入工作状态。

3、7123引脚BLANK和SYNC有没有固定接法?
答:引脚BLANK(消隐信号输入)和SYNC(复合同步输入)一般都是不用的,分别BLANK通过一个0欧电阻接高电平拉高,SYNC通过一个0欧电阻接地拉低,除非要同步到绿色通道,这种用法很少
4、/IOR /IOG /IOB的接法?
答:这是各颜色通道(模拟)的差分信号,它们分别和IOR IOG IOB配对做差分输出(类似于LVDS),不用的话可以接地,一般不用而一般输出接显示器只用到IOR 、IOG 、IOB。

5.电源电压如何判定
引脚13的电源电压为数字电路供电,引脚29、30的电源电压为模拟电路供电。
6.引脚37的电阻阻值如何确定
引脚37通过电阻RSET连接到地,其作用是控制最大输出电流的大小,典型值510Ω。建议RSET的阻值从510Ω~4933Ω,阻值越小,图像越亮。
7.负载电阻RL如何确定
根据不同的接口标准,负载电阻阻值不同,典型值75Ω。

8.资料下载

http://www.any2go.com/tbbs/viewforum.php?f=11
常用分辨率时序参数
在这里插入图片描述
如果实际连线不是默认的连线,则需要修改 swap 值。需要关注以下 4 个值:
m_bPanelSwapOdd_RG,其值为 0 或 3 时,对应 R;值为 1 时,对应 B;值为 2 时,对应 G;
在这里插入图片描述
m_bPanelSwapEven_RG,其值为 0 或 2 时,对应 G;值为 1 时,对应 B;值为 3 时,对应 R;
在这里插入图片描述
m_bPanelSwapOdd_GB,其值为 0 或 1 时,对应 B;值为 1 时,对应 B;值为 2 时,对应 G;
在这里插入图片描述
m_bPanelSwapEven_GB,其值为 0 时,RGB 高低位不反转;值为 1 时,RGB 高 低位反转
在这里插入图片描述
网络上的m3u8视频源地址
1、http://devimages.apple.com/iphone/samples/bipbop/bipbopall.m3u8
2、http://kbs-dokdo.gscdn.com/dokdo_300/definst/dokdo_300.stream/playlist.m3u8

五十一

route add default gw 192.168.82.1
echo "nameserver 8.8.8.8" >> /etc/resolv.conf
./nfs/ssplayer file https://live-play.cctvnews.cctv.com/cctv/merge_cctv13.m3u8

五十二、live555

https://download.videolan.org/pub/contrib/live555/
wget https://www.openssl.org/source/old/1.0.2/openssl-1.0.2h.tar.gz
为与ffplayer的openssl版本兼容,需要使用版本比较旧的live555与openssl

1、下载openssl
https://www.openssl.org/source/old/
我这里下载的是 openssl-1.1.0l.tar.gz

2、编译openssl

$ mkdir ssl_result
$ tar zxvf openssl-1.1.0l.tar.gz
$ cd openssl-1.1.0l

3、指定安装目录、交叉编译器

./config no-asm shared no-async --prefix=/home/dm/ssd201/live555/openssl-1.1.0l/build  --cross-compile-prefix=arm-linux-gnueabihf-

4、修改Make file,删除 -m64,可以在Makefile去搜索删除,共两处,也可以使用以下命令删除

sed -i 's/-m64//' Makefile

5、编译安装

make && make install

6、下载live555
http://www.live555.com/liveMedia/
下载的版本 live.2022.01.06.tar.gz

7、解压live555

$ tar zxvf live.2022.01.06.tar.gz 
$ cd live

8、生成Makefile
利用config.armlinux文件来生成Makefile,先复制config.armlinux为config.ssd202
修改config文件,交叉编译器,头文件包含路径,openssl链接库路径,添加c++20支持

CROSS_COMPILE?=		arm-linux-gnueabihf-
COMPILE_OPTS =		$(INCLUDES) -I/usr/local/include -I/home/dm/ssd201/live555/openssl-1.1.0l/build/include -I. -O2 -DSOCKLEN_T=socklen_t -DNO_SSTREAM=1 -D_LARGEFILE_SOURCE=1 -D_FILE_OFFSET_BITS=64
C =			c
C_COMPILER =		$(CROSS_COMPILE)gcc
C_FLAGS =		$(COMPILE_OPTS)
CPP =			cpp
CPLUSPLUS_COMPILER =	$(CROSS_COMPILE)g++
CPLUSPLUS_FLAGS =	$(COMPILE_OPTS) -Wall -DBSD=1 -std=c++2a
OBJ =			o
LINK =			$(CROSS_COMPILE)g++ -o
LINK_OPTS =		
CONSOLE_LINK_OPTS =	$(LINK_OPTS)
LIBRARY_LINK =		$(CROSS_COMPILE)ar cr 
LIBRARY_LINK_OPTS =	$(LINK_OPTS)
LIB_SUFFIX =			a
LIBS_FOR_CONSOLE_APPLICATION = -L/home/dm/ssd201/live555/openssl-1.1.0l/build/lib -lssl -lcrypto
LIBS_FOR_GUI_APPLICATION =
EXE =

生成Makefile

./genMakefiles ssd202

9、编译报错

BasicTaskScheduler.cpp:191:40: error: ‘struct std::atomic_flag’ has no member named ‘test’
       if (fTriggersAwaitingHandling[i].test()) {

Makefile:42: recipe for target 'BasicTaskScheduler.o' failed

找到BasicTaskScheduler.cpp,找到上面这段,修改test()为test_and_set()

**生成应用与视频要拷贝到板子,不能放在NFS,不然能启动但连接不上 **

需要使用live555流媒体服务器详细看看音视频编解器资料
https://blog.csdn.net/yangguoyu8023/category_9153627.html

LIVE555 适配SSD202 H264硬解
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

五十三、基于paho的MQTT客户端

1、git clone https://github.com/eclipse/paho.mqtt.c.git
2、cd paho.mqtt.c
3、mkdir build & cd build
4、cmake .. -DPAHO_BUILD_STATIC=TRUE -DCMAKE_TOOLCHAIN_FILE=../cmake/toolchain.linux-arm11.cmake

在build/src目录生成库

五十四、BOA WEB服务器编译

boa服务器的交叉编译

1 boa官网下载源码

    此处下载boa官网最新的release版本(boa-0.94.13)的源码为例(boa已经很久未进行更新和维护了),进行交叉编译;

    下载好的boa源码为:boa-0.94.13.tar.gz

2 解压boa,并进行如下操作:
tar -zvxf boa-0.94.13.tar.gz
gcf@ubuntu:~/workfile/tools/boa$ cd boa-0.94.13/
gcf@ubuntu:~/workfile/tools/boa/boa-0.94.13$ ls
boa.conf   contrib  docs      extras       README
ChangeLog  CREDITS  examples  Gnu_License  src
gcf@ubuntu:~/workfile/tools/boa/boa-0.94.13$ cd src/
gcf@ubuntu:~/workfile/tools/boa/boa-0.94.13/src$ 
gcf@ubuntu:~/workfile/tools/boa/boa-0.94.13/src$ ./configure 

3 执行"./configure" 后(若无法执行,请赋予 configure 文件的权限为755),在src目录下会生成一个Makefile
4 修改Makefile文件

找到Makefile中的如下两行:

#Makefile文件,找到如下两行
CC = gcc
CPP = gcc -E
将其修改为与你开发板所对应的交叉工具(请确保已将交叉编译工具设置为环境变量),如下所示:

CC = arm-linux-gnueabihf-gcc
CPP = arm-linux-gnueabihf-gcc -E
5、make
在这里插入图片描述
sudo apt install bison
在这里插入图片描述
sudo apt install flex
make 过程会遇到2个错误,安装软件包

在这里插入图片描述
一个编译错误
打开compat.h
在这里插入图片描述
将以上两个##符号去掉

6、部署
在这里插入图片描述
sudo mkdir /etc/boa
cp boa.conf /etc/boa

[14/Jan/2021:03:19:55 +0000] log.c:73 - unable to dup2 the error log: Bad file descriptor
在这里插入图片描述
在这里插入图片描述
注释掉两个log文件
添加静态网页路径
在这里插入图片描述
在这里插入图片描述
修改CGI路径
在这里插入图片描述
点击按钮触发CGI程序调用返回数据
在这里插入图片描述
在这里插入图片描述
前端下发请求,提示没有权限
Access to XMLHttpRequest at ‘http://192.168.82.168/cgi-bin/scene.cgi’ from origin ‘http://localhost:5173’ has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource.

CGI程序添加

printf("Content-Type: application/json\r\n");  
        
 // 设置允许的源。出于安全考虑,不要使用'*'。这里假设只允许example.com访问  
// const char *allowed_origin = "https://example.com";  
printf("Access-Control-Allow-Origin: *\r\n");  
                
// 如果需要,设置其他CORS头,例如允许的方法和头  
printf("Access-Control-Allow-Methods: GET, POST\r\n");  
printf("Access-Control-Allow-Headers: Content-Type\r\n");  
                
// 对于预检请求(OPTIONS),可能还需要设置其他响应头  
// 例如,设置缓存时间为一天  
printf("Access-Control-Max-Age: 86400\r\n");  
                
// 发送一个空行,标志着HTTP头的结束和内容的开始  
printf("\r\n");  

7、BOA交叉编译

(1)修改makefile
CC = arm-linux-gnueabihf-gcc
CPP = arm-linux-gnueabihf-gcc -E

(2)运行错误
No such user: nobody
此时,需要修改boa.conf
将 User nobody
Group nogroup
改为:User 0
Group 0

(3)Could not open mime.types file, “/etc/mime.types”, for reading
提示没有这个mime.types文件
我们将ubuntu系统里的这个文件拷贝到目标板/etc/目录下
cp /etc/mime.types /etc/

(4)gethostbyname:: Resource temporarily unavailable
提示无法获取主机名
修改boa.conf
去掉注释
ServerName www.your.org.here

(5)系统没有任何反应,ps查看进程 也没有boa
解决办法是回到src源码目录下打来boa.c文件,注释掉与icky相关语句
/*
if (setuid(0) != -1) {
DIE(“icky Linux kernel bug!”);
}
/
/

if (passwdbuf == NULL) {
DIE(“getpwuid”);
}
*/
再一次重新编译源代码

五十五、通过stm32f030cc扩展6路串口、IO与红外

由于实际项目需求,需要扩展18路串口,SSD202通过I2C与三片stm32f030cc通讯,实现串口扩展,适用于我低速外设的轮询
以下stm32端的I2C驱动代码,通过中断接收与发送操作

void I2C1_IRQHandler(void)
{
  /* USER CODE BEGIN I2C1_IRQn 0 */

  /* USER CODE END I2C1_IRQn 0 */
  if (hi2c1.Instance->ISR & (I2C_FLAG_BERR | I2C_FLAG_ARLO | I2C_FLAG_OVR)) {
    HAL_I2C_ER_IRQHandler(&hi2c1);
  } else {
    HAL_I2C_EV_IRQHandler(&hi2c1);
  }
  /* USER CODE BEGIN I2C1_IRQn 1 */

  /* USER CODE END I2C1_IRQn 1 */
}

/**
  * @brief I2C1 Initialization Function
  * @param None
  * @retval None
  */
static void MX_I2C1_Init(void)
{

  /* USER CODE BEGIN I2C1_Init 0 */

  /* USER CODE END I2C1_Init 0 */

  /* USER CODE BEGIN I2C1_Init 1 */

  /* USER CODE END I2C1_Init 1 */
  hi2c1.Instance = I2C1;
  hi2c1.Init.Timing = 0x20000215;
  hi2c1.Init.OwnAddress1 = storage_pmt_ptr()->i2c_addr;
  hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
  hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
  hi2c1.Init.OwnAddress2 = 0;
  hi2c1.Init.OwnAddress2Masks = I2C_OA2_NOMASK;
  hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
  hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
  if (HAL_I2C_Init(&hi2c1) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure Analogue filter
  */
  if (HAL_I2CEx_ConfigAnalogFilter(&hi2c1, I2C_ANALOGFILTER_ENABLE) != HAL_OK)
  {
    Error_Handler();
  }

  /** Configure Digital filter
  */
  if (HAL_I2CEx_ConfigDigitalFilter(&hi2c1, 0) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN I2C1_Init 2 */
    HAL_I2C_EnableListen_IT(&hi2c1);
  /* USER CODE END I2C1_Init 2 */
}

/**
  * Enable DMA controller clock
  */
//static void MX_DMA_Init(void)
//{

//  /* DMA controller clock enable */
//  __HAL_RCC_DMA1_CLK_ENABLE();

//  /* DMA interrupt init */
//  /* DMA1_Channel2_3_IRQn interrupt configuration */
//  HAL_NVIC_SetPriority(DMA1_Channel2_3_IRQn, 0, 0);
//  HAL_NVIC_EnableIRQ(DMA1_Channel2_3_IRQn);

//}

uint16_t recv_len;
uint8_t  recv_frame;
// 侦听完成回调函数(完成一次完整的i2c通信以后会进入该函数)
void HAL_I2C_ListenCpltCallback(I2C_HandleTypeDef *hi2c)
{
    // 完成一次通信,清除状态
    recv_frame = 0;
//    offset = 0;
    HAL_I2C_EnableListen_IT(hi2c); // slave is ready again
}

// I2C设备地址回调函数(地址匹配上以后会进入该函数)
void HAL_I2C_AddrCallback(I2C_HandleTypeDef *hi2c, uint8_t TransferDirection, uint16_t AddrMatchCode)
{
    if(TransferDirection == I2C_DIRECTION_TRANSMIT) 
    {// 主机发送,从机接收
        //接收前四个数据
        HAL_I2C_Slave_Seq_Receive_IT(hi2c, i2c_recv_buf, 4, I2C_NEXT_FRAME);  // 每次第1个数据均为偏移地址
        recv_frame = 1;
    } 
    else 
    {
        if( send_seg==0 ){
            send_seg = 1;
            HAL_I2C_Slave_Seq_Transmit_IT(hi2c, &i2c_send_buf[0], 4, I2C_NEXT_FRAME);  // 打开中断并把ram[]里面对应的数据发送给主机
        }
        else if( send_seg==1 ){
            send_seg = 0;
            HAL_I2C_Slave_Seq_Transmit_IT(hi2c, &i2c_send_buf[4], sizeof(i2c_send_buf)-4, I2C_NEXT_FRAME);
        }
    }
}

// I2C数据接收回调函数(在I2C完成一次接收时会关闭中断并调用该函数,因此在处理完成后需要手动重新打开中断)
void HAL_I2C_SlaveRxCpltCallback(I2C_HandleTypeDef *hi2c)
{
    if(recv_frame==1) 
    {
        //接收剩余数据
        recv_frame = 2;
        host_protocol_t *host_ptr = (host_protocol_t *)i2c_recv_buf;
        recv_len = host_ptr->len+2;
        HAL_I2C_Slave_Seq_Receive_IT(hi2c, &i2c_recv_buf[4], recv_len, I2C_NEXT_FRAME);
    } 
    else if(recv_frame==2) 
    {
        //接收完成
        host_protocol_t *host_ptr = (host_protocol_t *)i2c_recv_buf;
//        void *buf = rt_malloc(host_frame_len(host_ptr->len));
//        LOG_HEX("recvbuf", 16, i2c_recv_buf, host_frame_len(host_ptr->len));
//        if( buf ){
//            rt_memcpy(buf, i2c_recv_buf, host_frame_len(host_ptr->len));
            host_push_msg(i2c_recv_buf, host_frame_len(host_ptr->len));
//        }
    }
    // 打开I2C中断接收,下一个收到的数据将存放到ram[offset]
}

以下为主控端的驱动代码,所有I2C操作只能由主控发起

int expitf_write(uint8_t slave_addr,host_dev_t dev, host_cmd_t cmd, void *dev_data, uint16_t len)
{
    void *send_buf;
    int ret;
    
    uint16_t buf_len = sizeof(host_protocol_t)-1+len + 2;
    send_buf = malloc(buf_len);
    if( send_buf ){
        memset(send_buf,0,buf_len);
        
        host_protocol_t *host = (host_protocol_t *)send_buf;
        ir_t *ir_dest = (ir_t *)&host->data;
        host->dev = dev;
        host->cmd_reply = cmd;
        host->len = len;
        memcpy(&host->data,dev_data,len);
        
        uint16_t *crc = (uint16_t*)((uint8_t*)send_buf+buf_len-2);
        *crc = crc16_cal(send_buf, buf_len-2);
        
        i2c_write(expitf_fd, slave_addr, send_buf ,buf_len);

        free(send_buf);

        ret = 0;
    }
    else{
        ret = -1;
    }
    return ret;
}

void* expitf_read( uint8_t slave_addr )
{
    static uint8_t recv_buf[1024];
    i2c_read(expitf_fd, slave_addr, recv_buf ,4);

    host_protocol_t *host_ptr = (host_protocol_t *)recv_buf;
    uint16_t recv_len = host_ptr->len+2;

    i2c_read(expitf_fd, slave_addr, &recv_buf[4] ,recv_len);
    // debug_hexdump("i2c recv:", recv_buf, host_frame_len(host_ptr->len));

    uint16_t  crc = *((uint16_t*)((uint8_t*)recv_buf + crc_pos(host_ptr->len)));
    // if( crc16_cal(recv_buf, host_frame_len(host_ptr->len)) == crc )
    // else
    //     return NULL;

    return recv_buf;
}

五十六、搭建RTSP转M3U8服务

由于星宸官方的播放器只提供了m3u8流格式的播放,如需播放rtsp流,可用FFMPEG搭建RTSP转m3u8服务器
前提需要 有一个WEB服务器

ffmpeg -rtsp_transport tcp -i "rtsp://192.168.0.31:554/main" -fflags flush_packets -max_delay 1 -an -flags -global_header -hls_time 1 -hls_list_size 3 -hls_wrap 3 -vcodec copy -s 216x384 -b 1024k -y /home/dm/ssd201/boa/www/ajax_cgi-master/video/test2.m3u8

/home/dm/ssd201/boa/www/ajax_cgi-master/video为WEB服务器的目录

设备端输入即可播放

./nfs/ssplayer file http://192.168.82.168/video/test2.m3u8

VLC端输入址址也可播放

http://192.168.82.168/video/test2.m3u8

五十七、Ubuntu 16.04系统启动时卡在:(initramfs)

背景:
由于不正常的关机和重启,或者突然断电导致的关机,下次起来后不能进去系统,停留在(initramfs)。
解决方法:
使用如下命令修复

fsck -y /dev/sda1

五十八、几种视频流的捉包比较
1、M3U8
在这里插入图片描述
M3U8利用TCP传输视频帧及会话信息

2、MPEG TS RTSP封包
在这里插入图片描述
在这里插入图片描述
会话层使用RTSP,视频流的传输使用RTP,分成7个包,每个包188字节
3、RTP
在这里插入图片描述
rtp 摄像头用得多,rtsp会话层,rtp传输视频数据,如H264、H265,适合直接送到解码器解视频

4、MPEG TS TCP封包在这里插入图片描述
HTTP会话层,TCP视频流封包,不像MPEG TS RTSP分成多个小包

当然还有其它的传输模式,RTMP与RTSP相似,RTMP走TCP层,RTSP走UDP层,m3u8针对直播及网络电视,mpeg ts(HTTP、RTSP)针对数字电视,RTP RTSP针对网络摄像头

##ROS

参考链接
http://doc.industio.com/docs/1ssd20x-system/page_0
http://wx.comake.online/doc/doc/1TAKOYAKI_DLC00V050_20211216/customer/development/arch/arch.html
http://wx.comake.online/doc/182udj67fg21d-SSC339/index.html
https://wx.comake.online/doc/doc/1SigmaStarDocs-SSC9381G_9351_Pudding-ULS00V040-20210913/index.html
https://wx.comake.online/doc/1DD22dk2f3zx-SSD21X-SSD22X/index.html

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

纵向深耕

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值