diff --git a/404.html b/404.html new file mode 100644 index 00000000..58bcadfd --- /dev/null +++ b/404.html @@ -0,0 +1,89 @@ + + + + + + + Page Not Found + + + +
+
4 0 4
+
+ Page not found +
+
+ + + + + + Back + +
+
+ + + + \ No newline at end of file diff --git a/CNAME b/CNAME new file mode 100644 index 00000000..151bf65d --- /dev/null +++ b/CNAME @@ -0,0 +1 @@ +lxowalle.cc \ No newline at end of file diff --git a/archives/index.html b/archives/index.html new file mode 100644 index 00000000..0e68d780 --- /dev/null +++ b/archives/index.html @@ -0,0 +1,134 @@ + + + + +lxowalle + + + + + + + + + + + +
+
+ + + + + + + + +
+ + +
+ + + + +
+
+ + diff --git a/atom.xml b/atom.xml new file mode 100644 index 00000000..4599b595 --- /dev/null +++ b/atom.xml @@ -0,0 +1,485 @@ + + + https://lxowalle.github.io + lxowalle + 2023-07-26T13:17:17.297Z + https://github.com/jpmonette/feed + + + 温故而知新 + https://lxowalle.github.io/images/avatar.png + https://lxowalle.github.io/favicon.ico + All rights reserved 2023, lxowalle + + <![CDATA[[ROS2] CLI工具使用]]> + https://lxowalle.github.io/post/ros2-cli-gong-ju-shi-yong/ + + + 2023-07-25T10:01:03.000Z + 参考ROS2 IRON指南安装基本的环境。注意riscv架构的平台目前还不支持ROS2(2023-07-25)

+

参考使用turtlesim、ros2、 和rqt

+

基础环境

+

安装ros2后不能立马使用,需要将ROS2环境添加到环境变量中才能进一步操作。

+

添加步骤:

+
# 添加基础环境
+echo "source /opt/ros/iron/setup.bash" >> ~/.bashrc
+
+# 添加域ID,为了系统安全,域ID的值一般选0~101和215~232
+echo "export ROS_DOMAIN_ID=<your_domain_id>" >> ~/.bash_profile
+
+# 设置通信范围
+echo "export  ROS_AUTOMATIC_DISCOVERY_RANGE=SUBNET" >> ~/.bash_profile
+
+

使用turtlesim和rqt

+

turtlesim工具是一个海龟模拟器,一般被用来学习ROS2的通信机制。rqt是一个图形窗口,用来将可视化的展示各节点的服务、主题关系

+

安装turtlesim和rqt

+
sudo apt update
+sudo apt install ros-iron-turtlesim
+sudo apt install ~nros-iron-rqt*
+
+

使用turtlesim和rqt

+
# 启动一个节点,用来生成海龟
+ros2 run turtlesim turtlesim_node
+# 启动一个节点,用来控制海龟
+ros2 run turtlesim turtle_teleop_key
+# 启动rqt,用来监测和控制海龟
+rqt
+# 启动rqt_graph,用来图形化显示节点间的关系
+rqt_graph
+
+

更详细的使用方法参考这里

+

节点

+

ROS2中以节点为基本单位,每个节点之间可以通过topics(主题)、services(服务)、actions(操作)或parameters(参数)来通信。
+ROS2通过节点来实现功能单一、模块化。

+

通过命令行来操作节点

+
# 列出节点
+ros2 node list
+
+# 查看节点信息
+ros2 node info <节点名> # 例如ros2 node info /turtlesim
+
+# 将turtlesim_node的默认节点重映射为my_turtle节点
+ros2 run turtlesim turtlesim_node --ros-args --remap __node:=my_turtle
+
+

主题

+

主题是ROS2的一种基于发布者-订阅者的通信机制,节点可以将数据发布到任意数量的主题,并且同时订阅任意数量的主题。主题可以多对多。

+

通过命令行来操作主题

+
# 列出主题
+ros2 topic list
+
+# 列出主题(参数-t可以列出主题类型)
+ros2 topic list -t
+
+# # 列出指定主题的类型
+ros2 topic type <主题名>
+
+# 查看主题订阅数量、发布数量
+ros2 topic info <主题名>
+
+# 实时查看主题内的消息
+ros2 topic echo <主题名> # 例如:ros2 topic echo /turtle1/cmd_vel
+
+# 查看主题内消息的速率
+ros2 topic hz <topic_name>
+
+# 向主题发布消息
+ros2 topic pub <topic_name> <msg_type> '<args>'
+
+# 示例:只发送一次,向主题/turtle1/cmd_vel发布类型为geometry_msgs/msg/Twist的消息,注意消息用yaml语法输入
+ros2 topic pub --once /turtle1/cmd_vel geometry_msgs/msg/Twist "{linear: {x: 2.0, y: 0.0, z: 0.0}, angular: {x: 0.0, y: 0.0, z: 1.8}}"
+
+# 示例:每1s发送一次,向主题/turtle1/cmd_vel发布类型为geometry_msgs/msg/Twist的消息,注意消息用yaml语法输入
+ros2 topic pub --rate 1 /turtle1/cmd_vel geometry_msgs/msg/Twist "{linear: {x: 2.0, y: 0.0, z: 0.0}, angular: {x: 0.0, y: 0.0, z: 1.8}}"
+
+

服务

+

服务是ROS2一种基于调用-响应的通信机制。与主题的差异是,主题一般是持续的更新数据,而服务只在客户端调用时才提供数据。

+

通过命令行来操作服务

+
# 列出服务
+ros2 service list
+
+# 列出服务(参数-t可以列出服务类型)
+ros2 service list -t
+
+# 列出指定服务的类型
+ros2 service type <service_name>
+
+# 查找某个类型的所有服务
+ ros2 topic find <service_type>
+
+ # 调用服务
+ ros2 service call <service_name> <service_type> <arguments>
+
+ # 示例:调用spawn服务新生成一直海龟
+ ros2 service call /spawn turtlesim/srv/Spawn "{x: 2, y: 2, theta: 0.2, name: ''}"
+
+

动作

+

动作是ROS2建立在主题和服务的基础上的基于目标-反馈-结果的通信类型。动作与服务类似,但是可以中断上次操作。

+

通过命令行来操作动作

+
# 列出动作
+ros2 action list
+
+# 列出动作(参数-t可以列出动作类型)
+ros2 actions list
+
+# 列出动作的客户端数量、服务器数量
+ros2 action info <action_name>
+
+# 查看动作的接口结构
+ros2 action info <action_type>
+
+# 发起动作。<values>需要采用 YAML 格式,添加--feedback后可以获取实时反馈
+ros2 action send_goal <action_name> <action_type> <values>
+
+
+# 示例:查看动作/turtlesim/action/RotateAbsolute的结构
+ros2 interface show turtlesim/action/RotateAbsolute
+
+# 示例:向动作/turtle1/rotate_absolute发起旋转1.57?(反正是个动作)
+ros2 action send_goal /turtle1/rotate_absolute turtlesim/action/RotateAbsolute "{theta: 1.57}"
+
+# 示例:向动作/turtle1/rotate_absolute发起旋转1.57,并获取实时反馈
+ros2 action send_goal /turtle1/rotate_absolute turtlesim/action/RotateAbsolute "{theta: -1.57}" --feedback
+
+

参数

+

参数是节点的配置值。您可以将参数视为节点设置。节点可以将参数存储为整数、浮点数、布尔值、字符串和列表。在ROS 2中,每个节点维护自己的参数

+

通过命令行来操作参数

+
# 列出参数
+ros2 param list
+
+# 获取指定节点的参数类型和参数值
+ros2 param get <node_name> <parameter_name>
+
+# 设置指定节点的参数类型和参数值
+ros2 param set <node_name> <parameter_name> <value>
+
+# 导出指定节点的所有参数值
+ros2 param dump <node_name>
+
+# 导入参数到指定节点(parameter_file格式和dump出的格式一致)
+ros2 param load <node_name> <parameter_file>
+
+# 节点启动时加载参数文件
+ros2 run <package_name> <executable_name> --ros-args --params-file <file_name>
+
+# 示例:获取/turtlesim节点的background_g参数的类型和值
+ros2 param get /turtlesim background_g
+
+# 示例:设置/turtlesim节点的background_g参数值为20
+ros2 param set /turtlesim background_g 20
+
+# 示例:导出节点/turtlesim的参数到turtlesim.yaml文件
+ros2 param load /turtlesim turtlesim.yaml
+
+# 示例:将turtlesim.yaml文件参数导入到节点/turtlesim中
+ros2 param load /turtlesim turtlesim.yaml
+
+# 示例:启动turtlesim_node节点时,导入turtlesim.yaml文件的参数
+ros2 run turtlesim turtlesim_node --ros-args --params-file turtlesim.yaml
+
+

