Yuhang Zheng
Linux下amixer指令用法

amixer简介

amixer是命令行形式的配置指令,可以对ALSA(Advanced Linux Sound Architecture)架构类型的声卡驱动提供的接口进行音频参数配置,例如音量调节以及声卡开关。并且该amixer功能指令可以对多种类型声卡驱动接口进行配置。

另外注意还有alsamixer,作用和amixer一样,用于配置ALSA架构声卡各个音频参数,但是以图形界面形式显示,操作方便,显示直观。

amxier可以调节系统对应声卡的音量和选择音频通道。

amixer命令格式

使用 amixer命令如下:

amixer [-option] [cmd] 

amixer支持的功能

终端下输入#amixer -h查看amixer支持的功能和选项:

root@forlinx:~# amixer -h
Usage: amixer <options> [command]

Available options:
  -h,--help       this help
  -c,--card N     select the card
  -D,--device N   select the device, default 'default'
  -d,--debug      debug mode
  -n,--nocheck    do not perform range checking
  -v,--version    print version of this program
  -q,--quiet      be quiet
  -i,--inactive   show also inactive controls
  -a,--abstract L select abstraction level (none or basic)
  -s,--stdin      Read and execute commands from stdin sequentially
  -R,--raw-volume Use the raw value (default)
  -M,--mapped-volume Use the mapped volume

Available commands:
  scontrols       show all mixer simple controls
  scontents       show contents of all mixer simple controls (default command)
  sset sID P      set contents for one mixer simple control
  sget sID        get contents for one mixer simple control
  controls        show all controls for given card
  contents        show contents of all controls for given card
  cset cID P      set control contents for one control
  cget cID        get control contents for one control

上述指令对于amixer功能只是一个简单描述输出,具体解释可以输入#man 1 amixer查询。

自己理解的一些命令区别如下:

“controls”表示输出全部声卡驱动接口列表
“contents”表示输出全部声卡驱动接口列表以及对每个接口属性内容描述,接口的类型,值的大小
“scontrols”表示一些简单的接口的列表
“scontents”表示一些简单的接口的列表以及对每个接口属性内容描述,接口的类型,值的大小
关于wm8960音频芯片播放音频文件时的时钟测量

我们已经知道,对于WM8960音频芯片的Codec来说,与SOC连接的一共是有5个引脚:

DACLRC                    数字转模拟左右声道时钟
BCLK(Bit Clock)           位时钟
ADCDAT                    模拟转数字数据(录音数据)
DACDAT                    数字转模拟数据(放音数据)
MCLK                    外部24M时钟

关于这些引脚的作用,可以参看文章《音频的IIS引脚的理解》

这篇文章仅仅讨论播放音频文件时候的情况。

当播放音频文件时,使用示波器测量出来的LRC时钟就是音频的采样频率时钟,如果 /etc/asound.conf文件存在的话,那么LRC时钟就是使用的配置文件中设置的时钟,大多数是44.1kHz或者22.05kHz。

否则的话,LRC时钟就等于播放的音频文件的采样率大小。

使用file命令可以查看音频文件的采样率:

image-20220613165648571

从上面的例程中可以发现:

/forlinx/media/test.mp3:采样率:44.1 kHz
/run/media/sda1/ddd/1K_sin.mp3:采样率:48 kHz
/run/media/sda1/ddd/1K_sin.wav:采样率:11.025 kHz
Linux系统实现SATA热插拔功能

日前,工作中遇到了一个SATA热插拔的需求,客户想要在系统使用过程中能够通过一个开关来做控制,支持在不重启系统的情况下实现SATA硬盘的热插拔。

为了实现此功能,硬件设置如下:

GPIO2_3用于一个船型开关,开关闭合(船型开关置“1”)时与GND短路。
SATA_PWRLED连接LED,指示SATA电源,点亮表示SATA供电。
SATA_STALED连接LED,指示硬盘运行状态。

概况来说,就是有以下资源:

一个DI输入,接了一个船型开关,可以通过拨动开关来获取01值
一个DO输出,控制着SATA硬盘的电源,并连接了一个LED灯
一个DO输出,连接了一个LED灯,可以配置成指示SATA硬盘的读写状态(与实现SATA热插拔功能无关)

软件上想要实现的逻辑如下:

插入硬盘:

在SATA电源灯熄灭状态下,插入硬盘
拨动船型开关置“1”
SATA电源灯亮起,状态灯闪烁
硬盘正常工作

拔出硬盘:

拨动船型开关置“0”
稍等片刻,待SATA电源灯熄灭
拔出硬盘即可
关于动态库的链接调用问题的排查

日前在移植LSDK2108的时候,发现在启动weston服务的时候会报以下的错误

root@forlinx:~# weston --tty=1
Date: 2022-04-09 CST
[16:30:47.231] weston 9.0.0
               https://wayland.freedesktop.org
               Bug reports to: https://gitlab.freedesktop.org/wayland/weston/issues/
               Build: lf-5.10.35-2.0.0-rc2-1-gbf611255
[16:30:47.232] Command line: weston --tty=1
[16:30:47.232] OS: Linux, 5.10.35-g46e1a09b0512, #1 SMP PREEMPT Sat Apr 9 13:20:41 CST 2022, aarch64
[16:30:47.233] Using config file '/etc/xdg/weston/weston.ini'
[16:30:47.234] Output repaint window is 7 ms maximum.
[16:30:47.235] Loading module '/usr/lib/libweston-9/drm-backend.so'
[16:30:47.239] initializing drm backend
[16:30:47.244] using /dev/dri/card0
[16:30:47.245] DRM: supports atomic modesetting
[16:30:47.245] DRM: supports GBM modifiers
[16:30:47.245] DRM: supports picture aspect ratio
[16:30:47.245] Loading module '/usr/lib/libweston-9/gl-renderer.so'
[16:30:47.268] Failed to load module: /lib/libEGL.so.1: undefined symbol: gbm_surface_set_in_fence_fd
[16:30:47.268] failed to initialize egl
[16:30:47.269] fatal: failed to create compositor backend
Internal warning: debug scope 'drm-backend' has not been destroyed.

从错误上来看,就是加载/lib/libEGL.so.1模块的时候找不到gbm_surface_set_in_fence_fd符号

我们可以使用ldd -r /lib/libEGL.so.1命令来验证这一问题

root@forlinx:~# ldd -r /lib/libEGL.so.1
        linux-vdso.so.1 (0x0000ffff9ae6f000)
        libGAL.so => /lib/libGAL.so (0x0000ffff9ac04000)
        libwayland-server.so.0 => /lib/aarch64-linux-gnu/libwayland-server.so.0 (0x0000ffff9abe0000)
        libwayland-client.so.0 => /lib/aarch64-linux-gnu/libwayland-client.so.0 (0x0000ffff9abc1000)
        libdrm.so.2 => /lib/aarch64-linux-gnu/libdrm.so.2 (0x0000ffff9ab9f000)
        libgbm.so.1 => /lib/aarch64-linux-gnu/libgbm.so.1 (0x0000ffff9ab81000)
        libgbm_viv.so => /lib/libgbm_viv.so (0x0000ffff9ab6c000)
        libpthread.so.0 => /lib/aarch64-linux-gnu/libpthread.so.0 (0x0000ffff9ab3c000)
        libc.so.6 => /lib/aarch64-linux-gnu/libc.so.6 (0x0000ffff9a9c9000)
        /lib/ld-linux-aarch64.so.1 (0x0000ffff9ae3f000)
        libm.so.6 => /lib/aarch64-linux-gnu/libm.so.6 (0x0000ffff9a91c000)
        libdl.so.2 => /lib/aarch64-linux-gnu/libdl.so.2 (0x0000ffff9a908000)
        libffi.so.7 => /lib/aarch64-linux-gnu/libffi.so.7 (0x0000ffff9a8ef000)
        libexpat.so.1 => /lib/aarch64-linux-gnu/libexpat.so.1 (0x0000ffff9a8b8000)
