SDK默认自动加载USB存储模块,但没有自动挂载,插上U盘后识别sda
mount /dev/sda /mnt/
即可在/mnt查看U盘文件
kernel
make & make menuconfig 提示错误
打开新终端后输入
declare -x ARCH="arm"
declare -x CROSS_COMPILE="arm-linux-gnueabihf-"
→ Device Drivers → USB support → USB Serial Converter support
可找到对应的驱动模块加载编译即可
SSD201 HW Checklist V10(1).xlsx
文件可找到芯片引脚编号与驱动序号对照表
用于用户空间操作GPIO
在project/configs/current.configs文件中找到IMAGE_CONFIG对应的分区文件
修改ro为rw
在有些文档中能找到GPIO复用功能说明,例如I2C的GPIO
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
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
project/image/output/images/boot/SPINANDINFO.sni
使用工具打开,查看是否支持当前Flash,没有需添加
→ 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
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
参考链接: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
蓝牙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
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
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;
}
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
网络连通
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
下载连接: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
修改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点屏步骤:修改设备树为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
修改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")
针对8.3版本
添加编译器选项
/env_support/cmake,选择编译为静态库或动态库
cmake CMakeList.txt
make
make install
lvgl demo
针对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
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 = ; //SSD201_SZ_DEMO_BOARD PAD_GPIO1 EVB PAD_GPIO0
goodix_int = ; //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
修改project/configs/current.configs文件
./setup_config.sh ./configs/nvr/i2m/8.2.1/spinand.glibc.011a.64
make image
根据芯片手册修改参数
替换project目录下的SPINANDINFO.sni
配置设备树
配置引脚,如需要背光控制,启动不闪显,不需配置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
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调试了。
修改/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 1.mp3 -loop 0 < /dev/null > /dev/null 2>1 &
mplaye播放没声音
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模块,
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
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
//#include
#include
#include
#include
#include
#include
#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");
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
/rootfs/lib/libstdc++.so.6.0.25-gdb.py: File format not recognized
搜索strip,添加! -name “*.py”
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
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、偏色
1、MMC需要初始化成功
模块没有供电,初始化失败的信息
供电后初始化成功信息
加载驱动
insmod aic8800_bsp.ko
拷贝固件到板上指定目录
rwnx_load_firmware :firmware path = /vendor/etc/firmware/fw_patch_table_u03.bin
insmod aic8800_fdrv.ko
/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
1、修改UBOOT
2、修改cmd_bootlogo.c,打开背光开关,显示升级进度
setenv sdautoupgrade 1
setenv usbautoupgrade 1
setenv enable_version_chk 1
saveenv
./configure --prefix=/home/dm/ssd201/sqlite-autoconf-3430000/build --host=arm-linux-gnueabihf
make
make install
arm-linux-gnueabihf-strip 去掉库文件或执行文件的调试信息,减少文件尺寸
#include
#include
#include
#include
#include
#include
#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
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要驱动RGB前需通过SPI总线初始化,只需要执行一次,使用模拟SPI时序发送初始化指令,编译生成模块,显示前调用模块即可
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#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函数的初始化命令序列向屏厂获取
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
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
使用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
查看摄像头所有支持的格式
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
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
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
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服务器的交叉编译
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”);
}
*/
再一次重新编译源代码
由于实际项目需求,需要扩展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;
}
由于星宸官方的播放器只提供了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
背景:
由于不正常的关机和重启,或者突然断电导致的关机,下次起来后不能进去系统,停留在(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针对网络摄像头
参考链接
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