用来查看日志的rqt_console

+

rqt_console是一个 GUI 工具,用于在 ROS 2 中不同等级的日志消息。通常,日志消息会显示在您的终端中。使用rqt_console,您可以随着时间的推移收集这些消息,以更有条理的方式仔细查看它们,过滤它们,保存它们,甚至重新加载保存的文件以在不同时间进行反思。

+

rqt_console记录日志的级别:

+

每个级别的含义没有确切的标准,但可以肯定地假设:

+
    +
  • +

    Fatal消息表明系统将终止以尝试保护自身免受损害。

    +
  • +
  • +

    Error消息表明存在重大问题,这些问题不一定会损坏系统,但会阻止其正常运行。

    +
  • +
  • +

    Warn消息表明意外的活动或不理想的结果,可能代表更深层次的问题,但不会彻底损害功能。

    +
  • +
  • +

    Info消息指示事件和状态更新,作为系统是否按预期运行的视觉验证。

    +
  • +
  • +

    Debug消息详细说明了系统执行的整个逐步过程。

    +
  • +
+
# 启动rqt_console
+ros2 run rqt_console rqt_console
+
+# 示例:设置节点的记录器日志级别为WRAN
+ros2 run turtlesim turtlesim_node --ros-args --log-level WARN
+
+

记录并回放

+

ros2 bag是一个命令行工具,用于记录系统中主题发布的数据。它累积在任意数量的主题上传递的数据并将其保存在数据库中。然后,您可以重播数据以重现测试和实验的结果。

+

安装ros2 bag

+
sudo apt-get install ros-iron-ros2bag ros-iron-rosbag2-storage-default-plugins
+
+

开始记录

+
# 创建保存记录的目录
+mkdir bag_files
+cd bag_files
+
+# 记录主题(ctrl+c停止记录)
+ros2 bag record <topic_name>
+
+# 查看记录的信息
+ros2 bag info <bag_file_name>
+
+# 播放主题
+ros2 bag play <bag_file_name>
+
+# 示例:记录/turtle1/cmd_vel主题(ctrl+c停止记录)
+ros2 bag record /turtle1/cmd_vel
+
+# 示例:记录多个主题,记录/turtle1/cmd_vel主题和/turtle1/pose主题
+ros2 bag record -o subset /turtle1/cmd_vel /turtle1/pose
+
+

知识点

+
    +
  1. ROS_DOMAIN_ID变量
  2. +
+

ROS_DOMAIN_ID也可称为域ID,其值的选择与本地计算机环境有关,Linux环境下,使用0-65535作为端口号,并且32768-60999作为临时端口,临时端口在任何时候都可能会被Linux使用,所以用户端口应该尽量避免与临时端口冲突。
+ROS_DOMAIN_ID与端口号的关联来自一个公式:

+
端口号 = 7400 + 250 * ROS_DOMAIN_ID + 0
+ROS_DOMAIN_ID = (端口号 - 7400) / 250
+
+

为了安全使用,根据上面的计算公式和临时端口的区域可以得出以下限制:

+
    +
  • Linux环境下,域ID只能选择ID 0~101和ID 215~232
  • +
  • Linux环境下,域ID 101最多只能创建54个进程
  • +
  • Linux环境下,域ID 232最多只能创建63个进程
  • +
+

对于Windows、MacOS等环境,由于临时端口的分配区域不同,限制条件也有差异,详情见
+The ROS_DOMAIN_ID

+
    +
  1. ROS_AUTOMATIC_DISCOVERY_RANGE变量
  2. +
+

ROS_AUTOMATIC_DISCOVERY_RANGE变量可以设置 ROS 节点尝试相互发现的距离。

+

有效选项有:

+
    +
  • +

    SUBNET,默认值,对于基于 DDS 的中间件来说,这意味着它将发现通过多播可到达的任何节点。

    +
  • +
  • +

    LOCALHOST,节点只会尝试发现同一台机器上的其他节点。

    +
  • +
  • +

    OFF,该节点不会发现任何其他节点,即使在同一台机器上。

    +
  • +
  • +

    SYSTEM_DEFAULT,不更改任何发现设置

    +
  • +
+

详情见Improved Dynamic Discovery

+]]>
+
+ + <![CDATA[使用bouffalo sdk开发bl618]]> + https://lxowalle.github.io/post/shi-yong-bouffalo-sdk-kai-fa-bl618/ + + + 2023-07-11T07:08:37.000Z + 一、下载bouffalo sdk +
git clone https://github.com/bouffalolab/bouffalo_sdk.git
+
+

二、安装工具链

+

windows 下使用riscv64-unknown-elf-gcc
+Linux 下使用riscv64-unknown-elf-gcc

+
# 确认一下交叉编译工具链是否正常
+# 1. 如果是默认路径,确认CROSS_COMPILE ?= riscv64-unknown-elf-
+riscv64-unknown-elf-gcc -v
+
+# 2. 如果是自定义路径,确认配置CROSS_COMPILE ?= /opt/toolchain_gcc_t-head_linux/bin/riscv64-unknown-elf-(这里填的实际工具链位置)
+/opt/toolchain_gcc_t-head_linux/bin/riscv64-unknown-elf-gcc -v
+
+# 执行xxx-gcc -v后打印的末尾字段如下:
+Thread model: posix
+Supported LTO compression algorithms: zlib
+gcc version 10.2.0 (Xuantie-900 elf newlib gcc Toolchain V2.6.1 B-20220906) 
+
+

三、编译

+
cd examples/helloworld
+make CHIP=bl616 BOARD=bl616dk   
+
+

四、烧录

+

减轻敲代码的负担,为串口操作添加默认sudo权限

+
sudo usermod -aG dialout xxx # xxx 是你自己的用户名
+
+

烧录固件

+
cd examples/helloworld
+make flash CHIP=chip_name COMX=xxx # chip_name should be bl602/bl702/bl616/bl808/bl606p, COMX in Windows, /dev/ttyxxx in Linux
+
+

五、遇到了问题

+
    +
  1. 首先检查工具链是否正确,上文介绍了如何确认工具链是否正确
  2. +
  3. 可能是编译中间文件导致的问题,尝试make clean后再重新编译
  4. +
+]]>
+
+ + <![CDATA[开始使用LicheePi 4A记录]]> + https://lxowalle.github.io/post/kai-shi-shi-yong-licheepi-4a-ji-lu/ + + + 2023-07-07T02:24:14.000Z + LicheePi 4A 是基于 Lichee Module 4A 核心板的 高性能 RISC-V Linux 开发板,以 TH1520 为主控核心(4xC910@1.85G, RV64GCV,4TOPS@int8 NPU, 50GFLOP GPU),板载最大 16GB 64bit LPDDR4X,128GB eMMC,支持 HDMI+MIPI 双4K 显示输出,支持 4K 摄像头接入,双千兆网口(其中一个支持POE供电)和 4 个 USB3.0 接口,多种音频输入输出(由专用 C906 核心处理)。
+LicheePi 4A长这样的:
+

+
    +
  1. +

    开始供电,根据sipeed文档指示,如果不接显示屏之类的耗电高的外设,可以直接通过USB供电。接显示屏太麻烦了,所以这里直接typec口的USB接上HUB(有外部电源)供电。

    +
  2. +
  3. +

    接显示屏太麻烦了,所以直接用串口来操作系统。串口的连接方法参考:
    +

    +
  4. +
  5. +

    再插上网线。
    +插上网线后系统会自动识别设备,并获取ip地址。我手上的系统不带有ifconfig,所以用ip命令来查看ip地址

    +
  6. +
+
ip addr show
+
+
    +
  1. 通过ssh登录。开发过程中,通常在本地用vscode通过ssh连接目标机器开发,所以需要先连通ssh
  2. +
+
# 在licheepi 4a中执行
+sudo apt update                         # 更新软件源
+sudo apt instal openssh-server  # 安装sshd服务
+
+# 本地主机执行
+ssh sipeed@192.168.0.245        # 根据实际ip填写
+
+
    +
  1. OK,可以开始自由开发了
  2. +
+]]>
+
+ + <![CDATA[基于H616环境调试u-boot]]> + https://lxowalle.github.io/post/cong-0-kai-shi-da-jian-h616-de-kai-fa-huan-jing/ + + + 2023-07-04T03:07:08.000Z + 零、下载工具链 +

