全志 T113-S3 使用 Tina-SDK 指北
时间:04月26日 人气:...

想玩 linux 开发板的话,全志的板子就很具备性价比了,正好有朋友送我了快 T113-S3 开发板,所以我拿他一通折腾之后,决定将使用中的槽点分享出来,尽量帮助使用它的人少走些弯路。

首先需要找到相关的资料,因为是块 T113 开发板,当然就是从开发板生产商找了,我这个块开发板是百问网搞的,所以就能在百问网找资料了。在找资料的过程中,发现全志官方的网站就不太友好了,代码和文档下载权限需要申请,这那是普通的个人开发者所能申请到的呀……

好在百问网提供的资料很齐全,无论代码还是文档,非常齐全。唯一遗憾的就是百问网的论坛不太行,毕竟他上面都是学生来了,问问题的多,能解答问题的少,而韦老师它们对不挣钱的答疑肯定也不会投入了。所以:

  • 找资料就上百问网下载中心
  • 答疑就上全志开发者社区论坛

T113 开发也有好几种 SDK,其中 Tina-SDK 是推荐的,其架构也非常常规:

接下来就以韦老师提供的 SDK 来探讨了,建议直接到这里下载所有资料:

100ASK_T113-Pro开发板 开发资料汇总页面!

按照韦老师的环境搭建教程可以很容易的搭建好环境。但是不同的编译环境下可能存在的问题也不同,像我用的 ubuntu 系统,遇到了一些韦老师没提到的错误,可以参考 Ubuntu22 tina-linux 编译报错记录 解决。

之后每次编译时,需要进入到目录 tina-d1-h,先执行source build/envsetup.sh 再执行 lunch 3 或者 lunch 后在选择 3。如果每次都这样操作的是比较麻烦的,所以完全可以先修改 build/envsetup.sh文件

function evnsetup
{
    ......
    
    lunch 3
}

接下来修改 ~/.bashrc 文件

cd /home/yichen/tina-d1-h && source /home/yichen/tina-d1-h/build/envsetup.sh && cd ~

(也可以不添加 && cd ~ 这句)这样每次打开终端之后就会自动加载好环境变量,之后就可以执行 SDK 相关的操作命令了。

工具链在路径 tina-d1-h/prebuilt/gcc/linux-x86/arm/toolchain-sunxi-musl/toolchain/bin 下,工具链前缀为 arm-openwrt-linux-muslgnueabi-,如 gcc 则为 arm-openwrt-linux-muslgnueabi-gcc。有了工具链就可以自己交叉编译一些应用之类的东西,最简单的就可以通过 adb 推送到板子上去运行了。

需要注意这个工具链在自己单独使用的时候,编译的时候可能会产生警告,让配置两个路径 SYSROOTSTAGING_DIR,不配也不会有啥问题,但不想看见它的话,可以设置:

export SYSROOT=/home/yichen/tina-d1-h/out/100ask/staging_dir/target
export STAGING_DIR=/home/yichen/tina-d1-h/out/100ask/staging_dir

烧录固件的话,可以有好几种方法:

  • 空白 flash 的开发板,第一次上电只能进入烧录模式,它再也干不了啥。
  • 如果你将 flash 的短接线引出来了,那么就可以做一个烧录键,在烧录的时候按键进入烧录。
  • 上电之后在 uart 中狂按 2 键,有一定的几率就能进入烧录,但不是非常灵光。
  • 如果在 uboot 界面,可以输入 efex 就会进入烧录
  • 可以在linux跑起来之后,在 shell 中输入 reboot efex,重启后就会自动进入。
  • 如果使用了 adb 功能,那么在 PC 上执行 adb shell reboot efex 也一样可以

reboot efex 需要 RTC 功能的支持,所以需要在 make menuconfig 中启用 RTC 驱动才行:

make kernel_menuconfig

在 Device Driver->Real Time Clock->Allwinner sunxi RTC 里:

Suni rtc reboot flag

烧录固件可以用 TF 卡烧录,也可以使用数据线直接烧录。其中 TF 卡烧录可以在 windows 和 linux 下都能使用。

使用数据线烧录的话,windows 下有个 AllwinnertechPhoeniSuit 程序,这个使用非常简单(但是有个非常不好的习惯就是这个程序每次打开,他都会修改系统的 path 环境变量,看着乱七八糟的)。ubuntu 下全志也有提供了一个 QT 写的烧录程序,但是根本用不了,所以目前看来想直接烧录就只能在 windows 下使用。