undefined symbol: gbm_surface_set_in_fence_fd   (/lib/libEGL.so.1)

在上面的打印信息中,我们也看到了/lib/libEGL.so.1所链接的其他动态库

ARM平台获取CPUID的方法

目前工作中需要获取LS10xx平台的CPUID,然后网上搜到了一些方法,在这里先简单记录一下。

CPUID寄存器内容:

字段名:Implementer(venter 销售ID)|Variant(大版本号) | Architecture(架构版本)| Part Num(产品代码)|Revision(小版本号)

基址偏移量: [31-24] | [23-20] | [19-16] | [15-4] | [3-0]

下面直接上操作,以LS1046为例

1、使用cat /proc/cpuinfo命令可以看到

root@localhost:~# cat /proc/cpuinfo
processor       : 0
BogoMIPS        : 50.00
Features        : fp asimd evtstrm aes pmull sha1 sha2 crc32 cpuid
CPU implementer : 0x41
CPU architecture: 8
CPU variant     : 0x0
CPU part        : 0xd08
CPU revision    : 2

processor       : 1
BogoMIPS        : 50.00
Features        : fp asimd evtstrm aes pmull sha1 sha2 crc32 cpuid
CPU implementer : 0x41
CPU architecture: 8
CPU variant     : 0x0
CPU part        : 0xd08
CPU revision    : 2

processor       : 2
BogoMIPS        : 50.00
Features        : fp asimd evtstrm aes pmull sha1 sha2 crc32 cpuid
CPU implementer : 0x41
CPU architecture: 8
CPU variant     : 0x0
CPU part        : 0xd08
CPU revision    : 2

processor       : 3
BogoMIPS        : 50.00
Features        : fp asimd evtstrm aes pmull sha1 sha2 crc32 cpuid
CPU implementer : 0x41
CPU architecture: 8
CPU variant     : 0x0
CPU part        : 0xd08
CPU revision    : 2

按照上面的规则换算下来就是

Implementer        |Variant    | Architecture    |Part Num    |Revision
0x41            0            f                d08            2
LS10xx安全架构和安全启动

一、信任架构概述

QoriQ平台的信任架构可以使开发者仅仅靠运行”授权软件程序“来保护您设计的产品,并提供工具在运行环境的生命周期内不间断的检测硬件的安全状态,在运行时环境中检测到的异常会触发硬件状态更改,从而导致系统锁定对先前加密数据的访问或重启硬件。

所有具有信任架构的QorlQ Layerscape 设备都支持以下两种启动模式:

  • 正常启动(不信任环境)
  • 安全启动

预引导加载程序 pre-boot loader(PBL)允许您在正常引导或安全引导之间进行选择。有两种方法可以命令PBL启动安全启动过程:

  • 对正在运行的系统的安全意图 intent to secure(ITS)保险丝进行编程
  • 在原型设计之初就在RCW中设置启用安全启动 secure boot enable(SB_EN)位

在安全启动模式下,数字签名的启动映像会在启动期间进行验证。验证期间的失败要么使CPU进入自旋循环(具有ITS的系统),要么继续引导到非安全状态(具有SB_EN的环境)。

使用信任架构需要一些强制性最低配置可选配置

强制性最低配置和程序包括代码签名对安全熔断器处理器(SFP)中的某些字段进行编程

可选配置包括对一些增强功能的支持,例如篡改检测(tmp_detect)运行时完整性检查(RTIC)安全调试密钥撤销和安全数据存储(加密的二进制数据)

二、安全启动:最低要求

安全启动过程包括对现有软件必要的准备工作对安全启动过程使用的熔丝进行编程

在安全启动模式下,SoC的CPU是从一段包含内部安全启动代码 internal secure boot code(ISBC)的不可修改的内部启动ROM开始启动的。

ISBC的功能是去验证一段被称为外部安全启动代码 external secure boot code(ESBC)的可修改代码。

