xuan9527

常能遣其欲而心自静,澄其心而神自清。

0%

杂项笔记

J-Flash批处理脚本配置烧录:当然,前提是要添加J-Link的可执行程序路径到$PATH环境变量中

  • program.bat脚本代码如下,参考修改即可:
    1
    2
    3
    echo start...

    JLink -device N32L406CB -if swd -speed 4000 -CommanderScript "C:\Users\Breo\Desktop\Wireless moxibustion\Software\program.jlink"
  • program.jlink文件代码如下,其中目标设备、文件路径、烧录地址等根据需要配置:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    connect
    device N32L406CB
    si SWD
    speed 4000
    h // halt-停止
    r // 复位,可以考虑去掉
    erase // 或 erase 0x8002800,去掉也行,但可能会出现error fail address 0x00000000错误提示

    loadfile app.bin 0x8002800 // loadfile app.hex 或 loadfile app.bin 0x8000000
    verifybin app.bin 0x8002800
    r
    go // r go表示reset and run
    q // 退出J-Link命令行工具

Ubuntu 无法更新问题

Ubuntu 无法使用apt update

更改软件源

编辑 /etc/apt/sources.list 文件,将以下内容添加到文件末尾

deb https://mirrors.aliyun.com/ubuntu/ jammy main restricted universe multiverse
deb-src https://mirrors.aliyun.com/ubuntu/ jammy main restricted universe multiverse

deb https://mirrors.aliyun.com/ubuntu/ jammy-updates main restricted universe multiverse
deb-src https://mirrors.aliyun.com/ubuntu/ jammy-updates main restricted universe multiverse

deb https://mirrors.aliyun.com/ubuntu/ jammy-backports main restricted universe multiverse
deb-src https://mirrors.aliyun.com/ubuntu/ jammy-backports main restricted universe multiverse

清除 apt 缓存

sudo apt clean
sudo apt autoclean

尝试更新系统

sudo apt update

显示 ModuleNotFoundError: No module named 'apt_pkg',重新安装 “apt_pkg“ 模块:

sudo apt install --reinstall python3-apt

显示 ERROR:

E: Could not read response to hello message from hook [ ! -f /usr/bin/snap ] || /usr/bin/snap advise-snap --from-apt 2>/dev/null || true: Success

如果问题仍然存在,尝试修复 Python 包:

sudo apt install --fix-broken

然后就更新系统了:

sudo apt update
sudo apt upgrade

执行sudo apt upgrade后显示ERROR:

Errors were encountered while processing:
/tmp/apt-dpkg-install-cQBLJW/626-linux-iot-tools-common_5.4.0-1030.31_all.deb
E: Sub-process /usr/bin/dpkg returned an error code (1)

最后一步,修复损坏的软件包配置:

sudo dpkg --configure -a
sudo apt upgrade

Breo蓝牙启动异常

Breo蓝牙初始化

蓝牙初始化没完成,透传未开启,app就连接蓝牙了。
设置透传参数,开启透传的的状态中增加连接蓝牙接受指令。

心跳包回复超时

现在是接收/刷新设备数据200ms超时,延迟太长还可以缩短。

SPI级联led灯调试小助手

产品名称:1209RGB幻彩雾状
产品型号:XTQ-016B.RGB-2307125-20

SPI级联led灯问题汇总

充电闪灯问题

问题分析

充电中拔掉电源,立即再次插入,会闪一下灯;若等两秒再插入则不会出现,初步判断是此款芯片有锁存功能,会保存到寄存器中,未完全掉电再次插入则会继续执行上次的寄存器数据。

解决方法

充电中拔掉电源,程序不要立即断电,持续两秒反初始化spi灯珠,即给spi寄存器写全灭数据。

呼吸灯闪烁问题

问题分析

程序中呼吸灯会跑偶尔闪烁,影响显示效果。分析发现,代码中有电机的FG检测,此检测开启了输入捕获功能,会持续中断触发,虽然spi灯的驱动是dma发送,但是也是由CPU来调度的,并不能与中断并行。spi呼吸灯效果需要持续发送数据,且时序要求很高,中断会抢占spi的dma发送,打断spi传输数据,导致数据传输出错,造成闪灯效果。

解决方法

1、提高芯片主频,n32l403KB最高主频为64MHz,如果主频提高效果会好一些。
2、spi呼吸灯效果持续发送数据,不能与中断频繁的代码一起使用。

某项目充电保护仍充电

修改代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{-1, 1, PIN_CHARGE_CC_DETECT, PIN_MODE_INPUT},	//input/output switch

