Freertos和uart发送中断的必要性
Freertos and the necessity of uart transmit interrupt
对于 uart 接收,我很清楚在 'blocking receive' over uart 的情况下会出现什么问题。即使在具有从 uart 读取的专用任务的 freertos 中,上下文/任务切换也可能导致丢失在 uart 外设中接收到的字节。
但是对于传输我不太确定是否需要基于中断的方法。我从一个任务传输,在我的设计中,如果该任务被短时间阻塞是没有问题的。 (它也在互斥体上 blocks/sleeps 例如)。
在中断模式下使用 uart 传输是否还有另一个强有力的论据?我不会冒丢失数据的风险,对吧?
在我的例子中,我使用的是 stm32,但我想 mcu 的类型在这里并不真正相关。
让我们只关注 TX 并假设我们不使用中断并使用 RTOS 提供的工具处理所有传输。
µC UART硬件通常有一个发送移位寄存器(TSR)和某种数据寄存器(DR)。软件载入DR,如果TSR为空,DR立即转入TSR,TX开始。软件可以自由地将另一个字节加载到 DR,只要前一个字节的 TX(移出)完成,硬件就会将新字节从 DR 加载到 TSR。硬件提供状态位,用于查询 DR & TSR 的状态。这样,软件可以使用轮询的方式,仍然可以实现连续传输,字节之间没有间隙。
我不确定我上面描述的硬件配置是否适用于每个 µC。我有 8 位和 16 位 PIC 以及 STM32 F0、F1、F4 系列的经验。它们都很相似。 UART 硬件不提供额外的硬件缓冲区。
现在,回到 RTOS...显然,您的 TX 任务需要轮询 UART 状态位。如果我们假设 UART 波特率为 115200(这是一个常用值),您将浪费大约 90 微秒的轮询时间来处理每个字节。 RTOS 的一般规则是,如果您正在等待某事发生,您的任务需要被阻塞,以便其他任务可以 运行。但是阻止什么?什么会告诉你什么时候解锁?为此,您需要中断。您的任务阻塞在任务通知、(ulTaskNotifyTake()
),中断使用xTaskNotifyGive()
.
发出通知
所以,我无法想象不使用中断的任何其他方式。 但是,上面提到的方法也不好。阻塞是没有意义的 - 每个字节都解除阻塞。
有 2 种可能的解决方案:
- 将 TX 处理完全移至中断处理程序 (ISR),并在 TX 完成时通知任务。
- 改用 DMA! 几乎所有现代 32 位 µC 都支持 DMA。 DMA 在 TX 完成时生成单个中断。您可以从 DMA 传输完成中断通知任务。
关于这个答案,我主要关注 TX,但使用 DMA 也是处理接收 (RX) 的正确方法。
对于 uart 接收,我很清楚在 'blocking receive' over uart 的情况下会出现什么问题。即使在具有从 uart 读取的专用任务的 freertos 中,上下文/任务切换也可能导致丢失在 uart 外设中接收到的字节。
但是对于传输我不太确定是否需要基于中断的方法。我从一个任务传输,在我的设计中,如果该任务被短时间阻塞是没有问题的。 (它也在互斥体上 blocks/sleeps 例如)。
在中断模式下使用 uart 传输是否还有另一个强有力的论据?我不会冒丢失数据的风险,对吧?
在我的例子中,我使用的是 stm32,但我想 mcu 的类型在这里并不真正相关。
让我们只关注 TX 并假设我们不使用中断并使用 RTOS 提供的工具处理所有传输。
µC UART硬件通常有一个发送移位寄存器(TSR)和某种数据寄存器(DR)。软件载入DR,如果TSR为空,DR立即转入TSR,TX开始。软件可以自由地将另一个字节加载到 DR,只要前一个字节的 TX(移出)完成,硬件就会将新字节从 DR 加载到 TSR。硬件提供状态位,用于查询 DR & TSR 的状态。这样,软件可以使用轮询的方式,仍然可以实现连续传输,字节之间没有间隙。
我不确定我上面描述的硬件配置是否适用于每个 µC。我有 8 位和 16 位 PIC 以及 STM32 F0、F1、F4 系列的经验。它们都很相似。 UART 硬件不提供额外的硬件缓冲区。
现在,回到 RTOS...显然,您的 TX 任务需要轮询 UART 状态位。如果我们假设 UART 波特率为 115200(这是一个常用值),您将浪费大约 90 微秒的轮询时间来处理每个字节。 RTOS 的一般规则是,如果您正在等待某事发生,您的任务需要被阻塞,以便其他任务可以 运行。但是阻止什么?什么会告诉你什么时候解锁?为此,您需要中断。您的任务阻塞在任务通知、(ulTaskNotifyTake()
),中断使用xTaskNotifyGive()
.
所以,我无法想象不使用中断的任何其他方式。 但是,上面提到的方法也不好。阻塞是没有意义的 - 每个字节都解除阻塞。
有 2 种可能的解决方案:
- 将 TX 处理完全移至中断处理程序 (ISR),并在 TX 完成时通知任务。
- 改用 DMA! 几乎所有现代 32 位 µC 都支持 DMA。 DMA 在 TX 完成时生成单个中断。您可以从 DMA 传输完成中断通知任务。
关于这个答案,我主要关注 TX,但使用 DMA 也是处理接收 (RX) 的正确方法。