下载交叉工具链aarch64-none-linux-gnu

+
# 解压到/opt目录下,后边会用到
+sudo tar -xf arm-gnu-toolchain-12.2.rel1-x86_64-aarch64-none-linux-gnu.tar.xz -C /opt
+
+

一、编译调试u-boot

+

这里提供通过sunxi-tools工具来进行USB调试,将u-boot直接烧录到RAM中,方便调试。

+

安装sunxi-tools工具

+
git clone https://github.com/linux-sunxi/sunxi-tools
+cd sunxi-tools
+make
+
+# 或者直接从仓库下载
+sudo apt install sunxi-tools
+
+

编译可信启动固件arm-trusted-firmware

+

arm_trusted_firmware是用于arm芯片最最最初运行的启动代码,有兴趣可以了解一下ATF的资料。我们这里只编译bl31固件。

+
# 分支:`master` 版本:`e09b8aa5a517bae522feb11913a091067d9ed18e`
+git clone https://github.com/ARM-software/arm-trusted-firmware.git
+cd arm-trusted-firmware
+
+# 开始编译。这里是芯片是H616,所以填PLAT=sun50i_h616
+make CROSS_COMPILE=/opt/arm-gnu-toolchain-12.2.rel1-x86_64-aarch64-none-linux-gnu/bin/aarch64-none-linux-gnu-  PLAT=sun50i_h616 DEBUG=1 bl31
+
+

编译u-boot

+

直接上最新的u-boot。

+
# 分支:`master` 版本:`f95232c6f06cc0747801bb6a4372b33825ab0164`
+git clone git://git.denx.de/u-boot.git
+
+

需要修改两处代码来解决可能出现的两种问题:

+
    +
  1. 解决Failed to set core voltage! Can't set CPU frequency问题,原因是电源驱动不匹配,我测试时板子电源IC是AXP1530,所以可以直接修改drivers/power/axp305.c文件
  2. +
+
# drivers/power/axp305.c
+# 1/3 删除axp_set_dcdc4的代码实现
+int axp_set_dcdc4(unsigned int mvolt)
+{
+	(void)mvolt;
+	return 0;
+}
+# 2/3 添加设置dcdc3电压的函数
+#define AXP305_DCDC3_1200MV_OFFSET 71
+int axp_set_dcdc3(unsigned int mvolt)
+{
+	int ret;
+	u8 cfg;
+
+	if (mvolt >= 1220)
+	{
+		cfg = AXP305_DCDC3_1200MV_OFFSET +
+			axp305_mvolt_to_cfg(mvolt, 1220, 1840, 20);
+	}
+	else
+		cfg = axp305_mvolt_to_cfg(mvolt, 500, 1200, 10);
+
+	if (mvolt == 0)
+		return pmic_bus_clrbits(AXP305_OUTPUT_CTRL1,
+								AXP305_OUTPUT_CTRL1_DCDCD_EN);
+
+	ret = pmic_bus_write(AXP305_DCDCD_VOLTAGE, cfg);
+	if (ret)
+		return ret;
+ 
+	return pmic_bus_setbits(AXP305_OUTPUT_CTRL1,
+				0x1f);
+}
+
+# 3/3 修改axp_init函数的实现
+int axp_init(void)
+{
+	u8 axp_chip_id;
+	int ret;
+
+	ret = pmic_bus_init();
+	if (ret)
+		return ret;
+
+	ret = pmic_bus_read(AXP305_CHIP_VERSION, &axp_chip_id);
+	if (ret)
+		return ret;
+
+	if ((axp_chip_id & AXP305_CHIP_VERSION_MASK) != 0x4b) {
+		printf("AXP1530: Unsupported chip ID: 0x%x\n", axp_chip_id);		
+		return -ENODEV;
+	}
+
+	if (0 != axp_set_dcdc3(1500)) {
+		printf("AXP1530: Failed to set DCDC3\n");
+		return -ENODEV;
+	}
+
+	return ret;
+}
+
+
    +
  1. u-boot的一个bug会导致上传程序时出现usb_bulk_send() ERROR -7: Operation timed out的问题,需要修改arch/arm/mach-sunxi/dram_sun50i_h616.c文件
  2. +
+
# arch/arm/mach-sunxi/dram_sun50i_h616.c
+# 1/1 在mctl_phy_read_calibration函数开头添加udelay(0)来解决
+static bool mctl_phy_read_calibration(struct dram_para *para)
+{
+	bool result = true;
+	u32 val, tmp;
+	udelay(0);	// 为了修复usb_bulk_send() ERROR -7: Operation timed out问题而添加,问题根源位置,见https://github.com/linux-sunxi/sunxi-tools/issues/182
+	clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 0x30, 0x20);
+    // ...
+    // other code
+}
+
+

开始编译

+
# 使用orangepi_zero2_defconfig的配置
+make CROSS_COMPILE=/opt/arm-gnu-toolchain-12.2.rel1-x86_64-aarch64-none-linux-gnu/bin/aarch64-none-linux-gnu- BL31=../arm-trusted-firmware/build/sun50i_h616/debug/bl31.bin orangepi_zero2_defconfig
+
+# 编译
+make CROSS_COMPILE=/opt/arm-gnu-toolchain-12.2.rel1-x86_64-aarch64-none-linux-gnu/bin/aarch64-none-linux-gnu- BL31=../arm-trusted-firmware/build/sun50i_h616/debug/bl31.bin
+
+

二、 测试启动u-boot

+

1. 让板子进入fel模式

+

只要取出sd卡再上电,就可以直接进入fel模式

+

2. 通过USB启动板子

+

现在开始用安装的sunxi-tools来通过USB启动u-boot了

+
cd u-boot
+../sunxi-tools/sunxi-fel uboot u-boot-sunxi-with-spl.bin
+
+

此时板子就能跑起来~有问题的话先检查一下是否有漏操作的地方,或者查查资料吧

+]]>
+
+
\ No newline at end of file diff --git a/favicon.ico b/favicon.ico new file mode 100644 index 00000000..7196fe49 Binary files /dev/null and b/favicon.ico differ diff --git a/images/avatar.png b/images/avatar.png new file mode 100644 index 00000000..1a82a9a9 Binary files /dev/null and b/images/avatar.png differ diff --git a/index.html b/index.html new file mode 100644 index 00000000..73d625a9 --- /dev/null +++ b/index.html @@ -0,0 +1,169 @@ + + + + +lxowalle + + + + + + + + + + + +
+
+ + + +
+ + + + + + + + + +
+ + +
+ + +
+ + + + +
+
+ + diff --git a/post-images/hello-gridea.png b/post-images/hello-gridea.png new file mode 100644 index 00000000..bbd12058 Binary files /dev/null and b/post-images/hello-gridea.png differ diff --git a/post/cong-0-kai-shi-da-jian-h616-de-kai-fa-huan-jing/index.html b/post/cong-0-kai-shi-da-jian-h616-de-kai-fa-huan-jing/index.html new file mode 100644 index 00000000..e50f6039 --- /dev/null +++ b/post/cong-0-kai-shi-da-jian-h616-de-kai-fa-huan-jing/index.html @@ -0,0 +1,303 @@ + + + + +基于H616环境调试u-boot | lxowalle + + + + + + + + + + + + + + +
+
+ + +
+
+

+ 基于H616环境调试u-boot +

+ + +
+
+

零、下载工具链

+

下载交叉工具链aarch64-none-linux-gnu

+
# 解压到/opt目录下,后边会用到
+sudo tar -xf arm-gnu-toolchain-12.2.rel1-x86_64-aarch64-none-linux-gnu.tar.xz -C /opt
+
+

一、编译调试u-boot

+

这里提供通过sunxi-tools工具来进行USB调试,将u-boot直接烧录到RAM中,方便调试。

+

安装sunxi-tools工具

+
git clone https://github.com/linux-sunxi/sunxi-tools
+cd sunxi-tools
+make
+
+# 或者直接从仓库下载
+sudo apt install sunxi-tools
+
+

编译可信启动固件arm-trusted-firmware

+

arm_trusted_firmware是用于arm芯片最最最初运行的启动代码,有兴趣可以了解一下ATF的资料。我们这里只编译bl31固件。

