NXP iMX8MM Cortex-M4 核心 GPT Capture 测试
By Toradex秦海
1). 简介
NXP i.MX8 系列处理器均为异构多核架构 SoC,除了可以运行 Linux 等复杂操作系统的 Cortax-A 核心,还包含了可以运行实时操作系统比如 FreeRTOS 的 Cortex-M 核心,本文就演示通过 NXP i.MX8MM 处理器集成的 Cortex-M4 核心来运行 GPT (General Purpose Timer) 输入采集功能模块的测试。
I.MX8M Mini 处理器 GPT 模块硬件比较简单,如下框图,可以实现 Capture 捕获输入功能和 Compare 定时输出功能。
本文所演示的ARM平台来自于Toradex 基于NXP i.MX8M Mini ARM处理器的Verdin iMX8MM ARM嵌入式平台。
2. 准备
a). Verdin i.MX8MM ARM核心版配合Verdin Development Board,连接调试串口(载板X66)到开发主机方便调试,X66 连接了4个串口,其中第三个是 Cortex-M4 核心的默认调试串口,第四个是 Cortex-A53 核心的默认调试串口。
b). 为了测试 GPT 输入捕获, 相应的需要一个PWM 波发生设备,这里使用Toradex 基于NXP i.MX8M Plus ARM处理器的Verdin i.MX8MP 核心板配合 Dahlia Board 作为PWM output使用。同样连接调试串口(载板X18)到开发主机方便调试。
c). Verdin i.MX8MP Cortex-A53 核心系统使用Toradex Yocto Linux BSP6, 更多说明请参考这里。
d). 参考如下将 Verdin i.MX8MP PWM1 连接到 Verdin i.MX8MM GPT1 Capture 管脚,同时为了阻断载板其他电路干扰,将 Verdin Development Board X6 Pin_24 的跳线帽去掉。
Dahlia Board X20 Pin_9 -> Verdin Development Board X5Pin_24 SODIMM_252
3). Verdin i.MX8MM M4核心FreeRTOS基本资料
a). Verdin i.MX8MM HMP(Heterogeneous Multi-core Processing) 架构基本说明请参考如下:
https://developer.toradex.cn/software/cortex-m/hmp-memory-areas-on-toradex-soms/
b). 参考如下说明下载配置 NXP 用于开发 Cortex-M 核心的 MCUXpresso SDK
https://developer.toradex.cn/software/cortex-m/setting-up-sdk-toolchain/
c). Verdin i.MX8MM 编译运行 M4 firmware 操作流程请参考如下文章
https://developer.toradex.cn/software/real-time/freertos/freertos-on-the-cortex-m4-of-a-verdin-imx8mm
d). MCUXpresso SDK 包含的 sample 示例应用可以参考如下 SDK 源位置
-----------------------------
$cd <SDK_root>/boards/evkmimx8mm/
$ tree -L 2
.
├── cmsis_driver_examples
│ ├── ecspi
│ ├── enet
│ ├── i2c
│ └── uart
├── demo_apps
│ ├── hello_world
│ └── sai_low_power_audio
├── driver_examples
│ ├── ecspi
│ ├── enet
│ ├── gpio
│ ├── gpt
│ ├── i2c
│ ├── pdm
│ ├── pwm
│ ├── rdc
│ ├── sai
│ ├── sdma
│ ├── sema4
│ ├── tmu
│ ├── uart
│ └── wdog
├── evkmimx8mm.png
├── freertos_examples
│ ├── freertos_event
│ ├── freertos_generic
│ ├── freertos_hello
│ ├── freertos_mutex
│ ├── freertos_queue
│ ├── freertos_sem
│ ├── freertos_swtimer
│ └── freertos_tickless
├── multicore_examples
│ ├── rpmsg_lite_pingpong_rtos
│ └── rpmsg_lite_str_echo_rtos
└── project_template
├── board.c
├── board.h
├── BOARD_Project_Template_evkmimx8mm.cmake
├── clock_config.c
├── clock_config.h
├── peripherals.c
├── peripherals.h
├── pin_mux.c
└── pin_mux.h
-----------------------------
4). Verdin i.MX8MM Cortex-M4核心FreeRTOS GPT Capture示例驱动开发
a). Verdin i.MX8MM MCUXpresso SDK 已经包含一个简单的 GPT Capture sample驱动,本文基于此 sample 进行修改测试。
-----------------------------
$cd <SDK_root>/boards/evkmimx8mm/driver_examples/gpt/capture
$ tree -L 1
.
├── armgcc
├── board.c
├── board.h
├── clock_config.c
├── clock_config.h
├── empty_rsc_table.c
├── fsl_iomuxc.h
├── gpt_capture.c
├── gpt_capture_v3_14.xml
├── pin_mux.c
├── pin_mux.h
└── readme.md
-----------------------------
b). 首先先确认 pin_mux 定义以及其他 i.MX8MM 初始化基本配置,如果需要可以进行修改
./ pin_mux.h/pin_mux.c 用于确定项目中使用的管脚定义,本文中使用的正好就是示例默认的 GPT1 Capture1 管脚,因此无需修改。如果用到其他管脚,就需要进行修改,支持的所有管脚定义可以参考 fsl_iomuxc.h 文件。
-----------------------------
/* FUNCTION ************************************************************************************************************
*
* Function Name : BOARD_InitPins
* Description : Configures pin routing and optionally pin electrical features.
*
* END ****************************************************************************************************************/
void BOARD_InitPins(void) { /*!< Function assigned for the core: Cortex-M4[m4] */
IOMUXC_SetPinMux(IOMUXC_SAI3_RXFS_GPT1_CAPTURE1, 0U);
IOMUXC_SetPinMux(IOMUXC_UART4_RXD_UART4_RX, 0U);
...
-----------------------------
./ board.h/board.c 用于 i.MX8MM M4 核心基本初始化配置,本文不做修改。
./ clock_config.h/clock_config.c 用于 i.MX8MM M4 核心基本时钟配置,本文不做修改。
c). GPT Capture 功能实现
./ 本文 GPT Capture 功能定义
GPT1 capture1 管脚输入一个给定频率(如 1k Hz )和占空比(如 50% ) 的PWM 信号,通过捕获输入上升/下降沿中断,分别获得相邻两次中断的 GPT Counter 计数器的计数,并以此来计算输入 PWM 信号的半波周期。
./ GPT Capture 功能基本都是通过 gpt_capture.c 文件代码来实现,默认 sample 是捕获上升沿中断后,打印中断当时的 GPT Counter 计数数值。
./ 为了实现本文定义的捕获功能,首先增加如下全局变量定义
-----------------------------
/*******************************************************************************
* Variables
******************************************************************************/
volatile bool gptIsrFlag_Start = false;
volatile bool gptIsrFlag_Finish = false;
volatile uint8_t gptIsrFlag_Overflow = 0;
volatile uint32_t captureVal = 0;
volatile uint32_t captureVal_Last = 0;
-----------------------------
// gptIsrFlag_Start 定义为第一次捕获中断开始标志
// gptIsrFlag_Finish 定义为第二次捕获中断结束标志
// gptIsrFlag_Overflow 定义为 GPT Counter 溢出标志计数
// captureVal 定义为第二次中断 GPT Counter 数值
// captureVal_Last 定义为第一次中断 GPT Counter 数值
./ GPT Interrupt 函数修改如下:
首先处理计数器溢出情况,如果中断发生时候已经发生溢出,则增加 gptIsrFlag_Overflow 溢出标志计数的数值;然后通过 gptIsrFlag_Start / gptIsrFlag_Finish 标志位来分别处理第一次和第二次中断,获取第一次和第二次中断时候的 GPT Counter 数值,同时分别翻转 GPT Capture Interrupt 模式。
-----------------------------
void EXAMPLE_GPT_CAPTURE_IRQHandler(void)
{
/* GPT Counter Overflow processing */
if (GPT_GetStatusFlags(DEMO_GPT_BASE, kGPT_RollOverFlag) != false)
{
if (gptIsrFlag_Start == true)
{
gptIsrFlag_Overflow ++;
}
GPT_ClearStatusFlags(DEMO_GPT_BASE, kGPT_RollOverFlag);
}
if (GPT_GetStatusFlags(DEMO_GPT_BASE, kGPT_InputCapture1Flag) != false)
{
if(gptIsrFlag_Finish != true)
{
/* First time IRQ */
if (gptIsrFlag_Start == false)
{
captureVal_Last = GPT_GetInputCaptureValue(DEMO_GPT_BASE, BOARD_GPT_INPUT_CAPTURE_CHANNEL);
/* Switch Interrupt mode to falling edge */
GPT_SetInputOperationMode(DEMO_GPT_BASE, BOARD_GPT_INPUT_CAPTURE_CHANNEL, kGPT_InputOperation_FallEdge);
gptIsrFlag_Start = true;
}
/* Second time IRQ */
else
{
captureVal = GPT_GetInputCaptureValue(DEMO_GPT_BASE, BOARD_GPT_INPUT_CAPTURE_CHANNEL);
/* Switch Interrupt mode to rising edge */
GPT_SetInputOperationMode(DEMO_GPT_BASE, BOARD_GPT_INPUT_CAPTURE_CHANNEL, kGPT_InputOperation_RiseEdge);
gptIsrFlag_Start = false;
gptIsrFlag_Finish = true;
}
}
GPT_ClearStatusFlags(DEMO_GPT_BASE, BOARD_GPT_CHANNEL_FLAG);
}
SDK_ISR_EXIT_BARRIER;
}
-----------------------------
./ Main 主函数修改如下:
-----------------------------
int main(void)
{
uint64_t int_Peroid = 0;
uint32_t time_Ms = 0;
uint32_t time_Us = 0;
gpt_config_t gptConfig;
...
GPT_GetDefaultConfig(&gptConfig);
/* Initialize GPT module */
GPT_Init(DEMO_GPT_BASE, &gptConfig);
...
/* Setup input capture on a gpt channel */
GPT_SetInputOperationMode(DEMO_GPT_BASE, BOARD_GPT_INPUT_CAPTURE_CHANNEL, kGPT_InputOperation_RiseEdge);
...
/* Enable GPT Overflow interrupt */
GPT_EnableInterrupts(DEMO_GPT_BASE, kGPT_RollOverFlagInterruptEnable);
...
while (true)
{
/* Check whether occur 2nd interupt */
if (true == gptIsrFlag_Finish)
{
/* GPT counter diff value between 2 IRQs */
int_Peroid = gptIsrFlag_Overflow * (uint64_t) 0xffffffff;
int_Peroid = int_Peroid + captureVal;
int_Peroid = int_Peroid - captureVal_Last;
/* transfer counter value to peroid */
time_Us = (uint32_t) ((int_Peroid / 24) % 1000);
time_Ms = (uint32_t) ((int_Peroid / 24) / 1000);
PRINTF("\r\n interval between 2 rising edge =%u ms and %u us\r\n", time_Ms, time_Us);
gptIsrFlag_Overflow = 0;
gptIsrFlag_Finish = false;
}
else
{
__WFI();
}
}
}
-----------------------------
// 通过 GPT_GetDefaultConfig 函数获取默认的 GPT Capture 配置,参考 docs 目录下的 MCUXpresso SDK API Reference Manual_MIMX8MM6.pdf 文档,可以查到默认配置如下,如果需要也可以修改这个配置
-----------------------------
config->clockSource = kGPT_ClockSource_Periph;
config->divider = 1U;
config->enableRunInStop = true;
config->enableRunInWait = true;
config->enableRunInDoze = false;
config->enableRunInDbg = false;
config->enableFreeRun = false;
config->enableMode = true;
-----------------------------
// 通过 GPT_SetInputOperationMode 函数将 GPT Capture 模式初始配置为上升沿触发
// 为了处理 GPT Counter Overflow,使能对应中断
// while 函数循环执行当 gptIsrFlag_Finish 第二次中断采集结束标志位声明后,打印捕获的输入 PWM 波的半波周期。如果有溢出发生,则需要考虑增加相应的 0xffffffff 溢出计数次数。这里需要说明下,由于 NXP iMX8MM SoC 也受到如下 Errata 影响,因此 GPT Clock Source 只能使用内部 24M Hz 时钟源,所以这里直接使用 24M 来算出半波周期是多少 ms 和 us 。
https://www.nxp.com.cn/docs/en/errata/IMX8X_C0_0N99Z_ER.pdf
5). Verdin i.MX8MM Cortex-M4核心FreeRTOS GPT Capture示例部署测试
a). 将上述修改后的项目参考章节 3 的相关资料编译后,复制 gpt_capture.bin 可执行文件到 Verdin i.MX8MM 核心板 Linux /home/root 目录下保存。
b). 对Verdin i.MX8MM 模块进入 U-boot 命令行,通过如下命令配置 Cortex-M4 核心 Firmware 下载和运行
-----------------------------
# setenv load_cmd "ext4load mmc 0:2"
# setenv m4image "/home/root/gpt_capture.bin"
> setenv m4image_size 17000
> setenv loadm4image "${load_cmd} ${loadaddr} ${m4image}"
> setenv m4boot "${loadm4image}; cp.b ${loadaddr} 0x7e0000 ${m4image_size}; dcache flush; bootaux 0x7e0000"
> saveenv
> run m4boot
-----------------------------
c). Verdin i.MX8MM Cortex-M4 核心运行后其调试串口打印信息
-----------------------------
GPT input capture example
Once the input signal is received the input capture half peroid is printed
-----------------------------
d). 此时在 Verdin i.MX8MP 平台通过如下脚本使能 1kHz 50% 占空比 PWM 输出 10s 时间
-----------------------------
#!/bin/sh
cd /sys/class/pwm/pwmchip0/
echo 0 > export
echo 1000000 > pwm0/period
echo 500000 > pwm0/duty_cycle
echo "normal" > pwm0/polarity
echo 1 > pwm0/enable
sleep 10
echo 0 > pwm0/enable
-----------------------------
e). 这时 Verdin i.MX8MM Cortex-M4 调试串口就会打印出对应的半波周期
-----------------------------
...
Input Capture Half Period Value = 0ms and 500us
Input Capture Half Period Value = 0ms and 500us
Input Capture Half Period Value = 0ms and 500us
Input Capture Half Period Value = 0ms and 500us
...
-----------------------------
f). 尝试将 Verdin i.MX8MP PWM 修改为 10kHz 80%/20% 占空比
-----------------------------
...
echo 100000 > pwm0/period
echo 80000 > pwm0/duty_cycle
...
-----------------------------
g). Verdin i.MX8MM Cortex-M4 输出周期会对应变化
-----------------------------
Input Capture Half Period Value = 0ms and 80us
Input Capture Half Period Value = 0ms and 80us
Input Capture Half Period Value = 0ms and 80us
Input Capture Half Period Value = 0ms and 80us
-----------------------------
h). 最后,由于 Verdin i.MX8MM GPT1 CAPTURE1 管脚在 Cortex-A53 核心 Linux 下默认是用于 WAKEUP GPIO 使用,如果需要同时运行 Verdin i.MX8MM Cortex-A53 核心和 Cortex-M4 核心,就需要在 Linux device-tree 文件中将 WAKEUP gpio-key 功能替换为其他 GPIO 管脚资源。
imx8mm-verdin.dtsi « freescale « dts « boot « arm64 « arch - linux-toradex.git - Linux kernel for Apalis and Colibri modules
6). 总结
本文简单示例了基于i.MX8MM Cortex-M4 核心 GPT Capture 功能供参考。
相关文章:

NXP iMX8MM Cortex-M4 核心 GPT Capture 测试
By Toradex秦海 1). 简介 NXP i.MX8 系列处理器均为异构多核架构 SoC,除了可以运行 Linux 等复杂操作系统的 Cortax-A 核心,还包含了可以运行实时操作系统比如 FreeRTOS 的 Cortex-M 核心,本文就演示通过 NXP i.MX8MM 处理器集成的 Cortex-…...

2步破解官方sublime4
sublime简要破解流程 1.下载sublime官方最新版2. 破解流程 1.下载sublime官方最新版 打开 官方网站下载 portable version 版,省的安装。。解压到任意位置,备份 sublime_text.exe 文件 2. 破解流程 打开网址把文件 sublime_text.exe 拖入网页搜索替换…...

【智能家居】东胜物联ODM定制ZigBee网关,助力能源管理解决方案商,提升市场占有率
背景 本文案例服务的客户是专业从事智能家居能源管理的解决方案商,其产品与服务旨在帮助用户监测、管理和优化能源消耗,以提高能源使用效率。 随着公司的扩张,为了增加市场占有率,他们希望找到更好的硬件服务支持,以…...

Python爬虫实战第三例【三】【上】
零.实现目标 爬取视频网站视频 视频网站你们随意,在这里我选择飞某速(狗头保命)。 例如,作者上半年看过的“铃芽之旅”,突然想看了,但是在正版网站看要VIP,在盗版网站看又太卡了,…...

