Post

FreeRTOS interview questions

FreeRTOS interview questions

相关面试问题

  1. FreeRTOS的任务有哪些状态?

    • 就绪(Ready):该任务在就绪列表中,就绪的任务已经具备执行的能力,只等待调度器进行调度,新创建的任务会初始化为就绪态。

    • 运行(Running):该状态表明任务正在执行,此时它占用处理器,FreeRTOS调度器选择运行的永远是处于最高优先级的就绪态任务,当任务被运行的一刻,它的任务状态就变成了运行态。

    • 阻塞(Blocked):如果任务当前正在等待某个时序或外部中断,我们就说这个任务处于阻塞状态,该任务不在就绪列表中。包含任务被挂起、任务被延时、任务正在等待信号量、读写队列或者等待读写事件等。

    • 挂起态(Suspended):处于挂起态的任务对调度器而言是不可见的,让一个任务进入挂起状态的唯一办法就是调用 vTaskSuspend()函数;而把一个挂起状态的任务恢复的唯一途径就是调用 vTaskResume()或vTaskResumeFromISR()函数,我们可以这么理解挂起态与阻塞态的区别,当任务有较长的时间不允许运行的时候,我们可以挂起任务,这样子调度器就不会管这个任务的任何信息,直到我们调用恢复任务的API函数;而任务处于阻塞态的时候,系统还需要判断阻塞态的任务是否超时,是否可以解除阻塞。

  2. 你知道那些实时操作系统的调度算法

  3. 抢占式调度算法,时间片轮转调度算法

  4. FreeRTOS中的任务优先级是如何设置的?

    1. 配置文件中有一个最大优先级,推荐使用第四种优先级分组,也就是4bit抢占优先级,0bit响应优先级
    2. 创建任务时会让指定一个任务优先级
    3. 使用vTaskPrioritySet 来设置任务的优先级
  5. FreeRTOS中的任务延迟是如何实现的?

    1. 通过调用vTaskDelay函数,进入阻塞状态,实现延时
  6. FreeRTOS中实现任务间的消息传递?

  7. FreeRTOS的时间片轮转调度是如何工作的?

  8. 什么是任务控制块(TCB)?它在FreeRTOS中有什么作用?

    1. 任务控制块是 FreeRTOS 中用于描述和管理任务的数据结构,包含了任务的状态、优先级、堆栈等信息。全称为Task Control Block,也就是任务控制块,这个结构体包含了一个任务所有的信息例如:任务名称、任务优先级、栈顶指针
  9. FreeRTOS中的任务优先级反转问题是什么?如何解决?

  10. FreeRTOS的堆管理机制是怎样的?

  11. 在FreeRTOS中,如何实现任务的挂起和恢复?

    1. 调用vTaskSuspend()函数实现挂起

      1. 根据任务句柄获得任务控制块,如果句柄为NULL,则挂起自身
      2. 将要挂起的任务从相应的状态列表和事件列表中移除
      3. 将待挂起任务的任务状态列表向插入到挂起态任务列表末尾
      4. 判断任务调度器是否运行,在运行,更新下一次阻塞时间,防止被挂起任务为下一 次阻塞超时任务
      5. 、如果挂起的是任务自身,且调度器正在运行,需要进行一次任务切换(触发PendSV切换)
      6. 调度器没有运行,判断挂起任务数是否等于任务总数,是:当前控制块赋值为NULL, 否:寻找下一个最高优先级任务
    2. vTaskResume( )实现恢复任务

      1. 需将宏INCLUDE_vTaskSuspend 配置为 1

      2. 恢复任务不能是正在运行任务

      3. 判断任务是否在挂起列表中,是:就会将该任务在挂起列表中移除, 将该任务添加到就绪列表中

      4. 判断恢复的任务优先级是否大于当前正在运行的 是的话执行任务切换

  12. FreeRTOS中如何使用信号量?信号量的类型有哪些?

  13. FreeRTOS的队列机制是如何工作的?它有哪些应用场景?

  14. FreeRTOS中的软件定时器是如何实现的?

  15. 如何在FreeRTOS中处理任务间的共享资源?

  16. FreeRTOS支持哪些类型的中断?中断处理的基本原则是什么?

    1. FreeRTOS开关中断就是操作 BASEPRI 寄存器实现的,它可以关闭低于某个阈值的中断,高于阈值的中断不会被关闭。

    2. 内部中断,即任务与内核之间进行的,如SysTick中断、SVC中断和PendSV中断;外部中断FreeRTOS对外部事件的响应,如按键状态获取、传感器中断信号等

    3. 先响应高优先级中断,中断处理函数要快速执行完毕

  17. FreeRTOS的内存保护机制是如何实现的?

  18. FreeRTOS中的任务堆栈溢出检测是如何工作的?

  19. FreeRTOS中如何实现定时任务?

  20. FreeRTOS的配置文件中,configUSE_PREEMPTION和configUSE_IDLE_HOOK的作用是什么?

  21. FreeRTOS中的任务状态转换图是怎样的?

  22. FreeRTOS的任务通知机制是什么?如何使用?

  23. FreeRTOS如何处理异常和错误?

  24. 在FreeRTOS中,如何实现多核处理?

  25. FreeRTOS的任务调度是如何影响系统性能的?

  26. 如何在FreeRTOS中实现低功耗模式?

  27. FreeRTOS的移植过程通常需要考虑哪些硬件特性?

  28. FreeRTOS的API函数有哪些常用的错误处理机制?

  29. FreeRTOS中如何实现动态任务创建和删除?

  30. FreeRTOS的内存分配策略是什么?

  31. FreeRTOS如何与其他操作系统进行集成?

  32. FreeRTOS的调试工具和方法有哪些?

  33. FreeRTOS的任务调度简述

    1. 任务调度
      1. 启动第一个任务
      2. 启动任务调度器:vTaskStartScheduler
      3. 创建空闲任务:prvIdleTask;创建软件定时器任务:xTimerCreateTimerTask
      4. 关中断(在启动第一个任务时开启);初始化一些全局变量;初始化任务运行时间统计功能的时基定时器
      5. 调用函数xPortStartScheduler完成启动任务调度器
    2. 任务切换流程
      1. 触发任务切换:滴答定时器中断触发PendSV中断或调用FreeRTOS的API函数触发,如:portYIELD( )
      2. 当前的psp是正在运行的任务的栈指针,读取当前psp进程指针,存入r0
      3. 压栈(保存现场)
      4. 获取当前最高优先级任务的任务控制块
      5. 出栈(恢复现场)
      6. 更新切换后的任务的的栈指针给PSP
      7. bx r14 执行新任务函数