+
# 分支:`master` 版本:`e09b8aa5a517bae522feb11913a091067d9ed18e`
+git clone https://github.com/ARM-software/arm-trusted-firmware.git
+cd arm-trusted-firmware
+
+# 开始编译。这里是芯片是H616,所以填PLAT=sun50i_h616
+make CROSS_COMPILE=/opt/arm-gnu-toolchain-12.2.rel1-x86_64-aarch64-none-linux-gnu/bin/aarch64-none-linux-gnu-  PLAT=sun50i_h616 DEBUG=1 bl31
+
+

编译u-boot

+

直接上最新的u-boot。

+
# 分支:`master` 版本:`f95232c6f06cc0747801bb6a4372b33825ab0164`
+git clone git://git.denx.de/u-boot.git
+
+

需要修改两处代码来解决可能出现的两种问题:

+
    +
  1. 解决Failed to set core voltage! Can't set CPU frequency问题,原因是电源驱动不匹配,我测试时板子电源IC是AXP1530,所以可以直接修改drivers/power/axp305.c文件
  2. +
+
# drivers/power/axp305.c
+# 1/3 删除axp_set_dcdc4的代码实现
+int axp_set_dcdc4(unsigned int mvolt)
+{
+	(void)mvolt;
+	return 0;
+}
+# 2/3 添加设置dcdc3电压的函数
+#define AXP305_DCDC3_1200MV_OFFSET 71
+int axp_set_dcdc3(unsigned int mvolt)
+{
+	int ret;
+	u8 cfg;
+
+	if (mvolt >= 1220)
+	{
+		cfg = AXP305_DCDC3_1200MV_OFFSET +
+			axp305_mvolt_to_cfg(mvolt, 1220, 1840, 20);
+	}
+	else
+		cfg = axp305_mvolt_to_cfg(mvolt, 500, 1200, 10);
+
+	if (mvolt == 0)
+		return pmic_bus_clrbits(AXP305_OUTPUT_CTRL1,
+								AXP305_OUTPUT_CTRL1_DCDCD_EN);
+
+	ret = pmic_bus_write(AXP305_DCDCD_VOLTAGE, cfg);
+	if (ret)
+		return ret;
+ 
+	return pmic_bus_setbits(AXP305_OUTPUT_CTRL1,
+				0x1f);
+}
+
+# 3/3 修改axp_init函数的实现
+int axp_init(void)
+{
+	u8 axp_chip_id;
+	int ret;
+
+	ret = pmic_bus_init();
+	if (ret)
+		return ret;
+
+	ret = pmic_bus_read(AXP305_CHIP_VERSION, &axp_chip_id);
+	if (ret)
+		return ret;
+
+	if ((axp_chip_id & AXP305_CHIP_VERSION_MASK) != 0x4b) {
+		printf("AXP1530: Unsupported chip ID: 0x%x\n", axp_chip_id);		
+		return -ENODEV;
+	}
+
+	if (0 != axp_set_dcdc3(1500)) {
+		printf("AXP1530: Failed to set DCDC3\n");
+		return -ENODEV;
+	}
+
+	return ret;
+}
+
+
    +
  1. u-boot的一个bug会导致上传程序时出现usb_bulk_send() ERROR -7: Operation timed out的问题,需要修改arch/arm/mach-sunxi/dram_sun50i_h616.c文件
  2. +
+
# arch/arm/mach-sunxi/dram_sun50i_h616.c
+# 1/1 在mctl_phy_read_calibration函数开头添加udelay(0)来解决
+static bool mctl_phy_read_calibration(struct dram_para *para)
+{
+	bool result = true;
+	u32 val, tmp;
+	udelay(0);	// 为了修复usb_bulk_send() ERROR -7: Operation timed out问题而添加,问题根源位置,见https://github.com/linux-sunxi/sunxi-tools/issues/182
+	clrsetbits_le32(SUNXI_DRAM_PHY0_BASE + 8, 0x30, 0x20);
+    // ...
+    // other code
+}
+
+

开始编译

+
# 使用orangepi_zero2_defconfig的配置
+make CROSS_COMPILE=/opt/arm-gnu-toolchain-12.2.rel1-x86_64-aarch64-none-linux-gnu/bin/aarch64-none-linux-gnu- BL31=../arm-trusted-firmware/build/sun50i_h616/debug/bl31.bin orangepi_zero2_defconfig
+
+# 编译
+make CROSS_COMPILE=/opt/arm-gnu-toolchain-12.2.rel1-x86_64-aarch64-none-linux-gnu/bin/aarch64-none-linux-gnu- BL31=../arm-trusted-firmware/build/sun50i_h616/debug/bl31.bin
+
+

二、 测试启动u-boot

+

1. 让板子进入fel模式

+

只要取出sd卡再上电,就可以直接进入fel模式

+

2. 通过USB启动板子

+

现在开始用安装的sunxi-tools来通过USB启动u-boot了

+
cd u-boot
+../sunxi-tools/sunxi-fel uboot u-boot-sunxi-with-spl.bin
+
+

此时板子就能跑起来~有问题的话先检查一下是否有漏操作的地方,或者查查资料吧

+ +
+ +
+
+
+ + + + + + + +
+
+ + + + diff --git a/post/kai-shi-shi-yong-licheepi-4a-ji-lu/index.html b/post/kai-shi-shi-yong-licheepi-4a-ji-lu/index.html new file mode 100644 index 00000000..9cfd7197 --- /dev/null +++ b/post/kai-shi-shi-yong-licheepi-4a-ji-lu/index.html @@ -0,0 +1,195 @@ + + + + +开始使用LicheePi 4A记录 | lxowalle + + + + + + + + + + + + + + +
+
+ + +
+
+

+ 开始使用LicheePi 4A记录 +

+ + +
+
+

LicheePi 4A 是基于 Lichee Module 4A 核心板的 高性能 RISC-V Linux 开发板,以 TH1520 为主控核心(4xC910@1.85G, RV64GCV,4TOPS@int8 NPU, 50GFLOP GPU),板载最大 16GB 64bit LPDDR4X,128GB eMMC,支持 HDMI+MIPI 双4K 显示输出,支持 4K 摄像头接入,双千兆网口(其中一个支持POE供电)和 4 个 USB3.0 接口,多种音频输入输出(由专用 C906 核心处理)。
+LicheePi 4A长这样的:
+

+
    +
  1. +

    开始供电,根据sipeed文档指示,如果不接显示屏之类的耗电高的外设,可以直接通过USB供电。接显示屏太麻烦了,所以这里直接typec口的USB接上HUB(有外部电源)供电。

    +
  2. +
  3. +

    接显示屏太麻烦了,所以直接用串口来操作系统。串口的连接方法参考:
    +

    +
  4. +
  5. +

    再插上网线。
    +插上网线后系统会自动识别设备,并获取ip地址。我手上的系统不带有ifconfig,所以用ip命令来查看ip地址

    +
  6. +
+
ip addr show
+
+
    +
  1. 通过ssh登录。开发过程中,通常在本地用vscode通过ssh连接目标机器开发,所以需要先连通ssh
  2. +
+
# 在licheepi 4a中执行
+sudo apt update                         # 更新软件源
+sudo apt instal openssh-server  # 安装sshd服务
+
+# 本地主机执行
+ssh sipeed@192.168.0.245        # 根据实际ip填写
+
+
    +
  1. OK,可以开始自由开发了
  2. +
+ +
+
+ +
+
+
+
+ + + + + + + + + +
+
+ + + + diff --git a/post/ros2-cli-gong-ju-shi-yong/index.html b/post/ros2-cli-gong-ju-shi-yong/index.html new file mode 100644 index 00000000..65f819e1 --- /dev/null +++ b/post/ros2-cli-gong-ju-shi-yong/index.html @@ -0,0 +1,437 @@ + + + + +[ROS2] CLI工具使用 | lxowalle + + + + + + + + + + + + + + +
+
+ + +
+
+

+ [ROS2] CLI工具使用 +

+ + +
+
+

参考ROS2 IRON指南安装基本的环境。注意riscv架构的平台目前还不支持ROS2(2023-07-25)

+

参考使用turtlesim、ros2、 和rqt

+

基础环境

+

安装ros2后不能立马使用,需要将ROS2环境添加到环境变量中才能进一步操作。

+

添加步骤:

+
# 添加基础环境
+echo "source /opt/ros/iron/setup.bash" >> ~/.bashrc
+
+# 添加域ID,为了系统安全,域ID的值一般选0~101和215~232
+echo "export ROS_DOMAIN_ID=<your_domain_id>" >> ~/.bash_profile
+
+# 设置通信范围
+echo "export  ROS_AUTOMATIC_DISCOVERY_RANGE=SUBNET" >> ~/.bash_profile
+
+