ESBC可以是一个与引导设备(U-Boot、设备树、内核、rootfs)相关的连续内存空间中的单个集成镜像,也可以是存在于软件镜像链的第一阶段中可以单独验证和调用的程序。第二阶段也称为信任链。使用信任链时,您可以为链中的每个镜像使用单个密钥对,或为不同的镜像使用不同的密钥对。

为简单起见,本文档使用单个密钥对对安全启动中涉及的所有镜像进行签名。

使用fw_printenv修改uboot环境变量

最近遇到一个问题,有客户想要使用fw_printenv命令,在文件系统下查看和修改uboot环境变量。

网上搜索了一下相关的内容,发现fw_printenv真是一个好东西。

首先是fw_printenv工具的编译:

fw_printenv工具的源码在uboot源码目录下的tools/env/目录下,可以使用以下命令直接编译得到

make env ARCH=xxx CROSS_COMPILE=yyy
#其中xxx和yyy根据自己的交叉编译环境来配置

编译完成之后,就在tools/env下生成fw_printenv的可执行文件,将其拷贝到文件系统中就可以。

其次是fw_env.config文件的配置:

fw_env.config文件在文件系统的/etc目录下,记载着mtd分区、uboot环境变量的位置、大小等内容。

在uboot源码的tools/env/fw_env.config中也有一个简单的示例,具体的修改方法见fw_env.config文件中的说明及/tools/env/README文件。

对于LS1046来说,fw_env.config文件中的内容如下:

# MTD device name       Device offset   Env. size       Flash sector size
/dev/mtd0               0x300000          0x2000          0x40000

其中Device offset,Env size和Flash sector size应该分别对应于uboot源码目录中include/configs/xxxx.h相关文件中的

CONFIG_ENV_OFFSET,CONFIG_ENV_SIZE和CONFIG_ENV_SECT_SIZE三个宏定义

以include/configs/ls1046ardb.h为例,我们可以看到

#define CONFIG_ENV_SIZE                 0x2000          /* 8KB */
#define CONFIG_ENV_OFFSET               0x300000        /* 3MB */
#define CONFIG_ENV_SECT_SIZE            0x40000         /* 256KB */
网站自动签到的操作

前几天在网上找Steam VR游戏的时候,无意间找到了一个网站七星猫,然后发现上面的游戏基本上就是三个游戏币一个(一块钱一个游戏币),三十个游戏币可以直接VIP会员,全网站免费下载了,价格还不错。我购买了一个H3CVR的汉化版,下载之后游玩还可以,这个资源我已经找了很久了,网上基本上找不到免费的汉化的版本,哪怕是付费的也是相当的难找。

大概浏览了一下这个网站,上面的资源还是比较丰富的,PC和VR游戏都有很多,以后想找游戏的时候可以先在这里看看了。

在这个网站的侧边栏,我发现有签到的功能,每次签到给0.1个游戏币,这样算算每个月就能免费领一个游戏呢,10个月之后都能免费VIP了,想想白嫖还真是让人很兴奋呢。

不过每天如果手动签到也是太麻烦了,我想起来之前在网上找的用python写的什么值得买和glados的自动签到,代码我也看过,没什么难的,那何不自己做一个七星猫的自动签到脚本呢?

首先先看一下glados的自动签到脚本吧

import json
import requests
from requests import post

payload = "{\"token\":\"glados_network\"}"
headers = {
  'authority': 'glados.rocks',
  'accept': 'application/json, text/plain, */*',
  'dnt': '1',
  'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.80 Safari/537.36',
  'content-type': 'application/json;charset=UTF-8',
  'origin': 'https://glados.rocks',
  'sec-fetch-site': 'same-origin',
  'sec-fetch-mode': 'cors',
  'sec-fetch-dest': 'empty',
  'referer': 'https://glados.rocks/console/checkin',
  'accept-language': 'zh-CN,zh;q=0.9',
  'cookie': Cookie
}

if __name__ == '__main__':
    checkinUrl = 'https://glados.rocks/api/user/checkin'
    resp = requests.post(checkinUrl, headers=headers, data = payload)
    message = 'GLaDOS梯子签到 : \n\n' + json.loads(resp.text).get('message')
    print(message)