ADC与DMA相关

邮箱和队列有什么区别?

邮箱和信号量有什么区别?

邮箱是否需要额外资源(比如队列,需要创建队列)?

回顾什么是 data 段,什么是 bss 段,什么是堆、什么是栈,并在 stm32f4 中,在数据手册中,找到这些区域的地址段

ADC 的 ScanConvMode 参数什么意思?如果我只有一个通道,需要 Enable 吗?

ContinuousConvMode 参数的含义?

EOCSelection 参数的含义?

(选做:中阶面试话题)关于采样时间,为什么越长越准确?能从 ADC 的构造解释一下吗?

什么是SAR 类型的ADC, 什么是Pipelined 类型的ADC ? 什么是Integrating ADC?什么是Successive Approximation ADC?

ADC 外设引脚没有接任何输入,输出会怎么样?

引脚悬空,状态不确定,读取的电平也不确定(受外部电磁场影响)

这里的缓冲区是不是也可以用消息队列实现?

是的,但是这会存在将 buffer1 和 buffer2 中的值反复拷贝的情况,降低了系统效率,因为消息队列的函数发送时会拷贝一次,接收时又会拷贝一次。

为什么不直接在 DMA 的回调函数中启动新的 ADC+DMA 转换传输?

因为,ADC 转换和 DMA 传输非常快,很有可能你还没退出 DMA 的回调,新的 DMA 回调又产生了,此时 DMA 传输就会出错,造成程序卡死。由线程来决定什么时候启动传输是较为可控的,因为,现在我们这个作业就是经典的生产者消费者模型,消费者是线程 B,如果线程 B 都还没处理完数据,那么线程 A 肯定不能启动传输,否则就要丢数据。