使用turtlesim和rqt

+

turtlesim工具是一个海龟模拟器,一般被用来学习ROS2的通信机制。rqt是一个图形窗口,用来将可视化的展示各节点的服务、主题关系

+

安装turtlesim和rqt

+
sudo apt update
+sudo apt install ros-iron-turtlesim
+sudo apt install ~nros-iron-rqt*
+
+

使用turtlesim和rqt

+
# 启动一个节点,用来生成海龟
+ros2 run turtlesim turtlesim_node
+# 启动一个节点,用来控制海龟
+ros2 run turtlesim turtle_teleop_key
+# 启动rqt,用来监测和控制海龟
+rqt
+# 启动rqt_graph,用来图形化显示节点间的关系
+rqt_graph
+
+

更详细的使用方法参考这里

+

节点

+

ROS2中以节点为基本单位,每个节点之间可以通过topics(主题)、services(服务)、actions(操作)或parameters(参数)来通信。
+ROS2通过节点来实现功能单一、模块化。

+

通过命令行来操作节点

+
# 列出节点
+ros2 node list
+
+# 查看节点信息
+ros2 node info <节点名> # 例如ros2 node info /turtlesim
+
+# 将turtlesim_node的默认节点重映射为my_turtle节点
+ros2 run turtlesim turtlesim_node --ros-args --remap __node:=my_turtle
+
+

主题

+

主题是ROS2的一种基于发布者-订阅者的通信机制,节点可以将数据发布到任意数量的主题,并且同时订阅任意数量的主题。主题可以多对多。

+

通过命令行来操作主题

+
# 列出主题
+ros2 topic list
+
+# 列出主题(参数-t可以列出主题类型)
+ros2 topic list -t
+
+# # 列出指定主题的类型
+ros2 topic type <主题名>
+
+# 查看主题订阅数量、发布数量
+ros2 topic info <主题名>
+
+# 实时查看主题内的消息
+ros2 topic echo <主题名> # 例如:ros2 topic echo /turtle1/cmd_vel
+
+# 查看主题内消息的速率
+ros2 topic hz <topic_name>
+
+# 向主题发布消息
+ros2 topic pub <topic_name> <msg_type> '<args>'
+
+# 示例:只发送一次,向主题/turtle1/cmd_vel发布类型为geometry_msgs/msg/Twist的消息,注意消息用yaml语法输入
+ros2 topic pub --once /turtle1/cmd_vel geometry_msgs/msg/Twist "{linear: {x: 2.0, y: 0.0, z: 0.0}, angular: {x: 0.0, y: 0.0, z: 1.8}}"
+
+# 示例:每1s发送一次,向主题/turtle1/cmd_vel发布类型为geometry_msgs/msg/Twist的消息,注意消息用yaml语法输入
+ros2 topic pub --rate 1 /turtle1/cmd_vel geometry_msgs/msg/Twist "{linear: {x: 2.0, y: 0.0, z: 0.0}, angular: {x: 0.0, y: 0.0, z: 1.8}}"
+
+

服务

+

服务是ROS2一种基于调用-响应的通信机制。与主题的差异是,主题一般是持续的更新数据,而服务只在客户端调用时才提供数据。

+

通过命令行来操作服务

+
# 列出服务
+ros2 service list
+
+# 列出服务(参数-t可以列出服务类型)
+ros2 service list -t
+
+# 列出指定服务的类型
+ros2 service type <service_name>
+
+# 查找某个类型的所有服务
+ ros2 topic find <service_type>
+
+ # 调用服务
+ ros2 service call <service_name> <service_type> <arguments>
+
+ # 示例:调用spawn服务新生成一直海龟
+ ros2 service call /spawn turtlesim/srv/Spawn "{x: 2, y: 2, theta: 0.2, name: ''}"
+
+

动作

+

动作是ROS2建立在主题和服务的基础上的基于目标-反馈-结果的通信类型。动作与服务类似,但是可以中断上次操作。

+

通过命令行来操作动作

+
# 列出动作
+ros2 action list
+
+# 列出动作(参数-t可以列出动作类型)
+ros2 actions list
+
+# 列出动作的客户端数量、服务器数量
+ros2 action info <action_name>
+
+# 查看动作的接口结构
+ros2 action info <action_type>
+
+# 发起动作。<values>需要采用 YAML 格式,添加--feedback后可以获取实时反馈
+ros2 action send_goal <action_name> <action_type> <values>
+
+
+# 示例:查看动作/turtlesim/action/RotateAbsolute的结构
+ros2 interface show turtlesim/action/RotateAbsolute
+
+# 示例:向动作/turtle1/rotate_absolute发起旋转1.57?(反正是个动作)
+ros2 action send_goal /turtle1/rotate_absolute turtlesim/action/RotateAbsolute "{theta: 1.57}"
+
+# 示例:向动作/turtle1/rotate_absolute发起旋转1.57,并获取实时反馈
+ros2 action send_goal /turtle1/rotate_absolute turtlesim/action/RotateAbsolute "{theta: -1.57}" --feedback
+
+

参数

+

参数是节点的配置值。您可以将参数视为节点设置。节点可以将参数存储为整数、浮点数、布尔值、字符串和列表。在ROS 2中,每个节点维护自己的参数

+

通过命令行来操作参数

+
# 列出参数
+ros2 param list
+
+# 获取指定节点的参数类型和参数值
+ros2 param get <node_name> <parameter_name>
+
+# 设置指定节点的参数类型和参数值
+ros2 param set <node_name> <parameter_name> <value>
+
+# 导出指定节点的所有参数值
+ros2 param dump <node_name>
+
+# 导入参数到指定节点(parameter_file格式和dump出的格式一致)
+ros2 param load <node_name> <parameter_file>
+
+# 节点启动时加载参数文件
+ros2 run <package_name> <executable_name> --ros-args --params-file <file_name>
+
+# 示例:获取/turtlesim节点的background_g参数的类型和值
+ros2 param get /turtlesim background_g
+
+# 示例:设置/turtlesim节点的background_g参数值为20
+ros2 param set /turtlesim background_g 20
+
+# 示例:导出节点/turtlesim的参数到turtlesim.yaml文件
+ros2 param load /turtlesim turtlesim.yaml
+
+# 示例:将turtlesim.yaml文件参数导入到节点/turtlesim中
+ros2 param load /turtlesim turtlesim.yaml
+
+# 示例:启动turtlesim_node节点时,导入turtlesim.yaml文件的参数
+ros2 run turtlesim turtlesim_node --ros-args --params-file turtlesim.yaml
+
+

用来查看日志的rqt_console

+

rqt_console是一个 GUI 工具,用于在 ROS 2 中不同等级的日志消息。通常,日志消息会显示在您的终端中。使用rqt_console,您可以随着时间的推移收集这些消息,以更有条理的方式仔细查看它们,过滤它们,保存它们,甚至重新加载保存的文件以在不同时间进行反思。

+

rqt_console记录日志的级别:

+

每个级别的含义没有确切的标准,但可以肯定地假设:

+
    +
  • +

    Fatal消息表明系统将终止以尝试保护自身免受损害。

    +
  • +
  • +

    Error消息表明存在重大问题,这些问题不一定会损坏系统,但会阻止其正常运行。

    +
  • +
  • +

    Warn消息表明意外的活动或不理想的结果,可能代表更深层次的问题,但不会彻底损害功能。

    +
  • +
  • +

    Info消息指示事件和状态更新,作为系统是否按预期运行的视觉验证。

    +
  • +
  • +

    Debug消息详细说明了系统执行的整个逐步过程。

    +
  • +
+
# 启动rqt_console
+ros2 run rqt_console rqt_console
+
+# 示例:设置节点的记录器日志级别为WRAN
+ros2 run turtlesim turtlesim_node --ros-args --log-level WARN
+
+

记录并回放

+

ros2 bag是一个命令行工具,用于记录系统中主题发布的数据。它累积在任意数量的主题上传递的数据并将其保存在数据库中。然后,您可以重播数据以重现测试和实验的结果。

+

安装ros2 bag

+
sudo apt-get install ros-iron-ros2bag ros-iron-rosbag2-storage-default-plugins
+
+

开始记录

+
# 创建保存记录的目录
+mkdir bag_files
+cd bag_files
+
+# 记录主题(ctrl+c停止记录)
+ros2 bag record <topic_name>
+
+# 查看记录的信息
+ros2 bag info <bag_file_name>
+
+# 播放主题
+ros2 bag play <bag_file_name>
+
+# 示例:记录/turtle1/cmd_vel主题(ctrl+c停止记录)
+ros2 bag record /turtle1/cmd_vel
+
+# 示例:记录多个主题,记录/turtle1/cmd_vel主题和/turtle1/pose主题
+ros2 bag record -o subset /turtle1/cmd_vel /turtle1/pose
+
+

