Foreword

Debug遇到一个诡异情况,之前没注意过

单步失效

简单说系统里有很多地方在read,但是debug的那个read,在进入read内部以后,会出现整个堆栈指针都跳变成另外一个线程中read流程

ssize_t read(struct file *filep, void *buf, size_t nbytes)
{
  struct inode *inode;
  int ret = -EBADF;

  configASSERT(filep);
  inode = filep->f_inode;

  /* Was this file opened for read access? */
  if ((filep->f_oflags & O_RDOK) == 0)
  {
    /* No.. File is not read-able */
    ret = -EACCES;
  }

  /* Is a driver or mountpoint registered? If so, does it support the read
   * method?
   */
  else if (inode != NULL && inode->u.i_ops && inode->u.i_ops->read)
  {
    /* Yes.. then let it perform the read.  NOTE that for the case of the
     * mountpoint, we depend on the read methods being identical in
     * signature and position in the operations vtable.
     */
    ret = (int)inode->u.i_ops->read(filep, (char *)buf, (size_t)nbytes);
  }

  /* If an error occurred, set errno and return -1 (ERROR) */
  if (ret < 0)
  {
    set_errno(-ret);
    return ERR;
  }

  /* Otherwise, return the number of bytes read */
  return ret;
}

这种情况基本100%可以复现,单独去这个线程的实际read的接口处断点,完全没有问题,就是这个中间过程断不住。

汇编断点

尝试使用汇编单步执行,中间过程可以比较容易的进入,但是不能用step over,用一次就必然跳变。

这种方式依然不够好,如果中间过程很复杂,免不了要跳很多,手动得累死个人。

看了一下当前使用的JLink还是V9的老版本固件,刚好有闲置的新的V11JLink,更换以后依然停不住

Ozone

尝试使用Ozone进行调试,毕竟SES单独把这个调试工具独立出来,总有些独到之处吧。

新建工程选择芯片,设置内部或者外部Flash即可

设置调试接口,选择调试设备

直接选择工程的*.elf文件,会自动关联到对应的代码文件位置各种变量,总体来说还是挺方便的

额外选项,默认就行了

如果使用了FreeRTOS,这里会出现插件提示,应用插件 fix-ups,这样有额外的FreeRTOS的调度栈显示

如果直接continue,那么单步失效的情况依然会复现,但是如果用了插件,那么情况就大为改观

FreeRTOS插件

有了插件以后,可以看到每个任务的情况,并且可以看到每个任务的调度栈具体在哪里了。

FreeRTOSPlugin这个目前看只写了CM4的支持,所以可能看到的信息有一些缺漏或者不准确的地方

而这个插件是JS的,官方也给了SDK,需要的话可以自行增加更多的功能

关闭调试以后会提示保存调试工程,存储以后可以看到一个jdebug的文件,打开就能看到这里加载的CM4,搜了一下官方是有CM7的支持的

所以直接改成CM7即可

单步问题

单步进不去的问题,实际上我通过关闭一些高级任务的运行或者提高debug任务的级别,是可以让他正常单步进去的,概率提高了很多,虽然偶尔也会出问题,但是这种方式不符合实际使用的情况。

Ozone+FreeRTOS插件实际上也不是完美的,偶尔还是会出现整个调度栈闪变的情况。

而这个单步问题,应该就是JLink断点,但是单步时出现了系统调度出让CPU,进而调度栈整个发生了变更,等到停下来已经在别的线程中了。有了FreeRTOS插件加持以后,等于知道了你当前断点是在这个线程的断点,而非全局的断点,从而可以正确停在此线程的中间过程。

猜想内部实现应该是类似断点加条件判断,识别出来是这个线程才断点的

SES RTOS Awareness

SES自己也能开启RTOS插件辅助

  • 注意Task过多的情况下需要将25的默认值调高,方便调试

但是实测了以后,发现某些任务是识别不到的,这里只有27个任务,但是Ozone那边识别到了54个任务,这也是为什么SES挺不住了,任务数两边不对等导致的

这个问题提交给官方了,看官方怎么处理吧

Summary

稍微有点蛋疼

Quote

https://mcuoneclipse.com/2016/10/15/freertos-kernel-awareness-with-ozone/