static void board_charge_cc_set(bool en)
{
struct pin_status_desc *pin = pin_handle(PIN_CHARGE_CC_DETECT);
if(en)
{
pin->type = PIN_MODE_INPUT;
drv_pin_mode(pin->pin_id,pin->type);
pin->lvl_rt = -1; //重置lvl_rt,以防止output出问题
}else{
pin->type = PIN_MODE_OUTPUT;
drv_pin_mode(pin->pin_id,pin->type);
pin_set_func(pin, PIN_HIGH);
}
}

Git小贴士

执行 git pull 会覆盖本地的修改吗?

没有冲突的情况下,远端会直接更新至本地上,但不会改变本地未提交的变动;如果本地修改已提交,则会执行一个远端分支和本地分支的合并

git fetch 和 git pull 的区别与联系

git fetch用于从远程仓库获取最新的提交,保存到本地的远程跟踪分支中(FETCH_HEAD),可以通过查看此分支了解远程仓库的更新情况

  • git diff FETCH_HEAD比较查看该分支和当前工作分支的内容

git pull会自动获取远程仓库的更新,并且合并到当前分支上,相当于git fetch + git merge FETCH_HEAD

  • 将远程仓库中指定分支的最新提交 ID 保存到本地的 FETCH_HEAD 分支中
  • FETCH_HEAD 分支合并到当前工作分支中

基础非典型操作

本地git配置