接下来介绍几个重要的目录和文件

tina-d1-h/device/config/chips/t113/configs/100ask/
tina-d1-h/target/allwinner/100ask/
tina-d1-h/package/

这里面有几个比较重要的文件 env.cfguboot-board.dts 里的配置是为 uboot 的配置和设备树,文本文件可以直接打开修改。

board.dts 文件就是 kernel 的设备树了,需要注意的就是某些设备的配置会从 uboot 里传递给内核,并不会使用 board.dts。话说 linux 的设备树配置起来还是非常方便和灵活的,比如说配置 wifi 和 蓝牙:

rfkill: rfkill@0 {
		compatible    = "allwinner,sunxi-rfkill";
		chip_en;
		power_en;
		pinctrl-names = "default";
		status        = "okay";

		wlan: wlan@0 {
			compatible    = "allwinner,sunxi-wlan";
			clock-names = "32k-fanout1";
			clocks = <&ccu CLK_FANOUT1_OUT>;
			wlan_busnum    = <0x1>;
			wlan_regon    = <&pio PG 12 GPIO_ACTIVE_HIGH>;
			wlan_hostwake  = <&pio PG 10 GPIO_ACTIVE_HIGH>;
			wakeup-source;
		};

		bt: bt@0 {
			compatible    = "allwinner,sunxi-bt";
			pinctrl-names = "default";
			clock-names = "32k-fanout1";
			clocks = <&ccu CLK_FANOUT1_OUT>;
			bt_rst_n      = <&pio PG 15 GPIO_ACTIVE_LOW>;
			status        = "okay";
		};
	};

	btlpm: btlpm@0 {
		compatible  = "allwinner,sunxi-btlpm";
		uart_index  = <0x1>;
		bt_wake     = <&pio PG 13 GPIO_ACTIVE_HIGH>;
		bt_hostwake = <&pio PG 14 GPIO_ACTIVE_HIGH>;
		status      = "okay";
	};

sys_partition.fex 文件定义了分区设置,如 uboot 多大、kernel 多大等,需要注意的是 这里的 size 单位是 512 bytes,所以实际的大小就是 size * 512 才是具体的bytes。建议为除了 UDISK 的分区预留足够的就行,剩下的空间就会自动全部划给 UDISK 分区,我们 adb push、wget 之类的一些大文件到 UDISK 的话就非常方便了。

sys_config.fex 文件里有些全局性的设置,理论上会影响整个环境,但实际上韦老师的这套 SDK 就有个很大的坑,比如:

[target]
boot_clock = 1008

这里本来可以设置启动时 boot0 和 uboot 的 cpu 主频,但是韦老师却并么有使用它,在代码里硬写死为 1008 MHz。这非常的坑,所以需要修改启动主频时需要手动去改代码

lichee/brandy-2.0/spl/board/sun8iw20p1/clock.c

static void set_pll_cpux_axi(void)
{
    ......
}

如果你以 1008MHz 烧录固件不太行的话,就可以修改这里降低主频尝试了。如果注释掉这个代码,T113 默认的上电主频就是 408MHz。

说起韦老师的大坑,我还想起了一个关于启动速度的问题。众所周知,linux 通常启动速度比较慢,但也可以通过优化可以大幅降低 linux 启动的速度,我测试到经过优化后的 tina-sdk 启动到进入 kernel 大概只需要 2 秒就可以(关于启动速度优化可以参考这篇文档和全志官方文档《Tina_Linux_启动优化_开发指南.pdf》)。但韦老师的 SDK 启动的时候引入了 TEE 的机制,即使不用安全机制,它在启动时也要白白浪费了好几秒时间。

想上电显示 logo 图片的话(如 linux 启动的那个小企鹅),tian-sdk 这块已经现成的可以直接使用,只需要替换这张图即可:tina-d1-h\target\allwinner\generic\boot-resource\boot-resource\bootlogo.bmp

但同样有个坑,进入 kernel 才会显示这张图,但是 uboot 阶段却不显示,所以需要修改 uboot 的

tina-d1-h\lichee\brandy-2.0\u-boot-2018\include\configs\sun8i.h 文件增加代码:

#define CONFIG_VIDEO_LOGO
#define CONFIG_VIDEO_BMP_LOGO

不得不说,在 linux 操作调试各类驱动、设备都是太简单了。