知识点

+
    +
  1. ROS_DOMAIN_ID变量
  2. +
+

ROS_DOMAIN_ID也可称为域ID,其值的选择与本地计算机环境有关,Linux环境下,使用0-65535作为端口号,并且32768-60999作为临时端口,临时端口在任何时候都可能会被Linux使用,所以用户端口应该尽量避免与临时端口冲突。
+ROS_DOMAIN_ID与端口号的关联来自一个公式:

+
端口号 = 7400 + 250 * ROS_DOMAIN_ID + 0
+ROS_DOMAIN_ID = (端口号 - 7400) / 250
+
+

为了安全使用,根据上面的计算公式和临时端口的区域可以得出以下限制:

+
    +
  • Linux环境下,域ID只能选择ID 0~101和ID 215~232
  • +
  • Linux环境下,域ID 101最多只能创建54个进程
  • +
  • Linux环境下,域ID 232最多只能创建63个进程
  • +
+

对于Windows、MacOS等环境,由于临时端口的分配区域不同,限制条件也有差异,详情见
+The ROS_DOMAIN_ID

+
    +
  1. ROS_AUTOMATIC_DISCOVERY_RANGE变量
  2. +
+

ROS_AUTOMATIC_DISCOVERY_RANGE变量可以设置 ROS 节点尝试相互发现的距离。

+

有效选项有:

+
    +
  • +

    SUBNET,默认值,对于基于 DDS 的中间件来说,这意味着它将发现通过多播可到达的任何节点。

    +
  • +
  • +

    LOCALHOST,节点只会尝试发现同一台机器上的其他节点。

    +
  • +
  • +

    OFF,该节点不会发现任何其他节点,即使在同一台机器上。

    +
  • +
  • +

    SYSTEM_DEFAULT,不更改任何发现设置

    +
  • +
+

详情见Improved Dynamic Discovery

+ +
+ +
+
+
+ + + + + + + + + +
+
+ + + + diff --git a/post/shi-yong-bouffalo-sdk-kai-fa-bl618/index.html b/post/shi-yong-bouffalo-sdk-kai-fa-bl618/index.html new file mode 100644 index 00000000..7e32c1cd --- /dev/null +++ b/post/shi-yong-bouffalo-sdk-kai-fa-bl618/index.html @@ -0,0 +1,215 @@ + + + + +使用bouffalo sdk开发bl618 | lxowalle + + + + + + + + + + + + + + +
+
+ + +
+
+

+ 使用bouffalo sdk开发bl618 +

+ + +
+
+

一、下载bouffalo sdk

+
git clone https://github.com/bouffalolab/bouffalo_sdk.git
+
+

二、安装工具链

+

windows 下使用riscv64-unknown-elf-gcc
+Linux 下使用riscv64-unknown-elf-gcc

+
# 确认一下交叉编译工具链是否正常
+# 1. 如果是默认路径,确认CROSS_COMPILE ?= riscv64-unknown-elf-
+riscv64-unknown-elf-gcc -v
+
+# 2. 如果是自定义路径,确认配置CROSS_COMPILE ?= /opt/toolchain_gcc_t-head_linux/bin/riscv64-unknown-elf-(这里填的实际工具链位置)
+/opt/toolchain_gcc_t-head_linux/bin/riscv64-unknown-elf-gcc -v
+
+# 执行xxx-gcc -v后打印的末尾字段如下:
+Thread model: posix
+Supported LTO compression algorithms: zlib
+gcc version 10.2.0 (Xuantie-900 elf newlib gcc Toolchain V2.6.1 B-20220906) 
+
+

三、编译

+
cd examples/helloworld
+make CHIP=bl616 BOARD=bl616dk   
+
+

四、烧录

+

减轻敲代码的负担,为串口操作添加默认sudo权限

+
sudo usermod -aG dialout xxx # xxx 是你自己的用户名
+
+

烧录固件

+
cd examples/helloworld
+make flash CHIP=chip_name COMX=xxx # chip_name should be bl602/bl702/bl616/bl808/bl606p, COMX in Windows, /dev/ttyxxx in Linux
+
+

五、遇到了问题

+
    +
  1. 首先检查工具链是否正确,上文介绍了如何确认工具链是否正确
  2. +
  3. 可能是编译中间文件导致的问题,尝试make clean后再重新编译
  4. +