配置本地与远端的SSH密钥连接流程:

  • 本地生成SSH公钥和私钥(如果没有的话,另,linux下公钥通常存放于~/.ssh/*.pub)
    • ssh-keygen -t rsa -b 4096 -C xxx@xxx.com
  • 复制公钥,添加至远端平台的SSH设置上

查看本地配置:

  • git config --list查看当前项目的所有配置
  • git config --global --list查看全局配置

修改用户名(全局/当前项目)

此用户名即提交日志上所展示的用户名称

  • 修改全局用户名:git config --global user.name "xxx",影响用户的所有仓库
  • 修改当前路径项目的用户名:git config user.name "xxx"
  • 查看全局用户名:git config user.name

初始化本地工程并与远端已有仓库的main分支关联:

  • 进入工程根目录,git init初始化本地仓库
  • 添加远程仓库:git remote add origin <远程仓库地址>
  • git branch -M main将当前分支重命名为main,M即--move --force的缩写。(可以分别输入git add --allgit commit -m "first commit"完成对本地分支的首次提交)
  • 使用git pull origin main,将远程仓库的main分支拉取到本地,或者git push -u origin main -f将本地的xxx分支强制推送到远端main分支,其中-u是--set-upstream的缩写,后续会保持这个跟踪关系

可变参数函数详解

C语言中的可变参数函数允许您定义函数,其参数个数是不确定的,可以根据具体需求接受可变数量的参数。这在处理不定数量参数的情况下非常有用,比如printfscanf等函数。让我为您详细解释一下可变参数函数的原理和实现。

1. 原理与实现:

  • 可变参数函数的参数列表是从右往左压入堆栈的。假设堆栈中有以下参数:不可变参数1、不可变参数2、…、不可变参数n、可变参数1、可变参数2、…、可变参数n。

  • 为了获取可变参数,我们需要知道每个可变参数的地址。这是通过前一个不可变参数的地址和类型来实现的。

  • ANSI标准提供了三个宏来实现这个过程:

    • va_start(va_list arg_ptr, prev_param): 初始化可变参数列表,将arg_ptr指向第一个可变参数。

    • va_arg(va_list arg_ptr, type): 获取当前参数的值,类型由前面的不可变参数传递。例如,printf中的格式化字符串或者可变参数列表的参数类型和第几个不可变参数的相同。

    • va_end(va_list arg_ptr): 释放资源,结束可变参数列表的访问。

  • 这些宏的实现细节由编译器和标准库提供,我们只需调用它们即可。

2. 可变参数函数:

  • 可变参数函数允许在函数定义中接受不定数量的参数。
  • C语言提供了 stdarg.h 头文件来支持可变参数函数的实现。
  • 下面是一个示例代码,展示了如何实现一个可变参数函数 sum,它接受一个整数参数 count,表示接下来的可变参数的数量:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <stdio.h>
#include <stdarg.h>

int sum(int count, ...) {
int total = 0;
va_list args;
va_start(args, count);
for (int i = 0; i < count; i++) {
int num = va_arg(args, int);
total += num;
}
va_end(args);
return total;
}

int main() {
int result = sum(4, 10, 20, 30, 40);
printf("Sum: %d\n", result);
return 0;
}
  • 在这个示例中,我们定义了一个可变参数函数 sum,它计算传入的整数参数的总和。

3. 可变参数宏:

  • 可变参数宏允许在宏调用中接受可变数量的参数。
  • 在C语言中,可变参数宏使用 __VA_ARGS__ 表示可变参数的部分。
  • 下面是一个示例代码,展示了如何定义一个可变参数宏 PRINT_VALUES,它使用 printf 函数来打印可变数量的值:
1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>

#define PRINT_VALUES(...) do { \
printf("Values: "); \
printf(__VA_ARGS__); \
printf("\n"); \
} while (0)

int main() {
PRINT_VALUES("%d %s %f", 10, "hello", 3.14);
return 0;
}
  • 在这个示例中,我们定义了一个可变参数宏 PRINT_VALUES,它使用 printf 函数来打印多个值。

4. 实现自己的 printf 函数:

  • printf 函数接受一个格式字符串作为第一个参数,后面是可变数量的参数,用于替换格式字符串中的格式占位符。
  • 以下是一个简化版的示例代码,展示了一个实现类似于 printf 函数的功能的函数:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#include <stdio.h>
#include <stdarg.h>

void my_printf(const char* format, ...) {
va_list args;
va_start(args, format);
while (*format != '\0') {
if (*format == '%') {
format++; // 移动到占位符的下一个字符
if (*format == 'd') {
int value = va_arg(args, int);
printf("%d", value);
} else if (*format == 'f') {
double value = va_arg(args, double);
printf("%f", value);
} else if (*format == 's') {
char* value = va_arg(args, char*);
printf("%s", value);
} else if (*format == 'c') {
int value = va_arg(args, int);
printf("%c", value);
} else {
printf("Unsupported format specifier: %c", *format);
}
} else {
printf("%c", *format);
}
format++; // 移动到下一个字符
}
va_end(args);
}

int main() {
int num = 42;
double pi = 3.14159;
char str[] = "Hello, world!";
char ch = 'A';

my_printf("Integer: %d\n", num);
my_printf("Float: %f\n", pi);
my_printf("Float: %s\n", str);
my_printf("Float: %c\n", ch);

return 0;
}

汇编基础

参考文档:汇编语言入门教程

实例分析

了解寄存器和内存模型以后,就可以来看汇编语言到底是什么了。下面是一个简单的程序example.c。

1
2
3
4
5
6
7
int add_a_and_b(int a, int b) {
return a + b;
}

int main() {
return add_a_and_b(2, 3);
}

gcc 将这个程序转成汇编语言。

1
$ gcc -S example.c

example.s经过简化以后,大概是下面的样子。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
_add_a_and_b:
push %ebx
mov %eax, [%esp+8]
mov %ebx, [%esp+12]
add %eax, %ebx
pop %ebx
ret

_main:
push 3
push 2
call _add_a_and_b
add %esp, 8
ret

可以看到,原程序的两个函数add_a_and_b和main,对应两个标签_add_a_and_b和_main。每个标签里面是该函数所转成的 CPU 运行流程。

git合并小贴士

分支合并到main

以下是完整的命令流程:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 确保你的分支是最新的
git checkout your-branch
git pull origin your-branch

# 切换到 main 分支并拉取最新更改
git checkout main
git pull origin main

# 将你的分支的更改合并到 main 分支
git merge your-branch

# 解决冲突(如果需要)
git add <conflicted-files>
git commit

# 推送更改到远程 main 分支
git push origin main

如果你希望使用 git rebase 保持提交历史整洁,可以参考以下流程:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 确保你的分支是最新的
git checkout your-branch
git pull origin your-branch

# 基于 main 分支重新应用你的分支的更改
git rebase main

# 解决冲突(如果需要)
git add <conflicted-files>
git rebase --continue

# 切换到 main 分支并拉取最新更改
git checkout main
git pull origin main

# 将你的分支的更改合并到 main 分支
git merge your-branch

# 推送更改到远程 main 分支
git push origin main

main合并到分支

使用 git merge

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 确保本地 main 分支是最新的
git checkout main
git pull origin main

# 切换到目标分支
git checkout your-branch

# 将 main 分支的更改合并到目标分支
git merge main

# 解决冲突(如果需要)
git add <conflicted-files>
git commit

# 推送更改到远程目标分支
git push origin your-branch

使用 git rebase:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 确保本地 main 分支是最新的
git checkout main
git pull origin main

# 切换到目标分支
git checkout your-branch

# 将目标分支基于 main 分支重新应用更改
git rebase main

# 解决冲突(如果需要)
git add <conflicted-files>
git rebase --continue

# 推送更改到远程目标分支(可能需要强制推送)
git push origin your-branch --force