如果发现在 ADC 回调里容易卡死,可以尝试加这句话,为什么可以这样解决?有时候可能是因为 ADC_DMA 转换速度其实非常的快,有可能还没退出 ADC_DMA 中断回调就又产生了新的转换,这时候产生了 error。

为什么只能使用中断而不建议使用事件

STM32 中的外部事件和中断触发有以下一些区别:

触发目的:

外部事件:通常用于触发其他硬件模块的操作,例如触发定时器的计数、触发 ADC 的转换等,重点在于控制硬件模块的协同工作。

中断触发:主要目的是通知 CPU 暂停当前正在执行的任务,转而去执行中断服务程序,以处理紧急或重要的事件。

响应方式:

外部事件:不一定会立即引起 CPU 的响应和干预,只是产生一个触发信号。

中断触发:会立即打断 CPU 的当前执行流程,跳转到相应的中断服务程序执行。

优先级:

外部事件:一般没有明确的优先级概念。

中断触发:具有明确的优先级设置,高优先级的中断可以打断低优先级中断的执行。

资源占用:

外部事件:相对来说对系统资源的占用较少。

中断触发:由于需要保存现场和切换上下文,对系统资源的消耗相对较大。

软件 iic 读数据不能结合 dma 是吗

软件 iic 的 iic 通讯过程需要 cpu 参与,硬件 iic 不需要,切软件 ic 通信时需要屏蔽中断

DMA 配置 DMA_Init_Handle.Init.Mode = DMA_CIRCULAR 的用处是什么?

当传递到对应的数据长度时,DMA 的写入指针会回到首地址,继续覆盖持续写入。如果是配置为 DMA_NORMAL,则 DMA 传输完一个 Item 后就会暂停。

ADC 采样中的 Sampling Time 是干什么的?为什么设置久一些数据会更准确?

ADC 是一直处于采集状态吗,线程只是控制 DMA 的开启。

如果你设置 Continuous Conversion Mode(连续转换模式)为 Enable,则 ADC 会一直处于采样状态,一直采样,每当 ADC 采样、保持、转换,每完成一次采集流程,就会向 DMA 发送请求,让他搬运数据。

我们线程 A 完成切换目标缓冲区,线程 B 完成让 CPU 处理 adc 得到的数据

ADC 中如果 Continuous Conversion Mode(连续转换模式)和 Discontinuous Conversion Mode(非连续转换模式)都失能,会发生什么呢?

ADC 将在每个触发事件(比如调用 HAL_ADC_Start()来启动)下仅执行一次转换,然后停止,需要新的触发事件才能启动下一次转换,这种一般用于需要精确控制转换时机的场景,你比如一些信号有一些建立时间,需要在特定时间点采样才是精准的。

另外,解释一下这两个参数的含义:

第一个 Continuous Conversion Mode(连续转换模式)是控制:是否持续的对某一个通道不停地转换,你会在 DR 里面一直看到数据更新,EOC 标志位一直会产生。于是你可以通过轮询或者中断的方式一直来取 ADC 的数据。

第二个 Discontinuous Conversion Mode(非连续转换模式)是控制:是否 ADC 将进入 非连续转换模式(Discontinuous Conversion Mode),在 非连续转换模式下,ADC 会将配置的通道序列分成若干个小组,每个小组的大小由 Discontinuous Number(非连续数目)参数确定,范围是 1 到 8。ADC 会在每个触发事件(软件或硬件触发)下,仅转换一个小组的通道,然后停止,等待下一个触发事件。每次非连续转换都需要新的触发事件。这种模式适用于需要在多个触发事件下分批次采样的情况。例如,在实时控制系统中,可能希望在每个控制周期内只采样部分通道(而不是 全部通道),以减少 CPU 负担。

