1

stm32f103

  1. 错误现象:不使用 freertos 时,可以完成外设初始化,可以完成点灯,串口发送数据。使用 freertos 时,即使把外设初始化函数放到 main 函数最前面,然后立刻点灯,串口发数据,都看不到效果。使用 freertos 时,但删除掉 xTaskCreate 函数(包含heap初始化代码)后,可以点灯,收到数据。

    错误原因:在使用 freertos 操作系统时,如果开启了动态创建任务,需要加入内存管理文件(我的是 heap_4.c ),需要定义一个数组供其使用

    1
    2
    3
    4
    5
    6
    	static uint8_t ucHeap[ configTOTAL_HEAP_SIZE ];
    /*config.h*/
    //系统所有总的堆大小
    #define configTOTAL_HEAP_SIZE ((size_t)(5*1024)) //stm32f103x8 似乎最大只有 20k
    //这里被设置成了5k,需要注意的是,虽然sram容量大于10k,但如果设为10k没法运行
    //sram大小好像是20k

    需要注意的是,对应不同芯片,配置的值不同,我的有块 f103 芯片可以配置为 10k,而有块只能配置为 5k。编译完成后,可以在map文件中查看 rw zi 数据所占大小:

    1
    2
    3
    Total RO  Size (Code + RO Data)                11540 (  11.27kB)
    Total RW Size (RW Data + ZI Data) 10232 ( 9.99kB)
    Total ROM Size (Code + RO Data + RW Data) 11712 ( 11.44kB)
  2. 错误现象:外设能够初始化,freertos能创建任务,部分任务能正常运行,某个任务在打印数据时卡死了,QUEUE_Test_Recv_Task发送到字母R时卡死,系统停止调度。

    1
    2
    3
    4
    5
    6
    7
    8
    Start creating tasks
    Create test queue succeeded.
    Create led task succeeded.
    Create usart task succeeded.
    Create QUEUE_Test_Send_Task succeeded.
    Create QUEUE_Test_Recv_Task succeeded.
    USART is running!
    [QUEUE_Test_R

    错误原因:该任务的任务栈太小,没法完全容纳要打印的字符串,打印时便出错,将该任务栈适当增大后就可以正常运行了。

  3. 错误现象:gpio配置为输入时电平不稳定,哪怕使用上拉,下拉也是,不接杜邦线时稳定,接上杜邦线就不稳定了

    解决方法:换块板子,有块stm32f103c6t6的板子有以上问题,换上c8t6这个问题就解决了

  4. 错误现象:gpio配置为输入时检测不到输入电平,检测配置,毫无问题,相邻的几个引脚也没问题。

    错误原因:排针和板子的该引脚没焊上。。。

  5. 错误现象:串口显示错误信息 Error:..\freertos\port\port.c,680查看原文如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    /* The following assertion will fail if a service routine (ISR) for
    an interrupt that has been assigned a priority above
    configMAX_SYSCALL_INTERRUPT_PRIORITY calls an ISR safe FreeRTOS API
    function. ISR safe FreeRTOS API functions must *only* be called
    from interrupts that have been assigned a priority at or below
    configMAX_SYSCALL_INTERRUPT_PRIORITY.
    .....................
    */
    configASSERT( ucCurrentPriority >= ucMaxSysCallPriority );

    错误原因:大致就是说,要求使用到了 在中断调用了 freertos 安全api接口的中断,必须位于freertos可管理中断优先级之下。将中断优先级改到可管理的优先级之下就行了。

    检查错误时,还注意到了696行 configASSERT( ( portAIRCR_REG & portPRIORITY_GROUP_MASK ) <= ulMaxPRIGROUPValue ); 按理说应该报错的,因为它括号里的判断为假,但是它右边的值不是常量,是个变量,可能在运行中更改的。这点在检查bug中需要注意,不要 点一下 “ go to definition” 发现是 0 就以为它一直是 0 了。

C语言

  1. 错误现象:fsanitize报错,显示如下:

    1
    2
    3
    4
    5
    6
    7
    AddressSanitizer:DEADLYSIGNAL
    =================================================================
    ==739==ERROR: AddressSanitizer: SEGV on unknown address 0x00000000000f (pc 0x5625e6140822 bp 0x7ffce9918610
    sp 0x7ffce9918050 T0)
    ==739==The signal is caused by a READ memory access.
    ==739==Hint: address points to the zero page.
    AddressSanitizer:DEADLYSIGNAL

    错误原因:很可能是使用了未初始化的指针。这里报错是因为使用了文件描述符,但没有为其赋值,然后在使用 fclose 关闭它时报错。

    1
    2
    FILE * fp_res = NULL;//文件指针
    //fclose(fp_res);
  2. 错误现象:fsanitize报错,不加 -fsanitize=address 不报错,显示如下:

    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
    =================================================================
    ==1301==ERROR: AddressSanitizer: dynamic-stack-buffer-overflow on address 0x7fffca3868a4 at pc 0x564b815e8c89 bp 0x7fffca386850 sp 0x7fffca386840
    WRITE of size 4 at 0x7fffca3868a4 thread T0
    #0 0x564b815e8c88 in main (/mnt/d/stm32/flower/stm32-project/a_Server/t+0x2c88)
    #1 0x7fb02027e082 in __libc_start_main ../csu/libc-start.c:308
    #2 0x564b815e860d in _start (/mnt/d/stm32/flower/stm32-project/a_Server/t+0x260d)

    Address 0x7fffca3868a4 is located in stack of thread T0
    SUMMARY: AddressSanitizer: dynamic-stack-buffer-overflow (/mnt/d/stm32/flower/stm32-project/a_Server/t+0x2c88) in main
    Shadow bytes around the buggy address:
    0x100079468cc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    0x100079468cd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    0x100079468ce0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    0x100079468cf0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    0x100079468d00: 00 00 00 00 00 00 00 00 00 00 00 00 ca ca ca ca
    =>0x100079468d10: 00 00 00 00[04]cb cb cb cb cb cb cb 00 00 00 00
    0x100079468d20: 00 00 00 00 00 00 00 00 00 00 f1 f1 f1 f1 00 00
    0x100079468d30: f2 f2 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    0x100079468d40: 00 00 00 00 00 f2 f2 f2 f2 f2 f2 f2 f2 f2 00 00
    0x100079468d50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    0x100079468d60: 00 f2 f2 f2 f2 f2 f2 f2 f2 f2 00 00 00 00 00 00
    Shadow byte legend (one shadow byte represents 8 application bytes):
    Addressable: 00
    Partially addressable: 01 02 03 04 05 06 07
    Heap left redzone: fa
    Freed heap region: fd
    Stack left redzone: f1
    Stack mid redzone: f2
    Stack right redzone: f3
    Stack after return: f5
    Stack use after scope: f8
    Global redzone: f9
    Global init order: f6
    Poisoned by user: f7
    Container overflow: fc
    Array cookie: ac
    Intra object redzone: bb
    ASan internal: fe
    Left alloca redzone: ca
    Right alloca redzone: cb
    Shadow gap: cc
    #0 0x564b815e8c88 in main (/mnt/d/stm32/flower/stm32-project/a_Server/t+0x2c88)
    ==1301==ABORTING
    #1 0x7fb02027e082 in __libc_start_main ../csu/libc-start.c:308
    #2 0x564b815e860d in _start (/mnt/d/stm32/flower/stm32-project/a_Server/t+0x260d)

    错误原因:局部变量和数组没有正确的分配空间,导致写入了栈空间之外的内存。代码中有如下几段语句:

    1
    2
    3
    4
    pid_t  pid[atoi(argv[3])];
    *** 省略若干行 ***
    while(i <= atoi(argv[3])){
    pid[i] = fork();

    查明后,发现原因很简单,容易想到(甚至 chatGPT都给了明确的建议,如下),但找到这个错误过程还是挺长的。

    1. 递归调用没有正确的停止条件。
    2. 局部变量和数组没有正确的分配空间,导致写入了栈空间之外的内存。
    3. 指针未进行正确的内存管理,例如指向了已释放的内存、未初始化的指针或者越界访问了指针指向的内存。

    debug过程:

    第一,通过给出的偏移地址(t+0x2c88)查看反汇编(objdump -t xxx),但似乎地址没找对,也不太清除具体该汇编语句是什么含义:

    1
    2
    3
    4
    2c81:       48 89 c7                mov    %rax,%rdi
    2c84: e8 77 f7 ff ff callq 2400 <__asan_report_store4@plt>
    2c89: 48 8b 85 08 fc ff ff mov -0x3f8(%rbp),%rax
    2c90: 8b 95 f0 fb ff ff mov -0x410(%rbp),%edx

    通过上下文,基本可以将该语句锁定在while循环内,但不知道对应那条c语言语句。

    第二,查看影子寄存器,待研究

    第三,gdb调试,下面详述一下调试过程,

    先输入 gdb xxx, 然后设置参数 set args arg1 arg2 arg3 ,打断点break 函数名/行号,然后 run开始运行, 然后输入 next,一行一行调试。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    ttj@ttj /m/d/s/f/s/a_Server (master)> gdb t
    Reading symbols from t...
    (gdb) set args 172.27.2.164 7788 9
    (gdb) b 85
    Breakpoint 1 at 0x2c30: file virtual_terminal.c, line 85.
    (gdb) r
    Starting program: /mnt/d/stm32/flower/stm32-project/a_Server/t 172.27.2.164 7788 9
    [Thread debugging using libthread_db enabled]
    Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

    Breakpoint 1, main (argc=4, argv=0x7fffffffe3e8) at virtual_terminal.c:85
    85 while(i <= atoi(argv[3])){
    (gdb) n
    86 pid[i] = fork();
    (gdb) n
    [Detaching after fork from child process 2936]
    [pid](2936) stu_cli_res_pid_is_2936.txt is created!
    87 if(pid[i] == -1){
    (gdb) n
    92 else if(pid[i] == 0){

    最后会有一个报错,这里就直接把行号写出来了,86行,到这才发现是这个数组越界了。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    [Detaching after fork from child process 2952]
    =================================================================
    ==2952==ERROR: AddressSanitizer: dynamic-stack-buffer-overflow on address 0x7fffffffde44 at pc 0x555555556c89 bp 0x7fffffffddf0 sp 0x7fffffffdde0
    WRITE of size 4 at 0x7fffffffde44 thread T0
    =================================================================
    ==2932==ERROR: AddressSanitizer: dynamic-stack-buffer-overflow on address 0x7fffffffde44 at pc 0x555555556c89 bp 0x7fffffffddf0 sp 0x7fffffffdde0
    WRITE of size 4 at 0x7fffffffde44 thread T0
    #0 0x555555556c88 in main /mnt/d/stm32/flower/stm32-project/a_Server/virtual_terminal.c:86
    #1 0x7ffff73c2082 in __libc_start_main ../csu/libc-start.c:308
    #2 0x55555555660d in _start (/mnt/d/stm32/flower/stm32-project/a_Server/t+0x260d)
  3. 错误现象:此错误未知,用sscanf很难读取数据,一直没法读取下一个数据,只有用snprintf才成功。下次试试volatile

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    if(sscanf(read_buf, "%d", &user_num) == 1){
    regroup[regroup_index][i++] = user_num;
    }
    while(*(read_buf+si) <= '9' && *(read_buf+si) >= '0') si++;
    char *p = strchr(read_buf, ' ');
    while(1){
    int flag = sscanf(p+si, "%d", &user_num);
    //while(*(read_buf+si) <= '9' && *(read_buf+si) >= '0') si++;
    si += snprintf(NULL, 0, "%d", user_num); // 加上这一行
    if(flag == 1) {
    printf("p: %s; si : %d\n", p, si);
    regroup[regroup_index][i++] = user_num;
    }
    else{
    break;
    }
    //p = strchr(p, ' ');
    /*while(*read_buf != 0){
    *read_buf = 0;
    read_buf++;
    }
    printf("user_num: %d; %s\n", user_num, p);
    */
    }

imx6ull

相关使用可以查看《imx6ull使用》

  1. 错误现象

    1
    2
    3
    4
    5
    6
    7
    //申明:
    void rtc_setdatetime(struct rtcdatetime *datetime);
    //定义:
    void rtc_setdatetime(struct rtcdatetime *datetime){xxx}
    //报错如下:
    declaration is incompatible with "void rtc_setdatetime(struct rtcdatetime *datetime)" (declared at line 27 of "/home/vmttj/linux_src/ttj_imx6ull/Board_Drivers/16_rtc/bsp/rtc/bsp_rtc.h")
    declaration is incompatible with "void rtc_setdatetime(struct rtcdatetime *datetime)" (declared at line 39 of "/home/vmttj/linux_src/ttj_imx6ull/Board_Drivers/16_rtc/bsp/rtc/bsp_rtc.c")

    错误原因:结构体写错了,正确的写法是struct rtc_datetime,改过来就正确了,但为什么报错不兼容还不清楚。https://blog.csdn.net/ReadAir/article/details/90439479

python

  1. 错误现象:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    源代码:
    for l in range(1, L):
    ### START CODE HERE ### (≈ 2 lines of code)
    parameters['W' + str(l)] = np.random.randn(layer_dims[l], layer_dims[l - 1]) * 0.01
    parameters['b' + str(l)] = np.zeros((layer_dims[l], 1)
    ### END CODE HERE ###

    assert(parameters['W' + str(l)].shape == (layer_dims[l], layer_dims[l-1]))
    assert(parameters['b' + str(l)].shape == (layer_dims[l], 1))
    报错:
    Cell In[32], line 24
    assert(parameters['W' + str(l)].shape == (layer_dims[l], layer_dims[l-1]))
    ^
    SyntaxError: invalid syntax

    错误原因,上一行结尾少了一个右括号。

  2. 错误现象

1
2
3
4
5
6
7
代码:
print(x.grad)
x.grad.data.zero_()
out.backward()
print(x.grad)
------------------------------------------------
RuntimeError: Trying to backward through the graph a second time

错误原因:使用一次backward后,会自动删除中间结果(计算图),导致第二次使用时出错,(ps.看一篇文章说计算过程带加号就不会删除)。可以在backward函数中加上参数retain_graph=True来保留计算图。

  1. linux按照qt后无法打开,报如下错误(使用 export QT_DEBUG_PLUGINS=1显示错误信息):
1
2
3
4
5
6
7
8
Cannot load library /opt/Qt5.12.10/Tools/QtCreator/lib/Qt/plugins/platforms/libqxcb.so: (libxcb-
render-util.so.0: cannot open shared object file: No such file or directory)
QLibraryPrivate::loadPlugin failed on "/opt/Qt5.12.10/Tools/QtCreator/lib/Qt/plugins/platforms/l
ibqxcb.so" : "Cannot load library /opt/Qt5.12.10/Tools/QtCreator/lib/Qt/plugins/platforms/libqxc
b.so: (libxcb-render-util.so.0: cannot open shared object file: No such file or directory)"
qt.qpa.plugin: Could not load the Qt platform plugin "xcb" in "" even though it was found.
This application failed to start because no Qt platform plugin could be initialized. Reinstallin
g the application may fix this problem.

重点在这一行:libxcb-render-util.so.0: cannot open shared object file: No such file or directory,找不到这个库,下载安装即可,其对应的库名为libxcb-render-util0(都是类似的),更改后重新启动qt,有新的报错继续更改即可。

plus. 使用命令查看libqxcb依赖关系: ldd /opt/Qt5.12.10/Tools/QtCreator/lib/Qt/plugins/platforms/ libqxcb.so,结果如下:

1
2
3
4
5
6
7
......
libxcb-image.so.0 => /lib/x86_64-linux-gnu/libxcb-image.so.0 (0x00007fdc460d0000)
libxcb-shm.so.0 => /lib/x86_64-linux-gnu/libxcb-shm.so.0 (0x00007fdc460cb000)
libxcb-keysyms.so.1 => /lib/x86_64-linux-gnu/libxcb-keysyms.so.1 (0x00007fdc460c6000)
libxcb-randr.so.0 => /lib/x86_64-linux-gnu/libxcb-randr.so.0 (0x00007fdc460b3000)
libxcb-render-util.so.0 => not found
.....

表示缺少这个包。

  1. 在Qt中使用Python时报错,include了一个 <pybind11/embed.h>文件
1
2
3
4
5
6
//object.h
PyType_Slot *slots;
----------------------报错信息----------------------
/usr/include/python3.8/object.h:190: error: expected unqualified-id before ';' token
190 | PyType_Slot *slots; /* terminated by slot==0. */
| ^

这里是python中的object文件,不应该是这个头文件出错了,而是头文件里面冲突了,在Qt中,slots是特殊的宏,define slots __attribute__((annotate("qt_slot"))) 它被用来声明函数是槽函数,当qt的头文件在<pybind11/embed.h>之前时,后者的slots变量就被替换成了qt中的宏,导致分号前没有变量名字而报错。

解决方法:将<pybind11/embed.h>这个头文件放到Qt的头文件之前。

参考:https://github.com/pybind/pybind11/issues/2305#issuecomment-660540709

pthread_create陷阱

首先看一下该函数的函数原型。

1
2
3
4
5
1#include <pthread.h>
2int pthread_create (pthread_t *thread_tid, //返回新生成的线程的id
3 const pthread_attr_t *attr, //指向线程属性的指针,通常设置为NULL
4 void * (*start_routine) (void *), //处理线程函数的地址
5 void *arg); //start_routine()中的参数

函数原型中的第三个参数,为函数指针,指向处理线程函数的地址。该函数,要求为静态函数。如果处理线程函数为类成员函数时,需要将其设置为静态成员函数

this指针的锅

pthread_create的函数原型中第三个参数的类型为函数指针,指向的线程处理函数参数类型为(void *),若线程函数为类成员函数,则this指针会作为默认的参数被传进函数中,从而和线程函数参数(void*)不能匹配,不能通过编译。

静态成员函数就没有这个问题,里面没有this指针。

一般解决方法就是第三个参数传入一个静态函数,第四个参数传入一个对象,在静态函数中完成对对象中成员函数的调用。

找不到函数定义

  1. 虽然可以点击函数名字跳转,但就是会报错,找不到函数定义,可能是因为头文件和系统的文件重名了。
  2. 可能是cmake配置,或makefile配置没有编译某些文件,导致了这个问题。但是vsc编辑器可以帮我们进行跳转

size()

如下的代码:size()其实返回的是unsigned,如果size为0,减一后为超级大的数,导致出错。

1
2
for(int i = 0; i < ret.size() - 1; i++){
std::cout << "click " << ret[i] << " -> "; }