很简单不是么?点击签到按钮之后,也仅仅是向某个签到的url发送了一个特定的headers和data的数据而已,注意这里的data数据是一个json字符串。

那就仿照着这个来写一下七星猫的自动签到脚本吧,找一下它的签到的url和发送的数据的headers和data。

可调整大小的串行控制台窗口

在使用串口登录Linux嵌入式板卡时,只需要设置好相应的比特率和串口号,然后再打开调试串口并登录,就像使用 telnet 或 ssh 一样方便。

但是我们发现有一种情况,当你一旦使用像是vim的编辑器的时候 ,无论其实际大小,它都假定你的终端窗口只有 24 行高。

image-20211103094604863

即使在退出编辑器后,不知何故窗口都将被改变,它的窗口都会冻结在24行,底下的串口部分留空,这种情况下当输入长命令的时候它就会出现错位,无法看到命令的全部内容,很是难受

image-20211103094337626

后来通过网上找资料,发现这个和stty设置的行和列的大小有关,我们可以通过stty size命令来查看当前窗口的行和列的大小

forlinx@ubuntu:~$ stty size
24 80

当然我们也可以手动设置将行和列的值改大一点

forlinx@ubuntu:~$ stty rows 58 cols 237
forlinx@ubuntu:~$ stty size
58 237

设置完成之后,我们再使用vim命令去编辑文件的时候就可以看到效果了。

这个最终的问题是,在使用串口登录系统的时候,屏幕没有像 ssh、rsh 或 telnet 等远程登录程序那样传递终端大小信息的协议。那么,如何在登录时自动去设置终端大小呢?

我在网上找到了两个方法:

第一个是一个bash的脚本,可以命令为resize,这个只在运行的时候起作用,可以调整窗口的大小

old=$(stty -g)
stty -echo
printf '\033[18t'
IFS=';' read -d t _ rows cols _
stty "$old"
stty cols "$cols" rows "$rows"

第二个是一个命令,这个可以在每次运行命令的时候都进行窗口的大小的调整,不过有一个小问题就是会影响命令执行的速度

trap 'resize > /dev/null' DEBUG

亲测这两个都可以使用,可以把这些语句加到.profile里面。

以下是参考链接:

https://qastack.cn/unix/16578/resizable-serial-console-window

https://shallowsky.com/blog/tags/embedded/

风蚀的城堡

我曾经住在一个城堡里,一直都认为自己很厉害,长这么大经历了很多艰难的事情并一路走了过来,我一直以为这都是自己的本事。

后来我才知道,并非是我的本领高强,而是城堡的坚固保护才让我免于经受挫折与风雨。

可惜我并没有修缮城堡的能力,只能目睹它在岁月中被流年的风尘逐渐侵蚀,但是我一直侥幸它足够坚固,坚固到能支撑到永远。

在这时光的流转中,我慢慢的不敢再回头看它,我知道每次回头看到的,都将是一个更为摇晃的世界,我以为闭上眼睛,时光就会停滞。

可是,我终于在某一天听到了倒下的声音,童话的城堡已经开始崩塌~~曾经保护我的超人也开始离去和老去,在这支离的城堡中,有好多熟悉的房间开始变成了我再也无法触及的回忆之地。

我没有办法再躲在里面,我也得快快成为一个能保护自己的大人,盖一栋新的更坚固的小房子。

当城堡倒塌的时候,我一直想尽办法让自己迷失在当下的时间里,一直拼命向前看想忘记过去的记忆。想沉溺于一切都是梦的幻想里,告诉自己一切仍旧,一切都没有发生,一切仍如那个熟悉的过去。

终于有一天,当我有勇气后头看,那城堡的一角散落在地的残垣,曾经的记忆在脑海中浮现,那么多欢乐与幸福,终究还是要与自己永远的告别。

唯有岁月,是无法挽留的是么?也总有人逐渐消失于世界,带着那些难忘的记忆,一并融化在模糊的雾气里。