比如说,如果你配置了 6 个通道的序列,且将 Discontinuous Number 设置为 2,那么 ADC 会将这 6 个通道分成 3 组,每组 2 个通道。每次触发事件会启动一组(2 个通道)的转换,需要 3 次触发事件才能完成所有通道的转换。

使能 Discontinuous Conversion Mode 但仅把 Discontinuous Number 设为 1,是不是就和没开这个模式一样呢?

不一样,你想想,你如果 Discontinuous Number 设为 1,假如你原先有 5 个通道,那么这 5 个通道就会被分为 5 个组:

(1)Discontinuous Conversion Mode 是 Enable 的情况:

那么每次触发你只转换一个组,那么你就需要 5 次触发才能转换这五个组(每个组一个通道)。

(2)Discontinuous Conversion Mode 是 Disable 的情况:

那么只需要一次触发你就会直接连续转换这五个组(每个组一个通道)。

串口相关

1. 串口接收不定长数据的几种方式

1.帧头帧尾标志法

1.1 原理

帧头帧尾标志法是一种常用的方式,通过在数据包的开头和结尾添加特定的标志符号来标识数据包的起始和结束。接收端通过检测标志符号的位置,将接收到的数据拼接成完整的数据包。

1.2 实现步骤

  • 发送端:在数据包的开头添加帧头标志,例如0xAA;在数据包的结尾添加帧尾标志,例如0xBB。
  • 接收端:循环接收串口数据,并判断接收到的数据是否与帧头标志相匹配。如果匹配成功,则开始接收数据,直到遇到帧尾标志为止。

1.3 注意事项

使用帧头帧尾标志法时,需要注意以下事项:

  • 标志符号的选择应避免与数据包中的数据重复。
  • 如果数据包中可能出现标志符号本身,则需要进行转义处理,以避免误判。

2.长度字段法

2.1 原理

长度字段法是另一种常用的方式,通过在数据包中添加一个字节或多个字节的长度字段,来明确指示数据包的长度。接收端根据长度字段提前知道数据包的长度,从而正确接收并解析数据。

2.2 实现步骤

  • 发送端:在数据包中添加一个长度字段,表示数据包的长度。
  • 接收端:先接收长度字段,然后根据长度字段的值设定接收缓冲区的大小。之后再接收剩余的数据,并进行解析。

2.3 注意事项

使用长度字段法时,需要注意以下事项:

  • 长度字段的长度和编码方式需要提前约定好,以确保发送端和接收端一致。
  • 需要考虑字节序(大端序或小端序)的问题,以保证多字节长度字段的正确解析。

3.超时等待法

3.1 原理

超时等待法是一种简单直观的方式,通过设定一个接收超时时间,在接收到数据后等待一段时间,如果在超时时间内没有接收到新的数据,则认为数据接收完毕。

3.2 实现步骤

  • 发送端:连续发送数据包。
  • 接收端:设定一个接收超时时间。当接收到数据后开始计时,如果在超时时间内没有接收到新的数据,则认为数据接收完毕。

3.3 注意事项

使用超时等待法时,需要注意以下事项:

  • 超时时间的设置需要考虑到数据包的最大长度和串口传输速率,以确保足够的时间接收完整的数据包。
  • 如果数据包传输中出现错误或丢失数据,可能会导致超时判断错误,因此需要在设计中考虑数据的可靠性。

4.结束符法

4.1 原理

结束符法是一种简单直接的方式,通过在数据包的结尾添加一个特定的结束符号来标识数据包的结束。接收端通过检测结束符号的位置来确定数据包的边界。

4.2 实现步骤

  • 发送端:在数据包的结尾添加一个特定的结束符号,例如换行符’n’或回车符’r’。
  • 接收端:循环接收串口数据,并检测接收到的数据中是否包含结束符号。如果存在结束符号,则将之前接收到的数据视为一个完整的数据包。

4.3 注意事项

使用结束符法时,需要注意以下事项:

  • 结束符号的选择应避免与数据包中的数据重复。
  • 如果数据包中可能出现结束符号本身,则需要进行转义处理,以避免误判。
This post is licensed under CC BY 4.0 by the author.