+ +
+ +
+
+
+ + + + + + + + + +
+
+ + + + diff --git a/styles/main.css b/styles/main.css new file mode 100644 index 00000000..4f5f2c91 --- /dev/null +++ b/styles/main.css @@ -0,0 +1,976 @@ +/*! modern-normalize | MIT License | https://github.com/sindresorhus/modern-normalize */ +/* Document + ========================================================================== */ +/** + * Use a better box model (opinionated). + */ +html { + box-sizing: border-box; +} +*, +*::before, +*::after { + box-sizing: inherit; +} +/** + * Use a more readable tab size (opinionated). + */ +:root { + -moz-tab-size: 4; + tab-size: 4; +} +/** + * 1. Correct the line height in all browsers. + * 2. Prevent adjustments of font size after orientation changes in iOS. + */ +html { + line-height: 1.15; + /* 1 */ + -webkit-text-size-adjust: 100%; + /* 2 */ +} +/* Sections + ========================================================================== */ +/** + * Remove the margin in all browsers. + */ +body { + margin: 0; +} +/** + * Improve consistency of default fonts in all browsers. (https://github.com/sindresorhus/modern-normalize/issues/3) + */ +body { + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol'; +} +/* Grouping content + ========================================================================== */ +/* Text-level semantics + ========================================================================== */ +/** + * Add the correct text decoration in Chrome, Edge, and Safari. + */ +abbr[title] { + text-decoration: underline dotted; +} +/** + * Add the correct font weight in Chrome, Edge, and Safari. + */ +b, +strong { + font-weight: bolder; +} +/** + * 1. Improve consistency of default fonts in all browsers. (https://github.com/sindresorhus/modern-normalize/issues/3) + * 2. Correct the odd `em` font sizing in all browsers. + */ +code, +kbd, +samp, +pre { + font-family: SFMono-Regular, Consolas, 'Liberation Mono', Menlo, Courier, monospace; + /* 1 */ + font-size: 1em; + /* 2 */ +} +/** + * Add the correct font size in all browsers. + */ +small { + font-size: 80%; +} +/** + * Prevent `sub` and `sup` elements from affecting the line height in all browsers. + */ +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} +sub { + bottom: -0.25em; +} +sup { + top: -0.5em; +} +/* Forms + ========================================================================== */ +/** + * 1. Change the font styles in all browsers. + * 2. Remove the margin in Firefox and Safari. + */ +button, +input, +optgroup, +select, +textarea { + font-family: inherit; + /* 1 */ + font-size: 100%; + /* 1 */ + line-height: 1.15; + /* 1 */ + margin: 0; + /* 2 */ +} +/** + * Remove the inheritance of text transform in Edge and Firefox. + * 1. Remove the inheritance of text transform in Firefox. + */ +button, +select { + /* 1 */ + text-transform: none; +} +/** + * Correct the inability to style clickable types in iOS and Safari. + */ +button, +[type='button'], +[type='reset'], +[type='submit'] { + -webkit-appearance: button; +} +/** + * Remove the inner border and padding in Firefox. + */ +button::-moz-focus-inner, +[type='button']::-moz-focus-inner, +[type='reset']::-moz-focus-inner, +[type='submit']::-moz-focus-inner { + border-style: none; + padding: 0; +} +/** + * Restore the focus styles unset by the previous rule. + */ +button:-moz-focusring, +[type='button']:-moz-focusring, +[type='reset']:-moz-focusring, +[type='submit']:-moz-focusring { + outline: 1px dotted ButtonText; +} +/** + * Correct the padding in Firefox. + */ +fieldset { + padding: 0.35em 0.75em 0.625em; +} +/** + * Remove the padding so developers are not caught out when they zero out `fieldset` elements in all browsers. + */ +legend { + padding: 0; +} +/** + * Add the correct vertical alignment in Chrome and Firefox. + */ +progress { + vertical-align: baseline; +} +/** + * Correct the cursor style of increment and decrement buttons in Safari. + */ +[type='number']::-webkit-inner-spin-button, +[type='number']::-webkit-outer-spin-button { + height: auto; +} +/** + * 1. Correct the odd appearance in Chrome and Safari. + * 2. Correct the outline style in Safari. + */ +[type='search'] { + -webkit-appearance: textfield; + /* 1 */ + outline-offset: -2px; + /* 2 */ +} +/** + * Remove the inner padding in Chrome and Safari on macOS. + */ +[type='search']::-webkit-search-decoration { + -webkit-appearance: none; +} +/** + * 1. Correct the inability to style clickable types in iOS and Safari. + * 2. Change font properties to `inherit` in Safari. + */ +::-webkit-file-upload-button { + -webkit-appearance: button; + /* 1 */ + font: inherit; + /* 2 */ +} +/* Interactive + ========================================================================== */ +/* + * Add the correct display in Chrome and Safari. + */ +summary { + display: list-item; +} +*, +*:before, +*:after { + margin: 0; + padding: 0; +} +html, +body, +div, +span, +applet, +object, +iframe, +h1, +h2, +h3, +h4, +h5, +h6, +p, +blockquote, +pre, +a, +abbr, +acronym, +address, +big, +cite, +code, +del, +dfn, +em, +img, +ins, +kbd, +q, +s, +samp, +small, +strike, +strong, +sub, +sup, +tt, +var, +b, +u, +i, +center, +dl, +dt, +dd, +ol, +ul, +li, +fieldset, +form, +label, +legend, +table, +caption, +tbody, +tfoot, +thead, +tr, +th, +td, +article, +aside, +canvas, +details, +embed, +figure, +figcaption, +footer, +header, +hgroup, +menu, +nav, +output, +ruby, +section, +summary, +time, +mark, +audio, +video { + border: 0; + vertical-align: baseline; +} +html { + font-size: 58%; +} +body { + color: rgba(0, 0, 0, 0.86); + font: 400 16px/1.42 -apple-system, BlinkMacSystemFont, "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Droid Sans Fallback", "Microsoft YaHei", sans-serif; + letter-spacing: 0.05em; +} +a { + color: rgba(0, 0, 0, 0.98); + text-decoration: none; + transition: all 0.3s; +} +a:hover { + color: #006CFF; +} +body, +div, +a, +p, +ul, +li, +ol, +h1, +h2, +h3, +h4, +h5, +h6, +table, +tr, +td { + box-sizing: border-box; + margin: 0; + padding: 0; +} +.main { + max-width: 800px; + min-height: 100vh; + margin: 0 auto; + background: #fff; +} +.main .main-content { + flex: 1; + display: flex; + min-height: 100vh; + flex-direction: column; + padding: 0 24px; +} +.site-header { + padding: 48px 0; + text-align: center; +} +.site-header .site-title { + font-size: 32px; + font-weight: bold; +} +.site-header .site-description { + font-size: 16px; + padding: 24px; + color: #495057; + font-weight: lighter; +} +.site-header .menu-container { + display: flex; + justify-content: center; + flex-wrap: wrap; +} +.site-header .menu-container a.menu { + font-size: 16px; + padding: 8px 16px; + flex-shrink: 0; + font-weight: 600; +} +.site-header .avatar { + margin-bottom: 24px; + border-radius: 50%; + width: 120px; + height: 120px; +} +.site-header .social-container { + padding: 16px; + font-size: 18px; +} +.site-header .social-container a { + margin: 4px 8px; + color: #868e96; +} +@media (max-width: 600px) { + .site-header { + padding: 24px 0 0; + } + .site-header .avatar { + width: 80px; + height: 80px; + } +} +.post-container { + flex: 1; +} +.post-container .post { + padding-bottom: 32px; +} +.post-container .post .post-title { + font-size: 28px; + text-align: center; + padding: 24px 0; + font-weight: 900; + letter-spacing: 0.02em; +} +.post-container .post .post-info { + text-align: center; + font-size: 12px; + padding-bottom: 24px; +} +.post-container .post .post-info > span { + color: #5E5E5E; +} +.post-container .post .post-info > span:not(:first-child):before { + content: "/ "; + font-size: 10px; + color: rgba(0, 0, 0, 0.1); + margin: 0 4px; +} +.post-container .post .post-info .post-tag { + padding: 8px 8px; +} +.post-container .post .post-feature-image { + display: block; + width: 100%; + padding-top: 32.6%; + border-radius: 2px; + overflow: hidden; + background-size: cover; + background-position: center; + transition: all 0.3s; +} +.post-container .post .post-feature-image img { + width: 100%; +} +.post-container .post .post-feature-image:hover { + transform: scale(1.0082); +} +.post-container .post .post-abstract { + padding: 24px 0; + line-height: 1.5; + font-size: 16px; +} +.post-container .post .post-abstract strong { + font-weight: bolder; +} +.post-container .post .post-abstract a { + color: #006CFF; + transition: all 0.3s; +} +.post-container .post .post-abstract a:hover { + color: #0061e6; + border-bottom: 1px dotted #0061e6; +} +.post-container .post .post-abstract code { + font-family: monospace; + font-size: inherit; + background-color: rgba(0, 0, 0, 0.06); + padding: 0 2px; + border: 1px solid rgba(0, 0, 0, 0.08); + border-radius: 2px 2px; + line-height: initial; + word-wrap: break-word; + text-indent: 0; +} +.pagination-container { + padding: 32px 16px; + overflow: hidden; +} +.pagination-container .prev-page { + float: left; +} +.pagination-container .next-page { + float: right; +} +.pagination-container .prev-page, +.pagination-container .next-page { + padding: 6px 12px; + font-weight: bold; + border-bottom: 2px solid transparent; +} +.pagination-container .prev-page:hover, +.pagination-container .next-page:hover { + border-bottom: 2px solid; +} +@media (max-width: 600px) { + .post-container .post { + padding: 16px 16px; + } + .post-container .post .post-title { + padding: 16px 0; + font-size: 24px; + } + .post-container .post .post-abstract { + padding: 16px 0; + } + .post-container .post .post-feature-image { + padding-top: 56.25%; + } +} +.post-detail { + flex: 1; +} +.post-detail .post { + padding: 24px 32px; +} +.post-detail .post .post-feature-image { + width: 100%; + height: auto; + margin-bottom: 24px; + border-radius: 2px; +} +.post-detail .post .post-title { + font-size: 32px; + text-align: center; + padding: 24px 0; + font-weight: 900; + letter-spacing: 0.02em; +} +.post-detail .post .post-info { + text-align: center; + font-size: 12px; + padding-bottom: 24px; +} +.post-detail .post .post-info > span { + color: #5E5E5E; +} +.post-detail .post .post-info > span:not(:first-child):before { + content: "/ "; + font-size: 10px; + color: rgba(0, 0, 0, 0.1); + margin: 0 4px; +} +.post-detail .post .post-info .post-tag { + padding: 8px 8px; +} +.post-detail .post .post-content-wrapper { + display: flex; +} +.post-detail .post .post-content { + width: 100%; + flex-shrink: 0; + font-family: "Droid Serif", "PingFang SC", "Hiragino Sans GB", "Droid Sans Fallback", "Microsoft YaHei", sans-serif; +} +.post-detail .post .post-content a { + color: rgba(0, 0, 0, 0.98); + word-wrap: break-word; + text-decoration: none; + border-bottom: 1px solid rgba(0, 0, 0, 0.26); +} +.post-detail .post .post-content a:hover { + color: #0061e6; + border-bottom: 1px solid #0061e6; +} +.post-detail .post .post-content img { + display: block; + box-shadow: 0 0 30px #eee; + max-width: 100%; + border-radius: 2px; + margin: 24px auto; +} +.post-detail .post .post-content p { + line-height: 1.62; + margin-bottom: 1.12em; + font-size: 16px; + letter-spacing: 0.05em; + hyphens: auto; +} +.post-detail .post .post-content p code, +.post-detail .post .post-content li code { + font-family: 'Source Code Pro', Consolas, Menlo, Monaco, 'Courier New', monospace; + line-height: initial; + word-wrap: break-word; + border-radius: 0; + background-color: #fff5f5; + color: #c53030; + padding: 0.2em 0.33333333em; + margin-left: 0.125em; + margin-right: 0.125em; +} +.post-detail .post .post-content pre { + margin-bottom: 1.5rem; + padding: 0; + position: relative; +} +.post-detail .post .post-content pre code { + font-size: 0.96em; + font-family: 'Source Code Pro', Consolas, Menlo, Monaco, 'Courier New', monospace; + padding: 1em; + border-radius: 5px; + line-height: 1.5; +} +.post-detail .post .post-content blockquote { + color: #9a9a9a; + position: relative; + padding: 0.4em 0 0 2.2em; + font-size: 0.96em; +} +.post-detail .post .post-content blockquote:before { + position: absolute; + top: -4px; + left: 0; + content: "\201c"; + font: 700 62px/1 serif; + color: rgba(0, 0, 0, 0.1); +} +.post-detail .post .post-content table { + border-collapse: collapse; + margin: 1rem 0; + display: block; + overflow-x: auto; +} +.post-detail .post .post-content tr { + border-top: 1px solid #dfe2e5; +} +.post-detail .post .post-content td, +.post-detail .post .post-content th { + border: 1px solid #dfe2e5; + padding: 0.6em 1em; +} +.post-detail .post .post-content ul, +.post-detail .post .post-content ol { + padding-left: 35px; + line-height: 1.725; + margin-bottom: 16px; +} +.post-detail .post .post-content ul { + list-style-type: square; +} +.post-detail .post .post-content h1, +.post-detail .post .post-content h2, +.post-detail .post .post-content h3, +.post-detail .post .post-content h4, +.post-detail .post .post-content h5, +.post-detail .post .post-content h6 { + margin: 16px 0; + font-weight: 700; + padding-top: 16px; +} +.post-detail .post .post-content h1 { + font-size: 1.8em; +} +.post-detail .post .post-content h2 { + font-size: 1.42em; +} +.post-detail .post .post-content h3 { + font-size: 1.17em; +} +.post-detail .post .post-content h4 { + font-size: 1em; +} +.post-detail .post .post-content h5 { + font-size: 1em; +} +.post-detail .post .post-content h6 { + font-size: 1em; + font-weight: 500; +} +.post-detail .post .post-content hr { + display: block; + border: 0; + margin: 2.24em auto 2.86em; +} +.post-detail .post .post-content hr:before { + color: rgba(0, 0, 0, 0.2); + font-size: 1.1em; + display: block; + content: "* * *"; + text-align: center; +} +.post-detail .post .post-content mark { + background: #faf089; + color: #744210; + padding: 0.2em; +} +.post-detail .post .post-content .footnotes { + margin-left: auto; + margin-right: auto; + max-width: 760px; + padding-left: 18px; + padding-right: 18px; +} +.post-detail .post .post-content .footnotes:before { + content: ""; + display: block; + border-top: 4px solid rgba(0, 0, 0, 0.1); + width: 50%; + max-width: 100px; + margin: 40px 0 20px; +} +.post-detail .post .post-content .contains-task-list { + list-style-type: none; + padding-left: 30px; +} +.post-detail .post .post-content .task-list-item { + position: relative; +} +.post-detail .post .post-content .task-list-item-checkbox { + position: absolute; + cursor: pointer; + width: 16px; + height: 16px; + margin: 4px 0 0; + top: -1px; + left: -22px; + transform-origin: center; + transform: rotate(-90deg); + transition: all 0.2s ease; +} +.post-detail .post .post-content .task-list-item-checkbox:checked { + transform: rotate(0); +} +.post-detail .post .post-content .task-list-item-checkbox:checked:before { + border: transparent; + background-color: #51cf66; +} +.post-detail .post .post-content .task-list-item-checkbox:checked:after { + transform: rotate(-45deg) scale(1); +} +.post-detail .post .post-content .task-list-item-checkbox:checked + .task-list-item-label { + color: #a0a0a0; + text-decoration: line-through; +} +.post-detail .post .post-content .task-list-item-checkbox:before { + content: ""; + width: 16px; + height: 16px; + box-sizing: border-box; + display: inline-block; + border: 1px solid #9ae6b4; + border-radius: 2px; + background-color: #fff; + position: absolute; + top: 0; + left: 0; + transition: all 0.2s ease; +} +.post-detail .post .post-content .task-list-item-checkbox:after { + content: ""; + transform: rotate(-45deg) scale(0); + width: 9px; + height: 5px; + border: 1px solid #fff; + border-top: none; + border-right: none; + position: absolute; + display: inline-block; + top: 4px; + left: 4px; + transition: all 0.2s ease; +} +.next-post { + text-align: center; + padding: 24px 32px; +} +.next-post .next { + margin-bottom: 24px; + color: #343a40; + font-weight: lighter; +} +.next-post .post-title { + font-size: 20px; + font-weight: bold; + letter-spacing: 0.02em; +} +#gitalk-container, +#disqus_thread { + padding: 24px 32px; +} +.toc-container .markdownIt-TOC { + position: sticky; + top: 32px; + width: 200px; + font-size: 12px; + list-style: none; + padding-left: 0; + padding: 16px 8px; +} +.toc-container .markdownIt-TOC:before { + content: ""; + position: absolute; + top: 0; + left: 8px; + bottom: 0; + width: 1px; + background-color: #ebedef; + opacity: 0.5; +} +.toc-container ul { + list-style: none; +} +.toc-container li { + padding-left: 16px; +} +.toc-container li a { + color: #868e96; + padding: 4px; + display: block; + transition: all 0.3s; +} +.toc-container li a:hover { + background: #fafafa; +} +.toc-container li a.current { + color: #006CFF; + background: #fafafa; +} +@media (max-width: 600px) { + .post-detail .post { + padding: 16px; + } + .post-detail .post .post-title { + font-size: 24px; + padding: 16px 0; + } +} +@media (max-width: 1150px) { + .toc-container { + display: none; + } +} +.archives-container { + padding: 32px; + flex: 1; +} +.archives-container .year { + font-size: 1.375rem; + font-weight: bold; + margin: 24px 0 16px; + color: #868e96; + padding: 0 24px; +} +.archives-container .post { + padding: 16px 24px; + display: block; +} +.archives-container .post .post-title { + font-size: 16px; + font-weight: 900; + letter-spacing: 0.02em; +} +.archives-container .post .time { + font-size: 0.75rem; + margin-top: 8px; + color: #ced4da; +} +@media (max-width: 600px) { + .archives-container { + padding: 16px; + } +} +.tags-container { + padding: 32px 32px; + flex: 1; + text-align: center; +} +.tags-container .tag { + display: inline-block; + padding: 8px 16px; + margin: 8px; + background: #f8f9fa; + color: #495057; + border-radius: 2px; + font-size: 14px; +} +.tags-container .tag:hover { + background: #e9ecef; + color: #212529; +} +.current-tag-container .title { + text-align: center; + font-size: 18px; + margin-bottom: 24px; +} +.about-page { + padding: 24px 32px; +} +.site-footer { + font-size: 12px; + text-align: center; + padding: 40px 24px; + color: #868e96; + display: flex; + justify-content: center; + align-items: center; +} +.rss { + display: inline-flex; + align-items: center; + margin-left: 24px; +} +.hljs { + display: block; + overflow-x: auto; + padding: 0.5em; + color: #333; + background: #f9f7f3; +} +.hljs-comment, +.hljs-quote { + color: #998; + font-style: italic; +} +.hljs-keyword, +.hljs-selector-tag, +.hljs-subst { + color: #333; + font-weight: bold; +} +.hljs-number, +.hljs-literal, +.hljs-variable, +.hljs-template-variable, +.hljs-tag .hljs-attr { + color: #008080; +} +.hljs-string, +.hljs-doctag { + color: #d14; +} +.hljs-title, +.hljs-section, +.hljs-selector-id { + color: #900; + font-weight: bold; +} +.hljs-subst { + font-weight: normal; +} +.hljs-type, +.hljs-class .hljs-title { + color: #458; + font-weight: bold; +} +.hljs-tag, +.hljs-name, +.hljs-attribute { + color: #000080; + font-weight: normal; +} +.hljs-regexp, +.hljs-link { + color: #009926; +} +.hljs-symbol, +.hljs-bullet { + color: #990073; +} +.hljs-built_in, +.hljs-builtin-name { + color: #0086b3; +} +.hljs-meta { + color: #999; + font-weight: bold; +} +.hljs-deletion { + background: #fdd; +} +.hljs-addition { + background: #dfd; +} +.hljs-emphasis { + font-style: italic; +} +.hljs-strong { + font-weight: bold; +} diff --git a/tags/index.html b/tags/index.html new file mode 100644 index 00000000..546c4414 --- /dev/null +++ b/tags/index.html @@ -0,0 +1,86 @@ + + + + +lxowalle + + + + + + + + + + + +
+
+ + + +
+ +
+ + + +
+
+ +