解释器模式
解释器模式(Interpreter Pattern)是一种行为型设计模式,它用于定义一种语言的文法,并提供一个解释器来解释该语言中的表达式。这个模式主要用于解决问题领域中存在的特定语言或表达式的解释和执行问题。它将一个问题分解成一系列的…...
【UI自动化测试】如何提高UI自动化脚本的稳定性,
设计方面: 用例解耦、减少用例之前的互相依赖,避免影响其他用例的执行; 用例执行过后对测试场景还原,避免影响其他用例的执行; 脚本失败后可以加入testng的重试机制,提高用例的稳定性; PO模式…...
什么叫聊天中信息传达的框架效应framing effect,或展望理论Prospect theory
什么叫聊天中信息传达的框架效应,或展望理论 设计不能为产品带来良好体验?可能是你不懂心理学 框架效应- 维基百科,自由的百科全书 框架(社会科学)-展望理论 - 经济百科 jingjibaike 3 Answer 框架效应The theory of framing effects…...
日常开发Git命令
场景: 在远程库创建分支后,在本地开发后-合并代码-push到远程库 命令行 #查看现在分支 git branch #切换到master分支 git checkout master #拉取远程库修改 git pull git branch #切换到修改的分支 git checkout feature/s3-use-internel-name #merg…...