比如说操作 ADC 采集电压,则先在设备树里修改 &gpadc 所用通道号,其它的选项都无用。

接下来在 make kernel_menuconfig 中使能 gpadc 驱动,最后执行命令即可读取到 ADC 采集到的数据:

cat /sys/class/gpadc/data

不过,每采集一次驱动里都有一次打印,不知道是原版还是韦老师加的,看着很烦,可以自行注释掉,在文件 tina-d1-h/lichee/linux-5.4/drivers/input/sensor/sunxi_gpadc.c中:

u32 sunxi_gpadc_read_channel_data(u8 channel)
{
	u32 data, vol_data;

	data = readl(sunxi_gpadc->reg_base + GP_CS_EN_REG);

	if ((data & (0x01 << channel)) == 0)
		return VOL_RANGE + 1;

	data = sunxi_gpadc_read_data(sunxi_gpadc->reg_base, channel);

	data = ((VOL_RANGE / 4096)*data);	/* 12bits sample rate */
	vol_data = data / 1000;			//data to val_data

	//printk("vol_data: %d\n", vol_data);

	return vol_data;
}

比如说操作 GPIO,想将 PD22 配置输出模式,首先计算出索引号:,那么就可以输入

cd /sys/class/gpio
echo 118 > export
cd gpio118
echo "out" > direction #配置为输出模式
cat value              #查看当前电平状态
echo 1 > value         #设置拉高
echo 0 > value         #设置拉低

编程时,除了使用 system 这样操作之后,还可以使用 libgpiod 之类的进行操作,也非常方便。

我观察到 tina-sdk 目前的 linux-5.4 并没有提供 libgpiod,但是最新的 kernel 中其实是已经集成进去了的,所以为了方便使用,我对它进行了移植,有需要的可以自行下载 libgpiod.7z

如果想测试音频播放,则直接可以执行命令播放声音,甚至调节音量:

aplay demo.wav                                                 #播放wav文件
amixer cset numid=17,iface=MIXER,name="Headphone volume" 7     #调整音量
amixer cset numid=5,iface=MIXER,name="DAC volume" 160          #调整DAC增益

如果使用 i2c,那么也可以使用 i2c-tool 命令进行测试,如使用 twi3 操作设备地址 0x29 的设备:

i2cdetect  -y 3           #可以验证0x29设备是否存在
i2cget -y 3 0x29 0x87     #读0x87寄存器
i2cset -y 3 0x29 0x80 0x1 #写0x80寄存器值为0x1

编程时更加简单,标准的 open、read、write 即可:

int fd;
int dev_addr = 0x29;
unsigned char buf[6];

fd = open("/dev/i2c-3", O_RDWR);

ioctl(fd, I2C_SLAVE, dev_addr );
ioctl(fd, I2C_TIMEOUT, 5);
ioctl(fd, I2C_RETRIES, 3);

buf[0] = 0x30;
buf[1] = 0xA2;
write(fd, buf, 2);

read(fd, buf, 6);

close(fd);

当然不能忘了设备树也要修改:

twi3_pins_a: twi3@0 {
	pins = "PB6", "PB7";
	function = "twi3";
	drive-strength = <10>;
};

twi3_pins_b: twi3@1 {
	pins = "PB6", "PB7";
	function = "gpio_in";
};

&twi3 {
	clock-frequency = <400000>;
	pinctrl-0 = <&twi3_pins_a>;
	pinctrl-1 = <&twi3_pins_b>;
	pinctrl-names = "default", "sleep";
	status = "okay";
};

测试屏幕的话,就更简单了

echo 8 > /sys/class/disp/disp/attr/colorbar #显示8色图
cat /dev/urandom > /dev/fb0                 #花屏
dd if=/dev/zero of=/dev/fb0                 #清屏

话说 linux 下最爱使用触屏,所以也不能忘了触屏调试手法。一般的触摸屏也就是 显示+触摸两块组成,显示由 RGB 驱动支撑,触摸一般也就还是个 i2c(twi),触摸调试的时候,在 linux 里也非常的简单,比如使用 ft6336u 触摸芯片,kernel 自带驱动,只需修改设备树:

&twi2 { 
        clock-frequency = <400000>;
        pinctrl-0 = <&twi2_pins_a>;
        pinctrl-1 = <&twi2_pins_b>;
        pinctrl-names = "default", "sleep";
        dmas = <&dma 45>, <&dma 45>;
        dma-names = "tx", "rx";
        status = "okay";

        ctp@48 {
                compatible = "focaltech,fts";
                reg = <0x48>;
                status = "okay";
                interrupt-parent = <&pio>;
				interrupts = ;
				focaltech,reset-gpio = <&pio PB 2 GPIO_ACTIVE_HIGH>;
				focaltech,irq-gpio = <&pio PB 3 IRQ_TYPE_LEVEL_LOW>;
				focaltech,max-touch-number = <1>;
				focaltech,display-coords = <0 0 480 480>;
				focaltech,reg_vdd = <®_pio3_3>;
				focaltech,reg_avdd = <®_pio3_3>;
          };
};

kernel 就会创建这个输入设备,先可以查询触屏对应的输入设备是啥:

cat /proc/bus/input/devices

查到之后,就可以使用 getevent 工具对输入设备进行测试了,如:

getevent /dev/input/event2

之后每次点击屏幕,就会输出信息,进而可以直接观察调试了。

测试 pwm 的话,也很简单,比如操作 pwm2:

echo 2 > /sys/class/pwm/pwmchip0/export                #pwm2
echo 10000000 > /sys/class/pwm/pwmchip0/pwm2/period    #周期10ms
echo 1000000 > /sys/class/pwm/pwmchip0/pwm2/duty_cycle #占空比,这里1ms
echo normal > /sys/class/pwm/pwmchip0/pwm2/polarity    #极性反转,决定duty_cycle是高电平还是低电平
echo 0 > /sys/class/pwm/pwmchip0/pwm2/enable           #启动

使用蓝牙调试也非常简单:

hciconfig hci0 up                   #打开蓝牙
hcitool lescan | grep "LYWSD03MMC"   #ble扫描,列出指定名称的
gatttool -I                         #使用gatttool工具交互模式完成一次gatt client连接
connect A4:C1:38:28:C7:B4           #连接
primary                             #列出所有服务
primary UUID                        #只列出指定UUID的服务
characteristics 0x0001 0x00ff       #查看特征
char-write-req 0x0002 0100          #订阅通知
char-write-req 0x0001 0107          #写数据

操作 wifi 的话也很简单,之前文章已经有提过了,使用 wpa_cli 工具和驱动工具就可以。

此外,为了方便开发全志官方也提供了 wifimanager 和 btmanager 的编程接口,用户可以使用他们进行 wifi 和蓝牙的编程,而不用管更底层的 wpa_supplicant 以及 bluez 这些东西。既提供了 demo 又提供了手册,但一般只看 demo 就够了,使用非常简单,也就无需多说。

另外,tina-sdk 也可以自定添加软件包,它在定义软件包的 menuconfig 菜单和编译 makefile 规则时,将两者写在了同一个 makefile 文件中,不用特别的单独定义 Kconfig 文件,如我在 tina-d1-h/package/my_pkg/Makefile 中:

define Package/$(PKG_NAME)/config
choice MY_OPTION
	prompt "My option"
	default MY_OPTION_1

	config MY_OPTION_1
		bool "My option1"

	config MY_OPTION_2
		bool "My option2"

	config MY_OPTION_3
		bool "My option3"
endchoice

config MY_ENABLE
	bool "my enable"
	default n
endef

这样之后就可以在 make menuconfig 中显示出来一个名叫 my_pkg 的菜单,打开后就会用定义的这俩选项了。

当然也可以在其它包中引用这俩选项,如我又在 tina-d1-h/package/my_pkg2/Makefile 中:

define Build/Compile
	$(MAKE) -C $(PKG_BUILD_DIR)/src \
		ARCH="$(TARGET_ARCH)" \
		AR="$(TARGET_AR)" \
		RANLIB="$(TARGET_RANLIB)" \
		CC="$(TARGET_CC)" \
		CXX="$(TARGET_CXX)" \
		CFLAGS="$(TARGET_CFLAGS)"\
		LDFLAGS="$(TARGET_LDFLAGS)" \
		CONFIG_PREFIX="$(PKG_INSTALL_DIR)" \
		MY_OPTION=$(CONFIG_MY_OPTION) \
		MY_ENABLE=$(CONFIG_MY_ENABLE)
		all \
		V=1
endef

这样就可以在 my_pkg2/src/Makefile 中使用传递过来的变量 MY_OPTION 和 MY_ENABLE 了。

虽然添加的时候感觉混在一起怪怪的,但用起来也没啥两样。

未完待续……

热门评论