嵌入式学习第二十五天!(网络的概念、UDP编程)
网络: 可以用来:数据传输、数据共享 1. 网络协议模型: 1. OSI协议模型: 应用层实际收发的数据表示层发送的数据是否加密会话层是否建立会话连接传输层数据传输的方式(数据包,流式)网络层数据的…...

实操keepalived(高可用)+Nginx(四层代理+七层代理),实现高可用、负载均衡以及动静分离
一 vrrp技术 VRRP 相关术语 VRRP能够在不改变组网的情况下,将多台路由器虚拟成一个虚拟路由器,i通过配置虚拟路由器的IP地址为默认网关,实现网关的备份。 协议版本: VRRPv2 (常用) 和VRRPv3:0 VRRPv2仅适用于IPv4网络,VRRPv3适用…...
ES6基础3
函数的扩展 基本用法 函数参数的默认值 ES6允许为函数的参数设置默认值,即直接写在参数定义的后面。 参数变量是默认声明的,所以不能用let或const再次声明。下面代码中,参数变量x是默认声明的,在函数体中,不能用let或c…...

HarmonyOS 数据持久化 关系型数据库之 初始化操作
上文 HarmonyOS 数据持久化之首选项 preferences 我们有说用户首选项 但它只能处理一些比较简单的数据类型结构 的持久化处理 如果是一些批量较大 结构较为复杂的数据结构 那么 首选项就无法满足了 我们就要选择 关系型数据库 通过 SQLite 组件实现的一种本地数据库࿰…...

伊芙丽签约实在智能,实在Agent数字员工助力品牌效能飙升
近日,国内知名时尚女装品牌伊芙丽与实在智能达成合作,引入业内领先的平台级自动化产品实在Agent数字员工——取数宝,自动获取天猫、淘宝、抖音等线上平台营销数据,开启全域化营销的“提效之旅”。 实在Agent智能体 伊芙丽集团成立…...

第十五届蓝桥杯-UART接收不定长指令的处理
学习初衷: 不仅仅为了比赛! 目录 一、问题引入 二、UART常用的三种工作模式 1.UART工作在中断模式 2.UART工作在DMA模式下 3.uart工作在接收转空闲的模式下 三、获取指令中需要的数据 四、printf函数的实现 一、问题引入 问题引入:请…...
网络 协议 UDP编程
网络:数据传输,数据共享 1.网络协议模型: OSI协议模型 应用层 实际发送的数据 表示层 发送的数据是否加密 会话层 是否建立会话连接 传输层 数据传输的方式(数据报、流式)…...

3505. 这也是一道排序题
一、题目 输入 10 7334774857 8461862436 540886577 5245195052 9194400521 5412986878 6694133363 1186771950 1405713915 7115286932 输出 -29430338967 二、思考 构造差分数组:C[i] A[i1] - A[i] 由题目条件可知:当A[i] A[i1] A[i-1] - A[i]时&am…...

【Redis】Redis的应用场景
📝个人主页:五敷有你 🔥系列专栏:Redis ⛺️稳中求进,晒太阳 Redis的应用场景: 限流 要求10s内只能访问一次 RequestMapping("xian")public String xianLiu(String sign){String sign1 …...

计算机网络—以太网接口和链路配置
目录 1.拓扑图 2.以太网交换机基础配置 3.配置手动模式的链路聚合 4.配置静态 LACP 模式的链路聚合 5.配置文件 1.拓扑图 2.以太网交换机基础配置 华为交换机接口默认开启了自协商功能,需要手动配置S1与 S2上G0/0/9和G0/0/10接口的速率。 首先修改交换机的设…...
关于做副业、做自媒体:说几句扎心的话
今天在某乎看到一个问题:想尝试自媒体,想了一个月了,都没想好怎么起步,咋整呀? 恰好昨天陪退休老妈去探店,有感而发,就来唠一唠。 一、退休老妈的副业经历 老妈去年年初开始,在某…...
精通SpringBoot单元测试
引言 单元测试是软件开发中不可或缺的一部分,它对保障代码质量和软件的可靠性起着至关重要的作用。而SpringBoot作为一个流行的Java框架,为开发高效、易于部署的微服务提供了强大的支持。 单元测试的重要性: 确保代码正确性:通过…...

【SQL学习笔记1】增删改查+多表连接全解析(内附SQL免费在线练习工具)
可以使用Sqliteviz这个网站免费编写sql语句,它能够让用户直接在浏览器内练习SQL的语法,不需要安装任何软件。 链接如下: sqliteviz 注意: 在转写SQL语法时,关键字之间有一个特定的顺序,这个顺序会影响到…...

关键领域软件测试的突围之路:如何破解安全与效率的平衡难题
在数字化浪潮席卷全球的今天,软件系统已成为国家关键领域的核心战斗力。不同于普通商业软件,这些承载着国家安全使命的软件系统面临着前所未有的质量挑战——如何在确保绝对安全的前提下,实现高效测试与快速迭代?这一命题正考验着…...
QT3D学习笔记——圆台、圆锥
类名作用Qt3DWindow3D渲染窗口容器QEntity场景中的实体(对象或容器)QCamera控制观察视角QPointLight点光源QConeMesh圆锥几何网格QTransform控制实体的位置/旋转/缩放QPhongMaterialPhong光照材质(定义颜色、反光等)QFirstPersonC…...

Linux 中如何提取压缩文件 ?
Linux 是一种流行的开源操作系统,它提供了许多工具来管理、压缩和解压缩文件。压缩文件有助于节省存储空间,使数据传输更快。本指南将向您展示如何在 Linux 中提取不同类型的压缩文件。 1. Unpacking ZIP Files ZIP 文件是非常常见的,要在 …...

FFmpeg avformat_open_input函数分析
函数内部的总体流程如下: avformat_open_input 精简后的代码如下: int avformat_open_input(AVFormatContext **ps, const char *filename,ff_const59 AVInputFormat *fmt, AVDictionary **options) {AVFormatContext *s *ps;int i, ret 0;AVDictio…...
第八部分:阶段项目 6:构建 React 前端应用
现在,是时候将你学到的 React 基础知识付诸实践,构建一个简单的前端应用来模拟与后端 API 的交互了。在这个阶段,你可以先使用模拟数据,或者如果你的后端 API(阶段项目 5)已经搭建好,可以直接连…...

鸿蒙Navigation路由导航-基本使用介绍
1. Navigation介绍 Navigation组件是路由导航的根视图容器,一般作为Page页面的根容器使用,其内部默认包含了标题栏、内容区和工具栏,其中内容区默认首页显示导航内容(Navigation的子组件)或非首页显示(Nav…...
基于Java项目的Karate API测试
Karate 实现了可以只编写Feature 文件进行测试,但是对于熟悉Java语言的开发或是测试人员,可以通过编程方式集成 Karate 丰富的自动化和数据断言功能。 本篇快速介绍在Java Maven项目中编写和运行测试的示例。 创建Maven项目 最简单的创建项目的方式就是创建一个目录,里面…...
Shell 解释器 bash 和 dash 区别
bash 和 dash 都是 Unix/Linux 系统中的 Shell 解释器,但它们在功能、语法和性能上有显著区别。以下是它们的详细对比: 1. 基本区别 特性bash (Bourne-Again SHell)dash (Debian Almquist SHell)来源G…...
ubuntu清理垃圾
windows和ubuntu 双系统,ubuntu 150GB,开发用,基本不装太多软件。但是磁盘基本用完。 1、查看home目录 sudo du -h -d 1 $HOME | grep -v K 上面的命令查看$HOME一级目录大小,发现 .cache 有26GB,.local 有几个GB&am…...